]> rtime.felk.cvut.cz Git - can-eth-gw-linux.git/commitdiff
Merge remote-tracking branch 'regulator/topic/tps6586x' into regulator-next
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 10 Dec 2012 03:43:29 +0000 (12:43 +0900)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 10 Dec 2012 03:43:29 +0000 (12:43 +0900)
416 files changed:
CREDITS
Documentation/cgroups/memory.txt
Documentation/devicetree/bindings/net/mdio-gpio.txt
Documentation/devicetree/bindings/regulator/gpio-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/max8925-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/max8997-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/vexpress.txt [new file with mode: 0644]
Documentation/filesystems/proc.txt
Documentation/networking/netdev-features.txt
Documentation/networking/vxlan.txt
MAINTAINERS
Makefile
arch/alpha/kernel/osf_sys.c
arch/arm/boot/Makefile
arch/arm/boot/dts/tegra30.dtsi
arch/arm/mach-at91/at91rm9200_devices.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-exynos/dma.c
arch/arm/mach-exynos/include/mach/map.h
arch/arm/mach-highbank/system.c
arch/arm/mach-imx/clk-gate2.c
arch/arm/mach-imx/ehci-imx25.c
arch/arm/mach-imx/ehci-imx35.c
arch/arm/mach-omap2/board-igep0020.c
arch/arm/mach-omap2/clockdomains44xx_data.c
arch/arm/mach-omap2/common-board-devices.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/twl-common.c
arch/arm/mach-omap2/vc.c
arch/arm/mach-pxa/hx4700.c
arch/arm/mach-pxa/spitz_pm.c
arch/arm/plat-omap/i2c.c
arch/arm/plat-omap/include/plat/omap_hwmod.h
arch/arm/tools/Makefile
arch/arm64/include/asm/io.h
arch/arm64/include/asm/pgtable-hwdef.h
arch/arm64/include/asm/pgtable.h
arch/ia64/mm/init.c
arch/m68k/include/asm/signal.h
arch/mips/cavium-octeon/executive/cvmx-l2c.c
arch/mips/fw/arc/misc.c
arch/mips/include/asm/bitops.h
arch/mips/include/asm/compat.h
arch/mips/include/asm/io.h
arch/mips/include/asm/irqflags.h
arch/mips/include/asm/thread_info.h
arch/mips/kernel/setup.c
arch/mips/lib/Makefile
arch/mips/lib/bitops.c [new file with mode: 0644]
arch/mips/lib/mips-atomic.c [new file with mode: 0644]
arch/mips/mti-malta/malta-platform.c
arch/parisc/kernel/signal32.c
arch/parisc/kernel/sys_parisc.c
arch/powerpc/boot/dts/mpc5200b.dtsi
arch/powerpc/boot/dts/o2d.dtsi
arch/powerpc/boot/dts/pcm030.dts
arch/powerpc/platforms/52xx/mpc52xx_pic.c
arch/powerpc/platforms/pseries/eeh_pe.c
arch/powerpc/platforms/pseries/msi.c
arch/s390/Kconfig
arch/s390/include/asm/compat.h
arch/s390/include/asm/topology.h
arch/s390/include/uapi/asm/ptrace.h
arch/s390/kernel/compat_signal.c
arch/s390/kernel/signal.c
arch/s390/kernel/topology.c
arch/s390/mm/gup.c
arch/sparc/include/asm/prom.h
arch/sparc/kernel/signal_64.c
arch/unicore32/Kconfig
arch/unicore32/include/asm/Kbuild
arch/unicore32/include/asm/bug.h
arch/unicore32/include/asm/cmpxchg.h
arch/unicore32/include/asm/kvm_para.h [deleted file]
arch/unicore32/include/asm/processor.h
arch/unicore32/include/asm/ptrace.h
arch/unicore32/include/uapi/asm/Kbuild
arch/unicore32/include/uapi/asm/byteorder.h [moved from arch/unicore32/include/asm/byteorder.h with 100% similarity]
arch/unicore32/include/uapi/asm/ptrace.h [new file with mode: 0644]
arch/unicore32/include/uapi/asm/sigcontext.h [moved from arch/unicore32/include/asm/sigcontext.h with 100% similarity]
arch/unicore32/include/uapi/asm/unistd.h [moved from arch/unicore32/include/asm/unistd.h with 92% similarity]
arch/unicore32/kernel/entry.S
arch/unicore32/kernel/process.c
arch/unicore32/kernel/setup.h
arch/unicore32/kernel/sys.c
arch/unicore32/mm/fault.c
arch/x86/boot/compressed/eboot.c
arch/x86/boot/header.S
arch/x86/include/asm/ptrace.h
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/mcheck/mce_amd.c
arch/x86/kernel/cpu/mcheck/mce_intel.c
arch/x86/kernel/entry_64.S
arch/x86/kernel/microcode_amd.c
arch/x86/kernel/ptrace.c
arch/x86/kvm/cpuid.h
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/tlb.c
arch/x86/pci/ce4100.c
arch/x86/platform/ce4100/ce4100.c
block/blk-exec.c
drivers/ata/ahci_platform.c
drivers/ata/libata-acpi.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/ata/pata_arasan_cf.c
drivers/ata/sata_highbank.c
drivers/ata/sata_svw.c
drivers/base/power/qos.c
drivers/block/aoe/aoecmd.c
drivers/block/floppy.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/mtip32xx/mtip32xx.h
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/bus/omap-ocp2scp.c
drivers/clk/ux500/u8500_clk.c
drivers/edac/amd64_edac.h
drivers/edac/edac_stub.c
drivers/edac/mce_amd_inj.c
drivers/firewire/sbp2.c
drivers/gpio/Kconfig
drivers/gpio/gpio-mcp23s08.c
drivers/gpio/gpio-mvebu.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/engine/graph/ctxnv40.c
drivers/gpu/drm/nouveau/core/engine/graph/nv40.c
drivers/gpu/drm/nouveau/core/engine/graph/nv40.h
drivers/gpu/drm/nouveau/core/include/core/object.h
drivers/gpu/drm/nouveau/core/include/subdev/clock.h
drivers/gpu/drm/nouveau/core/subdev/bios/dcb.c
drivers/gpu/drm/nouveau/core/subdev/clock/nva3.c
drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/radeon_agp.c
drivers/gpu/drm/ttm/ttm_page_alloc.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
drivers/hid/hid-microsoft.c
drivers/i2c/busses/i2c-at91.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-omap.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/muxes/i2c-mux-pinctrl.c
drivers/input/input-mt.c
drivers/input/mousedev.c
drivers/input/touchscreen/ads7846.c
drivers/iommu/intel-iommu.c
drivers/iommu/tegra-smmu.c
drivers/irqchip/irq-bcm2835.c
drivers/leds/ledtrig-cpu.c
drivers/md/dm.c
drivers/md/md.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/mfd/max8997.c
drivers/mfd/wm5102-tables.c
drivers/mtd/devices/slram.c
drivers/mtd/nand/nand_base.c
drivers/mtd/ofpart.c
drivers/mtd/onenand/onenand_base.c
drivers/net/bonding/bond_main.c
drivers/net/ethernet/8390/ne.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/jme.c
drivers/net/ethernet/micrel/ksz884x.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/sis/sis900.c
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ethernet/tile/tilegx.c
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/ethernet/xscale/ixp4xx_eth.c
drivers/net/irda/sir_dev.c
drivers/net/phy/mdio-bitbang.c
drivers/net/phy/mdio-gpio.c
drivers/net/team/team_mode_broadcast.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/smsc95xx.c
drivers/net/vxlan.c
drivers/net/wan/ixp4xx_hss.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/iwlwifi/dvm/mac80211.c
drivers/net/wireless/iwlwifi/dvm/main.c
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/mwifiex/sdio.c
drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
drivers/net/xen-netfront.c
drivers/nfc/pn533.c
drivers/pinctrl/Kconfig
drivers/rapidio/rio.c
drivers/regulator/88pm8607.c
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/aat2870-regulator.c
drivers/regulator/ab3100.c
drivers/regulator/ab8500.c
drivers/regulator/ad5398.c
drivers/regulator/anatop-regulator.c
drivers/regulator/arizona-ldo1.c
drivers/regulator/arizona-micsupp.c
drivers/regulator/as3711-regulator.c [new file with mode: 0644]
drivers/regulator/core.c
drivers/regulator/da903x.c
drivers/regulator/da9052-regulator.c
drivers/regulator/da9055-regulator.c [new file with mode: 0644]
drivers/regulator/db8500-prcmu.c
drivers/regulator/dbx500-prcmu.c
drivers/regulator/dummy.c
drivers/regulator/fan53555.c
drivers/regulator/fixed.c
drivers/regulator/gpio-regulator.c
drivers/regulator/isl6271a-regulator.c
drivers/regulator/lp3971.c
drivers/regulator/lp3972.c
drivers/regulator/lp872x.c
drivers/regulator/lp8788-buck.c
drivers/regulator/lp8788-ldo.c
drivers/regulator/max1586.c
drivers/regulator/max77686.c
drivers/regulator/max8649.c
drivers/regulator/max8660.c
drivers/regulator/max8907-regulator.c
drivers/regulator/max8925-regulator.c
drivers/regulator/max8952.c
drivers/regulator/max8973-regulator.c [new file with mode: 0644]
drivers/regulator/max8997.c
drivers/regulator/max8998.c
drivers/regulator/mc13783-regulator.c
drivers/regulator/mc13892-regulator.c
drivers/regulator/mc13xxx-regulator-core.c
drivers/regulator/palmas-regulator.c
drivers/regulator/pcap-regulator.c
drivers/regulator/pcf50633-regulator.c
drivers/regulator/rc5t583-regulator.c
drivers/regulator/s2mps11.c
drivers/regulator/s5m8767.c
drivers/regulator/tps51632-regulator.c [new file with mode: 0644]
drivers/regulator/tps6105x-regulator.c
drivers/regulator/tps62360-regulator.c
drivers/regulator/tps65023-regulator.c
drivers/regulator/tps6507x-regulator.c
drivers/regulator/tps65090-regulator.c
drivers/regulator/tps65217-regulator.c
drivers/regulator/tps6524x-regulator.c
drivers/regulator/tps6586x-regulator.c
drivers/regulator/tps65910-regulator.c
drivers/regulator/tps65912-regulator.c
drivers/regulator/tps80031-regulator.c [new file with mode: 0644]
drivers/regulator/twl-regulator.c
drivers/regulator/vexpress.c [new file with mode: 0644]
drivers/regulator/virtual.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-isink.c
drivers/regulator/wm831x-ldo.c
drivers/regulator/wm8400-regulator.c
drivers/regulator/wm8994-regulator.c
drivers/s390/char/con3215.c
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/scsi/isci/request.c
drivers/scsi/scsi.c
drivers/scsi/scsi_lib.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/staging/android/android_alarm.h
drivers/tty/hvc/hvc_console.c
drivers/tty/serial/max310x.c
drivers/usb/core/hcd.c
drivers/usb/early/ehci-dbgp.c
drivers/usb/host/ehci-ls1x.c
drivers/usb/host/ohci-xls.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/ux500.c
drivers/usb/otg/Kconfig
drivers/usb/serial/keyspan.c
drivers/usb/serial/option.c
drivers/usb/serial/usb_wwan.c
drivers/usb/storage/scsiglue.c
drivers/video/omap2/dss/dsi.c
drivers/video/omap2/dss/dss.c
drivers/video/omap2/dss/hdmi.c
drivers/video/omap2/omapfb/omapfb-ioctl.c
drivers/xen/privcmd.c
fs/ext3/balloc.c
fs/file.c
fs/jffs2/file.c
fs/notify/fanotify/fanotify_user.c
fs/proc/base.c
fs/pstore/platform.c
fs/reiserfs/inode.c
fs/reiserfs/stree.c
fs/reiserfs/super.c
fs/ubifs/find.c
fs/ubifs/lprops.c
fs/ubifs/ubifs.h
fs/xfs/xfs_aops.c
fs/xfs/xfs_attr_leaf.c
fs/xfs/xfs_buf.c
include/drm/drm_pciids.h
include/linux/clk-provider.h
include/linux/i2c-omap.h
include/linux/mfd/arizona/registers.h
include/linux/mfd/da9055/pdata.h
include/linux/mfd/max8997-private.h
include/linux/mfd/max8997.h
include/linux/mfd/tps65090.h
include/linux/mm.h
include/linux/mmzone.h
include/linux/of_address.h
include/linux/platform_data/omap_ocp2scp.h [new file with mode: 0644]
include/linux/regulator/consumer.h
include/linux/regulator/driver.h
include/linux/regulator/max8973-regulator.h [new file with mode: 0644]
include/linux/regulator/tps51632-regulator.h [new file with mode: 0644]
include/linux/regulator/tps65090-regulator.h [deleted file]
include/linux/rio.h
include/linux/spi/ads7846.h
include/net/xfrm.h
include/scsi/scsi_device.h
include/uapi/linux/oom.h
kernel/futex.c
lib/mpi/longlong.h
mm/bootmem.c
mm/highmem.c
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/mmap.c
mm/mmzone.c
mm/nobootmem.c
mm/page_alloc.c
mm/shmem.c
mm/swapfile.c
mm/vmscan.c
net/batman-adv/soft-interface.c
net/batman-adv/translation-table.c
net/bluetooth/hci_core.c
net/bluetooth/mgmt.c
net/bluetooth/smp.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/net-sysfs.c
net/ipv4/ip_sockglue.c
net/ipv4/ip_vti.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_metrics.c
net/ipv4/tcp_output.c
net/ipv4/xfrm4_policy.c
net/ipv6/inet6_connection_sock.c
net/ipv6/ipv6_sockglue.c
net/mac80211/cfg.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/main.c
net/mac80211/scan.c
net/mac80211/sta_info.c
net/mac80211/status.c
net/mac80211/tx.c
net/mac80211/util.c
net/netfilter/ipset/ip_set_hash_ip.c
net/netfilter/ipset/ip_set_hash_ipport.c
net/netfilter/ipset/ip_set_hash_ipportip.c
net/netfilter/ipset/ip_set_hash_ipportnet.c
net/netfilter/nfnetlink_cttimeout.c
net/nfc/llcp/llcp.c
net/sctp/proc.c
net/wireless/reg.c
scripts/kconfig/expr.h
scripts/kconfig/list.h [new file with mode: 0644]
scripts/kconfig/lkc_proto.h
scripts/kconfig/mconf.c
scripts/kconfig/menu.c
scripts/sign-file
security/device_cgroup.c
security/selinux/netnode.c
sound/pci/es1968.c
sound/pci/fm801.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/arizona.c
sound/soc/codecs/cs4271.c
sound/soc/codecs/cs42l52.c
sound/soc/codecs/wm5102.c
sound/soc/codecs/wm8978.c
sound/soc/kirkwood/kirkwood-dma.c
sound/soc/kirkwood/kirkwood-i2s.c
sound/soc/mxs/mxs-saif.c
sound/soc/samsung/Kconfig
sound/soc/samsung/bells.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/usb/card.c
sound/usb/midi.c
sound/usb/pcm.c
tools/power/x86/turbostat/turbostat.c

diff --git a/CREDITS b/CREDITS
index d8fe12a9421fa2a7145e7218cc7d664232d0d7ce..2346b09ca8bb9cfc3c4371eb5ad6058be818d990 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1823,6 +1823,11 @@ S: Kattreinstr 38
 S: D-64295
 S: Germany
 
+N: Avi Kivity
+E: avi.kivity@gmail.com
+D: Kernel-based Virtual Machine (KVM)
+S: Ra'annana, Israel
+
 N: Andi Kleen
 E: andi@firstfloor.org
 U: http://www.halobates.de
index c07f7b4fb88d162ad012e69a3d77aa90d62868ff..71c4da413444d969519ae464250774db5c05de63 100644 (file)
@@ -466,6 +466,10 @@ Note:
 5.3 swappiness
 
 Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only.
+Please note that unlike the global swappiness, memcg knob set to 0
+really prevents from any swapping even if there is a swap storage
+available. This might lead to memcg OOM killer if there are no file
+pages to reclaim.
 
 Following cgroups' swappiness can't be changed.
 - root cgroup (uses /proc/sys/vm/swappiness).
index bc9549529014730bc6abd0cefba2d82824370e5e..c79bab025369af4bb6320ba0e90f7fb386942cc1 100644 (file)
@@ -8,9 +8,16 @@ gpios property as described in section VIII.1 in the following order:
 
 MDC, MDIO.
 
+Note: Each gpio-mdio bus should have an alias correctly numbered in "aliases"
+node.
+
 Example:
 
-mdio {
+aliases {
+       mdio-gpio0 = <&mdio0>;
+};
+
+mdio0: mdio {
        compatible = "virtual,mdio-gpio";
        #address-cells = <1>;
        #size-cells = <0>;
diff --git a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt
new file mode 100644 (file)
index 0000000..63c6598
--- /dev/null
@@ -0,0 +1,37 @@
+GPIO controlled regulators
+
+Required properties:
+- compatible           : Must be "regulator-gpio".
+- states               : Selection of available voltages and GPIO configs.
+                          if there are no states, then use a fixed regulator
+
+Optional properties:
+- enable-gpio          : GPIO to use to enable/disable the regulator.
+- gpios                        : GPIO group used to control voltage.
+- startup-delay-us     : Startup time in microseconds.
+- enable-active-high   : Polarity of GPIO is active high (default is low).
+
+Any property defined as part of the core regulator binding defined in
+regulator.txt can also be used.
+
+Example:
+
+       mmciv: gpio-regulator {
+               compatible = "regulator-gpio";
+
+               regulator-name = "mmci-gpio-supply";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <2600000>;
+               regulator-boot-on;
+
+               enable-gpio = <&gpio0 23 0x4>;
+               gpios = <&gpio0 24 0x4
+                        &gpio0 25 0x4>;
+               states = <1800000 0x3
+                         2200000 0x2
+                         2600000 0x1
+                         2900000 0x0>;
+
+               startup-delay-us = <100000>;
+               enable-active-high;
+       };
diff --git a/Documentation/devicetree/bindings/regulator/max8925-regulator.txt b/Documentation/devicetree/bindings/regulator/max8925-regulator.txt
new file mode 100644 (file)
index 0000000..0057695
--- /dev/null
@@ -0,0 +1,40 @@
+Max8925 Voltage regulators
+
+Required nodes:
+-nodes:
+  - SDV1 for SDV SDV1
+  - SDV2 for SDV SDV2
+  - SDV3 for SDV SDV3
+  - LDO1 for LDO LDO1
+  - LDO2 for LDO LDO2
+  - LDO3 for LDO LDO3
+  - LDO4 for LDO LDO4
+  - LDO5 for LDO LDO5
+  - LDO6 for LDO LDO6
+  - LDO7 for LDO LDO7
+  - LDO8 for LDO LDO8
+  - LDO9 for LDO LDO9
+  - LDO10 for LDO LDO10
+  - LDO11 for LDO LDO11
+  - LDO12 for LDO LDO12
+  - LDO13 for LDO LDO13
+  - LDO14 for LDO LDO14
+  - LDO15 for LDO LDO15
+  - LDO16 for LDO LDO16
+  - LDO17 for LDO LDO17
+  - LDO18 for LDO LDO18
+  - LDO19 for LDO LDO19
+  - LDO20 for LDO LDO20
+
+Optional properties:
+- Any optional property defined in bindings/regulator/regulator.txt
+
+Example:
+
+       SDV1 {
+               regulator-min-microvolt = <637500>;
+               regulator-max-microvolt = <1425000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+
diff --git a/Documentation/devicetree/bindings/regulator/max8997-regulator.txt b/Documentation/devicetree/bindings/regulator/max8997-regulator.txt
new file mode 100644 (file)
index 0000000..9fd69a1
--- /dev/null
@@ -0,0 +1,146 @@
+* Maxim MAX8997 Voltage and Current Regulator
+
+The Maxim MAX8997 is a multi-function device which includes volatage and
+current regulators, rtc, charger controller and other sub-blocks. It is
+interfaced to the host controller using a i2c interface. Each sub-block is
+addressed by the host system using different i2c slave address. This document
+describes the bindings for 'pmic' sub-block of max8997.
+
+Required properties:
+- compatible: Should be "maxim,max8997-pmic".
+- reg: Specifies the i2c slave address of the pmic block. It should be 0x66.
+
+- max8997,pmic-buck1-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
+  units for buck1 when changing voltage using gpio dvs. Refer to [1] below
+  for additional information.
+
+- max8997,pmic-buck2-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
+  units for buck2 when changing voltage using gpio dvs. Refer to [1] below
+  for additional information.
+
+- max8997,pmic-buck5-dvs-voltage: A set of 8 voltage values in micro-volt (uV)
+  units for buck5 when changing voltage using gpio dvs. Refer to [1] below
+  for additional information.
+
+[1] If none of the 'max8997,pmic-buck[1/2/5]-uses-gpio-dvs' optional
+    property is specified, the 'max8997,pmic-buck[1/2/5]-dvs-voltage'
+    property should specify atleast one voltage level (which would be a
+    safe operating voltage).
+
+    If either of the 'max8997,pmic-buck[1/2/5]-uses-gpio-dvs' optional
+    property is specified, then all the eigth voltage values for the
+    'max8997,pmic-buck[1/2/5]-dvs-voltage' should be specified.
+
+Optional properties:
+- interrupt-parent: Specifies the phandle of the interrupt controller to which
+  the interrupts from max8997 are delivered to.
+- interrupts: Interrupt specifiers for two interrupt sources.
+  - First interrupt specifier is for 'irq1' interrupt.
+  - Second interrupt specifier is for 'alert' interrupt.
+- max8997,pmic-buck1-uses-gpio-dvs: 'buck1' can be controlled by gpio dvs.
+- max8997,pmic-buck2-uses-gpio-dvs: 'buck2' can be controlled by gpio dvs.
+- max8997,pmic-buck5-uses-gpio-dvs: 'buck5' can be controlled by gpio dvs.
+
+Additional properties required if either of the optional properties are used:
+- max8997,pmic-ignore-gpiodvs-side-effect: When GPIO-DVS mode is used for
+  multiple bucks, changing the voltage value of one of the bucks may affect
+  that of another buck, which is the side effect of the change (set_voltage).
+  Use this property to ignore such side effects and change the voltage.
+
+- max8997,pmic-buck125-default-dvs-idx: Default voltage setting selected from
+  the possible 8 options selectable by the dvs gpios. The value of this
+  property should be between 0 and 7. If not specified or if out of range, the
+  default value of this property is set to 0.
+
+- max8997,pmic-buck125-dvs-gpios: GPIO specifiers for three host gpio's used
+  for dvs. The format of the gpio specifier depends in the gpio controller.
+
+Regulators: The regulators of max8997 that have to be instantiated should be
+included in a sub-node named 'regulators'. Regulator nodes included in this
+sub-node should be of the format as listed below.
+
+       regulator_name {
+               standard regulator bindings here
+       };
+
+The following are the names of the regulators that the max8997 pmic block
+supports. Note: The 'n' in LDOn and BUCKn represents the LDO or BUCK number
+as per the datasheet of max8997.
+
+       - LDOn
+                 - valid values for n are 1 to 18 and 21
+                 - Example: LDO0, LD01, LDO2, LDO21
+       - BUCKn
+                 - valid values for n are 1 to 7.
+                 - Example: BUCK1, BUCK2, BUCK3, BUCK7
+
+       - ENVICHG: Battery Charging Current Monitor Output. This is a fixed
+                  voltage type regulator
+
+       - ESAFEOUT1: (ldo19)
+       - ESAFEOUT2: (ld020)
+
+       - CHARGER_CV: main battery charger voltage control
+       - CHARGER: main battery charger current control
+       - CHARGER_TOPOFF: end of charge current threshold level
+
+The bindings inside the regulator nodes use the standard regulator bindings
+which are documented elsewhere.
+
+Example:
+
+       max8997_pmic@66 {
+               compatible = "maxim,max8997-pmic";
+               interrupt-parent = <&wakeup_eint>;
+               reg = <0x66>;
+               interrupts = <4 0>, <3 0>;
+
+               max8997,pmic-buck1-uses-gpio-dvs;
+               max8997,pmic-buck2-uses-gpio-dvs;
+               max8997,pmic-buck5-uses-gpio-dvs;
+
+               max8997,pmic-ignore-gpiodvs-side-effect;
+               max8997,pmic-buck125-default-dvs-idx = <0>;
+
+               max8997,pmic-buck125-dvs-gpios = <&gpx0 0 1 0 0>, /* SET1 */
+                                                <&gpx0 1 1 0 0>, /* SET2 */
+                                                <&gpx0 2 1 0 0>; /* SET3 */
+
+               max8997,pmic-buck1-dvs-voltage = <1350000>, <1300000>,
+                                                <1250000>, <1200000>,
+                                                <1150000>, <1100000>,
+                                                <1000000>, <950000>;
+
+               max8997,pmic-buck2-dvs-voltage = <1100000>, <1100000>,
+                                                <1100000>, <1100000>,
+                                                <1000000>, <1000000>,
+                                                <1000000>, <1000000>;
+
+               max8997,pmic-buck5-dvs-voltage = <1200000>, <1200000>,
+                                                <1200000>, <1200000>,
+                                                <1200000>, <1200000>,
+                                                <1200000>, <1200000>;
+
+               regulators {
+                       ldo1_reg: LDO1 {
+                               regulator-name = "VDD_ABB_3.3V";
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                       };
+
+                       ldo2_reg: LDO2 {
+                               regulator-name = "VDD_ALIVE_1.1V";
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-always-on;
+                       };
+
+                       buck1_reg: BUCK1 {
+                               regulator-name = "VDD_ARM_1.2V";
+                               regulator-min-microvolt = <950000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-always-on;
+                               regulator-boot-on;
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/regulator/vexpress.txt b/Documentation/devicetree/bindings/regulator/vexpress.txt
new file mode 100644 (file)
index 0000000..d775f72
--- /dev/null
@@ -0,0 +1,32 @@
+Versatile Express voltage regulators
+------------------------------------
+
+Requires node properties:
+- "compatible" value: "arm,vexpress-volt"
+- "arm,vexpress-sysreg,func" when controlled via vexpress-sysreg
+  (see Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
+  for more details)
+
+Required regulator properties:
+- "regulator-name"
+- "regulator-always-on"
+
+Optional regulator properties:
+- "regulator-min-microvolt"
+- "regulator-max-microvolt"
+
+See Documentation/devicetree/bindings/regulator/regulator.txt
+for more details about the regulator properties.
+
+When no "regulator-[min|max]-microvolt" properties are defined,
+the device is treated as fixed (or rather "read-only") regulator.
+
+Example:
+       volt@0 {
+               compatible = "arm,vexpress-volt";
+               arm,vexpress-sysreg,func = <2 0>;
+               regulator-name = "Cores";
+               regulator-min-microvolt = <800000>;
+               regulator-max-microvolt = <1050000>;
+               regulator-always-on;
+       };
index a1793d670cd01bd374eddf54ffdfc768504291ff..3844d21d6ca32223838b7856a2f353bf56ef2417 100644 (file)
@@ -33,7 +33,7 @@ Table of Contents
   2    Modifying System Parameters
 
   3    Per-Process Parameters
-  3.1  /proc/<pid>/oom_score_adj - Adjust the oom-killer
+  3.1  /proc/<pid>/oom_adj & /proc/<pid>/oom_score_adj - Adjust the oom-killer
                                                                score
   3.2  /proc/<pid>/oom_score - Display current oom-killer score
   3.3  /proc/<pid>/io - Display the IO accounting fields
@@ -1320,10 +1320,10 @@ of the kernel.
 CHAPTER 3: PER-PROCESS PARAMETERS
 ------------------------------------------------------------------------------
 
-3.1 /proc/<pid>/oom_score_adj- Adjust the oom-killer score
+3.1 /proc/<pid>/oom_adj & /proc/<pid>/oom_score_adj- Adjust the oom-killer score
 --------------------------------------------------------------------------------
 
-This file can be used to adjust the badness heuristic used to select which
+These file can be used to adjust the badness heuristic used to select which
 process gets killed in out of memory conditions.
 
 The badness heuristic assigns a value to each candidate task ranging from 0
@@ -1361,6 +1361,12 @@ same system, cpuset, mempolicy, or memory controller resources to use at least
 equivalent to discounting 50% of the task's allowed memory from being considered
 as scoring against the task.
 
+For backwards compatibility with previous kernels, /proc/<pid>/oom_adj may also
+be used to tune the badness score.  Its acceptable values range from -16
+(OOM_ADJUST_MIN) to +15 (OOM_ADJUST_MAX) and a special value of -17
+(OOM_DISABLE) to disable oom killing entirely for that task.  Its value is
+scaled linearly with /proc/<pid>/oom_score_adj.
+
 The value of /proc/<pid>/oom_score_adj may be reduced no lower than the last
 value set by a CAP_SYS_RESOURCE process. To reduce the value any lower
 requires CAP_SYS_RESOURCE.
@@ -1375,7 +1381,9 @@ minimal amount of work.
 -------------------------------------------------------------
 
 This file can be used to check the current score used by the oom-killer is for
-any given <pid>.
+any given <pid>. Use it together with /proc/<pid>/oom_score_adj to tune which
+process should be killed in an out-of-memory situation.
+
 
 3.3  /proc/<pid>/io - Display the IO accounting fields
 -------------------------------------------------------
index 4164f5c02e4bbdf406956818fc34b8306610ba55..f310edec8a776f0a8ffb4a943a386ea45990b1a6 100644 (file)
@@ -164,4 +164,4 @@ read the CRC recorded by the NIC on receipt of the packet.
 This requests that the NIC receive all possible frames, including errored
 frames (such as bad FCS, etc).  This can be helpful when sniffing a link with
 bad packets on it.  Some NICs may receive more packets if also put into normal
-PROMISC mdoe.
+PROMISC mode.
index 5b34b762d7d5139a8cf0a9a8eacf739cae279a5b..6d993510f091c2088877ccfc1edf15474c5c723f 100644 (file)
@@ -32,7 +32,7 @@ no entry is in the forwarding table.
   # ip link delete vxlan0
 
 3. Show vxlan info
-  # ip -d show vxlan0
+  # ip -d link show vxlan0
 
 It is possible to create, destroy and display the vxlan
 forwarding table using the new bridge command.
@@ -41,7 +41,7 @@ forwarding table using the new bridge command.
   # bridge fdb add to 00:17:42:8a:b4:05 dst 192.19.0.2 dev vxlan0
 
 2. Delete forwarding table entry
-  # bridge fdb delete 00:17:42:8a:b4:05
+  # bridge fdb delete 00:17:42:8a:b4:05 dev vxlan0
 
 3. Show forwarding table
   # bridge fdb show dev vxlan0
index 59203e77ce9ef8f1a5639e2cad19a006b4e59696..9386a63ea8f63b653b683379ea54c7bd91eb72ec 100644 (file)
@@ -526,17 +526,17 @@ F:        drivers/video/geode/
 F:     arch/x86/include/asm/geode.h
 
 AMD IOMMU (AMD-VI)
-M:     Joerg Roedel <joerg.roedel@amd.com>
+M:     Joerg Roedel <joro@8bytes.org>
 L:     iommu@lists.linux-foundation.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git
-S:     Supported
+S:     Maintained
 F:     drivers/iommu/amd_iommu*.[ch]
 F:     include/linux/amd-iommu.h
 
 AMD MICROCODE UPDATE SUPPORT
-M:     Andreas Herrmann <andreas.herrmann3@amd.com>
+M:     Andreas Herrmann <herrmann.der.user@googlemail.com>
 L:     amd64-microcode@amd64.org
-S:     Supported
+S:     Maintained
 F:     arch/x86/kernel/microcode_amd.c
 
 AMS (Apple Motion Sensor) DRIVER
@@ -841,6 +841,14 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kristoffer/linux-hpc.git
 F:     arch/arm/mach-sa1100/jornada720.c
 F:     arch/arm/mach-sa1100/include/mach/jornada720.h
 
+ARM/IGEP MACHINE SUPPORT
+M:     Enric Balletbo i Serra <eballetbo@gmail.com>
+M:     Javier Martinez Canillas <javier@dowhile0.org>
+L:     linux-omap@vger.kernel.org
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     arch/arm/mach-omap2/board-igep0020.c
+
 ARM/INCOME PXA270 SUPPORT
 M:     Marek Vasut <marek.vasut@gmail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -2708,10 +2716,10 @@ F:      include/linux/edac.h
 
 EDAC-AMD64
 M:     Doug Thompson <dougthompson@xmission.com>
-M:     Borislav Petkov <borislav.petkov@amd.com>
+M:     Borislav Petkov <bp@alien8.de>
 L:     linux-edac@vger.kernel.org
 W:     bluesmoke.sourceforge.net
-S:     Supported
+S:     Maintained
 F:     drivers/edac/amd64_edac*
 
 EDAC-E752X
@@ -3598,6 +3606,49 @@ F:       drivers/hid/hid-hyperv.c
 F:     drivers/net/hyperv/
 F:     drivers/staging/hv/
 
+I2C OVER PARALLEL PORT
+M:     Jean Delvare <khali@linux-fr.org>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     Documentation/i2c/busses/i2c-parport
+F:     Documentation/i2c/busses/i2c-parport-light
+F:     drivers/i2c/busses/i2c-parport.c
+F:     drivers/i2c/busses/i2c-parport-light.c
+
+I2C/SMBUS CONTROLLER DRIVERS FOR PC
+M:     Jean Delvare <khali@linux-fr.org>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     Documentation/i2c/busses/i2c-ali1535
+F:     Documentation/i2c/busses/i2c-ali1563
+F:     Documentation/i2c/busses/i2c-ali15x3
+F:     Documentation/i2c/busses/i2c-amd756
+F:     Documentation/i2c/busses/i2c-amd8111
+F:     Documentation/i2c/busses/i2c-i801
+F:     Documentation/i2c/busses/i2c-nforce2
+F:     Documentation/i2c/busses/i2c-piix4
+F:     Documentation/i2c/busses/i2c-sis5595
+F:     Documentation/i2c/busses/i2c-sis630
+F:     Documentation/i2c/busses/i2c-sis96x
+F:     Documentation/i2c/busses/i2c-via
+F:     Documentation/i2c/busses/i2c-viapro
+F:     drivers/i2c/busses/i2c-ali1535.c
+F:     drivers/i2c/busses/i2c-ali1563.c
+F:     drivers/i2c/busses/i2c-ali15x3.c
+F:     drivers/i2c/busses/i2c-amd756.c
+F:     drivers/i2c/busses/i2c-amd756-s4882.c
+F:     drivers/i2c/busses/i2c-amd8111.c
+F:     drivers/i2c/busses/i2c-i801.c
+F:     drivers/i2c/busses/i2c-isch.c
+F:     drivers/i2c/busses/i2c-nforce2.c
+F:     drivers/i2c/busses/i2c-nforce2-s4985.c
+F:     drivers/i2c/busses/i2c-piix4.c
+F:     drivers/i2c/busses/i2c-sis5595.c
+F:     drivers/i2c/busses/i2c-sis630.c
+F:     drivers/i2c/busses/i2c-sis96x.c
+F:     drivers/i2c/busses/i2c-via.c
+F:     drivers/i2c/busses/i2c-viapro.c
+
 I2C/SMBUS STUB DRIVER
 M:     "Mark M. Hoffman" <mhoffman@lightlink.com>
 L:     linux-i2c@vger.kernel.org
@@ -3605,9 +3656,8 @@ S:        Maintained
 F:     drivers/i2c/busses/i2c-stub.c
 
 I2C SUBSYSTEM
-M:     "Jean Delvare (PC drivers, core)" <khali@linux-fr.org>
+M:     Wolfram Sang <w.sang@pengutronix.de>
 M:     "Ben Dooks (embedded platforms)" <ben-linux@fluff.org>
-M:     "Wolfram Sang (embedded platforms)" <w.sang@pengutronix.de>
 L:     linux-i2c@vger.kernel.org
 W:     http://i2c.wiki.kernel.org/
 T:     quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/
@@ -3618,6 +3668,13 @@ F:       drivers/i2c/
 F:     include/linux/i2c.h
 F:     include/linux/i2c-*.h
 
+I2C-TAOS-EVM DRIVER
+M:     Jean Delvare <khali@linux-fr.org>
+L:     linux-i2c@vger.kernel.org
+S:     Maintained
+F:     Documentation/i2c/busses/i2c-taos-evm
+F:     drivers/i2c/busses/i2c-taos-evm.c
+
 I2C-TINY-USB DRIVER
 M:     Till Harbaum <till@harbaum.org>
 L:     linux-i2c@vger.kernel.org
@@ -3704,7 +3761,7 @@ S:        Maintained
 F:     drivers/platform/x86/ideapad-laptop.c
 
 IDE/ATAPI DRIVERS
-M:     Borislav Petkov <petkovbb@gmail.com>
+M:     Borislav Petkov <bp@alien8.de>
 L:     linux-ide@vger.kernel.org
 S:     Maintained
 F:     Documentation/cdrom/ide-cd
@@ -4231,8 +4288,8 @@ F:        include/linux/lockd/
 F:     include/linux/sunrpc/
 
 KERNEL VIRTUAL MACHINE (KVM)
-M:     Avi Kivity <avi@redhat.com>
 M:     Marcelo Tosatti <mtosatti@redhat.com>
+M:     Gleb Natapov <gleb@redhat.com>
 L:     kvm@vger.kernel.org
 W:     http://kvm.qumranet.com
 S:     Supported
@@ -5364,7 +5421,7 @@ S:        Maintained
 F:     sound/drivers/opl4/
 
 OPROFILE
-M:     Robert Richter <robert.richter@amd.com>
+M:     Robert Richter <rric@kernel.org>
 L:     oprofile-list@lists.sf.net
 S:     Maintained
 F:     arch/*/include/asm/oprofile*.h
@@ -7210,6 +7267,14 @@ L:       linux-xtensa@linux-xtensa.org
 S:     Maintained
 F:     arch/xtensa/
 
+THERMAL
+M:      Zhang Rui <rui.zhang@intel.com>
+L:      linux-pm@vger.kernel.org
+T:      git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
+S:      Supported
+F:      drivers/thermal/
+F:      include/linux/thermal.h
+
 THINKPAD ACPI EXTRAS DRIVER
 M:     Henrique de Moraes Holschuh <ibm-acpi@hmh.eng.br>
 L:     ibm-acpi-devel@lists.sourceforge.net
@@ -7887,13 +7952,6 @@ M:       Roger Luethi <rl@hellgate.ch>
 S:     Maintained
 F:     drivers/net/ethernet/via/via-rhine.c
 
-VIAPRO SMBUS DRIVER
-M:     Jean Delvare <khali@linux-fr.org>
-L:     linux-i2c@vger.kernel.org
-S:     Maintained
-F:     Documentation/i2c/busses/i2c-viapro
-F:     drivers/i2c/busses/i2c-viapro.c
-
 VIA SD/MMC CARD CONTROLLER DRIVER
 M:     Bruce Chang <brucechang@via.com.tw>
 M:     Harald Welte <HaraldWelte@viatech.com>
@@ -8148,7 +8206,7 @@ F:        drivers/platform/x86
 
 X86 MCE INFRASTRUCTURE
 M:     Tony Luck <tony.luck@intel.com>
-M:     Borislav Petkov <bp@amd64.org>
+M:     Borislav Petkov <bp@alien8.de>
 L:     linux-edac@vger.kernel.org
 S:     Maintained
 F:     arch/x86/kernel/cpu/mcheck/*
index 6edac73ee1baeebd107c4a6ccfdbc4bd84330aaa..3d2fc460b22f38b6d37ba31016a96c6926bdc0b1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 7
 SUBLEVEL = 0
-EXTRAVERSION = -rc5
+EXTRAVERSION = -rc7
 NAME = Terrified Chipmunk
 
 # *DOCUMENTATION*
index 1e6956a9060809e5b1cfed409d376f2d1e726f43..14db93e4c8a83662d459a6ff1a818318dbc61eeb 100644 (file)
@@ -445,7 +445,7 @@ struct procfs_args {
  * unhappy with OSF UFS. [CHECKME]
  */
 static int
-osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
+osf_ufs_mount(const char *dirname, struct ufs_args __user *args, int flags)
 {
        int retval;
        struct cdfs_args tmp;
@@ -465,7 +465,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
 }
 
 static int
-osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
+osf_cdfs_mount(const char *dirname, struct cdfs_args __user *args, int flags)
 {
        int retval;
        struct cdfs_args tmp;
@@ -485,7 +485,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
 }
 
 static int
-osf_procfs_mount(char *dirname, struct procfs_args __user *args, int flags)
+osf_procfs_mount(const char *dirname, struct procfs_args __user *args, int flags)
 {
        struct procfs_args tmp;
 
index f2aa09eb658e632c7703203d97cd3469d7996259..9137df539b61c649b218e26d8f56365f289a5c84 100644 (file)
@@ -33,7 +33,7 @@ ifeq ($(CONFIG_XIP_KERNEL),y)
 
 $(obj)/xipImage: vmlinux FORCE
        $(call if_changed,objcopy)
-       $(kecho) '  Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))'
+       @$(kecho) '  Kernel: $@ is ready (physical address: $(CONFIG_XIP_PHYS_ADDR))'
 
 $(obj)/Image $(obj)/zImage: FORCE
        @echo 'Kernel configured for XIP (CONFIG_XIP_KERNEL=y)'
@@ -48,14 +48,14 @@ $(obj)/xipImage: FORCE
 
 $(obj)/Image: vmlinux FORCE
        $(call if_changed,objcopy)
-       $(kecho) '  Kernel: $@ is ready'
+       @$(kecho) '  Kernel: $@ is ready'
 
 $(obj)/compressed/vmlinux: $(obj)/Image FORCE
        $(Q)$(MAKE) $(build)=$(obj)/compressed $@
 
 $(obj)/zImage: $(obj)/compressed/vmlinux FORCE
        $(call if_changed,objcopy)
-       $(kecho) '  Kernel: $@ is ready'
+       @$(kecho) '  Kernel: $@ is ready'
 
 endif
 
@@ -90,7 +90,7 @@ fi
 $(obj)/uImage: $(obj)/zImage FORCE
        @$(check_for_multiple_loadaddr)
        $(call if_changed,uimage)
-       $(kecho) '  Image $@ is ready'
+       @$(kecho) '  Image $@ is ready'
 
 $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
        $(Q)$(MAKE) $(build)=$(obj)/bootp $@
@@ -98,7 +98,7 @@ $(obj)/bootp/bootp: $(obj)/zImage initrd FORCE
 
 $(obj)/bootpImage: $(obj)/bootp/bootp FORCE
        $(call if_changed,objcopy)
-       $(kecho) '  Kernel: $@ is ready'
+       @$(kecho) '  Kernel: $@ is ready'
 
 PHONY += initrd FORCE
 initrd:
index b1497c7d7d6851db3753c1210e974cb9e47888c2..df7f2270fc91a4f98d0d7dd067817bb2ce8b62c0 100644 (file)
@@ -73,8 +73,8 @@
 
        pinmux: pinmux {
                compatible = "nvidia,tegra30-pinmux";
-               reg = <0x70000868 0xd0    /* Pad control registers */
-                      0x70003000 0x3e0>; /* Mux registers */
+               reg = <0x70000868 0xd4    /* Pad control registers */
+                      0x70003000 0x3e4>; /* Mux registers */
        };
 
        serial@70006000 {
index 1e122bcd7845e56c855afaf15d471fe69b2de3ef..3cee0e6ea7c3c126ec3b319497b01cf335f3f16a 100644 (file)
@@ -68,7 +68,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
index aa1e58729885299873d7dfc3a9feba9220914240..414bd855fb0cb7fd1d0295012016937175d9c449 100644 (file)
@@ -72,7 +72,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
index b9487696b7bec10b01d4a17f4b779fe7051a9003..cd604aad8e963c217301df7fa421637d1b0315a3 100644 (file)
@@ -72,7 +72,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
index cb85da2eccea1aa83710d58601b8d99524456b9f..9c61e59a2104e7f0399fc0dca4ea926d7136d4f9 100644 (file)
@@ -78,7 +78,7 @@ void __init at91_add_device_usbh(struct at91_usbh_data *data)
 
        /* Enable overcurrent notification */
        for (i = 0; i < data->ports; i++) {
-               if (data->overcurrent_pin[i])
+               if (gpio_is_valid(data->overcurrent_pin[i]))
                        at91_set_gpio_input(data->overcurrent_pin[i], 1);
        }
 
index b1596072dcc23cd1414a8449eb4c25a35ed11222..fcd233cb33d25d68417a992c3b09fac45e63501a 100644 (file)
@@ -1841,8 +1841,8 @@ static struct resource sha_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_AESTDESSHA,
-               .end    = AT91SAM9G45_ID_AESTDESSHA,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1874,8 +1874,8 @@ static struct resource tdes_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_AESTDESSHA,
-               .end    = AT91SAM9G45_ID_AESTDESSHA,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1910,8 +1910,8 @@ static struct resource aes_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_AESTDESSHA,
-               .end    = AT91SAM9G45_ID_AESTDESSHA,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AESTDESSHA,
                .flags  = IORESOURCE_IRQ,
        },
 };
index cd0c8b1e1ecfad4a868b9aae3f6180a1b1794ed1..14e9947bad6e028bc9c41aecb5e1f36b045fe79a 100644 (file)
@@ -713,8 +713,7 @@ static int dm644x_venc_setup_clock(enum vpbe_enc_timings_type type,
                break;
        case VPBE_ENC_CUSTOM_TIMINGS:
                if (pclock <= 27000000) {
-                       v |= DM644X_VPSS_MUXSEL_PLL2_MODE |
-                            DM644X_VPSS_DACCLKEN;
+                       v |= DM644X_VPSS_DACCLKEN;
                        writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
                } else {
                        /*
index 21d568b3b1497c90bb79eb841f45595020351db9..87e07d6fc615769df8edfe0af8be1569859d5422 100644 (file)
@@ -275,6 +275,9 @@ static int __init exynos_dma_init(void)
                exynos_pdma1_pdata.nr_valid_peri =
                        ARRAY_SIZE(exynos4210_pdma1_peri);
                exynos_pdma1_pdata.peri_id = exynos4210_pdma1_peri;
+
+               if (samsung_rev() == EXYNOS4210_REV_0)
+                       exynos_mdma1_device.res.start = EXYNOS4_PA_S_MDMA1;
        } else if (soc_is_exynos4212() || soc_is_exynos4412()) {
                exynos_pdma0_pdata.nr_valid_peri =
                        ARRAY_SIZE(exynos4212_pdma0_peri);
index 8480849affb922789d73b597c81b76c6778a16ba..ed4da4544cd2fded70c65dd7d5d5539635a94557 100644 (file)
@@ -90,6 +90,7 @@
 
 #define EXYNOS4_PA_MDMA0               0x10810000
 #define EXYNOS4_PA_MDMA1               0x12850000
+#define EXYNOS4_PA_S_MDMA1             0x12840000
 #define EXYNOS4_PA_PDMA0               0x12680000
 #define EXYNOS4_PA_PDMA1               0x12690000
 #define EXYNOS5_PA_MDMA0               0x10800000
index 82c27230d4a93e657ca4c4a4e1e79439c422bbae..86e37cd9376cc7a522a17a65ca39cc127dd7deeb 100644 (file)
@@ -28,6 +28,7 @@ void highbank_restart(char mode, const char *cmd)
                hignbank_set_pwr_soft_reset();
 
        scu_power_mode(scu_base_addr, SCU_PM_POWEROFF);
-       cpu_do_idle();
+       while (1)
+               cpu_do_idle();
 }
 
index 3c1b8ff9a0a61c24f2e7d6647a62168cd8a7e146..cc49c7ae186ed2bc0d3519bf7648a153ddb45d55 100644 (file)
@@ -112,7 +112,7 @@ struct clk *clk_register_gate2(struct device *dev, const char *name,
 
        clk = clk_register(dev, &gate->hw);
        if (IS_ERR(clk))
-               kfree(clk);
+               kfree(gate);
 
        return clk;
 }
index 412c583a24b01a7e35fc976572cdafc50e08e13e..576af7446952553acab68a77207cfd3d71298dbe 100644 (file)
@@ -30,7 +30,7 @@
 #define MX25_H1_SIC_SHIFT      21
 #define MX25_H1_SIC_MASK       (0x3 << MX25_H1_SIC_SHIFT)
 #define MX25_H1_PP_BIT         (1 << 18)
-#define MX25_H1_PM_BIT         (1 << 8)
+#define MX25_H1_PM_BIT         (1 << 16)
 #define MX25_H1_IPPUE_UP_BIT   (1 << 7)
 #define MX25_H1_IPPUE_DOWN_BIT (1 << 6)
 #define MX25_H1_TLL_BIT                (1 << 5)
index 779e16eb65cb49aeaa58af79b19aac4e08b9bb47..293397852e4e6506bb1e46e590c292ef10fb116c 100644 (file)
@@ -30,7 +30,7 @@
 #define MX35_H1_SIC_SHIFT      21
 #define MX35_H1_SIC_MASK       (0x3 << MX35_H1_SIC_SHIFT)
 #define MX35_H1_PP_BIT         (1 << 18)
-#define MX35_H1_PM_BIT         (1 << 8)
+#define MX35_H1_PM_BIT         (1 << 16)
 #define MX35_H1_IPPUE_UP_BIT   (1 << 7)
 #define MX35_H1_IPPUE_DOWN_BIT (1 << 6)
 #define MX35_H1_TLL_BIT                (1 << 5)
index 48d5e41dfbfabe3da59ef00f7457f5012cf2ec1a..378590694447bdbdd3ed4d7862624ac5d000c402 100644 (file)
@@ -580,6 +580,11 @@ static void __init igep_wlan_bt_init(void)
        } else
                return;
 
+       /* Make sure that the GPIO pins are muxed correctly */
+       omap_mux_init_gpio(igep_wlan_bt_gpios[0].gpio, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(igep_wlan_bt_gpios[1].gpio, OMAP_PIN_OUTPUT);
+       omap_mux_init_gpio(igep_wlan_bt_gpios[2].gpio, OMAP_PIN_OUTPUT);
+
        err = gpio_request_array(igep_wlan_bt_gpios,
                                 ARRAY_SIZE(igep_wlan_bt_gpios));
        if (err) {
index b56d06b48782a8608f77c43f9902972c1cb24bd5..95192a062d5db4b8401e73a78492c2990c26a463 100644 (file)
@@ -359,7 +359,7 @@ static struct clockdomain iss_44xx_clkdm = {
        .clkdm_offs       = OMAP4430_CM2_CAM_CAM_CDOFFS,
        .wkdep_srcs       = iss_wkup_sleep_deps,
        .sleepdep_srcs    = iss_wkup_sleep_deps,
-       .flags            = CLKDM_CAN_HWSUP_SWSUP,
+       .flags            = CLKDM_CAN_SWSUP,
 };
 
 static struct clockdomain l3_dss_44xx_clkdm = {
index 48daac2581b4a154a768923681ac108c084a5c98..84551f205e46fd20d5ef47849d279643f80f3b18 100644 (file)
@@ -64,30 +64,36 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
        struct spi_board_info *spi_bi = &ads7846_spi_board_info;
        int err;
 
-       err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
-       if (err) {
-               pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
-               return;
-       }
+       /*
+        * If a board defines get_pendown_state() function, request the pendown
+        * GPIO and set the GPIO debounce time.
+        * If a board does not define the get_pendown_state() function, then
+        * the ads7846 driver will setup the pendown GPIO itself.
+        */
+       if (board_pdata && board_pdata->get_pendown_state) {
+               err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
+               if (err) {
+                       pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
+                       return;
+               }
 
-       if (gpio_debounce)
-               gpio_set_debounce(gpio_pendown, gpio_debounce);
+               if (gpio_debounce)
+                       gpio_set_debounce(gpio_pendown, gpio_debounce);
+
+               gpio_export(gpio_pendown, 0);
+       }
 
        spi_bi->bus_num = bus_num;
        spi_bi->irq     = gpio_to_irq(gpio_pendown);
 
+       ads7846_config.gpio_pendown = gpio_pendown;
+
        if (board_pdata) {
                board_pdata->gpio_pendown = gpio_pendown;
+               board_pdata->gpio_pendown_debounce = gpio_debounce;
                spi_bi->platform_data = board_pdata;
-               if (board_pdata->get_pendown_state)
-                       gpio_export(gpio_pendown, 0);
-       } else {
-               ads7846_config.gpio_pendown = gpio_pendown;
        }
 
-       if (!board_pdata || (board_pdata && !board_pdata->get_pendown_state))
-               gpio_free(gpio_pendown);
-
        spi_register_board_info(&ads7846_spi_board_info, 1);
 }
 #else
index cba60e05e32ecef6a6c97cbf6679b99f474d4a5a..c72b5a7277200d08bc28e3b5348bfedcb677fefc 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/of.h>
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/omap4-keypad.h>
+#include <linux/platform_data/omap_ocp2scp.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
@@ -613,6 +614,83 @@ static void omap_init_vout(void)
 static inline void omap_init_vout(void) {}
 #endif
 
+#if defined(CONFIG_OMAP_OCP2SCP) || defined(CONFIG_OMAP_OCP2SCP_MODULE)
+static int count_ocp2scp_devices(struct omap_ocp2scp_dev *ocp2scp_dev)
+{
+       int cnt = 0;
+
+       while (ocp2scp_dev->drv_name != NULL) {
+               cnt++;
+               ocp2scp_dev++;
+       }
+
+       return cnt;
+}
+
+static void omap_init_ocp2scp(void)
+{
+       struct omap_hwmod       *oh;
+       struct platform_device  *pdev;
+       int                     bus_id = -1, dev_cnt = 0, i;
+       struct omap_ocp2scp_dev *ocp2scp_dev;
+       const char              *oh_name, *name;
+       struct omap_ocp2scp_platform_data *pdata;
+
+       if (!cpu_is_omap44xx())
+               return;
+
+       oh_name = "ocp2scp_usb_phy";
+       name    = "omap-ocp2scp";
+
+       oh = omap_hwmod_lookup(oh_name);
+       if (!oh) {
+               pr_err("%s: could not find omap_hwmod for %s\n", __func__,
+                                                               oh_name);
+               return;
+       }
+
+       pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               pr_err("%s: No memory for ocp2scp pdata\n", __func__);
+               return;
+       }
+
+       ocp2scp_dev = oh->dev_attr;
+       dev_cnt = count_ocp2scp_devices(ocp2scp_dev);
+
+       if (!dev_cnt) {
+               pr_err("%s: No devices connected to ocp2scp\n", __func__);
+               kfree(pdata);
+               return;
+       }
+
+       pdata->devices = kzalloc(sizeof(struct omap_ocp2scp_dev *)
+                                       * dev_cnt, GFP_KERNEL);
+       if (!pdata->devices) {
+               pr_err("%s: No memory for ocp2scp pdata devices\n", __func__);
+               kfree(pdata);
+               return;
+       }
+
+       for (i = 0; i < dev_cnt; i++, ocp2scp_dev++)
+               pdata->devices[i] = ocp2scp_dev;
+
+       pdata->dev_cnt  = dev_cnt;
+
+       pdev = omap_device_build(name, bus_id, oh, pdata, sizeof(*pdata), NULL,
+                                                               0, false);
+       if (IS_ERR(pdev)) {
+               pr_err("Could not build omap_device for %s %s\n",
+                                               name, oh_name);
+               kfree(pdata->devices);
+               kfree(pdata);
+               return;
+       }
+}
+#else
+static inline void omap_init_ocp2scp(void) { }
+#endif
+
 /*-------------------------------------------------------------------------*/
 
 static int __init omap2_init_devices(void)
@@ -640,6 +718,7 @@ static int __init omap2_init_devices(void)
        omap_init_sham();
        omap_init_aes();
        omap_init_vout();
+       omap_init_ocp2scp();
 
        return 0;
 }
index b969ab1d258b91894415c3507bd8b50cd2aefa50..87cc6d058de25cf2552c1b274af1a06f5d3ee509 100644 (file)
@@ -421,6 +421,38 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v)
        return 0;
 }
 
+/**
+ * _wait_softreset_complete - wait for an OCP softreset to complete
+ * @oh: struct omap_hwmod * to wait on
+ *
+ * Wait until the IP block represented by @oh reports that its OCP
+ * softreset is complete.  This can be triggered by software (see
+ * _ocp_softreset()) or by hardware upon returning from off-mode (one
+ * example is HSMMC).  Waits for up to MAX_MODULE_SOFTRESET_WAIT
+ * microseconds.  Returns the number of microseconds waited.
+ */
+static int _wait_softreset_complete(struct omap_hwmod *oh)
+{
+       struct omap_hwmod_class_sysconfig *sysc;
+       u32 softrst_mask;
+       int c = 0;
+
+       sysc = oh->class->sysc;
+
+       if (sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
+               omap_test_timeout((omap_hwmod_read(oh, sysc->syss_offs)
+                                  & SYSS_RESETDONE_MASK),
+                                 MAX_MODULE_SOFTRESET_WAIT, c);
+       else if (sysc->sysc_flags & SYSC_HAS_RESET_STATUS) {
+               softrst_mask = (0x1 << sysc->sysc_fields->srst_shift);
+               omap_test_timeout(!(omap_hwmod_read(oh, sysc->sysc_offs)
+                                   & softrst_mask),
+                                 MAX_MODULE_SOFTRESET_WAIT, c);
+       }
+
+       return c;
+}
+
 /**
  * _set_dmadisable: set OCP_SYSCONFIG.DMADISABLE bit in @v
  * @oh: struct omap_hwmod *
@@ -1282,6 +1314,18 @@ static void _enable_sysc(struct omap_hwmod *oh)
        if (!oh->class->sysc)
                return;
 
+       /*
+        * Wait until reset has completed, this is needed as the IP
+        * block is reset automatically by hardware in some cases
+        * (off-mode for example), and the drivers require the
+        * IP to be ready when they access it
+        */
+       if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+               _enable_optional_clocks(oh);
+       _wait_softreset_complete(oh);
+       if (oh->flags & HWMOD_CONTROL_OPT_CLKS_IN_RESET)
+               _disable_optional_clocks(oh);
+
        v = oh->_sysc_cache;
        sf = oh->class->sysc->sysc_flags;
 
@@ -1804,7 +1848,7 @@ static int _am33xx_disable_module(struct omap_hwmod *oh)
  */
 static int _ocp_softreset(struct omap_hwmod *oh)
 {
-       u32 v, softrst_mask;
+       u32 v;
        int c = 0;
        int ret = 0;
 
@@ -1834,19 +1878,7 @@ static int _ocp_softreset(struct omap_hwmod *oh)
        if (oh->class->sysc->srst_udelay)
                udelay(oh->class->sysc->srst_udelay);
 
-       if (oh->class->sysc->sysc_flags & SYSS_HAS_RESET_STATUS)
-               omap_test_timeout((omap_hwmod_read(oh,
-                                                   oh->class->sysc->syss_offs)
-                                  & SYSS_RESETDONE_MASK),
-                                 MAX_MODULE_SOFTRESET_WAIT, c);
-       else if (oh->class->sysc->sysc_flags & SYSC_HAS_RESET_STATUS) {
-               softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift);
-               omap_test_timeout(!(omap_hwmod_read(oh,
-                                                    oh->class->sysc->sysc_offs)
-                                  & softrst_mask),
-                                 MAX_MODULE_SOFTRESET_WAIT, c);
-       }
-
+       c = _wait_softreset_complete(oh);
        if (c == MAX_MODULE_SOFTRESET_WAIT)
                pr_warning("omap_hwmod: %s: softreset failed (waited %d usec)\n",
                           oh->name, MAX_MODULE_SOFTRESET_WAIT);
@@ -2352,6 +2384,9 @@ static int __init _setup_reset(struct omap_hwmod *oh)
        if (oh->_state != _HWMOD_STATE_INITIALIZED)
                return -EINVAL;
 
+       if (oh->flags & HWMOD_EXT_OPT_MAIN_CLK)
+               return -EPERM;
+
        if (oh->rst_lines_cnt == 0) {
                r = _enable(oh);
                if (r) {
index 652d0285bd6dd7b1a445bcbab02e395e04c5e11a..0b1249e003987da276c2072aed5d39bcc334e8f5 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/io.h>
 #include <linux/platform_data/gpio-omap.h>
 #include <linux/power/smartreflex.h>
+#include <linux/platform_data/omap_ocp2scp.h>
 
 #include <plat/omap_hwmod.h>
 #include <plat/i2c.h>
@@ -2125,6 +2126,14 @@ static struct omap_hwmod omap44xx_mcpdm_hwmod = {
        .name           = "mcpdm",
        .class          = &omap44xx_mcpdm_hwmod_class,
        .clkdm_name     = "abe_clkdm",
+       /*
+        * It's suspected that the McPDM requires an off-chip main
+        * functional clock, controlled via I2C.  This IP block is
+        * currently reset very early during boot, before I2C is
+        * available, so it doesn't seem that we have any choice in
+        * the kernel other than to avoid resetting it.
+        */
+       .flags          = HWMOD_EXT_OPT_MAIN_CLK,
        .mpu_irqs       = omap44xx_mcpdm_irqs,
        .sdma_reqs      = omap44xx_mcpdm_sdma_reqs,
        .main_clk       = "mcpdm_fck",
@@ -2681,6 +2690,32 @@ static struct omap_hwmod_class omap44xx_ocp2scp_hwmod_class = {
        .sysc   = &omap44xx_ocp2scp_sysc,
 };
 
+/* ocp2scp dev_attr */
+static struct resource omap44xx_usb_phy_and_pll_addrs[] = {
+       {
+               .name           = "usb_phy",
+               .start          = 0x4a0ad080,
+               .end            = 0x4a0ae000,
+               .flags          = IORESOURCE_MEM,
+       },
+       {
+               /* XXX: Remove this once control module driver is in place */
+               .name           = "ctrl_dev",
+               .start          = 0x4a002300,
+               .end            = 0x4a002303,
+               .flags          = IORESOURCE_MEM,
+       },
+       { }
+};
+
+static struct omap_ocp2scp_dev ocp2scp_dev_attr[] = {
+       {
+               .drv_name       = "omap-usb2",
+               .res            = omap44xx_usb_phy_and_pll_addrs,
+       },
+       { }
+};
+
 /* ocp2scp_usb_phy */
 static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
        .name           = "ocp2scp_usb_phy",
@@ -2694,6 +2729,7 @@ static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
                        .modulemode   = MODULEMODE_HWCTRL,
                },
        },
+       .dev_attr       = ocp2scp_dev_attr,
 };
 
 /*
index 635e109f5ad352e97e04dfad00c11e8728c72c98..a256135d8e48f59c0a6a103b2d449682caac9be2 100644 (file)
@@ -73,6 +73,7 @@ void __init omap4_pmic_init(const char *pmic_type,
 {
        /* PMIC part*/
        omap_mux_init_signal("sys_nirq1", OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE);
+       omap_mux_init_signal("fref_clk0_out.sys_drm_msecure", OMAP_PIN_OUTPUT);
        omap_pmic_init(1, 400, pmic_type, 7 + OMAP44XX_IRQ_GIC_START, pmic_data);
 
        /* Register additional devices on i2c1 bus if needed */
@@ -366,7 +367,7 @@ static struct regulator_init_data omap4_clk32kg_idata = {
 };
 
 static struct regulator_consumer_supply omap4_vdd1_supply[] = {
-       REGULATOR_SUPPLY("vcc", "mpu.0"),
+       REGULATOR_SUPPLY("vcc", "cpu0"),
 };
 
 static struct regulator_consumer_supply omap4_vdd2_supply[] = {
index 880249b170125b0c9f6b4d870e9f3d6a6420fc53..75878c37959bff682bfdefca0548afb001891734 100644 (file)
@@ -264,7 +264,7 @@ static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
 
        if (initialized) {
                if (voltdm->pmic->i2c_high_speed != i2c_high_speed)
-                       pr_warn("%s: I2C config for vdd_%s does not match other channels (%u).",
+                       pr_warn("%s: I2C config for vdd_%s does not match other channels (%u).\n",
                                __func__, voltdm->name, i2c_high_speed);
                return;
        }
index 5ecbd17b56416a40c0e966508b37066d29b81d55..e2c6391863fedd9b008d594c516eea1f55936e64 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/mfd/asic3.h>
 #include <linux/mtd/physmap.h>
 #include <linux/pda_power.h>
+#include <linux/pwm.h>
 #include <linux/pwm_backlight.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/gpio-regulator.h>
@@ -556,7 +557,7 @@ static struct platform_device hx4700_lcd = {
  */
 
 static struct platform_pwm_backlight_data backlight_data = {
-       .pwm_id         = 1,
+       .pwm_id         = -1,   /* Superseded by pwm_lookup */
        .max_brightness = 200,
        .dft_brightness = 100,
        .pwm_period_ns  = 30923,
@@ -571,6 +572,10 @@ static struct platform_device backlight = {
        },
 };
 
+static struct pwm_lookup hx4700_pwm_lookup[] = {
+       PWM_LOOKUP("pxa27x-pwm.1", 0, "pwm-backlight", NULL),
+};
+
 /*
  * USB "Transceiver"
  */
@@ -872,6 +877,7 @@ static void __init hx4700_init(void)
        pxa_set_stuart_info(NULL);
 
        platform_add_devices(devices, ARRAY_SIZE(devices));
+       pwm_add_table(hx4700_pwm_lookup, ARRAY_SIZE(hx4700_pwm_lookup));
 
        pxa_set_ficp_info(&ficp_info);
        pxa27x_set_i2c_power_info(NULL);
index 438f02fe122a6d1d727671675af53b7564b99ae4..842596d4d31e19e59cd898084125944a03db7b90 100644 (file)
@@ -86,10 +86,7 @@ static void spitz_discharge1(int on)
        gpio_set_value(SPITZ_GPIO_LED_GREEN, on);
 }
 
-static unsigned long gpio18_config[] = {
-       GPIO18_RDY,
-       GPIO18_GPIO,
-};
+static unsigned long gpio18_config = GPIO18_GPIO;
 
 static void spitz_presuspend(void)
 {
@@ -112,7 +109,7 @@ static void spitz_presuspend(void)
        PGSR3 &= ~SPITZ_GPIO_G3_STROBE_BIT;
        PGSR2 |= GPIO_bit(SPITZ_GPIO_KEY_STROBE0);
 
-       pxa2xx_mfp_config(&gpio18_config[0], 1);
+       pxa2xx_mfp_config(&gpio18_config, 1);
        gpio_request_one(18, GPIOF_OUT_INIT_HIGH, "Unknown");
        gpio_free(18);
 
@@ -131,7 +128,6 @@ static void spitz_presuspend(void)
 
 static void spitz_postsuspend(void)
 {
-       pxa2xx_mfp_config(&gpio18_config[1], 1);
 }
 
 static int spitz_should_wakeup(unsigned int resume_on_alarm)
index a5683a84c6ee0e313cb8f9daeeb7c72106952a4e..6013831a043e320fafd5e718a558d422fa67a624 100644 (file)
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/i2c-omap.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 
 #include <mach/irqs.h>
 #include <plat/i2c.h>
+#include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 
 #define OMAP_I2C_SIZE          0x3f
@@ -127,6 +129,16 @@ static inline int omap1_i2c_add_bus(int bus_id)
 
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
+/*
+ * XXX This function is a temporary compatibility wrapper - only
+ * needed until the I2C driver can be converted to call
+ * omap_pm_set_max_dev_wakeup_lat() and handle a return code.
+ */
+static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t)
+{
+       omap_pm_set_max_mpu_wakeup_lat(dev, t);
+}
+
 static inline int omap2_i2c_add_bus(int bus_id)
 {
        int l;
@@ -158,6 +170,15 @@ static inline int omap2_i2c_add_bus(int bus_id)
        dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr;
        pdata->flags = dev_attr->flags;
 
+       /*
+        * When waiting for completion of a i2c transfer, we need to
+        * set a wake up latency constraint for the MPU. This is to
+        * ensure quick enough wakeup from idle, when transfer
+        * completes.
+        * Only omap3 has support for constraints
+        */
+       if (cpu_is_omap34xx())
+               pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
        pdev = omap_device_build(name, bus_id, oh, pdata,
                        sizeof(struct omap_i2c_bus_platform_data),
                        NULL, 0, 0);
index b3349f7b1a2cda6458ed75b541a07298c84e7234..1db029438022066311c858079bf5753b08e359f5 100644 (file)
@@ -443,6 +443,11 @@ struct omap_hwmod_omap4_prcm {
  *     in order to complete the reset. Optional clocks will be disabled
  *     again after the reset.
  * HWMOD_16BIT_REG: Module has 16bit registers
+ * HWMOD_EXT_OPT_MAIN_CLK: The only main functional clock source for
+ *     this IP block comes from an off-chip source and is not always
+ *     enabled.  This prevents the hwmod code from being able to
+ *     enable and reset the IP block early.  XXX Eventually it should
+ *     be possible to query the clock framework for this information.
  */
 #define HWMOD_SWSUP_SIDLE                      (1 << 0)
 #define HWMOD_SWSUP_MSTANDBY                   (1 << 1)
@@ -453,6 +458,7 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_NO_IDLEST                                (1 << 6)
 #define HWMOD_CONTROL_OPT_CLKS_IN_RESET                (1 << 7)
 #define HWMOD_16BIT_REG                                (1 << 8)
+#define HWMOD_EXT_OPT_MAIN_CLK                 (1 << 9)
 
 /*
  * omap_hwmod._int_flags definitions
index cd60a81163e938a78b55b40fa9df6009408f5b57..32d05c8219dc35acf9db46a49e521ca312fc336e 100644 (file)
@@ -5,6 +5,6 @@
 #
 
 include/generated/mach-types.h: $(src)/gen-mach-types $(src)/mach-types
-       $(kecho) '  Generating $@'
+       @$(kecho) '  Generating $@'
        @mkdir -p $(dir $@)
        $(Q)$(AWK) -f $^ > $@ || { rm -f $@; /bin/false; }
index 54f6116697f7fa2d26fc4dafa5bcae05e02ed7d0..d2f05a608274534a08180fc3866658a225bb560c 100644 (file)
@@ -222,7 +222,7 @@ extern void __iomem *__ioremap(phys_addr_t phys_addr, size_t size, pgprot_t prot
 extern void __iounmap(volatile void __iomem *addr);
 
 #define PROT_DEFAULT           (PTE_TYPE_PAGE | PTE_AF | PTE_DIRTY)
-#define PROT_DEVICE_nGnRE      (PROT_DEFAULT | PTE_XN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
+#define PROT_DEVICE_nGnRE      (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_ATTRINDX(MT_DEVICE_nGnRE))
 #define PROT_NORMAL_NC         (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL_NC))
 
 #define ioremap(addr, size)            __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
index 0f3b4581d9251ab17b4750eb8501c8d77cbee428..75fd13d289b93193f261c89fa83fb6973738f6f2 100644 (file)
@@ -38,7 +38,8 @@
 #define PMD_SECT_S             (_AT(pmdval_t, 3) << 8)
 #define PMD_SECT_AF            (_AT(pmdval_t, 1) << 10)
 #define PMD_SECT_NG            (_AT(pmdval_t, 1) << 11)
-#define PMD_SECT_XN            (_AT(pmdval_t, 1) << 54)
+#define PMD_SECT_PXN           (_AT(pmdval_t, 1) << 53)
+#define PMD_SECT_UXN           (_AT(pmdval_t, 1) << 54)
 
 /*
  * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
@@ -57,7 +58,8 @@
 #define PTE_SHARED             (_AT(pteval_t, 3) << 8)         /* SH[1:0], inner shareable */
 #define PTE_AF                 (_AT(pteval_t, 1) << 10)        /* Access Flag */
 #define PTE_NG                 (_AT(pteval_t, 1) << 11)        /* nG */
-#define PTE_XN                 (_AT(pteval_t, 1) << 54)        /* XN */
+#define PTE_PXN                        (_AT(pteval_t, 1) << 53)        /* Privileged XN */
+#define PTE_UXN                        (_AT(pteval_t, 1) << 54)        /* User XN */
 
 /*
  * AttrIndx[2:0] encoding (mapping attributes defined in the MAIR* registers).
index 8960239be722893a8094ceef323da22ff26eef63..14aba2db6776d099935c76e95bd4797f3a707376 100644 (file)
@@ -62,23 +62,23 @@ extern pgprot_t pgprot_default;
 
 #define _MOD_PROT(p, b)        __pgprot(pgprot_val(p) | (b))
 
-#define PAGE_NONE              _MOD_PROT(pgprot_default, PTE_NG | PTE_XN | PTE_RDONLY)
-#define PAGE_SHARED            _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN)
-#define PAGE_SHARED_EXEC       _MOD_PROT(pgprot_default, PTE_USER | PTE_NG)
-#define PAGE_COPY              _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
-#define PAGE_COPY_EXEC         _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY)
-#define PAGE_READONLY          _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
-#define PAGE_READONLY_EXEC     _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_RDONLY)
-#define PAGE_KERNEL            _MOD_PROT(pgprot_default, PTE_XN | PTE_DIRTY)
-#define PAGE_KERNEL_EXEC       _MOD_PROT(pgprot_default, PTE_DIRTY)
-
-#define __PAGE_NONE            __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_XN | PTE_RDONLY)
-#define __PAGE_SHARED          __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN)
-#define __PAGE_SHARED_EXEC     __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG)
-#define __PAGE_COPY            __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
-#define __PAGE_COPY_EXEC       __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY)
-#define __PAGE_READONLY                __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_XN | PTE_RDONLY)
-#define __PAGE_READONLY_EXEC   __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_RDONLY)
+#define PAGE_NONE              _MOD_PROT(pgprot_default, PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define PAGE_SHARED            _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
+#define PAGE_SHARED_EXEC       _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN)
+#define PAGE_COPY              _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define PAGE_COPY_EXEC         _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
+#define PAGE_READONLY          _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define PAGE_READONLY_EXEC     _MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
+#define PAGE_KERNEL            _MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY)
+#define PAGE_KERNEL_EXEC       _MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY)
+
+#define __PAGE_NONE            __pgprot(_PAGE_DEFAULT | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define __PAGE_SHARED          __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
+#define __PAGE_SHARED_EXEC     __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
+#define __PAGE_COPY            __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define __PAGE_COPY_EXEC       __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
+#define __PAGE_READONLY                __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define __PAGE_READONLY_EXEC   __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_RDONLY)
 
 #endif /* __ASSEMBLY__ */
 
@@ -130,10 +130,10 @@ extern struct page *empty_zero_page;
 #define pte_young(pte)         (pte_val(pte) & PTE_AF)
 #define pte_special(pte)       (pte_val(pte) & PTE_SPECIAL)
 #define pte_write(pte)         (!(pte_val(pte) & PTE_RDONLY))
-#define pte_exec(pte)          (!(pte_val(pte) & PTE_XN))
+#define pte_exec(pte)          (!(pte_val(pte) & PTE_UXN))
 
 #define pte_present_exec_user(pte) \
-       ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_XN)) == \
+       ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == \
         (PTE_VALID | PTE_USER))
 
 #define PTE_BIT_FUNC(fn,op) \
@@ -262,7 +262,7 @@ static inline pmd_t *pmd_offset(pud_t *pud, unsigned long addr)
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
-       const pteval_t mask = PTE_USER | PTE_XN | PTE_RDONLY;
+       const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY;
        pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
        return pte;
 }
index acd5b68e887128e90f8e59530d77dc3985bf1e97..082e383c1b6f22dc8370fdac789489acbb04ffba 100644 (file)
@@ -637,7 +637,6 @@ mem_init (void)
 
        high_memory = __va(max_low_pfn * PAGE_SIZE);
 
-       reset_zone_present_pages();
        for_each_online_pgdat(pgdat)
                if (pgdat->bdata->node_bootmem_map)
                        totalram_pages += free_all_bootmem_node(pgdat);
index 67e489d8d1bd6450945b3b5a4320eaa4d1840953..2df26b57c26ada5cf34d6c608f75ebd7460f2063 100644 (file)
@@ -41,7 +41,7 @@ struct k_sigaction {
 static inline void sigaddset(sigset_t *set, int _sig)
 {
        asm ("bfset %0{%1,#1}"
-               : "+od" (*set)
+               : "+o" (*set)
                : "id" ((_sig - 1) ^ 31)
                : "cc");
 }
@@ -49,7 +49,7 @@ static inline void sigaddset(sigset_t *set, int _sig)
 static inline void sigdelset(sigset_t *set, int _sig)
 {
        asm ("bfclr %0{%1,#1}"
-               : "+od" (*set)
+               : "+o" (*set)
                : "id" ((_sig - 1) ^ 31)
                : "cc");
 }
@@ -65,7 +65,7 @@ static inline int __gen_sigismember(sigset_t *set, int _sig)
        int ret;
        asm ("bfextu %1{%2,#1},%0"
                : "=d" (ret)
-               : "od" (*set), "id" ((_sig-1) ^ 31)
+               : "o" (*set), "id" ((_sig-1) ^ 31)
                : "cc");
        return ret;
 }
index d38246e33ddb9f1eacb7f885f809db54057c5203..9f883bf769530d18c880416850060cd738bb0fa8 100644 (file)
@@ -30,6 +30,7 @@
  * measurement, and debugging facilities.
  */
 
+#include <linux/irqflags.h>
 #include <asm/octeon/cvmx.h>
 #include <asm/octeon/cvmx-l2c.h>
 #include <asm/octeon/cvmx-spinlock.h>
index 7cf80ca2c1d2117c239ba574406c6814ecb91961..f9f5307434c276a35624f5c137333867e2357794 100644 (file)
@@ -11,6 +11,7 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/irqflags.h>
 
 #include <asm/bcache.h>
 
index 82ad35ce2b45d975705e90a90db8cf82b7189255..46ac73abd5ee950b2bd14e57ad07d1b08ff7e010 100644 (file)
@@ -14,7 +14,6 @@
 #endif
 
 #include <linux/compiler.h>
-#include <linux/irqflags.h>
 #include <linux/types.h>
 #include <asm/barrier.h>
 #include <asm/byteorder.h>             /* sigh ... */
 #define smp_mb__before_clear_bit()     smp_mb__before_llsc()
 #define smp_mb__after_clear_bit()      smp_llsc_mb()
 
+
+/*
+ * These are the "slower" versions of the functions and are in bitops.c.
+ * These functions call raw_local_irq_{save,restore}().
+ */
+void __mips_set_bit(unsigned long nr, volatile unsigned long *addr);
+void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr);
+void __mips_change_bit(unsigned long nr, volatile unsigned long *addr);
+int __mips_test_and_set_bit(unsigned long nr,
+                           volatile unsigned long *addr);
+int __mips_test_and_set_bit_lock(unsigned long nr,
+                                volatile unsigned long *addr);
+int __mips_test_and_clear_bit(unsigned long nr,
+                             volatile unsigned long *addr);
+int __mips_test_and_change_bit(unsigned long nr,
+                              volatile unsigned long *addr);
+
+
 /*
  * set_bit - Atomically set a bit in memory
  * @nr: the bit to set
@@ -57,7 +74,7 @@
 static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 {
        unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long temp;
 
        if (kernel_uses_llsc && R10000_LLSC_WAR) {
@@ -92,17 +109,8 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
                        : "=&r" (temp), "+m" (*m)
                        : "ir" (1UL << bit));
                } while (unlikely(!temp));
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               *a |= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               __mips_set_bit(nr, addr);
 }
 
 /*
@@ -118,7 +126,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
 static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
 {
        unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long temp;
 
        if (kernel_uses_llsc && R10000_LLSC_WAR) {
@@ -153,17 +161,8 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
                        : "=&r" (temp), "+m" (*m)
                        : "ir" (~(1UL << bit)));
                } while (unlikely(!temp));
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               *a &= ~mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               __mips_clear_bit(nr, addr);
 }
 
 /*
@@ -191,7 +190,7 @@ static inline void clear_bit_unlock(unsigned long nr, volatile unsigned long *ad
  */
 static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
 
        if (kernel_uses_llsc && R10000_LLSC_WAR) {
                unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
@@ -220,17 +219,8 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
                        : "=&r" (temp), "+m" (*m)
                        : "ir" (1UL << bit));
                } while (unlikely(!temp));
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               *a ^= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               __mips_change_bit(nr, addr);
 }
 
 /*
@@ -244,7 +234,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
 static inline int test_and_set_bit(unsigned long nr,
        volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long res;
 
        smp_mb__before_llsc();
@@ -281,18 +271,8 @@ static inline int test_and_set_bit(unsigned long nr,
                } while (unlikely(!res));
 
                res = temp & (1UL << bit);
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               res = (mask & *a);
-               *a |= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               res = __mips_test_and_set_bit(nr, addr);
 
        smp_llsc_mb();
 
@@ -310,7 +290,7 @@ static inline int test_and_set_bit(unsigned long nr,
 static inline int test_and_set_bit_lock(unsigned long nr,
        volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long res;
 
        if (kernel_uses_llsc && R10000_LLSC_WAR) {
@@ -345,18 +325,8 @@ static inline int test_and_set_bit_lock(unsigned long nr,
                } while (unlikely(!res));
 
                res = temp & (1UL << bit);
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               res = (mask & *a);
-               *a |= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               res = __mips_test_and_set_bit_lock(nr, addr);
 
        smp_llsc_mb();
 
@@ -373,7 +343,7 @@ static inline int test_and_set_bit_lock(unsigned long nr,
 static inline int test_and_clear_bit(unsigned long nr,
        volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long res;
 
        smp_mb__before_llsc();
@@ -428,18 +398,8 @@ static inline int test_and_clear_bit(unsigned long nr,
                } while (unlikely(!res));
 
                res = temp & (1UL << bit);
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               res = (mask & *a);
-               *a &= ~mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               res = __mips_test_and_clear_bit(nr, addr);
 
        smp_llsc_mb();
 
@@ -457,7 +417,7 @@ static inline int test_and_clear_bit(unsigned long nr,
 static inline int test_and_change_bit(unsigned long nr,
        volatile unsigned long *addr)
 {
-       unsigned short bit = nr & SZLONG_MASK;
+       int bit = nr & SZLONG_MASK;
        unsigned long res;
 
        smp_mb__before_llsc();
@@ -494,18 +454,8 @@ static inline int test_and_change_bit(unsigned long nr,
                } while (unlikely(!res));
 
                res = temp & (1UL << bit);
-       } else {
-               volatile unsigned long *a = addr;
-               unsigned long mask;
-               unsigned long flags;
-
-               a += nr >> SZLONG_LOG;
-               mask = 1UL << bit;
-               raw_local_irq_save(flags);
-               res = (mask & *a);
-               *a ^= mask;
-               raw_local_irq_restore(flags);
-       }
+       } else
+               res = __mips_test_and_change_bit(nr, addr);
 
        smp_llsc_mb();
 
index 58277e0e9cd4075e001f79e48fcaaf928dd53064..3c5d1464b7bde4d93f5d4345fbedd31ccda7e47a 100644 (file)
@@ -290,7 +290,7 @@ struct compat_shmid64_ds {
 
 static inline int is_compat_task(void)
 {
-       return test_thread_flag(TIF_32BIT);
+       return test_thread_flag(TIF_32BIT_ADDR);
 }
 
 #endif /* _ASM_COMPAT_H */
index 29d9c23c20c72d87f847f28772666448cdd2711a..ff2e0345e0132744eb57fcfc12969c950bc97bf0 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/irqflags.h>
 
 #include <asm/addrspace.h>
 #include <asm/bug.h>
index 309cbcd6909cd808b92941e53deea0e3e3a5a756..9f3384c789d7bfdff5511706b0dffc3d2962c96c 100644 (file)
 #include <linux/compiler.h>
 #include <asm/hazards.h>
 
-__asm__(
-       "       .macro  arch_local_irq_enable                           \n"
-       "       .set    push                                            \n"
-       "       .set    reorder                                         \n"
-       "       .set    noat                                            \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "       mfc0    $1, $2, 1       # SMTC - clear TCStatus.IXMT    \n"
-       "       ori     $1, 0x400                                       \n"
-       "       xori    $1, 0x400                                       \n"
-       "       mtc0    $1, $2, 1                                       \n"
-#elif defined(CONFIG_CPU_MIPSR2)
-       "       ei                                                      \n"
-#else
-       "       mfc0    $1,$12                                          \n"
-       "       ori     $1,0x1f                                         \n"
-       "       xori    $1,0x1e                                         \n"
-       "       mtc0    $1,$12                                          \n"
-#endif
-       "       irq_enable_hazard                                       \n"
-       "       .set    pop                                             \n"
-       "       .endm");
+#if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC)
 
-extern void smtc_ipi_replay(void);
-
-static inline void arch_local_irq_enable(void)
-{
-#ifdef CONFIG_MIPS_MT_SMTC
-       /*
-        * SMTC kernel needs to do a software replay of queued
-        * IPIs, at the cost of call overhead on each local_irq_enable()
-        */
-       smtc_ipi_replay();
-#endif
-       __asm__ __volatile__(
-               "arch_local_irq_enable"
-               : /* no outputs */
-               : /* no inputs */
-               : "memory");
-}
-
-
-/*
- * For cli() we have to insert nops to make sure that the new value
- * has actually arrived in the status register before the end of this
- * macro.
- * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
- * no nops at all.
- */
-/*
- * For TX49, operating only IE bit is not enough.
- *
- * If mfc0 $12 follows store and the mfc0 is last instruction of a
- * page and fetching the next instruction causes TLB miss, the result
- * of the mfc0 might wrongly contain EXL bit.
- *
- * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
- *
- * Workaround: mask EXL bit of the result or place a nop before mfc0.
- */
 __asm__(
        "       .macro  arch_local_irq_disable\n"
        "       .set    push                                            \n"
        "       .set    noat                                            \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "       mfc0    $1, $2, 1                                       \n"
-       "       ori     $1, 0x400                                       \n"
-       "       .set    noreorder                                       \n"
-       "       mtc0    $1, $2, 1                                       \n"
-#elif defined(CONFIG_CPU_MIPSR2)
        "       di                                                      \n"
-#else
-       "       mfc0    $1,$12                                          \n"
-       "       ori     $1,0x1f                                         \n"
-       "       xori    $1,0x1f                                         \n"
-       "       .set    noreorder                                       \n"
-       "       mtc0    $1,$12                                          \n"
-#endif
        "       irq_disable_hazard                                      \n"
        "       .set    pop                                             \n"
        "       .endm                                                   \n");
@@ -106,46 +36,14 @@ static inline void arch_local_irq_disable(void)
                : "memory");
 }
 
-__asm__(
-       "       .macro  arch_local_save_flags flags                     \n"
-       "       .set    push                                            \n"
-       "       .set    reorder                                         \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "       mfc0    \\flags, $2, 1                                  \n"
-#else
-       "       mfc0    \\flags, $12                                    \n"
-#endif
-       "       .set    pop                                             \n"
-       "       .endm                                                   \n");
-
-static inline unsigned long arch_local_save_flags(void)
-{
-       unsigned long flags;
-       asm volatile("arch_local_save_flags %0" : "=r" (flags));
-       return flags;
-}
 
 __asm__(
        "       .macro  arch_local_irq_save result                      \n"
        "       .set    push                                            \n"
        "       .set    reorder                                         \n"
        "       .set    noat                                            \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "       mfc0    \\result, $2, 1                                 \n"
-       "       ori     $1, \\result, 0x400                             \n"
-       "       .set    noreorder                                       \n"
-       "       mtc0    $1, $2, 1                                       \n"
-       "       andi    \\result, \\result, 0x400                       \n"
-#elif defined(CONFIG_CPU_MIPSR2)
        "       di      \\result                                        \n"
        "       andi    \\result, 1                                     \n"
-#else
-       "       mfc0    \\result, $12                                   \n"
-       "       ori     $1, \\result, 0x1f                              \n"
-       "       xori    $1, 0x1f                                        \n"
-       "       .set    noreorder                                       \n"
-       "       mtc0    $1, $12                                         \n"
-#endif
        "       irq_disable_hazard                                      \n"
        "       .set    pop                                             \n"
        "       .endm                                                   \n");
@@ -160,61 +58,37 @@ static inline unsigned long arch_local_irq_save(void)
        return flags;
 }
 
+
 __asm__(
        "       .macro  arch_local_irq_restore flags                    \n"
        "       .set    push                                            \n"
        "       .set    noreorder                                       \n"
        "       .set    noat                                            \n"
-#ifdef CONFIG_MIPS_MT_SMTC
-       "mfc0   $1, $2, 1                                               \n"
-       "andi   \\flags, 0x400                                          \n"
-       "ori    $1, 0x400                                               \n"
-       "xori   $1, 0x400                                               \n"
-       "or     \\flags, $1                                             \n"
-       "mtc0   \\flags, $2, 1                                          \n"
-#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
+#if defined(CONFIG_IRQ_CPU)
        /*
         * Slow, but doesn't suffer from a relatively unlikely race
         * condition we're having since days 1.
         */
        "       beqz    \\flags, 1f                                     \n"
-       "        di                                                     \n"
+       "       di                                                      \n"
        "       ei                                                      \n"
        "1:                                                             \n"
-#elif defined(CONFIG_CPU_MIPSR2)
+#else
        /*
         * Fast, dangerous.  Life is fun, life is good.
         */
        "       mfc0    $1, $12                                         \n"
        "       ins     $1, \\flags, 0, 1                               \n"
        "       mtc0    $1, $12                                         \n"
-#else
-       "       mfc0    $1, $12                                         \n"
-       "       andi    \\flags, 1                                      \n"
-       "       ori     $1, 0x1f                                        \n"
-       "       xori    $1, 0x1f                                        \n"
-       "       or      \\flags, $1                                     \n"
-       "       mtc0    \\flags, $12                                    \n"
 #endif
        "       irq_disable_hazard                                      \n"
        "       .set    pop                                             \n"
        "       .endm                                                   \n");
 
-
 static inline void arch_local_irq_restore(unsigned long flags)
 {
        unsigned long __tmp1;
 
-#ifdef CONFIG_MIPS_MT_SMTC
-       /*
-        * SMTC kernel needs to do a software replay of queued
-        * IPIs, at the cost of branch and call overhead on each
-        * local_irq_restore()
-        */
-       if (unlikely(!(flags & 0x0400)))
-               smtc_ipi_replay();
-#endif
-
        __asm__ __volatile__(
                "arch_local_irq_restore\t%0"
                : "=r" (__tmp1)
@@ -232,6 +106,75 @@ static inline void __arch_local_irq_restore(unsigned long flags)
                : "0" (flags)
                : "memory");
 }
+#else
+/* Functions that require preempt_{dis,en}able() are in mips-atomic.c */
+void arch_local_irq_disable(void);
+unsigned long arch_local_irq_save(void);
+void arch_local_irq_restore(unsigned long flags);
+void __arch_local_irq_restore(unsigned long flags);
+#endif /* if defined(CONFIG_CPU_MIPSR2) && !defined(CONFIG_MIPS_MT_SMTC) */
+
+
+__asm__(
+       "       .macro  arch_local_irq_enable                           \n"
+       "       .set    push                                            \n"
+       "       .set    reorder                                         \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    $1, $2, 1       # SMTC - clear TCStatus.IXMT    \n"
+       "       ori     $1, 0x400                                       \n"
+       "       xori    $1, 0x400                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
+       "       ei                                                      \n"
+#else
+       "       mfc0    $1,$12                                          \n"
+       "       ori     $1,0x1f                                         \n"
+       "       xori    $1,0x1e                                         \n"
+       "       mtc0    $1,$12                                          \n"
+#endif
+       "       irq_enable_hazard                                       \n"
+       "       .set    pop                                             \n"
+       "       .endm");
+
+extern void smtc_ipi_replay(void);
+
+static inline void arch_local_irq_enable(void)
+{
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * SMTC kernel needs to do a software replay of queued
+        * IPIs, at the cost of call overhead on each local_irq_enable()
+        */
+       smtc_ipi_replay();
+#endif
+       __asm__ __volatile__(
+               "arch_local_irq_enable"
+               : /* no outputs */
+               : /* no inputs */
+               : "memory");
+}
+
+
+__asm__(
+       "       .macro  arch_local_save_flags flags                     \n"
+       "       .set    push                                            \n"
+       "       .set    reorder                                         \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    \\flags, $2, 1                                  \n"
+#else
+       "       mfc0    \\flags, $12                                    \n"
+#endif
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+static inline unsigned long arch_local_save_flags(void)
+{
+       unsigned long flags;
+       asm volatile("arch_local_save_flags %0" : "=r" (flags));
+       return flags;
+}
+
 
 static inline int arch_irqs_disabled_flags(unsigned long flags)
 {
@@ -245,7 +188,7 @@ static inline int arch_irqs_disabled_flags(unsigned long flags)
 #endif
 }
 
-#endif
+#endif /* #ifndef __ASSEMBLY__ */
 
 /*
  * Do the CPU's IRQ-state tracing from assembly code.
index 8debe9e917549097d09f5083489714605066a1cc..18806a52061c3c6869ed03c101ccabe740b64ac8 100644 (file)
@@ -112,12 +112,6 @@ register struct thread_info *__current_thread_info __asm__("$28");
 #define TIF_LOAD_WATCH         25      /* If set, load watch registers */
 #define TIF_SYSCALL_TRACE      31      /* syscall trace active */
 
-#ifdef CONFIG_MIPS32_O32
-#define TIF_32BIT TIF_32BIT_REGS
-#elif defined(CONFIG_MIPS32_N32)
-#define TIF_32BIT _TIF_32BIT_ADDR
-#endif /* CONFIG_MIPS32_O32 */
-
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1<<TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
index a53f8ec37aac68beef41b905b88cf1fe92e805d9..290dc6a1d7a344413e36f00fdacfa86e9d1bcbe3 100644 (file)
@@ -79,7 +79,7 @@ static struct resource data_resource = { .name = "Kernel data", };
 void __init add_memory_region(phys_t start, phys_t size, long type)
 {
        int x = boot_mem_map.nr_map;
-       struct boot_mem_map_entry *prev = boot_mem_map.map + x - 1;
+       int i;
 
        /* Sanity check */
        if (start + size < start) {
@@ -88,15 +88,29 @@ void __init add_memory_region(phys_t start, phys_t size, long type)
        }
 
        /*
-        * Try to merge with previous entry if any.  This is far less than
-        * perfect but is sufficient for most real world cases.
+        * Try to merge with existing entry, if any.
         */
-       if (x && prev->addr + prev->size == start && prev->type == type) {
-               prev->size += size;
+       for (i = 0; i < boot_mem_map.nr_map; i++) {
+               struct boot_mem_map_entry *entry = boot_mem_map.map + i;
+               unsigned long top;
+
+               if (entry->type != type)
+                       continue;
+
+               if (start + size < entry->addr)
+                       continue;                       /* no overlap */
+
+               if (entry->addr + entry->size < start)
+                       continue;                       /* no overlap */
+
+               top = max(entry->addr + entry->size, start + size);
+               entry->addr = min(entry->addr, start);
+               entry->size = top - entry->addr;
+
                return;
        }
 
-       if (x == BOOT_MEM_MAP_MAX) {
+       if (boot_mem_map.nr_map == BOOT_MEM_MAP_MAX) {
                pr_err("Ooops! Too many entries in the memory map!\n");
                return;
        }
index c4a82e841c7309d1659ceeac4e708e6796ee8c2c..eeddc58802e11a57595ee7d123e0538577af0c67 100644 (file)
@@ -2,8 +2,9 @@
 # Makefile for MIPS-specific library files..
 #
 
-lib-y  += csum_partial.o delay.o memcpy.o memset.o \
-          strlen_user.o strncpy_user.o strnlen_user.o uncached.o
+lib-y  += bitops.o csum_partial.o delay.o memcpy.o memset.o \
+          mips-atomic.o strlen_user.o strncpy_user.o \
+          strnlen_user.o uncached.o
 
 obj-y                  += iomap.o
 obj-$(CONFIG_PCI)      += iomap-pci.o
diff --git a/arch/mips/lib/bitops.c b/arch/mips/lib/bitops.c
new file mode 100644 (file)
index 0000000..239a9c9
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 1994-1997, 99, 2000, 06, 07 Ralf Baechle (ralf@linux-mips.org)
+ * Copyright (c) 1999, 2000  Silicon Graphics, Inc.
+ */
+#include <linux/bitops.h>
+#include <linux/irqflags.h>
+#include <linux/export.h>
+
+
+/**
+ * __mips_set_bit - Atomically set a bit in memory.  This is called by
+ * set_bit() if it cannot find a faster solution.
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ */
+void __mips_set_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       *a |= mask;
+       raw_local_irq_restore(flags);
+}
+EXPORT_SYMBOL(__mips_set_bit);
+
+
+/**
+ * __mips_clear_bit - Clears a bit in memory.  This is called by clear_bit() if
+ * it cannot find a faster solution.
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ */
+void __mips_clear_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       *a &= ~mask;
+       raw_local_irq_restore(flags);
+}
+EXPORT_SYMBOL(__mips_clear_bit);
+
+
+/**
+ * __mips_change_bit - Toggle a bit in memory.  This is called by change_bit()
+ * if it cannot find a faster solution.
+ * @nr: Bit to change
+ * @addr: Address to start counting from
+ */
+void __mips_change_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       *a ^= mask;
+       raw_local_irq_restore(flags);
+}
+EXPORT_SYMBOL(__mips_change_bit);
+
+
+/**
+ * __mips_test_and_set_bit - Set a bit and return its old value.  This is
+ * called by test_and_set_bit() if it cannot find a faster solution.
+ * @nr: Bit to set
+ * @addr: Address to count from
+ */
+int __mips_test_and_set_bit(unsigned long nr,
+                           volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+       unsigned long res;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       res = (mask & *a);
+       *a |= mask;
+       raw_local_irq_restore(flags);
+       return res;
+}
+EXPORT_SYMBOL(__mips_test_and_set_bit);
+
+
+/**
+ * __mips_test_and_set_bit_lock - Set a bit and return its old value.  This is
+ * called by test_and_set_bit_lock() if it cannot find a faster solution.
+ * @nr: Bit to set
+ * @addr: Address to count from
+ */
+int __mips_test_and_set_bit_lock(unsigned long nr,
+                                volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+       unsigned long res;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       res = (mask & *a);
+       *a |= mask;
+       raw_local_irq_restore(flags);
+       return res;
+}
+EXPORT_SYMBOL(__mips_test_and_set_bit_lock);
+
+
+/**
+ * __mips_test_and_clear_bit - Clear a bit and return its old value.  This is
+ * called by test_and_clear_bit() if it cannot find a faster solution.
+ * @nr: Bit to clear
+ * @addr: Address to count from
+ */
+int __mips_test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+       unsigned long res;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       res = (mask & *a);
+       *a &= ~mask;
+       raw_local_irq_restore(flags);
+       return res;
+}
+EXPORT_SYMBOL(__mips_test_and_clear_bit);
+
+
+/**
+ * __mips_test_and_change_bit - Change a bit and return its old value.  This is
+ * called by test_and_change_bit() if it cannot find a faster solution.
+ * @nr: Bit to change
+ * @addr: Address to count from
+ */
+int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
+{
+       volatile unsigned long *a = addr;
+       unsigned bit = nr & SZLONG_MASK;
+       unsigned long mask;
+       unsigned long flags;
+       unsigned long res;
+
+       a += nr >> SZLONG_LOG;
+       mask = 1UL << bit;
+       raw_local_irq_save(flags);
+       res = (mask & *a);
+       *a ^= mask;
+       raw_local_irq_restore(flags);
+       return res;
+}
+EXPORT_SYMBOL(__mips_test_and_change_bit);
diff --git a/arch/mips/lib/mips-atomic.c b/arch/mips/lib/mips-atomic.c
new file mode 100644 (file)
index 0000000..cd160be
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1994, 95, 96, 97, 98, 99, 2003 by Ralf Baechle
+ * Copyright (C) 1996 by Paul M. Antoine
+ * Copyright (C) 1999 Silicon Graphics
+ * Copyright (C) 2000 MIPS Technologies, Inc.
+ */
+#include <asm/irqflags.h>
+#include <asm/hazards.h>
+#include <linux/compiler.h>
+#include <linux/preempt.h>
+#include <linux/export.h>
+
+#if !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC)
+
+/*
+ * For cli() we have to insert nops to make sure that the new value
+ * has actually arrived in the status register before the end of this
+ * macro.
+ * R4000/R4400 need three nops, the R4600 two nops and the R10000 needs
+ * no nops at all.
+ */
+/*
+ * For TX49, operating only IE bit is not enough.
+ *
+ * If mfc0 $12 follows store and the mfc0 is last instruction of a
+ * page and fetching the next instruction causes TLB miss, the result
+ * of the mfc0 might wrongly contain EXL bit.
+ *
+ * ERT-TX49H2-027, ERT-TX49H3-012, ERT-TX49HL3-006, ERT-TX49H4-008
+ *
+ * Workaround: mask EXL bit of the result or place a nop before mfc0.
+ */
+__asm__(
+       "       .macro  arch_local_irq_disable\n"
+       "       .set    push                                            \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    $1, $2, 1                                       \n"
+       "       ori     $1, 0x400                                       \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
+       /* see irqflags.h for inline function */
+#else
+       "       mfc0    $1,$12                                          \n"
+       "       ori     $1,0x1f                                         \n"
+       "       xori    $1,0x1f                                         \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1,$12                                          \n"
+#endif
+       "       irq_disable_hazard                                      \n"
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+notrace void arch_local_irq_disable(void)
+{
+       preempt_disable();
+       __asm__ __volatile__(
+               "arch_local_irq_disable"
+               : /* no outputs */
+               : /* no inputs */
+               : "memory");
+       preempt_enable();
+}
+EXPORT_SYMBOL(arch_local_irq_disable);
+
+
+__asm__(
+       "       .macro  arch_local_irq_save result                      \n"
+       "       .set    push                                            \n"
+       "       .set    reorder                                         \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "       mfc0    \\result, $2, 1                                 \n"
+       "       ori     $1, \\result, 0x400                             \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $2, 1                                       \n"
+       "       andi    \\result, \\result, 0x400                       \n"
+#elif defined(CONFIG_CPU_MIPSR2)
+       /* see irqflags.h for inline function */
+#else
+       "       mfc0    \\result, $12                                   \n"
+       "       ori     $1, \\result, 0x1f                              \n"
+       "       xori    $1, 0x1f                                        \n"
+       "       .set    noreorder                                       \n"
+       "       mtc0    $1, $12                                         \n"
+#endif
+       "       irq_disable_hazard                                      \n"
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+notrace unsigned long arch_local_irq_save(void)
+{
+       unsigned long flags;
+       preempt_disable();
+       asm volatile("arch_local_irq_save\t%0"
+                    : "=r" (flags)
+                    : /* no inputs */
+                    : "memory");
+       preempt_enable();
+       return flags;
+}
+EXPORT_SYMBOL(arch_local_irq_save);
+
+
+__asm__(
+       "       .macro  arch_local_irq_restore flags                    \n"
+       "       .set    push                                            \n"
+       "       .set    noreorder                                       \n"
+       "       .set    noat                                            \n"
+#ifdef CONFIG_MIPS_MT_SMTC
+       "mfc0   $1, $2, 1                                               \n"
+       "andi   \\flags, 0x400                                          \n"
+       "ori    $1, 0x400                                               \n"
+       "xori   $1, 0x400                                               \n"
+       "or     \\flags, $1                                             \n"
+       "mtc0   \\flags, $2, 1                                          \n"
+#elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
+       /* see irqflags.h for inline function */
+#elif defined(CONFIG_CPU_MIPSR2)
+       /* see irqflags.h for inline function */
+#else
+       "       mfc0    $1, $12                                         \n"
+       "       andi    \\flags, 1                                      \n"
+       "       ori     $1, 0x1f                                        \n"
+       "       xori    $1, 0x1f                                        \n"
+       "       or      \\flags, $1                                     \n"
+       "       mtc0    \\flags, $12                                    \n"
+#endif
+       "       irq_disable_hazard                                      \n"
+       "       .set    pop                                             \n"
+       "       .endm                                                   \n");
+
+notrace void arch_local_irq_restore(unsigned long flags)
+{
+       unsigned long __tmp1;
+
+#ifdef CONFIG_MIPS_MT_SMTC
+       /*
+        * SMTC kernel needs to do a software replay of queued
+        * IPIs, at the cost of branch and call overhead on each
+        * local_irq_restore()
+        */
+       if (unlikely(!(flags & 0x0400)))
+               smtc_ipi_replay();
+#endif
+       preempt_disable();
+       __asm__ __volatile__(
+               "arch_local_irq_restore\t%0"
+               : "=r" (__tmp1)
+               : "0" (flags)
+               : "memory");
+       preempt_enable();
+}
+EXPORT_SYMBOL(arch_local_irq_restore);
+
+
+notrace void __arch_local_irq_restore(unsigned long flags)
+{
+       unsigned long __tmp1;
+
+       preempt_disable();
+       __asm__ __volatile__(
+               "arch_local_irq_restore\t%0"
+               : "=r" (__tmp1)
+               : "0" (flags)
+               : "memory");
+       preempt_enable();
+}
+EXPORT_SYMBOL(__arch_local_irq_restore);
+
+#endif /* !defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_MIPS_MT_SMTC) */
index 80562b81f0f2a2036fbf0a28781601b420c5d872..74732177851c31843add1f2259dab3233932726a 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/platform_device.h>
+#include <asm/mips-boards/maltaint.h>
 #include <mtd/mtd-abi.h>
 
 #define SMC_PORT(base, int)                                            \
@@ -48,7 +49,7 @@ static struct plat_serial8250_port uart8250_data[] = {
        SMC_PORT(0x2F8, 3),
        {
                .mapbase        = 0x1f000900,   /* The CBUS UART */
-               .irq            = MIPS_CPU_IRQ_BASE + 2,
+               .irq            = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB2,
                .uartclk        = 3686400,      /* Twice the usual clk! */
                .iotype         = UPIO_MEM32,
                .flags          = CBUS_UART_FLAGS,
index fd49aeda9eb8b0c4fef656e3dc00228c59251b99..5dede04f2f3ead372752fdbaaafceca5708b6902 100644 (file)
@@ -65,7 +65,8 @@ put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
 {
        compat_sigset_t s;
 
-       if (sz != sizeof *set) panic("put_sigset32()");
+       if (sz != sizeof *set)
+               return -EINVAL;
        sigset_64to32(&s, set);
 
        return copy_to_user(up, &s, sizeof s);
@@ -77,7 +78,8 @@ get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
        compat_sigset_t s;
        int r;
 
-       if (sz != sizeof *set) panic("put_sigset32()");
+       if (sz != sizeof *set)
+               return -EINVAL;
 
        if ((r = copy_from_user(&s, up, sz)) == 0) {
                sigset_32to64(set, &s);
index 7426e40699bdbf08575d0b69722e6594a1535076..f76c10863c6266c5a4fe6a3fbbe22d022a11e8c2 100644 (file)
@@ -73,6 +73,8 @@ static unsigned long get_shared_area(struct address_space *mapping,
        struct vm_area_struct *vma;
        int offset = mapping ? get_offset(mapping) : 0;
 
+       offset = (offset + (pgoff << PAGE_SHIFT)) & 0x3FF000;
+
        addr = DCACHE_ALIGN(addr - offset) + offset;
 
        for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
index 7ab286ab5300accb706fb72a2e343153cae85d18..39ed65a44c5fac5fc996b2d5ec25effbbf9853fa 100644 (file)
                        interrupts = <2 7 0>;
                };
 
+               sclpc@3c00 {
+                       compatible = "fsl,mpc5200-lpbfifo";
+                       reg = <0x3c00 0x60>;
+                       interrupts = <2 23 0>;
+               };
+
                i2c@3d00 {
                        #address-cells = <1>;
                        #size-cells = <0>;
index 3444eb8f0ade62305d0a935ca50a02d1fca16933..24f668039295b1b95ff279ff91974a7ad65582ff 100644 (file)
                                reg = <0>;
                        };
                };
-
-               sclpc@3c00 {
-                       compatible = "fsl,mpc5200-lpbfifo";
-                       reg = <0x3c00 0x60>;
-                       interrupts = <3 23 0>;
-               };
        };
 
        localbus {
index 9e354997eb7e3ccc29ac70ee5e7a31c3ce319b01..96512c05803336d937cabcf5b06aa86e43bc538b 100644 (file)
@@ -59,7 +59,7 @@
                        #gpio-cells = <2>;
                };
 
-               psc@2000 { /* PSC1 in ac97 mode */
+               audioplatform: psc@2000 { /* PSC1 in ac97 mode */
                        compatible = "mpc5200b-psc-ac97","fsl,mpc5200b-psc-ac97";
                        cell-index = <0>;
                };
        localbus {
                status = "disabled";
        };
+
+       sound {
+               compatible = "phytec,pcm030-audio-fabric";
+               asoc-platform = <&audioplatform>;
+       };
 };
index 8520b58a5e9a0f0027a95f0df2662cbab898c5cc..b89ef65392dc229b4ec026e23ddd9c5228ed05f1 100644 (file)
@@ -372,10 +372,11 @@ static int mpc52xx_irqhost_map(struct irq_domain *h, unsigned int virq,
        case MPC52xx_IRQ_L1_MAIN: irqchip = &mpc52xx_main_irqchip; break;
        case MPC52xx_IRQ_L1_PERP: irqchip = &mpc52xx_periph_irqchip; break;
        case MPC52xx_IRQ_L1_SDMA: irqchip = &mpc52xx_sdma_irqchip; break;
-       default:
-               pr_err("%s: invalid irq: virq=%i, l1=%i, l2=%i\n",
-                      __func__, virq, l1irq, l2irq);
-               return -EINVAL;
+       case MPC52xx_IRQ_L1_CRIT:
+               pr_warn("%s: Critical IRQ #%d is unsupported! Nopping it.\n",
+                       __func__, l2irq);
+               irq_set_chip(virq, &no_irq_chip);
+               return 0;
        }
 
        irq_set_chip_and_handler(virq, irqchip, handle_level_irq);
index 797cd181dc3f615fab312df9ccce4813263eedf4..d16c8ded10847ce19d67f26a39179587707ddbf0 100644 (file)
@@ -449,7 +449,7 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
                        if (list_empty(&pe->edevs)) {
                                cnt = 0;
                                list_for_each_entry(child, &pe->child_list, child) {
-                                       if (!(pe->type & EEH_PE_INVALID)) {
+                                       if (!(child->type & EEH_PE_INVALID)) {
                                                cnt++;
                                                break;
                                        }
index d19f4977c83492e1174be5456e1d0ff7ee33ca33..e5b084723131cc1ef0b6260f2a571f7071ee5995 100644 (file)
@@ -220,7 +220,8 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
 
        /* Get the top level device in the PE */
        edev = of_node_to_eeh_dev(dn);
-       edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
+       if (edev->pe)
+               edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
        dn = eeh_dev_to_of_node(edev);
        if (!dn)
                return NULL;
index 5dba755a43e60911ae2a5b922bde0c9f4a70b6f1..d385f396dfee90172e5a984702cd9ded8a76387d 100644 (file)
@@ -96,6 +96,7 @@ config S390
        select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_CMPXCHG_LOCAL
        select HAVE_CMPXCHG_DOUBLE
+       select HAVE_ALIGNED_STRUCT_PAGE if SLUB
        select HAVE_VIRT_CPU_ACCOUNTING
        select VIRT_CPU_ACCOUNTING
        select ARCH_DISCARD_MEMBLOCK
index a34a9d612fc0f2d4ecc9a4bfbcef2794fba7de41..18cd6b592650962010b7c72f32b0d401cf572a57 100644 (file)
@@ -20,7 +20,7 @@
 #define PSW32_MASK_CC          0x00003000UL
 #define PSW32_MASK_PM          0x00000f00UL
 
-#define PSW32_MASK_USER                0x00003F00UL
+#define PSW32_MASK_USER                0x0000FF00UL
 
 #define PSW32_ADDR_AMODE       0x80000000UL
 #define PSW32_ADDR_INSN                0x7FFFFFFFUL
index 9ca30538376001ffe6b07e9cac9db311707e195f..9935cbd6a46fdee89e8cdfd65c7f9acc0de474b9 100644 (file)
@@ -8,6 +8,9 @@ struct cpu;
 
 #ifdef CONFIG_SCHED_BOOK
 
+extern unsigned char cpu_socket_id[NR_CPUS];
+#define topology_physical_package_id(cpu) (cpu_socket_id[cpu])
+
 extern unsigned char cpu_core_id[NR_CPUS];
 extern cpumask_t cpu_core_map[NR_CPUS];
 
index 705588a16d70da6322ca349074a1b30de92f658a..a5ca214b34fdb1271e4fad48d9c7c7fb8c5a9437 100644 (file)
@@ -239,7 +239,7 @@ typedef struct
 #define PSW_MASK_EA            0x00000000UL
 #define PSW_MASK_BA            0x00000000UL
 
-#define PSW_MASK_USER          0x00003F00UL
+#define PSW_MASK_USER          0x0000FF00UL
 
 #define PSW_ADDR_AMODE         0x80000000UL
 #define PSW_ADDR_INSN          0x7FFFFFFFUL
@@ -269,7 +269,7 @@ typedef struct
 #define PSW_MASK_EA            0x0000000100000000UL
 #define PSW_MASK_BA            0x0000000080000000UL
 
-#define PSW_MASK_USER          0x00003F8180000000UL
+#define PSW_MASK_USER          0x0000FF8180000000UL
 
 #define PSW_ADDR_AMODE         0x0000000000000000UL
 #define PSW_ADDR_INSN          0xFFFFFFFFFFFFFFFFUL
index a1e8a8694bb70561a8c78c35558ff3a635e2203e..593fcc9253fc433650e54fbc8f8f829f5d961e98 100644 (file)
@@ -309,6 +309,10 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
        regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
                (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
                (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
+       /* Check for invalid user address space control. */
+       if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
+               regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
+                       (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
        for (i = 0; i < NUM_GPRS; i++)
                regs->gprs[i] = (__u64) regs32.gprs[i];
@@ -481,7 +485,10 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
 
        /* Set up registers for signal handler */
        regs->gprs[15] = (__force __u64) frame;
-       regs->psw.mask |= PSW_MASK_BA;          /* force amode 31 */
+       /* Force 31 bit amode and default user address space control. */
+       regs->psw.mask = PSW_MASK_BA |
+               (psw_user_bits & PSW_MASK_ASC) |
+               (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (__force __u64) ka->sa.sa_handler;
 
        regs->gprs[2] = map_signal(sig);
@@ -549,7 +556,10 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        /* Set up registers for signal handler */
        regs->gprs[15] = (__force __u64) frame;
-       regs->psw.mask |= PSW_MASK_BA;          /* force amode 31 */
+       /* Force 31 bit amode and default user address space control. */
+       regs->psw.mask = PSW_MASK_BA |
+               (psw_user_bits & PSW_MASK_ASC) |
+               (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (__u64) ka->sa.sa_handler;
 
        regs->gprs[2] = map_signal(sig);
index c13a2a37ef007b2634a508b7053b0c3cc12e30b2..d1259d875074179ff11b232258fcc36ef98b90c3 100644 (file)
@@ -136,6 +136,10 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs)
        /* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */
        regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
                (user_sregs.regs.psw.mask & PSW_MASK_USER);
+       /* Check for invalid user address space control. */
+       if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC))
+               regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) |
+                       (regs->psw.mask & ~PSW_MASK_ASC);
        /* Check for invalid amode */
        if (regs->psw.mask & PSW_MASK_EA)
                regs->psw.mask |= PSW_MASK_BA;
@@ -273,7 +277,10 @@ static int setup_frame(int sig, struct k_sigaction *ka,
 
        /* Set up registers for signal handler */
        regs->gprs[15] = (unsigned long) frame;
-       regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA;    /* 64 bit amode */
+       /* Force default amode and default user address space control. */
+       regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
+               (psw_user_bits & PSW_MASK_ASC) |
+               (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
 
        regs->gprs[2] = map_signal(sig);
@@ -346,7 +353,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 
        /* Set up registers for signal handler */
        regs->gprs[15] = (unsigned long) frame;
-       regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA;    /* 64 bit amode */
+       /* Force default amode and default user address space control. */
+       regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
+               (psw_user_bits & PSW_MASK_ASC) |
+               (regs->psw.mask & ~PSW_MASK_ASC);
        regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
 
        regs->gprs[2] = map_signal(sig);
index 54d93f4b681813927aabd8adbffbeb6204387d4b..dd55f7c2010448a5b842c741ac6d93fc673591da 100644 (file)
@@ -40,6 +40,7 @@ static DEFINE_SPINLOCK(topology_lock);
 static struct mask_info core_info;
 cpumask_t cpu_core_map[NR_CPUS];
 unsigned char cpu_core_id[NR_CPUS];
+unsigned char cpu_socket_id[NR_CPUS];
 
 static struct mask_info book_info;
 cpumask_t cpu_book_map[NR_CPUS];
@@ -83,11 +84,12 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
                        cpumask_set_cpu(lcpu, &book->mask);
                        cpu_book_id[lcpu] = book->id;
                        cpumask_set_cpu(lcpu, &core->mask);
+                       cpu_core_id[lcpu] = rcpu;
                        if (one_core_per_cpu) {
-                               cpu_core_id[lcpu] = rcpu;
+                               cpu_socket_id[lcpu] = rcpu;
                                core = core->next;
                        } else {
-                               cpu_core_id[lcpu] = core->id;
+                               cpu_socket_id[lcpu] = core->id;
                        }
                        smp_cpu_set_polarization(lcpu, tl_cpu->pp);
                }
index 8b8285310b5a172a2f1e650b4c52d6c908bc193a..1f5315d1215c2640f5691555801e9ff7885c7fcf 100644 (file)
@@ -180,8 +180,7 @@ int __get_user_pages_fast(unsigned long start, int nr_pages, int write,
        addr = start;
        len = (unsigned long) nr_pages << PAGE_SHIFT;
        end = start + len;
-       if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ,
-                                       (void __user *)start, len)))
+       if ((end < start) || (end > TASK_SIZE))
                return 0;
 
        local_irq_save(flags);
@@ -229,7 +228,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write,
        addr = start;
        len = (unsigned long) nr_pages << PAGE_SHIFT;
        end = start + len;
-       if (end < start)
+       if ((end < start) || (end > TASK_SIZE))
                goto slow_irqon;
 
        /*
index f93003123bce01119544ef88b15b3e479fbf92cd..67c62578d17043bbff42e1880f1f7e8986cb971c 100644 (file)
@@ -63,10 +63,13 @@ extern char *of_console_options;
 extern void irq_trans_init(struct device_node *dp);
 extern char *build_path_component(struct device_node *dp);
 
-/* SPARC has a local implementation */
+/* SPARC has local implementations */
 extern int of_address_to_resource(struct device_node *dev, int index,
                                  struct resource *r);
 #define of_address_to_resource of_address_to_resource
 
+void __iomem *of_iomap(struct device_node *node, int index);
+#define of_iomap of_iomap
+
 #endif /* __KERNEL__ */
 #endif /* _SPARC_PROM_H */
index 867de2f8189c32acf359fe5575cd139ede6b7048..689e1ba628097e12ab95496d60df2225817483d3 100644 (file)
@@ -295,9 +295,7 @@ void do_rt_sigreturn(struct pt_regs *regs)
                err |= restore_fpu_state(regs, fpu_save);
 
        err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
-       err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf);
-
-       if (err)
+       if (err || do_sigaltstack(&sf->stack, NULL, (unsigned long)sf) == -EFAULT)
                goto segv;
 
        err |= __get_user(rwin_save, &sf->rwin_save);
index e5c5473e69cea62bc28dcc281e4fb9d1cfcca704..c4fbb21e802b15349e7bfb09d06484b6163169cc 100644 (file)
@@ -16,6 +16,8 @@ config UNICORE32
        select ARCH_WANT_FRAME_POINTERS
        select GENERIC_IOMAP
        select MODULES_USE_ELF_REL
+       select GENERIC_KERNEL_THREAD
+       select GENERIC_KERNEL_EXECVE
        help
          UniCore-32 is 32-bit Instruction Set Architecture,
          including a series of low-power-consumption RISC chip
@@ -64,6 +66,9 @@ config GENERIC_CALIBRATE_DELAY
 config ARCH_MAY_HAVE_PC_FDC
        bool
 
+config ZONE_DMA
+       def_bool y
+
 config NEED_DMA_MAP_STATE
        def_bool y
 
@@ -216,7 +221,7 @@ config PUV3_GPIO
        bool
        depends on !ARCH_FPGA
        select GENERIC_GPIO
-       select GPIO_SYSFS if EXPERIMENTAL
+       select GPIO_SYSFS
        default y
 
 if PUV3_NB0916
index c910c9857e114316991b2e9c711819a3939cdad5..601e92f18af6d85d5bb314733e409f97436df804 100644 (file)
@@ -1,4 +1,3 @@
-include include/asm-generic/Kbuild.asm
 
 generic-y += atomic.h
 generic-y += auxvec.h
index b1ff8cadb0866bf38ead0c95353c0020160a3c62..93a56f3e2344079b49de459ad08bb798ad9b7935 100644 (file)
@@ -19,9 +19,4 @@ extern void die(const char *msg, struct pt_regs *regs, int err);
 extern void uc32_notify_die(const char *str, struct pt_regs *regs,
                struct siginfo *info, unsigned long err, unsigned long trap);
 
-extern asmlinkage void __backtrace(void);
-extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
-
-extern void __show_regs(struct pt_regs *);
-
 #endif /* __UNICORE_BUG_H__ */
index df4d5acfd19f96c9a10598a9230a0331fb7be798..8e797ad4fa24f52cbadb7b6a860a3b214d83eb3f 100644 (file)
@@ -35,7 +35,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
                        : "memory", "cc");
                break;
        default:
-               ret = __xchg_bad_pointer();
+               __xchg_bad_pointer();
        }
 
        return ret;
diff --git a/arch/unicore32/include/asm/kvm_para.h b/arch/unicore32/include/asm/kvm_para.h
deleted file mode 100644 (file)
index 14fab8f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#include <asm-generic/kvm_para.h>
index 14382cb09657f67333f5a32f4d95910ae10e0b1d..4eaa4216766772055849a3ffdb1b6e20d30edecb 100644 (file)
@@ -72,11 +72,6 @@ unsigned long get_wchan(struct task_struct *p);
 
 #define cpu_relax()                    barrier()
 
-/*
- * Create a new kernel thread
- */
-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
-
 #define task_pt_regs(p) \
        ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
 
index b9caf9b0997b21952e5b8ecd26172e3933c8a97e..726749dab52fff679f6b787ff07498053f75e7e0 100644 (file)
 #ifndef __UNICORE_PTRACE_H__
 #define __UNICORE_PTRACE_H__
 
-#define PTRACE_GET_THREAD_AREA 22
-
-/*
- * PSR bits
- */
-#define USER_MODE      0x00000010
-#define REAL_MODE      0x00000011
-#define INTR_MODE      0x00000012
-#define PRIV_MODE      0x00000013
-#define ABRT_MODE      0x00000017
-#define EXTN_MODE      0x0000001b
-#define SUSR_MODE      0x0000001f
-#define MODE_MASK      0x0000001f
-#define PSR_R_BIT      0x00000040
-#define PSR_I_BIT      0x00000080
-#define PSR_V_BIT      0x10000000
-#define PSR_C_BIT      0x20000000
-#define PSR_Z_BIT      0x40000000
-#define PSR_S_BIT      0x80000000
-
-/*
- * Groups of PSR bits
- */
-#define PSR_f          0xff000000      /* Flags                */
-#define PSR_c          0x000000ff      /* Control              */
+#include <uapi/asm/ptrace.h>
 
 #ifndef __ASSEMBLY__
 
-/*
- * This struct defines the way the registers are stored on the
- * stack during a system call.  Note that sizeof(struct pt_regs)
- * has to be a multiple of 8.
- */
-struct pt_regs {
-       unsigned long uregs[34];
-};
-
-#define UCreg_asr              uregs[32]
-#define UCreg_pc               uregs[31]
-#define UCreg_lr               uregs[30]
-#define UCreg_sp               uregs[29]
-#define UCreg_ip               uregs[28]
-#define UCreg_fp               uregs[27]
-#define UCreg_26               uregs[26]
-#define UCreg_25               uregs[25]
-#define UCreg_24               uregs[24]
-#define UCreg_23               uregs[23]
-#define UCreg_22               uregs[22]
-#define UCreg_21               uregs[21]
-#define UCreg_20               uregs[20]
-#define UCreg_19               uregs[19]
-#define UCreg_18               uregs[18]
-#define UCreg_17               uregs[17]
-#define UCreg_16               uregs[16]
-#define UCreg_15               uregs[15]
-#define UCreg_14               uregs[14]
-#define UCreg_13               uregs[13]
-#define UCreg_12               uregs[12]
-#define UCreg_11               uregs[11]
-#define UCreg_10               uregs[10]
-#define UCreg_09               uregs[9]
-#define UCreg_08               uregs[8]
-#define UCreg_07               uregs[7]
-#define UCreg_06               uregs[6]
-#define UCreg_05               uregs[5]
-#define UCreg_04               uregs[4]
-#define UCreg_03               uregs[3]
-#define UCreg_02               uregs[2]
-#define UCreg_01               uregs[1]
-#define UCreg_00               uregs[0]
-#define UCreg_ORIG_00          uregs[33]
-
-#ifdef __KERNEL__
-
 #define user_mode(regs)        \
        (processor_mode(regs) == USER_MODE)
 
@@ -125,9 +55,5 @@ static inline int valid_user_regs(struct pt_regs *regs)
 
 #define instruction_pointer(regs)      ((regs)->UCreg_pc)
 
-#endif /* __KERNEL__ */
-
 #endif /* __ASSEMBLY__ */
-
 #endif
-
index baebb3da1d44160fc6f6f259886656e6f494b167..0514d7ad68551de6b0e7a7946263bfc6c6249ab0 100644 (file)
@@ -1,3 +1,10 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
+header-y += byteorder.h
+header-y += kvm_para.h
+header-y += ptrace.h
+header-y += sigcontext.h
+header-y += unistd.h
+
+generic-y += kvm_para.h
diff --git a/arch/unicore32/include/uapi/asm/ptrace.h b/arch/unicore32/include/uapi/asm/ptrace.h
new file mode 100644 (file)
index 0000000..187aa2e
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * linux/arch/unicore32/include/asm/ptrace.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 _UAPI__UNICORE_PTRACE_H__
+#define _UAPI__UNICORE_PTRACE_H__
+
+#define PTRACE_GET_THREAD_AREA 22
+
+/*
+ * PSR bits
+ */
+#define USER_MODE      0x00000010
+#define REAL_MODE      0x00000011
+#define INTR_MODE      0x00000012
+#define PRIV_MODE      0x00000013
+#define ABRT_MODE      0x00000017
+#define EXTN_MODE      0x0000001b
+#define SUSR_MODE      0x0000001f
+#define MODE_MASK      0x0000001f
+#define PSR_R_BIT      0x00000040
+#define PSR_I_BIT      0x00000080
+#define PSR_V_BIT      0x10000000
+#define PSR_C_BIT      0x20000000
+#define PSR_Z_BIT      0x40000000
+#define PSR_S_BIT      0x80000000
+
+/*
+ * Groups of PSR bits
+ */
+#define PSR_f          0xff000000      /* Flags                */
+#define PSR_c          0x000000ff      /* Control              */
+
+#ifndef __ASSEMBLY__
+
+/*
+ * This struct defines the way the registers are stored on the
+ * stack during a system call.  Note that sizeof(struct pt_regs)
+ * has to be a multiple of 8.
+ */
+struct pt_regs {
+       unsigned long uregs[34];
+};
+
+#define UCreg_asr              uregs[32]
+#define UCreg_pc               uregs[31]
+#define UCreg_lr               uregs[30]
+#define UCreg_sp               uregs[29]
+#define UCreg_ip               uregs[28]
+#define UCreg_fp               uregs[27]
+#define UCreg_26               uregs[26]
+#define UCreg_25               uregs[25]
+#define UCreg_24               uregs[24]
+#define UCreg_23               uregs[23]
+#define UCreg_22               uregs[22]
+#define UCreg_21               uregs[21]
+#define UCreg_20               uregs[20]
+#define UCreg_19               uregs[19]
+#define UCreg_18               uregs[18]
+#define UCreg_17               uregs[17]
+#define UCreg_16               uregs[16]
+#define UCreg_15               uregs[15]
+#define UCreg_14               uregs[14]
+#define UCreg_13               uregs[13]
+#define UCreg_12               uregs[12]
+#define UCreg_11               uregs[11]
+#define UCreg_10               uregs[10]
+#define UCreg_09               uregs[9]
+#define UCreg_08               uregs[8]
+#define UCreg_07               uregs[7]
+#define UCreg_06               uregs[6]
+#define UCreg_05               uregs[5]
+#define UCreg_04               uregs[4]
+#define UCreg_03               uregs[3]
+#define UCreg_02               uregs[2]
+#define UCreg_01               uregs[1]
+#define UCreg_00               uregs[0]
+#define UCreg_ORIG_00          uregs[33]
+
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _UAPI__UNICORE_PTRACE_H__ */
similarity index 92%
rename from arch/unicore32/include/asm/unistd.h
rename to arch/unicore32/include/uapi/asm/unistd.h
index 2abcf61c615dd82bfe10114357d663a8482dff10..d18a3be89b38db8b9b2f370bfc1d64ab43ff5efe 100644 (file)
@@ -12,3 +12,4 @@
 
 /* Use the standard ABI for syscalls. */
 #include <asm-generic/unistd.h>
+#define __ARCH_WANT_SYS_EXECVE
index dcb87ab19ddd8b5912dfa2d765c4158fa1bbad73..7049350c790fea708301996647e041431a8feef5 100644 (file)
@@ -573,17 +573,16 @@ ENDPROC(ret_to_user)
  */
 ENTRY(ret_from_fork)
        b.l     schedule_tail
-       get_thread_info tsk
-       ldw     r1, [tsk+], #TI_FLAGS           @ check for syscall tracing
-       mov     why, #1
-       cand.a  r1, #_TIF_SYSCALL_TRACE         @ are we tracing syscalls?
-       beq     ret_slow_syscall
-       mov     r1, sp
-       mov     r0, #1                          @ trace exit [IP = 1]
-       b.l     syscall_trace
        b       ret_slow_syscall
 ENDPROC(ret_from_fork)
 
+ENTRY(ret_from_kernel_thread)
+       b.l     schedule_tail
+       mov     r0, r5
+       adr     lr, ret_slow_syscall
+       mov     pc, r4
+ENDPROC(ret_from_kernel_thread)
+
 /*=============================================================================
  * SWI handler
  *-----------------------------------------------------------------------------
@@ -669,11 +668,6 @@ __cr_alignment:
 #endif
        .ltorg
 
-ENTRY(sys_execve)
-               add     r3, sp, #S_OFF
-               b       __sys_execve
-ENDPROC(sys_execve)
-
 ENTRY(sys_clone)
                add     ip, sp, #S_OFF
                stw     ip, [sp+], #4
index b008586dad753a1b29010735b95ee71e1a704900..a8fe265ce2c0fad25b2a2d330636b3ee05800392 100644 (file)
@@ -258,6 +258,7 @@ void release_thread(struct task_struct *dead_task)
 }
 
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
 
 int
 copy_thread(unsigned long clone_flags, unsigned long stack_start,
@@ -266,17 +267,22 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
        struct thread_info *thread = task_thread_info(p);
        struct pt_regs *childregs = task_pt_regs(p);
 
-       *childregs = *regs;
-       childregs->UCreg_00 = 0;
-       childregs->UCreg_sp = stack_start;
-
        memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
        thread->cpu_context.sp = (unsigned long)childregs;
-       thread->cpu_context.pc = (unsigned long)ret_from_fork;
-
-       if (clone_flags & CLONE_SETTLS)
-               childregs->UCreg_16 = regs->UCreg_03;
+       if (unlikely(!regs)) {
+               thread->cpu_context.pc = (unsigned long)ret_from_kernel_thread;
+               thread->cpu_context.r4 = stack_start;
+               thread->cpu_context.r5 = stk_sz;
+               memset(childregs, 0, sizeof(struct pt_regs));
+       } else {
+               thread->cpu_context.pc = (unsigned long)ret_from_fork;
+               *childregs = *regs;
+               childregs->UCreg_00 = 0;
+               childregs->UCreg_sp = stack_start;
 
+               if (clone_flags & CLONE_SETTLS)
+                       childregs->UCreg_16 = regs->UCreg_03;
+       }
        return 0;
 }
 
@@ -305,42 +311,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fp)
 }
 EXPORT_SYMBOL(dump_fpu);
 
-/*
- * Shuffle the argument into the correct register before calling the
- * thread function.  r1 is the thread argument, r2 is the pointer to
- * the thread function, and r3 points to the exit function.
- */
-asm(".pushsection .text\n"
-"      .align\n"
-"      .type   kernel_thread_helper, #function\n"
-"kernel_thread_helper:\n"
-"      mov.a   asr, r7\n"
-"      mov     r0, r4\n"
-"      mov     lr, r6\n"
-"      mov     pc, r5\n"
-"      .size   kernel_thread_helper, . - kernel_thread_helper\n"
-"      .popsection");
-
-/*
- * Create a kernel thread.
- */
-pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
-{
-       struct pt_regs regs;
-
-       memset(&regs, 0, sizeof(regs));
-
-       regs.UCreg_04 = (unsigned long)arg;
-       regs.UCreg_05 = (unsigned long)fn;
-       regs.UCreg_06 = (unsigned long)do_exit;
-       regs.UCreg_07 = PRIV_MODE;
-       regs.UCreg_pc = (unsigned long)kernel_thread_helper;
-       regs.UCreg_asr = regs.UCreg_07 | PSR_I_BIT;
-
-       return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
-}
-EXPORT_SYMBOL(kernel_thread);
-
 unsigned long get_wchan(struct task_struct *p)
 {
        struct stackframe frame;
index f23955028a183f70c0e0982ff934a06157bad659..30f749da8f7317ecf0613089ad0876f02ed533c7 100644 (file)
@@ -30,4 +30,10 @@ extern char __vectors_start[], __vectors_end[];
 extern void kernel_thread_helper(void);
 
 extern void __init early_signal_init(void);
+
+extern asmlinkage void __backtrace(void);
+extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
+
+extern void __show_regs(struct pt_regs *);
+
 #endif
index fabdee96110b46821c911fa9de0be5ba30460b57..9680134b31f0ddd8a0be50f8dd2183a8392328c3 100644 (file)
@@ -42,69 +42,6 @@ asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp,
                        parent_tid, child_tid);
 }
 
-/* sys_execve() executes a new program.
- * This is called indirectly via a small wrapper
- */
-asmlinkage long __sys_execve(const char __user *filename,
-                         const char __user *const __user *argv,
-                         const char __user *const __user *envp,
-                         struct pt_regs *regs)
-{
-       int error;
-       struct filename *fn;
-
-       fn = getname(filename);
-       error = PTR_ERR(fn);
-       if (IS_ERR(fn))
-               goto out;
-       error = do_execve(fn->name, argv, envp, regs);
-       putname(fn);
-out:
-       return error;
-}
-
-int kernel_execve(const char *filename,
-                 const char *const argv[],
-                 const char *const envp[])
-{
-       struct pt_regs regs;
-       int ret;
-
-       memset(&regs, 0, sizeof(struct pt_regs));
-       ret = do_execve(filename,
-                       (const char __user *const __user *)argv,
-                       (const char __user *const __user *)envp, &regs);
-       if (ret < 0)
-               goto out;
-
-       /*
-        * Save argc to the register structure for userspace.
-        */
-       regs.UCreg_00 = ret;
-
-       /*
-        * We were successful.  We won't be returning to our caller, but
-        * instead to user space by manipulating the kernel stack.
-        */
-       asm("add        r0, %0, %1\n\t"
-               "mov    r1, %2\n\t"
-               "mov    r2, %3\n\t"
-               "mov    r22, #0\n\t"    /* not a syscall */
-               "mov    r23, %0\n\t"    /* thread structure */
-               "b.l    memmove\n\t"    /* copy regs to top of stack */
-               "mov    sp, r0\n\t"     /* reposition stack pointer */
-               "b      ret_to_user"
-               :
-               : "r" (current_thread_info()),
-                 "Ir" (THREAD_START_SP - sizeof(regs)),
-                 "r" (&regs),
-                 "Ir" (sizeof(regs))
-               : "r0", "r1", "r2", "r3", "ip", "lr", "memory");
-
- out:
-       return ret;
-}
-
 /* Note: used by the compat code even in 64-bit Linux. */
 SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
                unsigned long, prot, unsigned long, flags,
index 2eeb9c04cab057b5a2c6f542e251d6762cd6621b..f9b5c10bccee96e8838484aaf6effc39b3c89bd1 100644 (file)
@@ -168,7 +168,7 @@ static inline bool access_error(unsigned int fsr, struct vm_area_struct *vma)
 }
 
 static int __do_pf(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
-               struct task_struct *tsk)
+               unsigned int flags, struct task_struct *tsk)
 {
        struct vm_area_struct *vma;
        int fault;
@@ -194,14 +194,7 @@ good_area:
         * If for any reason at all we couldn't handle the fault, make
         * sure we exit gracefully rather than endlessly redo the fault.
         */
-       fault = handle_mm_fault(mm, vma, addr & PAGE_MASK,
-                           (!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
-       if (unlikely(fault & VM_FAULT_ERROR))
-               return fault;
-       if (fault & VM_FAULT_MAJOR)
-               tsk->maj_flt++;
-       else
-               tsk->min_flt++;
+       fault = handle_mm_fault(mm, vma, addr & PAGE_MASK, flags);
        return fault;
 
 check_stack:
@@ -216,6 +209,8 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
        struct task_struct *tsk;
        struct mm_struct *mm;
        int fault, sig, code;
+       unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE |
+                                ((!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
 
        tsk = current;
        mm = tsk->mm;
@@ -236,6 +231,7 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
                if (!user_mode(regs)
                    && !search_exception_tables(regs->UCreg_pc))
                        goto no_context;
+retry:
                down_read(&mm->mmap_sem);
        } else {
                /*
@@ -251,7 +247,28 @@ static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 #endif
        }
 
-       fault = __do_pf(mm, addr, fsr, tsk);
+       fault = __do_pf(mm, addr, fsr, flags, tsk);
+
+       /* If we need to retry but a fatal signal is pending, handle the
+        * signal first. We do not need to release the mmap_sem because
+        * it would already be released in __lock_page_or_retry in
+        * mm/filemap.c. */
+       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+               return 0;
+
+       if (!(fault & VM_FAULT_ERROR) && (flags & FAULT_FLAG_ALLOW_RETRY)) {
+               if (fault & VM_FAULT_MAJOR)
+                       tsk->maj_flt++;
+               else
+                       tsk->min_flt++;
+               if (fault & VM_FAULT_RETRY) {
+                       /* Clear FAULT_FLAG_ALLOW_RETRY to avoid any risk
+                       * of starvation. */
+                       flags &= ~FAULT_FLAG_ALLOW_RETRY;
+                       goto retry;
+               }
+       }
+
        up_read(&mm->mmap_sem);
 
        /*
index c760e073963ed59004f66ed65aade6355c852da9..e87b0cac14b5e5d735ab21f9f3b163db52349938 100644 (file)
@@ -12,6 +12,8 @@
 #include <asm/setup.h>
 #include <asm/desc.h>
 
+#undef memcpy                  /* Use memcpy from misc.c */
+
 #include "eboot.h"
 
 static efi_system_table_t *sys_table;
index 2a017441b8b2ebc665a24a001f5d635f7dbc9955..8c132a625b94991c179def21973bb8ad3c3a56d5 100644 (file)
@@ -476,6 +476,3 @@ die:
 setup_corrupt:
        .byte   7
        .string "No setup signature found...\n"
-
-       .data
-dummy: .long   0
index dcfde52979c3e63be0d42627cc567cf76c733090..19f16ebaf4fa826216c7858d224365b2fdb74670 100644 (file)
@@ -205,21 +205,14 @@ static inline bool user_64bit_mode(struct pt_regs *regs)
 }
 #endif
 
-/*
- * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
- * when it traps.  The previous stack will be directly underneath the saved
- * registers, and 'sp/ss' won't even have been saved. Thus the '&regs->sp'.
- *
- * This is valid only for kernel mode traps.
- */
-static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
-{
 #ifdef CONFIG_X86_32
-       return (unsigned long)(&regs->sp);
+extern unsigned long kernel_stack_pointer(struct pt_regs *regs);
 #else
+static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
+{
        return regs->sp;
-#endif
 }
+#endif
 
 #define GET_IP(regs) ((regs)->ip)
 #define GET_FP(regs) ((regs)->bp)
index f7e98a2c0d123ae0ebe7f61f1521f7dd7090a335..1b7d1656a042ff5e1886c6fff40bbde1ff3a472d 100644 (file)
@@ -631,6 +631,20 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
                }
        }
 
+       /*
+        * The way access filter has a performance penalty on some workloads.
+        * Disable it on the affected CPUs.
+        */
+       if ((c->x86 == 0x15) &&
+           (c->x86_model >= 0x02) && (c->x86_model < 0x20)) {
+               u64 val;
+
+               if (!rdmsrl_safe(0xc0011021, &val) && !(val & 0x1E)) {
+                       val |= 0x1E;
+                       wrmsrl_safe(0xc0011021, val);
+               }
+       }
+
        cpu_detect_cache_sizes(c);
 
        /* Multi core CPU? */
index 698b6ec12e0f40f9c292b9f84206b38214d9fe7e..1ac581f38dfa2771ba054c980cd9163546e8c9db 100644 (file)
@@ -6,7 +6,7 @@
  *
  *  Written by Jacob Shin - AMD, Inc.
  *
- *  Support: borislav.petkov@amd.com
+ *  Maintained by: Borislav Petkov <bp@alien8.de>
  *
  *  April 2006
  *     - added support for AMD Family 0x10 processors
index 5f88abf07e9ccc2237b27fea29c57b4b59315a64..4f9a3cbfc4a33fb801ab1bf2c822a83e76122897 100644 (file)
@@ -285,34 +285,39 @@ void cmci_clear(void)
        raw_spin_unlock_irqrestore(&cmci_discover_lock, flags);
 }
 
+static long cmci_rediscover_work_func(void *arg)
+{
+       int banks;
+
+       /* Recheck banks in case CPUs don't all have the same */
+       if (cmci_supported(&banks))
+               cmci_discover(banks);
+
+       return 0;
+}
+
 /*
  * After a CPU went down cycle through all the others and rediscover
  * Must run in process context.
  */
 void cmci_rediscover(int dying)
 {
-       int banks;
-       int cpu;
-       cpumask_var_t old;
+       int cpu, banks;
 
        if (!cmci_supported(&banks))
                return;
-       if (!alloc_cpumask_var(&old, GFP_KERNEL))
-               return;
-       cpumask_copy(old, &current->cpus_allowed);
 
        for_each_online_cpu(cpu) {
                if (cpu == dying)
                        continue;
-               if (set_cpus_allowed_ptr(current, cpumask_of(cpu)))
+
+               if (cpu == smp_processor_id()) {
+                       cmci_rediscover_work_func(NULL);
                        continue;
-               /* Recheck banks in case CPUs don't all have the same */
-               if (cmci_supported(&banks))
-                       cmci_discover(banks);
-       }
+               }
 
-       set_cpus_allowed_ptr(current, old);
-       free_cpumask_var(old);
+               work_on_cpu(cpu, cmci_rediscover_work_func, NULL);
+       }
 }
 
 /*
index b51b2c7ee51fcbc3738ed8bd05fb4fd67d9fe1ab..1328fe49a3f14d7a33615e892efca8d110aeb6e6 100644 (file)
@@ -995,8 +995,8 @@ END(interrupt)
         */
        .p2align CONFIG_X86_L1_CACHE_SHIFT
 common_interrupt:
-       ASM_CLAC
        XCPT_FRAME
+       ASM_CLAC
        addq $-0x80,(%rsp)              /* Adjust vector to [-256,-1] range */
        interrupt do_IRQ
        /* 0(%rsp): old_rsp-ARGOFFSET */
@@ -1135,8 +1135,8 @@ END(common_interrupt)
  */
 .macro apicinterrupt num sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        INTR_FRAME
+       ASM_CLAC
        pushq_cfi $~(\num)
 .Lcommon_\sym:
        interrupt \do_sym
@@ -1190,8 +1190,8 @@ apicinterrupt IRQ_WORK_VECTOR \
  */
 .macro zeroentry sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        INTR_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
        subq $ORIG_RAX-R15, %rsp
@@ -1208,8 +1208,8 @@ END(\sym)
 
 .macro paranoidzeroentry sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        INTR_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
        subq $ORIG_RAX-R15, %rsp
@@ -1227,8 +1227,8 @@ END(\sym)
 #define INIT_TSS_IST(x) PER_CPU_VAR(init_tss) + (TSS_ist + ((x) - 1) * 8)
 .macro paranoidzeroentry_ist sym do_sym ist
 ENTRY(\sym)
-       ASM_CLAC
        INTR_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        pushq_cfi $-1           /* ORIG_RAX: no syscall to restart */
        subq $ORIG_RAX-R15, %rsp
@@ -1247,8 +1247,8 @@ END(\sym)
 
 .macro errorentry sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        XCPT_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        subq $ORIG_RAX-R15, %rsp
        CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
@@ -1266,8 +1266,8 @@ END(\sym)
        /* error code is on the stack already */
 .macro paranoiderrorentry sym do_sym
 ENTRY(\sym)
-       ASM_CLAC
        XCPT_FRAME
+       ASM_CLAC
        PARAVIRT_ADJUST_EXCEPTION_FRAME
        subq $ORIG_RAX-R15, %rsp
        CFI_ADJUST_CFA_OFFSET ORIG_RAX-R15
index 7720ff5a9ee292a449ad13a9347e603def50df53..efdec7cd8e01057aeee63c95b16713c4803c7e61 100644 (file)
@@ -8,8 +8,8 @@
  *  Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
  *
  *  Maintainers:
- *  Andreas Herrmann <andreas.herrmann3@amd.com>
- *  Borislav Petkov <borislav.petkov@amd.com>
+ *  Andreas Herrmann <herrmann.der.user@googlemail.com>
+ *  Borislav Petkov <bp@alien8.de>
  *
  *  This driver allows to upgrade microcode on F10h AMD
  *  CPUs and later.
@@ -190,6 +190,7 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
 #define F1XH_MPB_MAX_SIZE 2048
 #define F14H_MPB_MAX_SIZE 1824
 #define F15H_MPB_MAX_SIZE 4096
+#define F16H_MPB_MAX_SIZE 3458
 
        switch (c->x86) {
        case 0x14:
@@ -198,6 +199,9 @@ static unsigned int verify_patch_size(int cpu, u32 patch_size,
        case 0x15:
                max_size = F15H_MPB_MAX_SIZE;
                break;
+       case 0x16:
+               max_size = F16H_MPB_MAX_SIZE;
+               break;
        default:
                max_size = F1XH_MPB_MAX_SIZE;
                break;
index b00b33a183908bdb201aa38266e40ad87d89754d..5e0596b0632e244676c686bb0b338ea1e255473f 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/perf_event.h>
 #include <linux/hw_breakpoint.h>
 #include <linux/rcupdate.h>
+#include <linux/module.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -166,6 +167,35 @@ static inline bool invalid_selector(u16 value)
 
 #define FLAG_MASK              FLAG_MASK_32
 
+/*
+ * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode
+ * when it traps.  The previous stack will be directly underneath the saved
+ * registers, and 'sp/ss' won't even have been saved. Thus the '&regs->sp'.
+ *
+ * Now, if the stack is empty, '&regs->sp' is out of range. In this
+ * case we try to take the previous stack. To always return a non-null
+ * stack pointer we fall back to regs as stack if no previous stack
+ * exists.
+ *
+ * This is valid only for kernel mode traps.
+ */
+unsigned long kernel_stack_pointer(struct pt_regs *regs)
+{
+       unsigned long context = (unsigned long)regs & ~(THREAD_SIZE - 1);
+       unsigned long sp = (unsigned long)&regs->sp;
+       struct thread_info *tinfo;
+
+       if (context == (sp & ~(THREAD_SIZE - 1)))
+               return sp;
+
+       tinfo = (struct thread_info *)context;
+       if (tinfo->previous_esp)
+               return tinfo->previous_esp;
+
+       return (unsigned long)regs;
+}
+EXPORT_SYMBOL_GPL(kernel_stack_pointer);
+
 static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno)
 {
        BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0);
index a10e4601685135f0b5da599508be35eb754816ec..58fc5148882857c014a49b78403a597424c08e64 100644 (file)
@@ -24,6 +24,9 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
 
+       if (!static_cpu_has(X86_FEATURE_XSAVE))
+               return 0;
+
        best = kvm_find_cpuid_entry(vcpu, 1, 0);
        return best && (best->ecx & bit(X86_FEATURE_XSAVE));
 }
index ad6b1dd06f8b967356d4f081f4cde119f2a2bfe8..f85815945fc6d62532c9735747759452cbe7c101 100644 (file)
@@ -6549,19 +6549,22 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
                }
        }
 
-       exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
        /* Exposing INVPCID only when PCID is exposed */
        best = kvm_find_cpuid_entry(vcpu, 0x7, 0);
        if (vmx_invpcid_supported() &&
            best && (best->ebx & bit(X86_FEATURE_INVPCID)) &&
            guest_cpuid_has_pcid(vcpu)) {
+               exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
                exec_control |= SECONDARY_EXEC_ENABLE_INVPCID;
                vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
                             exec_control);
        } else {
-               exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID;
-               vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
-                            exec_control);
+               if (cpu_has_secondary_exec_ctrls()) {
+                       exec_control = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
+                       exec_control &= ~SECONDARY_EXEC_ENABLE_INVPCID;
+                       vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
+                                    exec_control);
+               }
                if (best)
                        best->ebx &= ~bit(X86_FEATURE_INVPCID);
        }
index 224a7e78cb6c40330dfebc943e315c0a7231efa1..4f7641756be2d046cd55e3d59de76e145d3c39ae 100644 (file)
@@ -5781,6 +5781,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        int pending_vec, max_bits, idx;
        struct desc_ptr dt;
 
+       if (!guest_cpuid_has_xsave(vcpu) && (sregs->cr4 & X86_CR4_OSXSAVE))
+               return -EINVAL;
+
        dt.size = sregs->idt.limit;
        dt.address = sregs->idt.base;
        kvm_x86_ops->set_idt(vcpu, &dt);
index 0777f042e4002e695b316c99889b594daebc5448..60f926cd8b0edbf44277a18718dd86cb4a077bd1 100644 (file)
@@ -197,7 +197,7 @@ void flush_tlb_mm_range(struct mm_struct *mm, unsigned long start,
        }
 
        if (end == TLB_FLUSH_ALL || tlb_flushall_shift == -1
-                                       || vmflag == VM_HUGETLB) {
+                                       || vmflag & VM_HUGETLB) {
                local_flush_tlb();
                goto flush_all;
        }
index 41bd2a2d2c50f61a4948f954f296631c8dfd7961..b914e20b5a0033c7cb856c1e82eeea207187eb07 100644 (file)
@@ -115,6 +115,16 @@ static void sata_revid_read(struct sim_dev_reg *reg, u32 *value)
        reg_read(reg, value);
 }
 
+static void reg_noirq_read(struct sim_dev_reg *reg, u32 *value)
+{
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&pci_config_lock, flags);
+       /* force interrupt pin value to 0 */
+       *value = reg->sim_reg.value & 0xfff00ff;
+       raw_spin_unlock_irqrestore(&pci_config_lock, flags);
+}
+
 static struct sim_dev_reg bus1_fixups[] = {
        DEFINE_REG(2, 0, 0x10, (16*MB), reg_init, reg_read, reg_write)
        DEFINE_REG(2, 0, 0x14, (256), reg_init, reg_read, reg_write)
@@ -144,6 +154,7 @@ static struct sim_dev_reg bus1_fixups[] = {
        DEFINE_REG(11, 5, 0x10, (64*KB), reg_init, reg_read, reg_write)
        DEFINE_REG(11, 6, 0x10, (256), reg_init, reg_read, reg_write)
        DEFINE_REG(11, 7, 0x10, (64*KB), reg_init, reg_read, reg_write)
+       DEFINE_REG(11, 7, 0x3c, 256, reg_init, reg_noirq_read, reg_write)
        DEFINE_REG(12, 0, 0x10, (128*KB), reg_init, reg_read, reg_write)
        DEFINE_REG(12, 0, 0x14, (256), reg_init, reg_read, reg_write)
        DEFINE_REG(12, 1, 0x10, (1024), reg_init, reg_read, reg_write)
@@ -161,8 +172,10 @@ static struct sim_dev_reg bus1_fixups[] = {
        DEFINE_REG(16, 0, 0x10, (64*KB), reg_init, reg_read, reg_write)
        DEFINE_REG(16, 0, 0x14, (64*MB), reg_init, reg_read, reg_write)
        DEFINE_REG(16, 0, 0x18, (64*MB), reg_init, reg_read, reg_write)
+       DEFINE_REG(16, 0, 0x3c, 256, reg_init, reg_noirq_read, reg_write)
        DEFINE_REG(17, 0, 0x10, (128*KB), reg_init, reg_read, reg_write)
        DEFINE_REG(18, 0, 0x10, (1*KB), reg_init, reg_read, reg_write)
+       DEFINE_REG(18, 0, 0x3c, 256, reg_init, reg_noirq_read, reg_write)
 };
 
 static void __init init_sim_regs(void)
index 4c61b52191eb293bcaef2cac2380c6114cdaefcf..92525cb8e54c84c0ebe6b2caeacb47f4f8ab299b 100644 (file)
 #include <asm/i8259.h>
 #include <asm/io.h>
 #include <asm/io_apic.h>
+#include <asm/emergency-restart.h>
 
 static int ce4100_i8042_detect(void)
 {
        return 0;
 }
 
+/*
+ * The CE4100 platform has an internal 8051 Microcontroller which is
+ * responsible for signaling to the external Power Management Unit the
+ * intention to reset, reboot or power off the system. This 8051 device has
+ * its command register mapped at I/O port 0xcf9 and the value 0x4 is used
+ * to power off the system.
+ */
+static void ce4100_power_off(void)
+{
+       outb(0x4, 0xcf9);
+}
+
 #ifdef CONFIG_SERIAL_8250
 
 static unsigned int mem_serial_in(struct uart_port *p, int offset)
@@ -139,8 +152,19 @@ void __init x86_ce4100_early_setup(void)
        x86_init.mpparse.find_smp_config = x86_init_noop;
        x86_init.pci.init = ce4100_pci_init;
 
+       /*
+        * By default, the reboot method is ACPI which is supported by the
+        * CE4100 bootloader CEFDK using FADT.ResetReg Address and ResetValue
+        * the bootloader will however issue a system power off instead of
+        * reboot. By using BOOT_KBD we ensure proper system reboot as
+        * expected.
+        */
+       reboot_type = BOOT_KBD;
+
 #ifdef CONFIG_X86_IO_APIC
        x86_init.pci.init_irq = sdv_pci_init;
        x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
 #endif
+
+       pm_power_off = ce4100_power_off;
 }
index 8b6dc5bd4dd061336172b144ae8c09da6bbc56f8..f71eac35c1b942005f3973fd9c919091b9b08bbd 100644 (file)
@@ -52,11 +52,17 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
                           rq_end_io_fn *done)
 {
        int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
+       bool is_pm_resume;
 
        WARN_ON(irqs_disabled());
 
        rq->rq_disk = bd_disk;
        rq->end_io = done;
+       /*
+        * need to check this before __blk_run_queue(), because rq can
+        * be freed before that returns.
+        */
+       is_pm_resume = rq->cmd_type == REQ_TYPE_PM_RESUME;
 
        spin_lock_irq(q->queue_lock);
 
@@ -71,7 +77,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
        __elv_add_request(q, rq, where);
        __blk_run_queue(q);
        /* the queue is stopped so it won't be run */
-       if (rq->cmd_type == REQ_TYPE_PM_RESUME)
+       if (is_pm_resume)
                q->request_fn(q);
        spin_unlock_irq(q->queue_lock);
 }
index b1ae48054dc5773eab42917d5e9d10f9764602ae..b7078afddb74fe91c403642cf4679beec06c0ef9 100644 (file)
@@ -238,7 +238,7 @@ static int __devexit ahci_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ahci_suspend(struct device *dev)
 {
        struct ahci_platform_data *pdata = dev_get_platdata(dev);
index fd9ecf74e631afc800e56927069d97bd61774862..5b0ba3f20edcfd4603538ce7505d69dd93f8bb29 100644 (file)
@@ -1105,10 +1105,15 @@ static int ata_acpi_bind_device(struct ata_port *ap, struct scsi_device *sdev,
        struct acpi_device *acpi_dev;
        struct acpi_device_power_state *states;
 
-       if (ap->flags & ATA_FLAG_ACPI_SATA)
-               ata_dev = &ap->link.device[sdev->channel];
-       else
+       if (ap->flags & ATA_FLAG_ACPI_SATA) {
+               if (!sata_pmp_attached(ap))
+                       ata_dev = &ap->link.device[sdev->id];
+               else
+                       ata_dev = &ap->pmp_link[sdev->channel].device[sdev->id];
+       }
+       else {
                ata_dev = &ap->link.device[sdev->id];
+       }
 
        *handle = ata_dev_acpi_handle(ata_dev);
 
index 3cc7096cfda758e9b3ffd514aaf6e70928ec7f8d..f46fbd3bd3fb6b4456032a0255bad894e8fc9cdb 100644 (file)
@@ -2942,6 +2942,10 @@ const struct ata_timing *ata_timing_find_mode(u8 xfer_mode)
 
        if (xfer_mode == t->mode)
                return t;
+
+       WARN_ONCE(true, "%s: unable to find timing for xfer_mode 0x%x\n",
+                       __func__, xfer_mode);
+
        return NULL;
 }
 
index e3bda074fa12f59381f9e8911338c49a88611f36..a6df6a351d6e4ce263f717ad52bf1ebb72a1aae0 100644 (file)
@@ -1052,6 +1052,8 @@ static void ata_scsi_sdev_config(struct scsi_device *sdev)
 {
        sdev->use_10_for_rw = 1;
        sdev->use_10_for_ms = 1;
+       sdev->no_report_opcodes = 1;
+       sdev->no_write_same = 1;
 
        /* Schedule policy is determined by ->qc_defer() callback and
         * it needs to see every deferred qc.  Set dev_blocked to 1 to
index 26201ebef3ca652a16c12c6719eae2127ed212ad..371fd2c698b70ce1b283672c0c2472f8ce6ac263 100644 (file)
@@ -317,6 +317,12 @@ static int cf_init(struct arasan_cf_dev *acdev)
                return ret;
        }
 
+       ret = clk_set_rate(acdev->clk, 166000000);
+       if (ret) {
+               dev_warn(acdev->host->dev, "clock set rate failed");
+               return ret;
+       }
+
        spin_lock_irqsave(&acdev->host->lock, flags);
        /* configure CF interface clock */
        writel((pdata->cf_if_clk <= CF_IF_CLK_200M) ? pdata->cf_if_clk :
@@ -908,7 +914,7 @@ static int __devexit arasan_cf_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int arasan_cf_suspend(struct device *dev)
 {
        struct ata_host *host = dev_get_drvdata(dev);
index 0d7c4c2cd26fed3d81ecf2bfe78a1a4939588da9..400bf1c3e982eac392652d086358858ef903ca82 100644 (file)
@@ -260,7 +260,7 @@ static const struct of_device_id ahci_of_match[] = {
 };
 MODULE_DEVICE_TABLE(of, ahci_of_match);
 
-static int __init ahci_highbank_probe(struct platform_device *pdev)
+static int __devinit ahci_highbank_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct ahci_host_priv *hpriv;
@@ -378,7 +378,7 @@ static int __devexit ahci_highbank_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int ahci_highbank_suspend(struct device *dev)
 {
        struct ata_host *host = dev_get_drvdata(dev);
index 44a4256533e1bd4e8aef978abdfc7e34361ad053..08608de87e4e6a971e9a36ef701f343a6982d5b7 100644 (file)
@@ -142,6 +142,39 @@ static int k2_sata_scr_write(struct ata_link *link,
        return 0;
 }
 
+static int k2_sata_softreset(struct ata_link *link,
+                            unsigned int *class, unsigned long deadline)
+{
+       u8 dmactl;
+       void __iomem *mmio = link->ap->ioaddr.bmdma_addr;
+
+       dmactl = readb(mmio + ATA_DMA_CMD);
+
+       /* Clear the start bit */
+       if (dmactl & ATA_DMA_START) {
+               dmactl &= ~ATA_DMA_START;
+               writeb(dmactl, mmio + ATA_DMA_CMD);
+       }
+
+       return ata_sff_softreset(link, class, deadline);
+}
+
+static int k2_sata_hardreset(struct ata_link *link,
+                            unsigned int *class, unsigned long deadline)
+{
+       u8 dmactl;
+       void __iomem *mmio = link->ap->ioaddr.bmdma_addr;
+
+       dmactl = readb(mmio + ATA_DMA_CMD);
+
+       /* Clear the start bit */
+       if (dmactl & ATA_DMA_START) {
+               dmactl &= ~ATA_DMA_START;
+               writeb(dmactl, mmio + ATA_DMA_CMD);
+       }
+
+       return sata_sff_hardreset(link, class, deadline);
+}
 
 static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf)
 {
@@ -346,6 +379,8 @@ static struct scsi_host_template k2_sata_sht = {
 
 static struct ata_port_operations k2_sata_ops = {
        .inherits               = &ata_bmdma_port_ops,
+       .softreset              = k2_sata_softreset,
+       .hardreset              = k2_sata_hardreset,
        .sff_tf_load            = k2_sata_tf_load,
        .sff_tf_read            = k2_sata_tf_read,
        .sff_check_status       = k2_stat_check_status,
index 74a67e0019a2d246820ccb2858399bca193ff789..fbbd4ed2edf288318f8d165760c91ee420f1812c 100644 (file)
@@ -451,7 +451,7 @@ int dev_pm_qos_add_ancestor_request(struct device *dev,
        if (ancestor)
                error = dev_pm_qos_add_request(ancestor, req, value);
 
-       if (error)
+       if (error < 0)
                req->dev = NULL;
 
        return error;
index 3804a0af3ef192c441643eee425d06f747b86d97..9fe4f1865558abce9ccd7ebf1ee10a56284caf61 100644 (file)
@@ -935,7 +935,7 @@ aoe_end_request(struct aoedev *d, struct request *rq, int fastfail)
 
        /* cf. http://lkml.org/lkml/2006/10/31/28 */
        if (!fastfail)
-               q->request_fn(q);
+               __blk_run_queue(q);
 }
 
 static void
index 1c49d7173966ae52754cd75776ff50fa48f30d60..2ddd64a9ffdee43429653806be3262a80c372240 100644 (file)
@@ -4330,6 +4330,7 @@ out_unreg_region:
 out_unreg_blkdev:
        unregister_blkdev(FLOPPY_MAJOR, "fd");
 out_put_disk:
+       destroy_workqueue(floppy_wq);
        for (drive = 0; drive < N_DRIVE; drive++) {
                if (!disks[drive])
                        break;
@@ -4340,7 +4341,6 @@ out_put_disk:
                }
                put_disk(disks[drive]);
        }
-       destroy_workqueue(floppy_wq);
        return err;
 }
 
@@ -4555,6 +4555,8 @@ static void __exit floppy_module_exit(void)
        unregister_blkdev(FLOPPY_MAJOR, "fd");
        platform_driver_unregister(&floppy_driver);
 
+       destroy_workqueue(floppy_wq);
+
        for (drive = 0; drive < N_DRIVE; drive++) {
                del_timer_sync(&motor_off_timer[drive]);
 
@@ -4578,7 +4580,6 @@ static void __exit floppy_module_exit(void)
 
        cancel_delayed_work_sync(&fd_timeout);
        cancel_delayed_work_sync(&fd_timer);
-       destroy_workqueue(floppy_wq);
 
        if (atomic_read(&usage_count))
                floppy_release_irq_and_dma();
index adc6f36564cf3c9f214ca37c9b3cf8faffbe6cf8..9694dd99bbbc7253af1c3626823899f985b1afc2 100644 (file)
@@ -559,7 +559,7 @@ static void mtip_timeout_function(unsigned long int data)
        struct mtip_cmd *command;
        int tag, cmdto_cnt = 0;
        unsigned int bit, group;
-       unsigned int num_command_slots = port->dd->slot_groups * 32;
+       unsigned int num_command_slots;
        unsigned long to, tagaccum[SLOTBITS_IN_LONGS];
 
        if (unlikely(!port))
@@ -572,6 +572,7 @@ static void mtip_timeout_function(unsigned long int data)
        }
        /* clear the tag accumulator */
        memset(tagaccum, 0, SLOTBITS_IN_LONGS * sizeof(long));
+       num_command_slots = port->dd->slot_groups * 32;
 
        for (tag = 0; tag < num_command_slots; tag++) {
                /*
@@ -2218,8 +2219,8 @@ static int exec_drive_taskfile(struct driver_data *dd,
                fis.device);
 
        /* check for erase mode support during secure erase.*/
-       if ((fis.command == ATA_CMD_SEC_ERASE_UNIT)
-                                       && (outbuf[0] & MTIP_SEC_ERASE_MODE)) {
+       if ((fis.command == ATA_CMD_SEC_ERASE_UNIT) && outbuf &&
+                                       (outbuf[0] & MTIP_SEC_ERASE_MODE)) {
                erasemode = 1;
        }
 
@@ -2439,7 +2440,7 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd,
  * return value
  *     None
  */
-static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
+static void mtip_hw_submit_io(struct driver_data *dd, sector_t sector,
                              int nsect, int nents, int tag, void *callback,
                              void *data, int dir)
 {
@@ -2447,6 +2448,7 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
        struct mtip_port *port = dd->port;
        struct mtip_cmd *command = &port->commands[tag];
        int dma_dir = (dir == READ) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+       u64 start = sector;
 
        /* Map the scatter list for DMA access */
        nents = dma_map_sg(&dd->pdev->dev, command->sg, nents, dma_dir);
@@ -2465,8 +2467,12 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start,
        fis->opts        = 1 << 7;
        fis->command     =
                (dir == READ ? ATA_CMD_FPDMA_READ : ATA_CMD_FPDMA_WRITE);
-       *((unsigned int *) &fis->lba_low) = (start & 0xFFFFFF);
-       *((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xFFFFFF);
+       fis->lba_low     = start & 0xFF;
+       fis->lba_mid     = (start >> 8) & 0xFF;
+       fis->lba_hi      = (start >> 16) & 0xFF;
+       fis->lba_low_ex  = (start >> 24) & 0xFF;
+       fis->lba_mid_ex  = (start >> 32) & 0xFF;
+       fis->lba_hi_ex   = (start >> 40) & 0xFF;
        fis->device      = 1 << 6;
        fis->features    = nsect & 0xFF;
        fis->features_ex = (nsect >> 8) & 0xFF;
index 5f4a917bd8bbcfe88283b3509e365a0faefbb3b5..b1742640556a782cee77701c78c4ddf7e961591a 100644 (file)
@@ -34,7 +34,7 @@
 #define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET  0x48
 
 /* check for erase mode support during secure erase */
-#define MTIP_SEC_ERASE_MODE     0x3
+#define MTIP_SEC_ERASE_MODE     0x2
 
 /* # of times to retry timed out/failed IOs */
 #define MTIP_MAX_RETRIES       2
@@ -155,14 +155,14 @@ enum {
        MTIP_DDF_REBUILD_FAILED_BIT = 8,
 };
 
-__packed struct smart_attr{
+struct smart_attr {
        u8 attr_id;
        u16 flags;
        u8 cur;
        u8 worst;
        u32 data;
        u8 res[3];
-};
+} __packed;
 
 /* Register Frame Information Structure (FIS), host to device. */
 struct host_to_dev_fis {
index fc2de5528dcc94eb65537baa17b78048a5002827..b00000e8aef6f9cb06955049d3fa4faaba25e38b 100644 (file)
@@ -67,6 +67,7 @@ static struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x13d3, 0x3304) },
        { USB_DEVICE(0x0930, 0x0215) },
        { USB_DEVICE(0x0489, 0xE03D) },
+       { USB_DEVICE(0x0489, 0xE027) },
 
        /* Atheros AR9285 Malbec with sflash firmware */
        { USB_DEVICE(0x03F0, 0x311D) },
index debda27df9b0452e3d7f3e5d2b06855c1b7af1f4..ee82f2fb65f0ab2c76135416ac8547f1d9c1fa3c 100644 (file)
@@ -124,6 +124,7 @@ static struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
        { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
        { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
+       { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
 
        /* Atheros AR9285 Malbec with sflash firmware */
        { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
index ff63560b8467962ae781d5c3d6b64c122129a390..0c48b0e05ed6e7165a221399822e894e09c9fa18 100644 (file)
 #include <linux/pm_runtime.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#include <linux/platform_data/omap_ocp2scp.h>
+
+/**
+ * _count_resources - count for the number of resources
+ * @res: struct resource *
+ *
+ * Count and return the number of resources populated for the device that is
+ * connected to ocp2scp.
+ */
+static unsigned _count_resources(struct resource *res)
+{
+       int cnt = 0;
+
+       while (res->start != res->end) {
+               cnt++;
+               res++;
+       }
+
+       return cnt;
+}
 
 static int ocp2scp_remove_devices(struct device *dev, void *c)
 {
@@ -34,20 +54,62 @@ static int ocp2scp_remove_devices(struct device *dev, void *c)
 
 static int __devinit omap_ocp2scp_probe(struct platform_device *pdev)
 {
-       int                     ret;
-       struct device_node      *np = pdev->dev.of_node;
+       int ret;
+       unsigned res_cnt, i;
+       struct device_node *np = pdev->dev.of_node;
+       struct platform_device *pdev_child;
+       struct omap_ocp2scp_platform_data *pdata = pdev->dev.platform_data;
+       struct omap_ocp2scp_dev *dev;
 
        if (np) {
                ret = of_platform_populate(np, NULL, NULL, &pdev->dev);
                if (ret) {
-                       dev_err(&pdev->dev, "failed to add resources for ocp2scp child\n");
+                       dev_err(&pdev->dev,
+                           "failed to add resources for ocp2scp child\n");
                        goto err0;
                }
+       } else if (pdata) {
+               for (i = 0, dev = *pdata->devices; i < pdata->dev_cnt; i++,
+                   dev++) {
+                       res_cnt = _count_resources(dev->res);
+
+                       pdev_child = platform_device_alloc(dev->drv_name,
+                           PLATFORM_DEVID_AUTO);
+                       if (!pdev_child) {
+                               dev_err(&pdev->dev,
+                                 "failed to allocate mem for ocp2scp child\n");
+                               goto err0;
+                       }
+
+                       ret = platform_device_add_resources(pdev_child,
+                           dev->res, res_cnt);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                "failed to add resources for ocp2scp child\n");
+                               goto err1;
+                       }
+
+                       pdev_child->dev.parent  = &pdev->dev;
+
+                       ret = platform_device_add(pdev_child);
+                       if (ret) {
+                               dev_err(&pdev->dev,
+                                  "failed to register ocp2scp child device\n");
+                               goto err1;
+                       }
+               }
+       } else {
+               dev_err(&pdev->dev, "OCP2SCP initialized without plat data\n");
+               return -EINVAL;
        }
+
        pm_runtime_enable(&pdev->dev);
 
        return 0;
 
+err1:
+       platform_device_put(pdev_child);
+
 err0:
        device_for_each_child(&pdev->dev, NULL, ocp2scp_remove_devices);
 
index ca4a25ed844c379315c2834dcd239c4b9d50940d..e2c17d187d98b7bb09fe4252258641bbd424a1c5 100644 (file)
@@ -40,7 +40,7 @@ void u8500_clk_init(void)
                                CLK_IS_ROOT|CLK_IGNORE_UNUSED,
                                32768);
        clk_register_clkdev(clk, "clk32k", NULL);
-       clk_register_clkdev(clk, NULL, "rtc-pl031");
+       clk_register_clkdev(clk, "apb_pclk", "rtc-pl031");
 
        /* PRCMU clocks */
        fw_version = prcmu_get_fw_version();
@@ -228,10 +228,17 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", U8500_CLKRST1_BASE,
                                BIT(2), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.1");
+
        clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", U8500_CLKRST1_BASE,
                                BIT(3), 0);
+       clk_register_clkdev(clk, "apb_pclk", "msp0");
+       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.0");
+
        clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", U8500_CLKRST1_BASE,
                                BIT(4), 0);
+       clk_register_clkdev(clk, "apb_pclk", "msp1");
+       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.1");
 
        clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", U8500_CLKRST1_BASE,
                                BIT(5), 0);
@@ -239,6 +246,7 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", U8500_CLKRST1_BASE,
                                BIT(6), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.2");
 
        clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", U8500_CLKRST1_BASE,
                                BIT(7), 0);
@@ -246,6 +254,7 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", U8500_CLKRST1_BASE,
                                BIT(8), 0);
+       clk_register_clkdev(clk, "apb_pclk", "slimbus0");
 
        clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", U8500_CLKRST1_BASE,
                                BIT(9), 0);
@@ -255,11 +264,16 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", U8500_CLKRST1_BASE,
                                BIT(10), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.4");
+
        clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", U8500_CLKRST1_BASE,
                                BIT(11), 0);
+       clk_register_clkdev(clk, "apb_pclk", "msp3");
+       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.3");
 
        clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", U8500_CLKRST2_BASE,
                                BIT(0), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.3");
 
        clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", U8500_CLKRST2_BASE,
                                BIT(1), 0);
@@ -279,12 +293,13 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", U8500_CLKRST2_BASE,
                                BIT(5), 0);
+       clk_register_clkdev(clk, "apb_pclk", "msp2");
+       clk_register_clkdev(clk, "apb_pclk", "ux500-msp-i2s.2");
 
        clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", U8500_CLKRST2_BASE,
                                BIT(6), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi1");
 
-
        clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", U8500_CLKRST2_BASE,
                                BIT(7), 0);
        clk_register_clkdev(clk, "apb_pclk", "sdi3");
@@ -316,10 +331,15 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", U8500_CLKRST3_BASE,
                                BIT(1), 0);
+       clk_register_clkdev(clk, "apb_pclk", "ssp0");
+
        clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", U8500_CLKRST3_BASE,
                                BIT(2), 0);
+       clk_register_clkdev(clk, "apb_pclk", "ssp1");
+
        clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", U8500_CLKRST3_BASE,
                                BIT(3), 0);
+       clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.0");
 
        clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", U8500_CLKRST3_BASE,
                                BIT(4), 0);
@@ -401,10 +421,17 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk",
                        U8500_CLKRST1_BASE, BIT(2), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.1");
+
        clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk",
                        U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "msp0");
+       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.0");
+
        clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk",
                        U8500_CLKRST1_BASE, BIT(4), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "msp1");
+       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.1");
 
        clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmcclk",
                        U8500_CLKRST1_BASE, BIT(5), CLK_SET_RATE_GATE);
@@ -412,17 +439,25 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk",
                        U8500_CLKRST1_BASE, BIT(6), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.2");
+
        clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk",
-                       U8500_CLKRST1_BASE, BIT(3), CLK_SET_RATE_GATE);
-       /* FIXME: Redefinition of BIT(3). */
+                       U8500_CLKRST1_BASE, BIT(8), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "slimbus0");
+
        clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk",
                        U8500_CLKRST1_BASE, BIT(9), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.4");
+
        clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk",
                        U8500_CLKRST1_BASE, BIT(10), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "msp3");
+       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.3");
 
        /* Periph2 */
        clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk",
                        U8500_CLKRST2_BASE, BIT(0), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.3");
 
        clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmcclk",
                        U8500_CLKRST2_BASE, BIT(2), CLK_SET_RATE_GATE);
@@ -430,6 +465,8 @@ void u8500_clk_init(void)
 
        clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk",
                        U8500_CLKRST2_BASE, BIT(3), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "msp2");
+       clk_register_clkdev(clk, NULL, "ux500-msp-i2s.2");
 
        clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmcclk",
                        U8500_CLKRST2_BASE, BIT(4), CLK_SET_RATE_GATE);
@@ -450,10 +487,15 @@ void u8500_clk_init(void)
        /* Periph3 */
        clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk",
                        U8500_CLKRST3_BASE, BIT(1), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "ssp0");
+
        clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk",
                        U8500_CLKRST3_BASE, BIT(2), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "ssp1");
+
        clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk",
                        U8500_CLKRST3_BASE, BIT(3), CLK_SET_RATE_GATE);
+       clk_register_clkdev(clk, NULL, "nmk-i2c.0");
 
        clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmcclk",
                        U8500_CLKRST3_BASE, BIT(4), CLK_SET_RATE_GATE);
index 8d4804732bacb77be17f07465e48f24ea513ab0c..8c4139647efc06acf50528a8d66f1e09995cc4cc 100644 (file)
@@ -33,7 +33,7 @@
  *             detection. The mods to Rev F required more family
  *             information detection.
  *
- *     Changes/Fixes by Borislav Petkov <borislav.petkov@amd.com>:
+ *     Changes/Fixes by Borislav Petkov <bp@alien8.de>:
  *             - misc fixes and code cleanups
  *
  * This module is based on the following documents
index 6c86f6e545587202d3a9f729457ef38314490f70..351945fa2ecdca3f59a691db38206a0f13795797 100644 (file)
@@ -5,7 +5,7 @@
  *
  * 2007 (c) MontaVista Software, Inc.
  * 2010 (c) Advanced Micro Devices Inc.
- *         Borislav Petkov <borislav.petkov@amd.com>
+ *         Borislav Petkov <bp@alien8.de>
  *
  * This file is licensed under the terms of the GNU General Public
  * License version 2. This program is licensed "as is" without any
index 66b5151c10807083e1e724cb58cc384cdde2f11c..2ae78f20cc28f3850cc26a9156927c7b4e8b085e 100644 (file)
@@ -6,7 +6,7 @@
  * This file may be distributed under the terms of the GNU General Public
  * License version 2.
  *
- * Copyright (c) 2010:  Borislav Petkov <borislav.petkov@amd.com>
+ * Copyright (c) 2010:  Borislav Petkov <bp@alien8.de>
  *                     Advanced Micro Devices Inc.
  */
 
@@ -168,6 +168,6 @@ module_init(edac_init_mce_inject);
 module_exit(edac_exit_mce_inject);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Borislav Petkov <borislav.petkov@amd.com>");
+MODULE_AUTHOR("Borislav Petkov <bp@alien8.de>");
 MODULE_AUTHOR("AMD Inc.");
 MODULE_DESCRIPTION("MCE injection facility for testing MCE decoding");
index 1162d6b3bf8561d6ed1cfe399643dff6deb4027b..bb1b392f5cdacd1194e9af1772469c834e4192dd 100644 (file)
@@ -1546,6 +1546,8 @@ static int sbp2_scsi_slave_configure(struct scsi_device *sdev)
        struct sbp2_logical_unit *lu = sdev->hostdata;
 
        sdev->use_10_for_rw = 1;
+       sdev->no_report_opcodes = 1;
+       sdev->no_write_same = 1;
 
        if (sbp2_param_exclusive_login)
                sdev->manage_start_stop = 1;
index f11d8e3b4041b780c8c9f9ec154c3f0878025ec6..47150f5ded04ea4df13c14434fc3fa553141abaf 100644 (file)
@@ -466,7 +466,7 @@ config GPIO_ADP5588_IRQ
 
 config GPIO_ADNP
        tristate "Avionic Design N-bit GPIO expander"
-       depends on I2C && OF
+       depends on I2C && OF_GPIO
        help
          This option enables support for N GPIOs found on Avionic Design
          I2C GPIO expanders. The register space will be extended by powers
index 0f425189de11b3b5b8003a9c9abb330d9debd116..ce1c847600764602f568994f08167b8fc044dd9a 100644 (file)
@@ -77,7 +77,7 @@ struct mcp23s08_driver_data {
 
 /*----------------------------------------------------------------------*/
 
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
 
 static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg)
 {
@@ -399,7 +399,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
                break;
 #endif /* CONFIG_SPI_MASTER */
 
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
        case MCP_TYPE_008:
                mcp->ops = &mcp23008_ops;
                mcp->chip.ngpio = 8;
@@ -473,7 +473,7 @@ fail:
 
 /*----------------------------------------------------------------------*/
 
-#ifdef CONFIG_I2C
+#if IS_ENABLED(CONFIG_I2C)
 
 static int __devinit mcp230xx_probe(struct i2c_client *client,
                                    const struct i2c_device_id *id)
index cf7afb9eb61ab02c4060532dbdd39e2c2c6e9561..be65c0451ad556e174b961f3542cc8d7b40e201c 100644 (file)
@@ -92,6 +92,11 @@ static inline void __iomem *mvebu_gpioreg_out(struct mvebu_gpio_chip *mvchip)
        return mvchip->membase + GPIO_OUT_OFF;
 }
 
+static inline void __iomem *mvebu_gpioreg_blink(struct mvebu_gpio_chip *mvchip)
+{
+       return mvchip->membase + GPIO_BLINK_EN_OFF;
+}
+
 static inline void __iomem *mvebu_gpioreg_io_conf(struct mvebu_gpio_chip *mvchip)
 {
        return mvchip->membase + GPIO_IO_CONF_OFF;
@@ -206,6 +211,23 @@ static int mvebu_gpio_get(struct gpio_chip *chip, unsigned pin)
        return (u >> pin) & 1;
 }
 
+static void mvebu_gpio_blink(struct gpio_chip *chip, unsigned pin, int value)
+{
+       struct mvebu_gpio_chip *mvchip =
+               container_of(chip, struct mvebu_gpio_chip, chip);
+       unsigned long flags;
+       u32 u;
+
+       spin_lock_irqsave(&mvchip->lock, flags);
+       u = readl_relaxed(mvebu_gpioreg_blink(mvchip));
+       if (value)
+               u |= 1 << pin;
+       else
+               u &= ~(1 << pin);
+       writel_relaxed(u, mvebu_gpioreg_blink(mvchip));
+       spin_unlock_irqrestore(&mvchip->lock, flags);
+}
+
 static int mvebu_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
 {
        struct mvebu_gpio_chip *mvchip =
@@ -244,6 +266,7 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
        if (ret)
                return ret;
 
+       mvebu_gpio_blink(chip, pin, 0);
        mvebu_gpio_set(chip, pin, value);
 
        spin_lock_irqsave(&mvchip->lock, flags);
index b726b478a4f5db604b6804ad679f7a887168705c..6345878ae1e73e260a9a3fdfcaaf760e6ec6e2c1 100644 (file)
@@ -143,7 +143,7 @@ static void intel_crt_dpms(struct drm_connector *connector, int mode)
        int old_dpms;
 
        /* PCH platforms and VLV only support on/off. */
-       if (INTEL_INFO(dev)->gen < 5 && mode != DRM_MODE_DPMS_ON)
+       if (INTEL_INFO(dev)->gen >= 5 && mode != DRM_MODE_DPMS_ON)
                mode = DRM_MODE_DPMS_OFF;
 
        if (mode == connector->dpms)
index 461a637f1ef7d96a21ced8cd31ffd1536a7257a2..4154bcd7a0708b957d4b176607662933ac49fc0d 100644 (file)
@@ -3841,6 +3841,17 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc,
                        }
                }
 
+               if (intel_encoder->type == INTEL_OUTPUT_EDP) {
+                       /* Use VBT settings if we have an eDP panel */
+                       unsigned int edp_bpc = dev_priv->edp.bpp / 3;
+
+                       if (edp_bpc < display_bpc) {
+                               DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc);
+                               display_bpc = edp_bpc;
+                       }
+                       continue;
+               }
+
                /*
                 * HDMI is either 12 or 8, so if the display lets 10bpc sneak
                 * through, clamp it down.  (Note: >12bpc will be caught below.)
index 79d308da29ff8e67cc064b94a31500c0d614a0ad..c600fb06e25e6a4798cd7f7f5841593025d3f484 100644 (file)
@@ -2382,6 +2382,18 @@ intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, uint16_t flags)
        return true;
 }
 
+static void intel_sdvo_output_cleanup(struct intel_sdvo *intel_sdvo)
+{
+       struct drm_device *dev = intel_sdvo->base.base.dev;
+       struct drm_connector *connector, *tmp;
+
+       list_for_each_entry_safe(connector, tmp,
+                                &dev->mode_config.connector_list, head) {
+               if (intel_attached_encoder(connector) == &intel_sdvo->base)
+                       intel_sdvo_destroy(connector);
+       }
+}
+
 static bool intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,
                                          struct intel_sdvo_connector *intel_sdvo_connector,
                                          int type)
@@ -2705,7 +2717,8 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
                                    intel_sdvo->caps.output_flags) != true) {
                DRM_DEBUG_KMS("SDVO output failed to setup on %s\n",
                              SDVO_NAME(intel_sdvo));
-               goto err;
+               /* Output_setup can leave behind connectors! */
+               goto err_output;
        }
 
        /* Only enable the hotplug irq if we need it, to work around noisy
@@ -2718,12 +2731,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
 
        /* Set the input timing to the screen. Assume always input 0. */
        if (!intel_sdvo_set_target_input(intel_sdvo))
-               goto err;
+               goto err_output;
 
        if (!intel_sdvo_get_input_pixel_clock_range(intel_sdvo,
                                                    &intel_sdvo->pixel_clock_min,
                                                    &intel_sdvo->pixel_clock_max))
-               goto err;
+               goto err_output;
 
        DRM_DEBUG_KMS("%s device VID/DID: %02X:%02X.%02X, "
                        "clock range %dMHz - %dMHz, "
@@ -2743,6 +2756,9 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
                        (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
        return true;
 
+err_output:
+       intel_sdvo_output_cleanup(intel_sdvo);
+
 err:
        drm_encoder_cleanup(&intel_encoder->base);
        i2c_del_adapter(&intel_sdvo->ddc);
index 05a909a17ceee67590195f0e9c60fd4a10857ed1..15b182c84ce8b74b55f0cb1073c452a410329f6e 100644 (file)
@@ -49,13 +49,7 @@ nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
                if (chan->vblank.crtc != crtc)
                        continue;
 
-               if (nv_device(priv)->chipset == 0x50) {
-                       nv_wr32(priv, 0x001704, chan->vblank.channel);
-                       nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
-                       bar->flush(bar);
-                       nv_wr32(priv, 0x001570, chan->vblank.offset);
-                       nv_wr32(priv, 0x001574, chan->vblank.value);
-               } else {
+               if (nv_device(priv)->chipset >= 0xc0) {
                        nv_wr32(priv, 0x001718, 0x80000000 | chan->vblank.channel);
                        bar->flush(bar);
                        nv_wr32(priv, 0x06000c,
@@ -63,6 +57,17 @@ nv50_disp_intr_vblank(struct nv50_disp_priv *priv, int crtc)
                        nv_wr32(priv, 0x060010,
                                lower_32_bits(chan->vblank.offset));
                        nv_wr32(priv, 0x060014, chan->vblank.value);
+               } else {
+                       nv_wr32(priv, 0x001704, chan->vblank.channel);
+                       nv_wr32(priv, 0x001710, 0x80000000 | chan->vblank.ctxdma);
+                       bar->flush(bar);
+                       if (nv_device(priv)->chipset == 0x50) {
+                               nv_wr32(priv, 0x001570, chan->vblank.offset);
+                               nv_wr32(priv, 0x001574, chan->vblank.value);
+                       } else {
+                               nv_wr32(priv, 0x060010, chan->vblank.offset);
+                               nv_wr32(priv, 0x060014, chan->vblank.value);
+                       }
                }
 
                list_del(&chan->vblank.head);
index e45035efb8ca084c37785ffd4a0ca789523d4a2b..7bbb1e1b7a8d1ebbeeb275dd38e27caaa7a1400c 100644 (file)
@@ -669,21 +669,27 @@ nv40_grctx_fill(struct nouveau_device *device, struct nouveau_gpuobj *mem)
                           });
 }
 
-void
+int
 nv40_grctx_init(struct nouveau_device *device, u32 *size)
 {
-       u32 ctxprog[256], i;
+       u32 *ctxprog = kmalloc(256 * 4, GFP_KERNEL), i;
        struct nouveau_grctx ctx = {
                .device = device,
                .mode = NOUVEAU_GRCTX_PROG,
                .data = ctxprog,
-               .ctxprog_max = ARRAY_SIZE(ctxprog)
+               .ctxprog_max = 256,
        };
 
+       if (!ctxprog)
+               return -ENOMEM;
+
        nv40_grctx_generate(&ctx);
 
        nv_wr32(device, 0x400324, 0);
        for (i = 0; i < ctx.ctxprog_len; i++)
                nv_wr32(device, 0x400328, ctxprog[i]);
        *size = ctx.ctxvals_pos * 4;
+
+       kfree(ctxprog);
+       return 0;
 }
index 425001204a89b6133648d6752fb362159fca4cef..cc6574eeb80e6459166224185a5bd81ce41e9aa4 100644 (file)
@@ -346,7 +346,9 @@ nv40_graph_init(struct nouveau_object *object)
                return ret;
 
        /* generate and upload context program */
-       nv40_grctx_init(nv_device(priv), &priv->size);
+       ret = nv40_grctx_init(nv_device(priv), &priv->size);
+       if (ret)
+               return ret;
 
        /* No context present currently */
        nv_wr32(priv, NV40_PGRAPH_CTXCTL_CUR, 0x00000000);
index d2ac975afc2e8f46feff64c6be4c16e04faf73b3..7da35a4e7970d1684433f3fd036c60492a5ddb0d 100644 (file)
@@ -15,7 +15,7 @@ nv44_graph_class(void *priv)
        return !(0x0baf & (1 << (device->chipset & 0x0f)));
 }
 
-void nv40_grctx_init(struct nouveau_device *, u32 *size);
+int  nv40_grctx_init(struct nouveau_device *, u32 *size);
 void nv40_grctx_fill(struct nouveau_device *, struct nouveau_gpuobj *);
 
 #endif
index 818feabbf4a0969f090f897852fe4476a422b1b6..486f1a9217fd6cd51dc2c5530d455eaa155c86b4 100644 (file)
@@ -175,14 +175,18 @@ nv_mo32(void *obj, u32 addr, u32 mask, u32 data)
        return temp;
 }
 
-static inline bool
-nv_strncmp(void *obj, u32 addr, u32 len, const char *str)
+static inline int
+nv_memcmp(void *obj, u32 addr, const char *str, u32 len)
 {
+       unsigned char c1, c2;
+
        while (len--) {
-               if (nv_ro08(obj, addr++) != *(str++))
-                       return false;
+               c1 = nv_ro08(obj, addr++);
+               c2 = *(str++);
+               if (c1 != c2)
+                       return c1 - c2;
        }
-       return true;
+       return 0;
 }
 
 #endif
index 39e73b91d360a3753dbcc3c210ca1e77f00332ec..41b7a6a76f1981ae3427278bacaf8d2c99edbe09 100644 (file)
@@ -54,6 +54,7 @@ int nv04_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
                        int clk, struct nouveau_pll_vals *);
 int nv04_clock_pll_prog(struct nouveau_clock *, u32 reg1,
                        struct nouveau_pll_vals *);
-
+int nva3_clock_pll_calc(struct nouveau_clock *, struct nvbios_pll *,
+                       int clk, struct nouveau_pll_vals *);
 
 #endif
index 7d750382a833c33b64fbbf40c98a1d8f936399e2..c511971577490499002426ed04087a517d8e0dab 100644 (file)
@@ -64,7 +64,7 @@ dcb_table(struct nouveau_bios *bios, u8 *ver, u8 *hdr, u8 *cnt, u8 *len)
                }
        } else
        if (*ver >= 0x15) {
-               if (!nv_strncmp(bios, dcb - 7, 7, "DEV_REC")) {
+               if (!nv_memcmp(bios, dcb - 7, "DEV_REC", 7)) {
                        u16 i2c = nv_ro16(bios, dcb + 2);
                        *hdr = 4;
                        *cnt = (i2c - dcb) / 10;
index cc8d7d162d7c348da6770d7404f195e9191d41e1..9068c98b96f64f2f8c0c5a18d478400d09855553 100644 (file)
@@ -66,6 +66,24 @@ nva3_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq)
        return ret;
 }
 
+int
+nva3_clock_pll_calc(struct nouveau_clock *clock, struct nvbios_pll *info,
+                   int clk, struct nouveau_pll_vals *pv)
+{
+       int ret, N, M, P;
+
+       ret = nva3_pll_calc(clock, info, clk, &N, NULL, &M, &P);
+
+       if (ret > 0) {
+               pv->refclk = info->refclk;
+               pv->N1 = N;
+               pv->M1 = M;
+               pv->log2P = P;
+       }
+       return ret;
+}
+
+
 static int
 nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                struct nouveau_oclass *oclass, void *data, u32 size,
@@ -80,6 +98,7 @@ nva3_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                return ret;
 
        priv->base.pll_set = nva3_clock_pll_set;
+       priv->base.pll_calc = nva3_clock_pll_calc;
        return 0;
 }
 
index 5ccce0b17bf3dd209bde225486b41bab55fcdf79..f6962c9b6c36b6f00db2715287dedf1c3adb9f4e 100644 (file)
@@ -79,6 +79,7 @@ nvc0_clock_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
                return ret;
 
        priv->base.pll_set = nvc0_clock_pll_set;
+       priv->base.pll_calc = nva3_clock_pll_calc;
        return 0;
 }
 
index cc79c796afee316cd810125b93dd86fbef940d5e..cbf1fc60a38682be197dc1bb1f0f15c8853a06e6 100644 (file)
@@ -241,6 +241,10 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
 
        if (unlikely(!abi16))
                return -ENOMEM;
+
+       if (!drm->channel)
+               return nouveau_abi16_put(abi16, -ENODEV);
+
        client = nv_client(abi16->client);
 
        if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0)
index 0910125cbbc3be3cfa757f0976f3afea8cac6a21..8503b2ea570a0616234e409c524593f37a98648e 100644 (file)
@@ -129,7 +129,8 @@ nouveau_accel_init(struct nouveau_drm *drm)
 
        /* initialise synchronisation routines */
        if      (device->card_type < NV_10) ret = nv04_fence_create(drm);
-       else if (device->chipset   <  0x84) ret = nv10_fence_create(drm);
+       else if (device->card_type < NV_50) ret = nv10_fence_create(drm);
+       else if (device->chipset   <  0x84) ret = nv50_fence_create(drm);
        else if (device->card_type < NV_C0) ret = nv84_fence_create(drm);
        else                                ret = nvc0_fence_create(drm);
        if (ret) {
index ba498f8e47a211c7bc9a8e749624be6cbd8b395b..010bae19554ad204537a31a5e02584d130086ff3 100644 (file)
@@ -1625,7 +1625,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
                        /* some early dce3.2 boards have a bug in their transmitter control table */
-                       if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730))
+                       if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730))
                                atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
                }
                if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
index af31f829f4a8bd6910b8e19ec5bff001b660d3e6..219942c660d7d2129e7c21ac375761dcd5309c9f 100644 (file)
@@ -1330,6 +1330,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
                                        break;
                                udelay(1);
                        }
+               } else {
+                       save->crtc_enabled[i] = false;
                }
        }
 
index 10ea17a6b2a6edfae76955f7e8f2ccd08ea7b1fe..42433344cb1b24860998067fe7c96baf332c1ece 100644 (file)
@@ -69,9 +69,12 @@ static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = {
        /* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/
        { PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59,
                PCI_VENDOR_ID_DELL, 0x00e3, 2},
-       /* Intel 82852/82855 host bridge / Mobility FireGL 9000 R250 Needs AGPMode 1 (lp #296617) */
+       /* Intel 82852/82855 host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 (lp #296617) */
        { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66,
                PCI_VENDOR_ID_DELL, 0x0149, 1},
+       /* Intel 82855PM host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 for suspend/resume */
+       { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66,
+               PCI_VENDOR_ID_IBM, 0x0531, 1},
        /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */
        { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50,
                0x1025, 0x0061, 1},
index 860dc4813e9991fe67754333ad487686605a7b26..bd2a3b40cd129b30d4445a8cdca8adec2eb492f9 100644 (file)
@@ -749,7 +749,10 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags,
        /* clear the pages coming from the pool if requested */
        if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) {
                list_for_each_entry(p, &plist, lru) {
-                       clear_page(page_address(p));
+                       if (PageHighMem(p))
+                               clear_highpage(p);
+                       else
+                               clear_page(page_address(p));
                }
        }
 
index bf8260133ea9dc2cd6058118864cd481fbe8dcff..7d759a4302943bb6c5904356dd9e81dec6d4588f 100644 (file)
@@ -308,9 +308,7 @@ int ttm_tt_swapin(struct ttm_tt *ttm)
                if (unlikely(to_page == NULL))
                        goto out_err;
 
-               preempt_disable();
                copy_highpage(to_page, from_page);
-               preempt_enable();
                page_cache_release(from_page);
        }
 
@@ -358,9 +356,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
                        ret = PTR_ERR(to_page);
                        goto out_err;
                }
-               preempt_disable();
                copy_highpage(to_page, from_page);
-               preempt_enable();
                set_page_dirty(to_page);
                mark_page_accessed(to_page);
                page_cache_release(to_page);
index b07ca2e4d04b5852c6b59438aaae27bbe478acd2..7290811f89bef5956019f90acc59f543206e49e7 100644 (file)
@@ -110,6 +110,8 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
        memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
 
        ret = copy_to_user(buffer, bounce, size);
+       if (ret)
+               ret = -EFAULT;
        vfree(bounce);
 
        if (unlikely(ret != 0))
index f676c01bb4710e8b786d388fbd453f27d8220a68..6fcd466d082512f675d027aafd7600eb34edebaf 100644 (file)
@@ -46,9 +46,9 @@ static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                rdesc[559] = 0x45;
        }
        /* the same as above (s/usage/physical/) */
-       if ((quirks & MS_RDESC_3K) && *rsize == 106 &&
-                       !memcmp((char []){ 0x19, 0x00, 0x29, 0xff },
-                               &rdesc[94], 4)) {
+       if ((quirks & MS_RDESC_3K) && *rsize == 106 && rdesc[94] == 0x19 &&
+                       rdesc[95] == 0x00 && rdesc[96] == 0x29 &&
+                       rdesc[97] == 0xff) {
                rdesc[94] = 0x35;
                rdesc[96] = 0x45;
        }
index aa59a254be2c3e3755a377d0c0c1f02dfa6c797d..c02bf208084f0a52cbb08548a36cece9c0ca3fb9 100644 (file)
@@ -39,6 +39,7 @@
 #define        AT91_TWI_STOP           0x0002  /* Send a Stop Condition */
 #define        AT91_TWI_MSEN           0x0004  /* Master Transfer Enable */
 #define        AT91_TWI_SVDIS          0x0020  /* Slave Transfer Disable */
+#define        AT91_TWI_QUICK          0x0040  /* SMBus quick command */
 #define        AT91_TWI_SWRST          0x0080  /* Software Reset */
 
 #define        AT91_TWI_MMR            0x0004  /* Master Mode Register */
@@ -212,7 +213,11 @@ static int at91_do_twi_transfer(struct at91_twi_dev *dev)
 
        INIT_COMPLETION(dev->cmd_complete);
        dev->transfer_status = 0;
-       if (dev->msg->flags & I2C_M_RD) {
+
+       if (!dev->buf_len) {
+               at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_QUICK);
+               at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP);
+       } else if (dev->msg->flags & I2C_M_RD) {
                unsigned start_flags = AT91_TWI_START;
 
                if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) {
index 286ca191782098fe44f8a9c995b0015e2e3693ef..0670da79ee5e53cd0682dbdc1e7b311a196f73e1 100644 (file)
@@ -287,12 +287,14 @@ read_init_dma_fail:
 select_init_dma_fail:
        dma_unmap_sg(i2c->dev, &i2c->sg_io[0], 1, DMA_TO_DEVICE);
 select_init_pio_fail:
+       dmaengine_terminate_all(i2c->dmach);
        return -EINVAL;
 
 /* Write failpath. */
 write_init_dma_fail:
        dma_unmap_sg(i2c->dev, i2c->sg_io, 2, DMA_TO_DEVICE);
 write_init_pio_fail:
+       dmaengine_terminate_all(i2c->dmach);
        return -EINVAL;
 }
 
index db31eaed6ea59b32083df49f757c1fc949c60303..3525c9e62cb0f9bf23f47705fd86d3bba9707b45 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/slab.h>
 #include <linux/i2c-omap.h>
 #include <linux/pm_runtime.h>
-#include <linux/pm_qos.h>
 
 /* I2C controller revisions */
 #define OMAP_I2C_OMAP1_REV_2           0x20
@@ -187,8 +186,9 @@ struct omap_i2c_dev {
        int                     reg_shift;      /* bit shift for I2C register addresses */
        struct completion       cmd_complete;
        struct resource         *ioarea;
-       u32                     latency;        /* maximum MPU wkup latency */
-       struct pm_qos_request   pm_qos_request;
+       u32                     latency;        /* maximum mpu wkup latency */
+       void                    (*set_mpu_wkup_lat)(struct device *dev,
+                                                   long latency);
        u32                     speed;          /* Speed of bus in kHz */
        u32                     dtrev;          /* extra revision from DT */
        u32                     flags;
@@ -494,7 +494,9 @@ static void omap_i2c_resize_fifo(struct omap_i2c_dev *dev, u8 size, bool is_rx)
                dev->b_hw = 1; /* Enable hardware fixes */
 
        /* calculate wakeup latency constraint for MPU */
-       dev->latency = (1000000 * dev->threshold) / (1000 * dev->speed / 8);
+       if (dev->set_mpu_wkup_lat != NULL)
+               dev->latency = (1000000 * dev->threshold) /
+                       (1000 * dev->speed / 8);
 }
 
 /*
@@ -522,6 +524,9 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
        dev->buf = msg->buf;
        dev->buf_len = msg->len;
 
+       /* make sure writes to dev->buf_len are ordered */
+       barrier();
+
        omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
 
        /* Clear the FIFO Buffers */
@@ -579,7 +584,6 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
         */
        timeout = wait_for_completion_timeout(&dev->cmd_complete,
                                                OMAP_I2C_TIMEOUT);
-       dev->buf_len = 0;
        if (timeout == 0) {
                dev_err(dev->dev, "controller timed out\n");
                omap_i2c_init(dev);
@@ -629,16 +633,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
        if (r < 0)
                goto out;
 
-       /*
-        * When waiting for completion of a i2c transfer, we need to
-        * set a wake up latency constraint for the MPU. This is to
-        * ensure quick enough wakeup from idle, when transfer
-        * completes.
-        */
-       if (dev->latency)
-               pm_qos_add_request(&dev->pm_qos_request,
-                                  PM_QOS_CPU_DMA_LATENCY,
-                                  dev->latency);
+       if (dev->set_mpu_wkup_lat != NULL)
+               dev->set_mpu_wkup_lat(dev->dev, dev->latency);
 
        for (i = 0; i < num; i++) {
                r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
@@ -646,8 +642,8 @@ omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
                        break;
        }
 
-       if (dev->latency)
-               pm_qos_remove_request(&dev->pm_qos_request);
+       if (dev->set_mpu_wkup_lat != NULL)
+               dev->set_mpu_wkup_lat(dev->dev, -1);
 
        if (r == 0)
                r = num;
@@ -1104,6 +1100,7 @@ omap_i2c_probe(struct platform_device *pdev)
        } else if (pdata != NULL) {
                dev->speed = pdata->clkrate;
                dev->flags = pdata->flags;
+               dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
                dev->dtrev = pdata->rev;
        }
 
@@ -1159,8 +1156,9 @@ omap_i2c_probe(struct platform_device *pdev)
                        dev->b_hw = 1; /* Enable hardware fixes */
 
                /* calculate wakeup latency constraint for MPU */
-               dev->latency = (1000000 * dev->fifo_size) /
-                              (1000 * dev->speed / 8);
+               if (dev->set_mpu_wkup_lat != NULL)
+                       dev->latency = (1000000 * dev->fifo_size) /
+                                      (1000 * dev->speed / 8);
        }
 
        /* reset ASAP, clearing any IRQs */
index 3e0335f1fc60df8b78ce50c7a4e5284e82ad432f..9d902725bac94f28c91aa26ec57615988cd96e77 100644 (file)
@@ -806,6 +806,7 @@ static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c)
                        dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio);
                        goto free_gpio;
                }
+               i2c->gpios[idx] = gpio;
 
                ret = gpio_request(gpio, "i2c-bus");
                if (ret) {
index 5f097f309b9f9e92c59a5525db04283ab699fc74..7fa5b24b16db9a4a1c4c1a360f16dd01b018a215 100644 (file)
@@ -169,7 +169,7 @@ static int __devinit i2c_mux_pinctrl_probe(struct platform_device *pdev)
        mux->busses = devm_kzalloc(&pdev->dev,
                                   sizeof(mux->busses) * mux->pdata->bus_count,
                                   GFP_KERNEL);
-       if (!mux->states) {
+       if (!mux->busses) {
                dev_err(&pdev->dev, "Cannot allocate busses\n");
                ret = -ENOMEM;
                goto err;
index c0ec7d42c3be05ffd574daec1870d44d560ed15a..1abbc170d8b77f302154323a0ea944474bfd5d37 100644 (file)
@@ -26,10 +26,14 @@ static void copy_abs(struct input_dev *dev, unsigned int dst, unsigned int src)
  * input_mt_init_slots() - initialize MT input slots
  * @dev: input device supporting MT events and finger tracking
  * @num_slots: number of slots used by the device
+ * @flags: mt tasks to handle in core
  *
  * This function allocates all necessary memory for MT slot handling
  * in the input device, prepares the ABS_MT_SLOT and
  * ABS_MT_TRACKING_ID events for use and sets up appropriate buffers.
+ * Depending on the flags set, it also performs pointer emulation and
+ * frame synchronization.
+ *
  * May be called repeatedly. Returns -EINVAL if attempting to
  * reinitialize with a different number of slots.
  */
index 8f02e3d0e712789dc2cccbb0cb52fe40fc0620db..4c842c320c2ede9f2bf42d507ee5c91f00eef7e3 100644 (file)
@@ -12,8 +12,8 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #define MOUSEDEV_MINOR_BASE    32
-#define MOUSEDEV_MINORS                32
-#define MOUSEDEV_MIX           31
+#define MOUSEDEV_MINORS                31
+#define MOUSEDEV_MIX           63
 
 #include <linux/sched.h>
 #include <linux/slab.h>
index f02028ec3db6a6384dc194e7633ee12e8bbb7685..78e5d9ab0ba7fd991e55cff240257248f42b7ba1 100644 (file)
@@ -955,7 +955,8 @@ static int ads7846_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume);
 
-static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts)
+static int __devinit ads7846_setup_pendown(struct spi_device *spi,
+                                          struct ads7846 *ts)
 {
        struct ads7846_platform_data *pdata = spi->dev.platform_data;
        int err;
@@ -981,6 +982,9 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784
 
                ts->gpio_pendown = pdata->gpio_pendown;
 
+               if (pdata->gpio_pendown_debounce)
+                       gpio_set_debounce(pdata->gpio_pendown,
+                                         pdata->gpio_pendown_debounce);
        } else {
                dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n");
                return -EINVAL;
index d4a4cd445cabb40504bd2a1c7d5300656feceaff..0badfa48b32b7e84a16449ebc8804e461529c8b9 100644 (file)
@@ -4108,7 +4108,7 @@ static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to)
 static int intel_iommu_add_device(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
-       struct pci_dev *bridge, *dma_pdev;
+       struct pci_dev *bridge, *dma_pdev = NULL;
        struct iommu_group *group;
        int ret;
 
@@ -4122,7 +4122,7 @@ static int intel_iommu_add_device(struct device *dev)
                        dma_pdev = pci_get_domain_bus_and_slot(
                                                pci_domain_nr(pdev->bus),
                                                bridge->subordinate->number, 0);
-               else
+               if (!dma_pdev)
                        dma_pdev = pci_dev_get(bridge);
        } else
                dma_pdev = pci_dev_get(pdev);
index a649f146d17bad0b62d15a1d174c57147a9a2a2f..c0f7a42662635a288fc8c98fabe3d8f1b35f1141 100644 (file)
@@ -1054,6 +1054,7 @@ static int smmu_debugfs_stats_show(struct seq_file *s, void *v)
                        stats[i], val, offs);
        }
        seq_printf(s, "\n");
+       dput(dent);
 
        return 0;
 }
index dc670ccc6978614330a85fa4138c0df47febcfba..16c78f1c5ef25ad4121b1ee7e2b7fab30cedce95 100644 (file)
@@ -168,7 +168,8 @@ static int __init armctrl_of_init(struct device_node *node,
 }
 
 static struct of_device_id irq_of_match[] __initconst = {
-       { .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init }
+       { .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init },
+       { }
 };
 
 void __init bcm2835_init_irq(void)
index b312056da14d3c5f9ef602a455d8bbc80fc8c125..4239b3955ff08f27edacbc4311bb09f93231bd69 100644 (file)
@@ -33,8 +33,6 @@
 struct led_trigger_cpu {
        char name[MAX_NAME_LEN];
        struct led_trigger *_trig;
-       struct mutex lock;
-       int lock_is_inited;
 };
 
 static DEFINE_PER_CPU(struct led_trigger_cpu, cpu_trig);
@@ -50,12 +48,6 @@ void ledtrig_cpu(enum cpu_led_event ledevt)
 {
        struct led_trigger_cpu *trig = &__get_cpu_var(cpu_trig);
 
-       /* mutex lock should be initialized before calling mutex_call() */
-       if (!trig->lock_is_inited)
-               return;
-
-       mutex_lock(&trig->lock);
-
        /* Locate the correct CPU LED */
        switch (ledevt) {
        case CPU_LED_IDLE_END:
@@ -75,8 +67,6 @@ void ledtrig_cpu(enum cpu_led_event ledevt)
                /* Will leave the LED as it is */
                break;
        }
-
-       mutex_unlock(&trig->lock);
 }
 EXPORT_SYMBOL(ledtrig_cpu);
 
@@ -117,14 +107,9 @@ static int __init ledtrig_cpu_init(void)
        for_each_possible_cpu(cpu) {
                struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
 
-               mutex_init(&trig->lock);
-
                snprintf(trig->name, MAX_NAME_LEN, "cpu%d", cpu);
 
-               mutex_lock(&trig->lock);
                led_trigger_register_simple(trig->name, &trig->_trig);
-               trig->lock_is_inited = 1;
-               mutex_unlock(&trig->lock);
        }
 
        register_syscore_ops(&ledtrig_cpu_syscore_ops);
@@ -142,15 +127,9 @@ static void __exit ledtrig_cpu_exit(void)
        for_each_possible_cpu(cpu) {
                struct led_trigger_cpu *trig = &per_cpu(cpu_trig, cpu);
 
-               mutex_lock(&trig->lock);
-
                led_trigger_unregister_simple(trig->_trig);
                trig->_trig = NULL;
                memset(trig->name, 0, MAX_NAME_LEN);
-               trig->lock_is_inited = 0;
-
-               mutex_unlock(&trig->lock);
-               mutex_destroy(&trig->lock);
        }
 
        unregister_syscore_ops(&ledtrig_cpu_syscore_ops);
index 02db9183ca01e8b64ce54a649dacc943c883f38f..77e6eff41cae9bb7c693aac363c509f65c44251d 100644 (file)
@@ -740,8 +740,14 @@ static void rq_completed(struct mapped_device *md, int rw, int run_queue)
        if (!md_in_flight(md))
                wake_up(&md->wait);
 
+       /*
+        * Run this off this callpath, as drivers could invoke end_io while
+        * inside their request_fn (and holding the queue lock). Calling
+        * back into ->request_fn() could deadlock attempting to grab the
+        * queue lock again.
+        */
        if (run_queue)
-               blk_run_queue(md->queue);
+               blk_run_queue_async(md->queue);
 
        /*
         * dm_put() must be at the end of this function. See the comment above
index 9ab768acfb623f8bbb13870e5f65150a60ecad07..61200717687b85b3fed040f9599ffd1987b8842d 100644 (file)
@@ -1817,10 +1817,10 @@ retry:
                        memset(bbp, 0xff, PAGE_SIZE);
 
                        for (i = 0 ; i < bb->count ; i++) {
-                               u64 internal_bb = *p++;
+                               u64 internal_bb = p[i];
                                u64 store_bb = ((BB_OFFSET(internal_bb) << 10)
                                                | BB_LEN(internal_bb));
-                               *bbp++ = cpu_to_le64(store_bb);
+                               bbp[i] = cpu_to_le64(store_bb);
                        }
                        bb->changed = 0;
                        if (read_seqretry(&bb->lock, seq))
@@ -5294,7 +5294,7 @@ void md_stop_writes(struct mddev *mddev)
 }
 EXPORT_SYMBOL_GPL(md_stop_writes);
 
-void md_stop(struct mddev *mddev)
+static void __md_stop(struct mddev *mddev)
 {
        mddev->ready = 0;
        mddev->pers->stop(mddev);
@@ -5304,6 +5304,18 @@ void md_stop(struct mddev *mddev)
        mddev->pers = NULL;
        clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
 }
+
+void md_stop(struct mddev *mddev)
+{
+       /* stop the array and free an attached data structures.
+        * This is called from dm-raid
+        */
+       __md_stop(mddev);
+       bitmap_destroy(mddev);
+       if (mddev->bio_set)
+               bioset_free(mddev->bio_set);
+}
+
 EXPORT_SYMBOL_GPL(md_stop);
 
 static int md_set_readonly(struct mddev *mddev, struct block_device *bdev)
@@ -5364,7 +5376,7 @@ static int do_md_stop(struct mddev * mddev, int mode,
                        set_disk_ro(disk, 0);
 
                __md_stop_writes(mddev);
-               md_stop(mddev);
+               __md_stop(mddev);
                mddev->queue->merge_bvec_fn = NULL;
                mddev->queue->backing_dev_info.congested_fn = NULL;
 
@@ -7936,9 +7948,9 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors,
                   sector_t *first_bad, int *bad_sectors)
 {
        int hi;
-       int lo = 0;
+       int lo;
        u64 *p = bb->page;
-       int rv = 0;
+       int rv;
        sector_t target = s + sectors;
        unsigned seq;
 
@@ -7953,7 +7965,8 @@ int md_is_badblock(struct badblocks *bb, sector_t s, int sectors,
 
 retry:
        seq = read_seqbegin(&bb->lock);
-
+       lo = 0;
+       rv = 0;
        hi = bb->count;
 
        /* Binary search between lo and hi for 'target'
index d1295aff41739eea048f0e43513dfba6ade4c8f1..0d5d0ff2c0f7beb47a02bd4692273b31369b2bc5 100644 (file)
@@ -499,7 +499,7 @@ static void raid10_end_write_request(struct bio *bio, int error)
         */
        one_write_done(r10_bio);
        if (dec_rdev)
-               rdev_dec_pending(conf->mirrors[dev].rdev, conf->mddev);
+               rdev_dec_pending(rdev, conf->mddev);
 }
 
 /*
@@ -1334,18 +1334,21 @@ retry_write:
                        blocked_rdev = rrdev;
                        break;
                }
+               if (rdev && (test_bit(Faulty, &rdev->flags)
+                            || test_bit(Unmerged, &rdev->flags)))
+                       rdev = NULL;
                if (rrdev && (test_bit(Faulty, &rrdev->flags)
                              || test_bit(Unmerged, &rrdev->flags)))
                        rrdev = NULL;
 
                r10_bio->devs[i].bio = NULL;
                r10_bio->devs[i].repl_bio = NULL;
-               if (!rdev || test_bit(Faulty, &rdev->flags) ||
-                   test_bit(Unmerged, &rdev->flags)) {
+
+               if (!rdev && !rrdev) {
                        set_bit(R10BIO_Degraded, &r10_bio->state);
                        continue;
                }
-               if (test_bit(WriteErrorSeen, &rdev->flags)) {
+               if (rdev && test_bit(WriteErrorSeen, &rdev->flags)) {
                        sector_t first_bad;
                        sector_t dev_sector = r10_bio->devs[i].addr;
                        int bad_sectors;
@@ -1387,8 +1390,10 @@ retry_write:
                                        max_sectors = good_sectors;
                        }
                }
-               r10_bio->devs[i].bio = bio;
-               atomic_inc(&rdev->nr_pending);
+               if (rdev) {
+                       r10_bio->devs[i].bio = bio;
+                       atomic_inc(&rdev->nr_pending);
+               }
                if (rrdev) {
                        r10_bio->devs[i].repl_bio = bio;
                        atomic_inc(&rrdev->nr_pending);
@@ -1444,69 +1449,71 @@ retry_write:
        for (i = 0; i < conf->copies; i++) {
                struct bio *mbio;
                int d = r10_bio->devs[i].devnum;
-               if (!r10_bio->devs[i].bio)
-                       continue;
+               if (r10_bio->devs[i].bio) {
+                       struct md_rdev *rdev = conf->mirrors[d].rdev;
+                       mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+                       md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
+                                   max_sectors);
+                       r10_bio->devs[i].bio = mbio;
+
+                       mbio->bi_sector = (r10_bio->devs[i].addr+
+                                          choose_data_offset(r10_bio,
+                                                             rdev));
+                       mbio->bi_bdev = rdev->bdev;
+                       mbio->bi_end_io = raid10_end_write_request;
+                       mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
+                       mbio->bi_private = r10_bio;
 
-               mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-               md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
-                           max_sectors);
-               r10_bio->devs[i].bio = mbio;
+                       atomic_inc(&r10_bio->remaining);
 
-               mbio->bi_sector = (r10_bio->devs[i].addr+
-                                  choose_data_offset(r10_bio,
-                                                     conf->mirrors[d].rdev));
-               mbio->bi_bdev = conf->mirrors[d].rdev->bdev;
-               mbio->bi_end_io = raid10_end_write_request;
-               mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
-               mbio->bi_private = r10_bio;
+                       cb = blk_check_plugged(raid10_unplug, mddev,
+                                              sizeof(*plug));
+                       if (cb)
+                               plug = container_of(cb, struct raid10_plug_cb,
+                                                   cb);
+                       else
+                               plug = NULL;
+                       spin_lock_irqsave(&conf->device_lock, flags);
+                       if (plug) {
+                               bio_list_add(&plug->pending, mbio);
+                               plug->pending_cnt++;
+                       } else {
+                               bio_list_add(&conf->pending_bio_list, mbio);
+                               conf->pending_count++;
+                       }
+                       spin_unlock_irqrestore(&conf->device_lock, flags);
+                       if (!plug)
+                               md_wakeup_thread(mddev->thread);
+               }
 
-               atomic_inc(&r10_bio->remaining);
+               if (r10_bio->devs[i].repl_bio) {
+                       struct md_rdev *rdev = conf->mirrors[d].replacement;
+                       if (rdev == NULL) {
+                               /* Replacement just got moved to main 'rdev' */
+                               smp_mb();
+                               rdev = conf->mirrors[d].rdev;
+                       }
+                       mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
+                       md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
+                                   max_sectors);
+                       r10_bio->devs[i].repl_bio = mbio;
+
+                       mbio->bi_sector = (r10_bio->devs[i].addr +
+                                          choose_data_offset(
+                                                  r10_bio, rdev));
+                       mbio->bi_bdev = rdev->bdev;
+                       mbio->bi_end_io = raid10_end_write_request;
+                       mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
+                       mbio->bi_private = r10_bio;
 
-               cb = blk_check_plugged(raid10_unplug, mddev, sizeof(*plug));
-               if (cb)
-                       plug = container_of(cb, struct raid10_plug_cb, cb);
-               else
-                       plug = NULL;
-               spin_lock_irqsave(&conf->device_lock, flags);
-               if (plug) {
-                       bio_list_add(&plug->pending, mbio);
-                       plug->pending_cnt++;
-               } else {
+                       atomic_inc(&r10_bio->remaining);
+                       spin_lock_irqsave(&conf->device_lock, flags);
                        bio_list_add(&conf->pending_bio_list, mbio);
                        conf->pending_count++;
+                       spin_unlock_irqrestore(&conf->device_lock, flags);
+                       if (!mddev_check_plugged(mddev))
+                               md_wakeup_thread(mddev->thread);
                }
-               spin_unlock_irqrestore(&conf->device_lock, flags);
-               if (!plug)
-                       md_wakeup_thread(mddev->thread);
-
-               if (!r10_bio->devs[i].repl_bio)
-                       continue;
-
-               mbio = bio_clone_mddev(bio, GFP_NOIO, mddev);
-               md_trim_bio(mbio, r10_bio->sector - bio->bi_sector,
-                           max_sectors);
-               r10_bio->devs[i].repl_bio = mbio;
-
-               /* We are actively writing to the original device
-                * so it cannot disappear, so the replacement cannot
-                * become NULL here
-                */
-               mbio->bi_sector = (r10_bio->devs[i].addr +
-                                  choose_data_offset(
-                                          r10_bio,
-                                          conf->mirrors[d].replacement));
-               mbio->bi_bdev = conf->mirrors[d].replacement->bdev;
-               mbio->bi_end_io = raid10_end_write_request;
-               mbio->bi_rw = WRITE | do_sync | do_fua | do_discard;
-               mbio->bi_private = r10_bio;
-
-               atomic_inc(&r10_bio->remaining);
-               spin_lock_irqsave(&conf->device_lock, flags);
-               bio_list_add(&conf->pending_bio_list, mbio);
-               conf->pending_count++;
-               spin_unlock_irqrestore(&conf->device_lock, flags);
-               if (!mddev_check_plugged(mddev))
-                       md_wakeup_thread(mddev->thread);
        }
 
        /* Don't remove the bias on 'remaining' (one_write_done) until
index c5439dce0295078ecf82094af5474a649284ce61..a4502686e7a8763fb5aeded988f026b2a9dd1c99 100644 (file)
@@ -2774,10 +2774,12 @@ static void handle_stripe_clean_event(struct r5conf *conf,
                        dev = &sh->dev[i];
                        if (!test_bit(R5_LOCKED, &dev->flags) &&
                            (test_bit(R5_UPTODATE, &dev->flags) ||
-                            test_and_clear_bit(R5_Discard, &dev->flags))) {
+                            test_bit(R5_Discard, &dev->flags))) {
                                /* We can return any write requests */
                                struct bio *wbi, *wbi2;
                                pr_debug("Return write for disc %d\n", i);
+                               if (test_and_clear_bit(R5_Discard, &dev->flags))
+                                       clear_bit(R5_UPTODATE, &dev->flags);
                                wbi = dev->written;
                                dev->written = NULL;
                                while (wbi && wbi->bi_sector <
@@ -2795,7 +2797,8 @@ static void handle_stripe_clean_event(struct r5conf *conf,
                                         !test_bit(STRIPE_DEGRADED, &sh->state),
                                                0);
                        }
-               }
+               } else if (test_bit(R5_Discard, &sh->dev[i].flags))
+                       clear_bit(R5_Discard, &sh->dev[i].flags);
 
        if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state))
                if (atomic_dec_and_test(&conf->pending_full_writes))
@@ -3490,40 +3493,6 @@ static void handle_stripe(struct stripe_head *sh)
                        handle_failed_sync(conf, sh, &s);
        }
 
-       /*
-        * might be able to return some write requests if the parity blocks
-        * are safe, or on a failed drive
-        */
-       pdev = &sh->dev[sh->pd_idx];
-       s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx)
-               || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx);
-       qdev = &sh->dev[sh->qd_idx];
-       s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx)
-               || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx)
-               || conf->level < 6;
-
-       if (s.written &&
-           (s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
-                            && !test_bit(R5_LOCKED, &pdev->flags)
-                            && (test_bit(R5_UPTODATE, &pdev->flags) ||
-                                test_bit(R5_Discard, &pdev->flags))))) &&
-           (s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
-                            && !test_bit(R5_LOCKED, &qdev->flags)
-                            && (test_bit(R5_UPTODATE, &qdev->flags) ||
-                                test_bit(R5_Discard, &qdev->flags))))))
-               handle_stripe_clean_event(conf, sh, disks, &s.return_bi);
-
-       /* Now we might consider reading some blocks, either to check/generate
-        * parity, or to satisfy requests
-        * or to load a block that is being partially written.
-        */
-       if (s.to_read || s.non_overwrite
-           || (conf->level == 6 && s.to_write && s.failed)
-           || (s.syncing && (s.uptodate + s.compute < disks))
-           || s.replacing
-           || s.expanding)
-               handle_stripe_fill(sh, &s, disks);
-
        /* Now we check to see if any write operations have recently
         * completed
         */
@@ -3561,6 +3530,40 @@ static void handle_stripe(struct stripe_head *sh)
                        s.dec_preread_active = 1;
        }
 
+       /*
+        * might be able to return some write requests if the parity blocks
+        * are safe, or on a failed drive
+        */
+       pdev = &sh->dev[sh->pd_idx];
+       s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx)
+               || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx);
+       qdev = &sh->dev[sh->qd_idx];
+       s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx)
+               || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx)
+               || conf->level < 6;
+
+       if (s.written &&
+           (s.p_failed || ((test_bit(R5_Insync, &pdev->flags)
+                            && !test_bit(R5_LOCKED, &pdev->flags)
+                            && (test_bit(R5_UPTODATE, &pdev->flags) ||
+                                test_bit(R5_Discard, &pdev->flags))))) &&
+           (s.q_failed || ((test_bit(R5_Insync, &qdev->flags)
+                            && !test_bit(R5_LOCKED, &qdev->flags)
+                            && (test_bit(R5_UPTODATE, &qdev->flags) ||
+                                test_bit(R5_Discard, &qdev->flags))))))
+               handle_stripe_clean_event(conf, sh, disks, &s.return_bi);
+
+       /* Now we might consider reading some blocks, either to check/generate
+        * parity, or to satisfy requests
+        * or to load a block that is being partially written.
+        */
+       if (s.to_read || s.non_overwrite
+           || (conf->level == 6 && s.to_write && s.failed)
+           || (s.syncing && (s.uptodate + s.compute < disks))
+           || s.replacing
+           || s.expanding)
+               handle_stripe_fill(sh, &s, disks);
+
        /* Now to consider new write requests and what else, if anything
         * should be read.  We do not handle new writes when:
         * 1/ A 'write' operation (copy+xor) is already in flight.
@@ -5529,6 +5532,10 @@ static int run(struct mddev *mddev)
                 * discard data disk but write parity disk
                 */
                stripe = stripe * PAGE_SIZE;
+               /* Round up to power of 2, as discard handling
+                * currently assumes that */
+               while ((stripe-1) & stripe)
+                       stripe = (stripe | (stripe-1)) + 1;
                mddev->queue->limits.discard_alignment = stripe;
                mddev->queue->limits.discard_granularity = stripe;
                /*
index f123517065ec911ff6e4154aa25a3f8e1dd0bd98..abd5c80c7cf5f59c9a3adf78d188482148ecf512 100644 (file)
  * This driver is based on max8998.c
  */
 
+#include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
+#include <linux/of_irq.h>
 #include <linux/interrupt.h>
 #include <linux/pm_runtime.h>
 #include <linux/module.h>
@@ -47,6 +49,13 @@ static struct mfd_cell max8997_devs[] = {
        { .name = "max8997-led", .id = 2 },
 };
 
+#ifdef CONFIG_OF
+static struct of_device_id __devinitdata max8997_pmic_dt_match[] = {
+       { .compatible = "maxim,max8997-pmic", .data = TYPE_MAX8997 },
+       {},
+};
+#endif
+
 int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
 {
        struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
@@ -123,6 +132,58 @@ int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
 }
 EXPORT_SYMBOL_GPL(max8997_update_reg);
 
+#ifdef CONFIG_OF
+/*
+ * Only the common platform data elements for max8997 are parsed here from the
+ * device tree. Other sub-modules of max8997 such as pmic, rtc and others have
+ * to parse their own platform data elements from device tree.
+ *
+ * The max8997 platform data structure is instantiated here and the drivers for
+ * the sub-modules need not instantiate another instance while parsing their
+ * platform data.
+ */
+static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
+                                       struct device *dev)
+{
+       struct max8997_platform_data *pd;
+
+       pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL);
+       if (!pd) {
+               dev_err(dev, "could not allocate memory for pdata\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       pd->ono = irq_of_parse_and_map(dev->of_node, 1);
+
+       /*
+        * ToDo: the 'wakeup' member in the platform data is more of a linux
+        * specfic information. Hence, there is no binding for that yet and
+        * not parsed here.
+        */
+
+       return pd;
+}
+#else
+static struct max8997_platform_data *max8997_i2c_parse_dt_pdata(
+                                       struct device *dev)
+{
+       return 0;
+}
+#endif
+
+static inline int max8997_i2c_get_driver_data(struct i2c_client *i2c,
+                                               const struct i2c_device_id *id)
+{
+#ifdef CONFIG_OF
+       if (i2c->dev.of_node) {
+               const struct of_device_id *match;
+               match = of_match_node(max8997_pmic_dt_match, i2c->dev.of_node);
+               return (int)match->data;
+       }
+#endif
+       return (int)id->driver_data;
+}
+
 static int max8997_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
@@ -137,12 +198,21 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
        i2c_set_clientdata(i2c, max8997);
        max8997->dev = &i2c->dev;
        max8997->i2c = i2c;
-       max8997->type = id->driver_data;
+       max8997->type = max8997_i2c_get_driver_data(i2c, id);
        max8997->irq = i2c->irq;
 
+       if (max8997->dev->of_node) {
+               pdata = max8997_i2c_parse_dt_pdata(max8997->dev);
+               if (IS_ERR(pdata)) {
+                       ret = PTR_ERR(pdata);
+                       goto err;
+               }
+       }
+
        if (!pdata)
                goto err;
 
+       max8997->pdata = pdata;
        max8997->ono = pdata->ono;
 
        mutex_init(&max8997->iolock);
@@ -434,6 +504,7 @@ static struct i2c_driver max8997_i2c_driver = {
                   .name = "max8997",
                   .owner = THIS_MODULE,
                   .pm = &max8997_pm,
+                  .of_match_table = of_match_ptr(max8997_pmic_dt_match),
        },
        .probe = max8997_i2c_probe,
        .remove = max8997_i2c_remove,
index 01b9255ed6310cf9f984d4177fc59b9e21b6348e..b829a5710ddcaa39356aabf46f4f2aec05d25f05 100644 (file)
@@ -775,6 +775,7 @@ static const struct reg_default wm5102_reg_default[] = {
        { 0x00000154, 0x0000 },   /* R340   - Rate Estimator 3 */ 
        { 0x00000155, 0x0000 },   /* R341   - Rate Estimator 4 */ 
        { 0x00000156, 0x0000 },   /* R342   - Rate Estimator 5 */ 
+       { 0x00000161, 0x0000 },   /* R353   - Dynamic Frequency Scaling 1 */ 
        { 0x00000171, 0x0000 },   /* R369   - FLL1 Control 1 */ 
        { 0x00000172, 0x0008 },   /* R370   - FLL1 Control 2 */ 
        { 0x00000173, 0x0018 },   /* R371   - FLL1 Control 3 */ 
@@ -1564,6 +1565,7 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_RATE_ESTIMATOR_3:
        case ARIZONA_RATE_ESTIMATOR_4:
        case ARIZONA_RATE_ESTIMATOR_5:
+       case ARIZONA_DYNAMIC_FREQUENCY_SCALING_1:
        case ARIZONA_FLL1_CONTROL_1:
        case ARIZONA_FLL1_CONTROL_2:
        case ARIZONA_FLL1_CONTROL_3:
@@ -1596,6 +1598,7 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_FLL2_GPIO_CLOCK:
        case ARIZONA_MIC_CHARGE_PUMP_1:
        case ARIZONA_LDO1_CONTROL_1:
+       case ARIZONA_LDO1_CONTROL_2:
        case ARIZONA_LDO2_CONTROL_1:
        case ARIZONA_MIC_BIAS_CTRL_1:
        case ARIZONA_MIC_BIAS_CTRL_2:
index 8f52fc858e48bec08f900963996c0d37bd4601cb..5a5cd2ace4a6b05126e642e06d04950f52108ab8 100644 (file)
@@ -240,7 +240,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength)
 
        if (*(szlength) != '+') {
                devlength = simple_strtoul(szlength, &buffer, 0);
-               devlength = handle_unit(devlength, buffer) - devstart;
+               devlength = handle_unit(devlength, buffer);
                if (devlength < devstart)
                        goto err_out;
 
index ec6841d8e956f74f5224363392632900a39e1f8e..1a03b7f673ce0d59c8613144fd51d1ffb299e4fd 100644 (file)
@@ -2983,13 +2983,15 @@ static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
        /*
         * Field definitions are in the following datasheets:
         * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
-        * New style   (6 byte ID): Samsung K9GAG08U0F (p.44)
+        * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44)
         * Hynix MLC   (6 byte ID): Hynix H27UBG8T2B (p.22)
         *
-        * Check for ID length, cell type, and Hynix/Samsung ID to decide what
-        * to do.
+        * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung
+        * ID to decide what to do.
         */
-       if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG) {
+       if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG &&
+                       (chip->cellinfo & NAND_CI_CELLTYPE_MSK) &&
+                       id_data[5] != 0x00) {
                /* Calc pagesize */
                mtd->writesize = 2048 << (extid & 0x03);
                extid >>= 2;
index 64be8f0848b075cdccb647309ff88d12b3fa547d..d9127e2ed808eab6ddfe5835c68cfa88ef490cf0 100644 (file)
@@ -121,7 +121,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master,
        nr_parts = plen / sizeof(part[0]);
 
        *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL);
-       if (!pparts)
+       if (!*pparts)
                return -ENOMEM;
 
        names = of_get_property(dp, "partition-names", &plen);
index 7153e0d27101e3eed06ac17addcdbd4734c7ccc3..b3f41f200622b39f5ef7d46ab6b772ed2eb9e97e 100644 (file)
@@ -3694,7 +3694,7 @@ static int flexonenand_check_blocks_erased(struct mtd_info *mtd, int start, int
  * flexonenand_set_boundary    - Writes the SLC boundary
  * @param mtd                  - mtd info structure
  */
-int flexonenand_set_boundary(struct mtd_info *mtd, int die,
+static int flexonenand_set_boundary(struct mtd_info *mtd, int die,
                                    int boundary, int lock)
 {
        struct onenand_chip *this = mtd->priv;
index b2530b00212558411f917abbe077ec75cb985f5e..5f5b69f37d2e50d4a6ebbe91f4c3bc1346e042e3 100644 (file)
@@ -1379,6 +1379,8 @@ static void bond_compute_features(struct bonding *bond)
        struct net_device *bond_dev = bond->dev;
        netdev_features_t vlan_features = BOND_VLAN_FEATURES;
        unsigned short max_hard_header_len = ETH_HLEN;
+       unsigned int gso_max_size = GSO_MAX_SIZE;
+       u16 gso_max_segs = GSO_MAX_SEGS;
        int i;
        unsigned int flags, dst_release_flag = IFF_XMIT_DST_RELEASE;
 
@@ -1394,11 +1396,16 @@ static void bond_compute_features(struct bonding *bond)
                dst_release_flag &= slave->dev->priv_flags;
                if (slave->dev->hard_header_len > max_hard_header_len)
                        max_hard_header_len = slave->dev->hard_header_len;
+
+               gso_max_size = min(gso_max_size, slave->dev->gso_max_size);
+               gso_max_segs = min(gso_max_segs, slave->dev->gso_max_segs);
        }
 
 done:
        bond_dev->vlan_features = vlan_features;
        bond_dev->hard_header_len = max_hard_header_len;
+       bond_dev->gso_max_segs = gso_max_segs;
+       netif_set_gso_max_size(bond_dev, gso_max_size);
 
        flags = bond_dev->priv_flags & ~IFF_XMIT_DST_RELEASE;
        bond_dev->priv_flags = flags | dst_release_flag;
index d04911d33b647080278f81678869c032e1a3c853..47618e505355ae91fc0ade4e50231ec780bcc56f 100644 (file)
@@ -813,6 +813,7 @@ static int __init ne_drv_probe(struct platform_device *pdev)
                dev->irq = irq[this_dev];
                dev->mem_end = bad[this_dev];
        }
+       SET_NETDEV_DEV(dev, &pdev->dev);
        err = do_ne_probe(dev);
        if (err) {
                free_netdev(dev);
index bd1fd3d87c24d3979f01a0e9864af9866c62b9aa..01611b33a93de82c8b735b2e1c3e115a9b8e807f 100644 (file)
@@ -9545,10 +9545,13 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp)
  */
 static void __devinit bnx2x_prev_interrupted_dmae(struct bnx2x *bp)
 {
-       u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS);
-       if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) {
-               BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing");
-               REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, 1 << BP_FUNC(bp));
+       if (!CHIP_IS_E1x(bp)) {
+               u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS);
+               if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) {
+                       BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing");
+                       REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR,
+                              1 << BP_FUNC(bp));
+               }
        }
 }
 
index 92317e9c0f736821f605a4e3008b089b1ba9cb63..60ac46f4ac085380630c5f35af7892e65cc980f5 100644 (file)
@@ -1860,10 +1860,14 @@ jme_open(struct net_device *netdev)
        jme_clear_pm(jme);
        JME_NAPI_ENABLE(jme);
 
-       tasklet_enable(&jme->linkch_task);
-       tasklet_enable(&jme->txclean_task);
-       tasklet_hi_enable(&jme->rxclean_task);
-       tasklet_hi_enable(&jme->rxempty_task);
+       tasklet_init(&jme->linkch_task, jme_link_change_tasklet,
+                    (unsigned long) jme);
+       tasklet_init(&jme->txclean_task, jme_tx_clean_tasklet,
+                    (unsigned long) jme);
+       tasklet_init(&jme->rxclean_task, jme_rx_clean_tasklet,
+                    (unsigned long) jme);
+       tasklet_init(&jme->rxempty_task, jme_rx_empty_tasklet,
+                    (unsigned long) jme);
 
        rc = jme_request_irq(jme);
        if (rc)
@@ -3079,22 +3083,6 @@ jme_init_one(struct pci_dev *pdev,
        tasklet_init(&jme->pcc_task,
                     jme_pcc_tasklet,
                     (unsigned long) jme);
-       tasklet_init(&jme->linkch_task,
-                    jme_link_change_tasklet,
-                    (unsigned long) jme);
-       tasklet_init(&jme->txclean_task,
-                    jme_tx_clean_tasklet,
-                    (unsigned long) jme);
-       tasklet_init(&jme->rxclean_task,
-                    jme_rx_clean_tasklet,
-                    (unsigned long) jme);
-       tasklet_init(&jme->rxempty_task,
-                    jme_rx_empty_tasklet,
-                    (unsigned long) jme);
-       tasklet_disable_nosync(&jme->linkch_task);
-       tasklet_disable_nosync(&jme->txclean_task);
-       tasklet_disable_nosync(&jme->rxclean_task);
-       tasklet_disable_nosync(&jme->rxempty_task);
        jme->dpi.cur = PCC_P1;
 
        jme->reg_ghc = 0;
index e558edd1cb6c106d643f6b16413b67f26dfeb778..69e01977a1dd0cf14466bb397bfe6e0b27c11f36 100644 (file)
@@ -5459,8 +5459,10 @@ static int prepare_hardware(struct net_device *dev)
        rc = request_irq(dev->irq, netdev_intr, IRQF_SHARED, dev->name, dev);
        if (rc)
                return rc;
-       tasklet_enable(&hw_priv->rx_tasklet);
-       tasklet_enable(&hw_priv->tx_tasklet);
+       tasklet_init(&hw_priv->rx_tasklet, rx_proc_task,
+                    (unsigned long) hw_priv);
+       tasklet_init(&hw_priv->tx_tasklet, tx_proc_task,
+                    (unsigned long) hw_priv);
 
        hw->promiscuous = 0;
        hw->all_multi = 0;
@@ -7033,16 +7035,6 @@ static int __devinit pcidev_init(struct pci_dev *pdev,
        spin_lock_init(&hw_priv->hwlock);
        mutex_init(&hw_priv->lock);
 
-       /* tasklet is enabled. */
-       tasklet_init(&hw_priv->rx_tasklet, rx_proc_task,
-               (unsigned long) hw_priv);
-       tasklet_init(&hw_priv->tx_tasklet, tx_proc_task,
-               (unsigned long) hw_priv);
-
-       /* tasklet_enable will decrement the atomic counter. */
-       tasklet_disable(&hw_priv->rx_tasklet);
-       tasklet_disable(&hw_priv->tx_tasklet);
-
        for (i = 0; i < TOTAL_PORT_NUM; i++)
                init_waitqueue_head(&hw_priv->counter[i].counter);
 
index 1c818254b7bec650da02fc352625570a3937b6f8..b01f83a044c4d77f70141c81fee3815cd050f258 100644 (file)
@@ -979,17 +979,6 @@ static void cp_init_hw (struct cp_private *cp)
        cpw32_f (MAC0 + 0, le32_to_cpu (*(__le32 *) (dev->dev_addr + 0)));
        cpw32_f (MAC0 + 4, le32_to_cpu (*(__le32 *) (dev->dev_addr + 4)));
 
-       cpw32_f(HiTxRingAddr, 0);
-       cpw32_f(HiTxRingAddr + 4, 0);
-
-       ring_dma = cp->ring_dma;
-       cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
-       cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
-
-       ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
-       cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
-       cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
-
        cp_start_hw(cp);
        cpw8(TxThresh, 0x06); /* XXX convert magic num to a constant */
 
@@ -1003,6 +992,17 @@ static void cp_init_hw (struct cp_private *cp)
 
        cpw8(Config5, cpr8(Config5) & PMEStatus);
 
+       cpw32_f(HiTxRingAddr, 0);
+       cpw32_f(HiTxRingAddr + 4, 0);
+
+       ring_dma = cp->ring_dma;
+       cpw32_f(RxRingAddr, ring_dma & 0xffffffff);
+       cpw32_f(RxRingAddr + 4, (ring_dma >> 16) >> 16);
+
+       ring_dma += sizeof(struct cp_desc) * CP_RX_RING_SIZE;
+       cpw32_f(TxRingAddr, ring_dma & 0xffffffff);
+       cpw32_f(TxRingAddr + 4, (ring_dma >> 16) >> 16);
+
        cpw16(MultiIntr, 0);
 
        cpw8_f(Cfg9346, Cfg9346_Lock);
index fb9f6b38511f97beddbff380c2ae7d31878e4ff4..edf5edb13140fb5908f0197298d17cf3b1cb7503 100644 (file)
@@ -2479,7 +2479,7 @@ static int sis900_resume(struct pci_dev *pci_dev)
        netif_start_queue(net_dev);
 
        /* Workaround for EDB */
-       sis900_set_mode(ioaddr, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
+       sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED);
 
        /* Enable all known interrupts by setting the interrupt mask. */
        sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE);
index 62d1baf111ea8f7afb3f1fa049b63666853861f5..c53c0f4e2ce311cc5083d218bff9f5d1ed8e56e0 100644 (file)
@@ -2110,7 +2110,7 @@ static void __devinit smsc911x_read_mac_address(struct net_device *dev)
 static int __devinit smsc911x_init(struct net_device *dev)
 {
        struct smsc911x_data *pdata = netdev_priv(dev);
-       unsigned int byte_test;
+       unsigned int byte_test, mask;
        unsigned int to = 100;
 
        SMSC_TRACE(pdata, probe, "Driver Parameters:");
@@ -2130,9 +2130,22 @@ static int __devinit smsc911x_init(struct net_device *dev)
        /*
         * poll the READY bit in PMT_CTRL. Any other access to the device is
         * forbidden while this bit isn't set. Try for 100ms
+        *
+        * Note that this test is done before the WORD_SWAP register is
+        * programmed. So in some configurations the READY bit is at 16 before
+        * WORD_SWAP is written to. This issue is worked around by waiting
+        * until either bit 0 or bit 16 gets set in PMT_CTRL.
+        *
+        * SMSC has confirmed that checking bit 16 (marked as reserved in
+        * the datasheet) is fine since these bits "will either never be set
+        * or can only go high after READY does (so also indicate the device
+        * is ready)".
         */
-       while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to)
+
+       mask = PMT_CTRL_READY_ | swahw32(PMT_CTRL_READY_);
+       while (!(smsc911x_reg_read(pdata, PMT_CTRL) & mask) && --to)
                udelay(1000);
+
        if (to == 0) {
                pr_err("Device not READY in 100ms aborting\n");
                return -ENODEV;
index 4e9810013850ca3b4765ce002de0715d6b2c935b..66e025ad5df1a6e998ce0115f7057f89067b7bd3 100644 (file)
@@ -917,7 +917,7 @@ static int tile_net_setup_interrupts(struct net_device *dev)
        ingress_irq = rc;
        tile_irq_activate(ingress_irq, TILE_IRQ_PERCPU);
        rc = request_irq(ingress_irq, tile_net_handle_ingress_irq,
-                        0, NULL, NULL);
+                        0, "tile_net", NULL);
        if (rc != 0) {
                netdev_err(dev, "request_irq failed: %d\n", rc);
                destroy_irq(ingress_irq);
index 1d04754a6637ad5b815db648ee3aa75a75a68485..a788501e978e116908cf0e7a0c92745c275b2009 100644 (file)
@@ -894,6 +894,8 @@ out:
        return IRQ_HANDLED;
 }
 
+static void axienet_dma_err_handler(unsigned long data);
+
 /**
  * axienet_open - Driver open routine.
  * @ndev:      Pointer to net_device structure
@@ -942,6 +944,10 @@ static int axienet_open(struct net_device *ndev)
                phy_start(lp->phy_dev);
        }
 
+       /* Enable tasklets for Axi DMA error handling */
+       tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler,
+                    (unsigned long) lp);
+
        /* Enable interrupts for Axi DMA Tx */
        ret = request_irq(lp->tx_irq, axienet_tx_irq, 0, ndev->name, ndev);
        if (ret)
@@ -950,8 +956,7 @@ static int axienet_open(struct net_device *ndev)
        ret = request_irq(lp->rx_irq, axienet_rx_irq, 0, ndev->name, ndev);
        if (ret)
                goto err_rx_irq;
-       /* Enable tasklets for Axi DMA error handling */
-       tasklet_enable(&lp->dma_err_tasklet);
+
        return 0;
 
 err_rx_irq:
@@ -960,6 +965,7 @@ err_tx_irq:
        if (lp->phy_dev)
                phy_disconnect(lp->phy_dev);
        lp->phy_dev = NULL;
+       tasklet_kill(&lp->dma_err_tasklet);
        dev_err(lp->dev, "request_irq() failed\n");
        return ret;
 }
@@ -1613,10 +1619,6 @@ static int __devinit axienet_of_probe(struct platform_device *op)
                goto err_iounmap_2;
        }
 
-       tasklet_init(&lp->dma_err_tasklet, axienet_dma_err_handler,
-                    (unsigned long) lp);
-       tasklet_disable(&lp->dma_err_tasklet);
-
        return 0;
 
 err_iounmap_2:
index 98934bdf6acffc053fcd317721e8d92cf649ba14..477d6729b17f7f391c34a520bc08f8031bfbd4ae 100644 (file)
@@ -1102,10 +1102,12 @@ static int init_queues(struct port *port)
 {
        int i;
 
-       if (!ports_open)
-               if (!(dma_pool = dma_pool_create(DRV_NAME, NULL,
-                                                POOL_ALLOC_SIZE, 32, 0)))
+       if (!ports_open) {
+               dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev,
+                                          POOL_ALLOC_SIZE, 32, 0);
+               if (!dma_pool)
                        return -ENOMEM;
+       }
 
        if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
                                              &port->desc_tab_phys)))
index 5039f08f5a5b23cacd0f145cd790a30fce47806e..43e9ab4f4d7edc0b6771c1664d2064c164e37ec3 100644 (file)
@@ -222,7 +222,7 @@ static void sirdev_config_fsm(struct work_struct *work)
                        break;
 
                case SIRDEV_STATE_DONGLE_SPEED:
-                       if (dev->dongle_drv->reset) {
+                       if (dev->dongle_drv->set_speed) {
                                ret = dev->dongle_drv->set_speed(dev, fsm->param);
                                if (ret < 0) {
                                        fsm->result = ret;
index 6428fcbbdd4bf4f6967e7eb3fee32e97fceba566..daec9b05d168ca4f0f103f3638fcc3259e9ea304 100644 (file)
@@ -234,7 +234,6 @@ void free_mdio_bitbang(struct mii_bus *bus)
        struct mdiobb_ctrl *ctrl = bus->priv;
 
        module_put(ctrl->ops->owner);
-       mdiobus_unregister(bus);
        mdiobus_free(bus);
 }
 EXPORT_SYMBOL(free_mdio_bitbang);
index 899274f2f9b1dd1da0aac0442807b6e42b0cddc2..2ed1140df3e9fc0afbc25bce03e5a6eba7ceb228 100644 (file)
@@ -185,17 +185,20 @@ static int __devinit mdio_gpio_probe(struct platform_device *pdev)
 {
        struct mdio_gpio_platform_data *pdata;
        struct mii_bus *new_bus;
-       int ret;
+       int ret, bus_id;
 
-       if (pdev->dev.of_node)
+       if (pdev->dev.of_node) {
                pdata = mdio_gpio_of_get_data(pdev);
-       else
+               bus_id = of_alias_get_id(pdev->dev.of_node, "mdio-gpio");
+       } else {
                pdata = pdev->dev.platform_data;
+               bus_id = pdev->id;
+       }
 
        if (!pdata)
                return -ENODEV;
 
-       new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, pdev->id);
+       new_bus = mdio_gpio_bus_init(&pdev->dev, pdata, bus_id);
        if (!new_bus)
                return -ENODEV;
 
index 9db0171e93669f483eeae19791ed4e090c333bb0..c5db428e73fa2200f3ef8a5ea5124ceeebb6ef78 100644 (file)
@@ -29,8 +29,8 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb)
                        if (last) {
                                skb2 = skb_clone(skb, GFP_ATOMIC);
                                if (skb2) {
-                                       ret = team_dev_queue_xmit(team, last,
-                                                                 skb2);
+                                       ret = !team_dev_queue_xmit(team, last,
+                                                                  skb2);
                                        if (!sum_ret)
                                                sum_ret = ret;
                                }
@@ -39,7 +39,7 @@ static bool bc_transmit(struct team *team, struct sk_buff *skb)
                }
        }
        if (last) {
-               ret = team_dev_queue_xmit(team, last, skb);
+               ret = !team_dev_queue_xmit(team, last, skb);
                if (!sum_ret)
                        sum_ret = ret;
        }
index 4cd582a4f625d55d5edd8c2cd3952d5571074921..74fab1a4015657b52bd5b4c690990120171dc509 100644 (file)
@@ -540,10 +540,12 @@ advance:
            (ctx->ether_desc == NULL) || (ctx->control != intf))
                goto error;
 
-       /* claim interfaces, if any */
-       temp = usb_driver_claim_interface(driver, ctx->data, dev);
-       if (temp)
-               goto error;
+       /* claim data interface, if different from control */
+       if (ctx->data != ctx->control) {
+               temp = usb_driver_claim_interface(driver, ctx->data, dev);
+               if (temp)
+                       goto error;
+       }
 
        iface_no = ctx->data->cur_altsetting->desc.bInterfaceNumber;
 
@@ -623,6 +625,10 @@ static void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
 
        tasklet_kill(&ctx->bh);
 
+       /* handle devices with combined control and data interface */
+       if (ctx->control == ctx->data)
+               ctx->data = NULL;
+
        /* disconnect master --> disconnect slave */
        if (intf == ctx->control && ctx->data) {
                usb_set_intfdata(ctx->data, NULL);
@@ -1245,6 +1251,14 @@ static const struct usb_device_id cdc_devs[] = {
          .driver_info = (unsigned long) &wwan_info,
        },
 
+       /* Huawei NCM devices disguised as vendor specific */
+       { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16),
+         .driver_info = (unsigned long)&wwan_info,
+       },
+       { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46),
+         .driver_info = (unsigned long)&wwan_info,
+       },
+
        /* Generic CDC-NCM devices */
        { USB_INTERFACE_INFO(USB_CLASS_COMM,
                USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
index 3286166415b479969cf0624a522baf3b6a97eb73..362cb8cfeb92b6021f48995226117ccd0c971faf 100644 (file)
@@ -184,7 +184,7 @@ static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx)
        /* set the address, index & direction (read from PHY) */
        phy_id &= dev->mii.phy_id_mask;
        idx &= dev->mii.reg_num_mask;
-       addr = (phy_id << 11) | (idx << 6) | MII_READ_;
+       addr = (phy_id << 11) | (idx << 6) | MII_READ_ | MII_BUSY_;
        ret = smsc95xx_write_reg(dev, MII_ADDR, addr);
        check_warn_goto_done(ret, "Error writing MII_ADDR");
 
@@ -221,7 +221,7 @@ static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx,
        /* set the address, index & direction (write to PHY) */
        phy_id &= dev->mii.phy_id_mask;
        idx &= dev->mii.reg_num_mask;
-       addr = (phy_id << 11) | (idx << 6) | MII_WRITE_;
+       addr = (phy_id << 11) | (idx << 6) | MII_WRITE_ | MII_BUSY_;
        ret = smsc95xx_write_reg(dev, MII_ADDR, addr);
        check_warn_goto_done(ret, "Error writing MII_ADDR");
 
index 7b4adde93c016b7e020306220e372524da9f5deb..8b5c6191707626ba64bad7bdceeab2c299e5bcfc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * VXLAN: Virtual eXtensiable Local Area Network
+ * VXLAN: Virtual eXtensible Local Area Network
  *
  * Copyright (c) 2012 Vyatta Inc.
  *
@@ -50,8 +50,8 @@
 
 #define VXLAN_N_VID    (1u << 24)
 #define VXLAN_VID_MASK (VXLAN_N_VID - 1)
-/* VLAN + IP header + UDP + VXLAN */
-#define VXLAN_HEADROOM (4 + 20 + 8 + 8)
+/* IP header + UDP + VXLAN + Ethernet header */
+#define VXLAN_HEADROOM (20 + 8 + 8 + 14)
 
 #define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required value. */
 
@@ -1102,6 +1102,10 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
 
                if (!tb[IFLA_MTU])
                        dev->mtu = lowerdev->mtu - VXLAN_HEADROOM;
+
+               /* update header length based on lower device */
+               dev->hard_header_len = lowerdev->hard_header_len +
+                                      VXLAN_HEADROOM;
        }
 
        if (data[IFLA_VXLAN_TOS])
index 3f575afd8cfcb03f283df0932f6fb33bb1495cca..e9a3da588e954b1ae38b8becf465b132dbbcd22f 100644 (file)
@@ -969,10 +969,12 @@ static int init_hdlc_queues(struct port *port)
 {
        int i;
 
-       if (!ports_open)
-               if (!(dma_pool = dma_pool_create(DRV_NAME, NULL,
-                                                POOL_ALLOC_SIZE, 32, 0)))
+       if (!ports_open) {
+               dma_pool = dma_pool_create(DRV_NAME, &port->netdev->dev,
+                                          POOL_ALLOC_SIZE, 32, 0);
+               if (!dma_pool)
                        return -ENOMEM;
+       }
 
        if (!(port->desc_tab = dma_pool_alloc(dma_pool, GFP_KERNEL,
                                              &port->desc_tab_phys)))
index 8e1559aba495a0bd7447ac2c79703d49caf70abd..1829b445d0b01852ea11111692174c766b3c7e55 100644 (file)
@@ -1456,7 +1456,7 @@ static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type)
        switch (type) {
        case ATH9K_RESET_POWER_ON:
                ret = ath9k_hw_set_reset_power_on(ah);
-               if (!ret)
+               if (ret)
                        ah->reset_power_on = true;
                break;
        case ATH9K_RESET_WARM:
index a6f1e81660085766ffbd2b38ae896566f0e9eb3c..481345c23ded3250bf68c002089809e815abb3fe 100644 (file)
@@ -4401,7 +4401,7 @@ static s32 brcmf_mode_to_nl80211_iftype(s32 mode)
 
 static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
 {
-#ifndef CONFIG_BRCMFISCAN
+#ifndef CONFIG_BRCMISCAN
        /* scheduled scan settings */
        wiphy->max_sched_scan_ssids = BRCMF_PNO_MAX_PFN_COUNT;
        wiphy->max_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
index ff8162d4c4543d3d2976c964ed2f790a8f7cb6a1..2d9eee93c743aa0f7bfe6d98330ccacead4fe201 100644 (file)
@@ -521,7 +521,7 @@ static void iwlagn_mac_tx(struct ieee80211_hw *hw,
                     ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
 
        if (iwlagn_tx_skb(priv, control->sta, skb))
-               dev_kfree_skb_any(skb);
+               ieee80211_free_txskb(hw, skb);
 }
 
 static void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
@@ -1354,6 +1354,20 @@ static int iwlagn_mac_add_interface(struct ieee80211_hw *hw,
        vif_priv->ctx = ctx;
        ctx->vif = vif;
 
+       /*
+        * In SNIFFER device type, the firmware reports the FCS to
+        * the host, rather than snipping it off. Unfortunately,
+        * mac80211 doesn't (yet) provide a per-packet flag for
+        * this, so that we have to set the hardware flag based
+        * on the interfaces added. As the monitor interface can
+        * only be present by itself, and will be removed before
+        * other interfaces are added, this is safe.
+        */
+       if (vif->type == NL80211_IFTYPE_MONITOR)
+               priv->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS;
+       else
+               priv->hw->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
+
        err = iwl_setup_interface(priv, ctx);
        if (!err || reset)
                goto out;
index 7ff3f14306784169f886e5c7ca570d8b217a7309..408132cf83c18285d4eff4ba7a67add5fde64bda 100644 (file)
@@ -2114,7 +2114,7 @@ static void iwl_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
 
        info = IEEE80211_SKB_CB(skb);
        iwl_trans_free_tx_cmd(priv->trans, info->driver_data[1]);
-       dev_kfree_skb_any(skb);
+       ieee80211_free_txskb(priv->hw, skb);
 }
 
 static void iwl_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
index 17c8e5d82681022383d657da550924d48d0d9289..bb69f8f90b3b47c441fde750c14d0a9b9a3a6da0 100644 (file)
@@ -321,6 +321,14 @@ static void iwl_rx_allocate(struct iwl_trans *trans, gfp_t priority)
                        dma_map_page(trans->dev, page, 0,
                                     PAGE_SIZE << trans_pcie->rx_page_order,
                                     DMA_FROM_DEVICE);
+               if (dma_mapping_error(trans->dev, rxb->page_dma)) {
+                       rxb->page = NULL;
+                       spin_lock_irqsave(&rxq->lock, flags);
+                       list_add(&rxb->list, &rxq->rx_used);
+                       spin_unlock_irqrestore(&rxq->lock, flags);
+                       __free_pages(page, trans_pcie->rx_page_order);
+                       return;
+               }
                /* dma address must be no more than 36 bits */
                BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
                /* and also 256 byte aligned! */
@@ -488,8 +496,19 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
                        dma_map_page(trans->dev, rxb->page, 0,
                                     PAGE_SIZE << trans_pcie->rx_page_order,
                                     DMA_FROM_DEVICE);
-               list_add_tail(&rxb->list, &rxq->rx_free);
-               rxq->free_count++;
+               if (dma_mapping_error(trans->dev, rxb->page_dma)) {
+                       /*
+                        * free the page(s) as well to not break
+                        * the invariant that the items on the used
+                        * list have no page(s)
+                        */
+                       __free_pages(rxb->page, trans_pcie->rx_page_order);
+                       rxb->page = NULL;
+                       list_add_tail(&rxb->list, &rxq->rx_used);
+               } else {
+                       list_add_tail(&rxb->list, &rxq->rx_free);
+                       rxq->free_count++;
+               }
        } else
                list_add_tail(&rxb->list, &rxq->rx_used);
        spin_unlock_irqrestore(&rxq->lock, flags);
index 105e3af3c621b0b9e335fbe42d1ea1e444bfa579..79a4ddc002d3dac1ce4aa9182bd2a2a0cf76630b 100644 (file)
@@ -480,20 +480,12 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
 void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       u16 rd_ptr, wr_ptr;
-       int n_bd = trans_pcie->txq[txq_id].q.n_bd;
 
        if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) {
                WARN_ONCE(1, "queue %d not used", txq_id);
                return;
        }
 
-       rd_ptr = iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (n_bd - 1);
-       wr_ptr = iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id));
-
-       WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]",
-                 txq_id, rd_ptr, wr_ptr);
-
        iwl_txq_set_inactive(trans, txq_id);
        IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id);
 }
index 8d465107f52b2c5073acad20d8d0acbe0485be5e..ae9010ed58debd4a8dc5001e03cbe866b2c9a8a2 100644 (file)
@@ -890,9 +890,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
                return;
        }
        cmd_node = adapter->curr_cmd;
-       if (cmd_node->wait_q_enabled)
-               adapter->cmd_wait_q.status = -ETIMEDOUT;
-
        if (cmd_node) {
                adapter->dbg.timeout_cmd_id =
                        adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index];
@@ -938,6 +935,14 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
 
                dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n",
                        adapter->ps_mode, adapter->ps_state);
+
+               if (cmd_node->wait_q_enabled) {
+                       adapter->cmd_wait_q.status = -ETIMEDOUT;
+                       wake_up_interruptible(&adapter->cmd_wait_q.wait);
+                       mwifiex_cancel_pending_ioctl(adapter);
+                       /* reset cmd_sent flag to unblock new commands */
+                       adapter->cmd_sent = false;
+               }
        }
        if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING)
                mwifiex_init_fw_complete(adapter);
index fc8a9bfa1248305fababa37b59ca90110a57afaa..82cf0fa2d9f683a391bb2215f94447d53d09ef40 100644 (file)
@@ -161,7 +161,6 @@ static int mwifiex_sdio_suspend(struct device *dev)
        struct sdio_mmc_card *card;
        struct mwifiex_adapter *adapter;
        mmc_pm_flag_t pm_flag = 0;
-       int hs_actived = 0;
        int i;
        int ret = 0;
 
@@ -188,12 +187,14 @@ static int mwifiex_sdio_suspend(struct device *dev)
        adapter = card->adapter;
 
        /* Enable the Host Sleep */
-       hs_actived = mwifiex_enable_hs(adapter);
-       if (hs_actived) {
-               pr_debug("cmd: suspend with MMC_PM_KEEP_POWER\n");
-               ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+       if (!mwifiex_enable_hs(adapter)) {
+               dev_err(adapter->dev, "cmd: failed to suspend\n");
+               return -EFAULT;
        }
 
+       dev_dbg(adapter->dev, "cmd: suspend with MMC_PM_KEEP_POWER\n");
+       ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
+
        /* Indicate device suspended */
        adapter->is_suspended = true;
 
index 9970c2b1b19979dc3577472c7c21e27703a38a76..b7e6607e6b6d038bd604657bb4fdcc883b171d7a 100644 (file)
@@ -297,6 +297,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
        /*=== Customer ID ===*/
        /****** 8188CU ********/
        {RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/
+       {RTL_USB_DEVICE(0x050d, 0x11f2, rtl92cu_hal_cfg)}, /*Belkin - ISY*/
        {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/
        {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
        {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
index caa011008cd0c9fe11b38507e7f550552bd93170..fc24eb9b3948666b0819156539138958dd6888f1 100644 (file)
@@ -452,29 +452,85 @@ static void xennet_make_frags(struct sk_buff *skb, struct net_device *dev,
        /* Grant backend access to each skb fragment page. */
        for (i = 0; i < frags; i++) {
                skb_frag_t *frag = skb_shinfo(skb)->frags + i;
+               struct page *page = skb_frag_page(frag);
 
-               tx->flags |= XEN_NETTXF_more_data;
+               len = skb_frag_size(frag);
+               offset = frag->page_offset;
 
-               id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
-               np->tx_skbs[id].skb = skb_get(skb);
-               tx = RING_GET_REQUEST(&np->tx, prod++);
-               tx->id = id;
-               ref = gnttab_claim_grant_reference(&np->gref_tx_head);
-               BUG_ON((signed short)ref < 0);
+               /* Data must not cross a page boundary. */
+               BUG_ON(len + offset > PAGE_SIZE<<compound_order(page));
 
-               mfn = pfn_to_mfn(page_to_pfn(skb_frag_page(frag)));
-               gnttab_grant_foreign_access_ref(ref, np->xbdev->otherend_id,
-                                               mfn, GNTMAP_readonly);
+               /* Skip unused frames from start of page */
+               page += offset >> PAGE_SHIFT;
+               offset &= ~PAGE_MASK;
 
-               tx->gref = np->grant_tx_ref[id] = ref;
-               tx->offset = frag->page_offset;
-               tx->size = skb_frag_size(frag);
-               tx->flags = 0;
+               while (len > 0) {
+                       unsigned long bytes;
+
+                       BUG_ON(offset >= PAGE_SIZE);
+
+                       bytes = PAGE_SIZE - offset;
+                       if (bytes > len)
+                               bytes = len;
+
+                       tx->flags |= XEN_NETTXF_more_data;
+
+                       id = get_id_from_freelist(&np->tx_skb_freelist,
+                                                 np->tx_skbs);
+                       np->tx_skbs[id].skb = skb_get(skb);
+                       tx = RING_GET_REQUEST(&np->tx, prod++);
+                       tx->id = id;
+                       ref = gnttab_claim_grant_reference(&np->gref_tx_head);
+                       BUG_ON((signed short)ref < 0);
+
+                       mfn = pfn_to_mfn(page_to_pfn(page));
+                       gnttab_grant_foreign_access_ref(ref,
+                                                       np->xbdev->otherend_id,
+                                                       mfn, GNTMAP_readonly);
+
+                       tx->gref = np->grant_tx_ref[id] = ref;
+                       tx->offset = offset;
+                       tx->size = bytes;
+                       tx->flags = 0;
+
+                       offset += bytes;
+                       len -= bytes;
+
+                       /* Next frame */
+                       if (offset == PAGE_SIZE && len) {
+                               BUG_ON(!PageCompound(page));
+                               page++;
+                               offset = 0;
+                       }
+               }
        }
 
        np->tx.req_prod_pvt = prod;
 }
 
+/*
+ * Count how many ring slots are required to send the frags of this
+ * skb. Each frag might be a compound page.
+ */
+static int xennet_count_skb_frag_slots(struct sk_buff *skb)
+{
+       int i, frags = skb_shinfo(skb)->nr_frags;
+       int pages = 0;
+
+       for (i = 0; i < frags; i++) {
+               skb_frag_t *frag = skb_shinfo(skb)->frags + i;
+               unsigned long size = skb_frag_size(frag);
+               unsigned long offset = frag->page_offset;
+
+               /* Skip unused frames from start of page */
+               offset &= ~PAGE_MASK;
+
+               pages += PFN_UP(offset + size);
+       }
+
+       return pages;
+}
+
 static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        unsigned short id;
@@ -487,23 +543,23 @@ static int xennet_start_xmit(struct sk_buff *skb, struct net_device *dev)
        grant_ref_t ref;
        unsigned long mfn;
        int notify;
-       int frags = skb_shinfo(skb)->nr_frags;
+       int slots;
        unsigned int offset = offset_in_page(data);
        unsigned int len = skb_headlen(skb);
        unsigned long flags;
 
-       frags += DIV_ROUND_UP(offset + len, PAGE_SIZE);
-       if (unlikely(frags > MAX_SKB_FRAGS + 1)) {
-               printk(KERN_ALERT "xennet: skb rides the rocket: %d frags\n",
-                      frags);
-               dump_stack();
+       slots = DIV_ROUND_UP(offset + len, PAGE_SIZE) +
+               xennet_count_skb_frag_slots(skb);
+       if (unlikely(slots > MAX_SKB_FRAGS + 1)) {
+               net_alert_ratelimited(
+                       "xennet: skb rides the rocket: %d slots\n", slots);
                goto drop;
        }
 
        spin_lock_irqsave(&np->tx_lock, flags);
 
        if (unlikely(!netif_carrier_ok(dev) ||
-                    (frags > 1 && !xennet_can_sg(dev)) ||
+                    (slots > 1 && !xennet_can_sg(dev)) ||
                     netif_needs_gso(skb, netif_skb_features(skb)))) {
                spin_unlock_irqrestore(&np->tx_lock, flags);
                goto drop;
index 97c440a8cd615798a1e61250628e0030ede37694..30ae18a03a9ccc650a195547086866a66646cd98 100644 (file)
@@ -698,13 +698,14 @@ static void pn533_wq_cmd(struct work_struct *work)
 
        cmd = list_first_entry(&dev->cmd_queue, struct pn533_cmd, queue);
 
+       list_del(&cmd->queue);
+
        mutex_unlock(&dev->cmd_lock);
 
        __pn533_send_cmd_frame_async(dev, cmd->out_frame, cmd->in_frame,
                                     cmd->in_frame_len, cmd->cmd_complete,
                                     cmd->arg, cmd->flags);
 
-       list_del(&cmd->queue);
        kfree(cmd);
 }
 
@@ -1678,11 +1679,14 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev,
 static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
                                                u8 *params, int params_len)
 {
-       struct pn533_cmd_jump_dep *cmd;
        struct pn533_cmd_jump_dep_response *resp;
        struct nfc_target nfc_target;
        u8 target_gt_len;
        int rc;
+       struct pn533_cmd_jump_dep *cmd = (struct pn533_cmd_jump_dep *)arg;
+       u8 active = cmd->active;
+
+       kfree(arg);
 
        if (params_len == -ENOENT) {
                nfc_dev_dbg(&dev->interface->dev, "");
@@ -1704,7 +1708,6 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
        }
 
        resp = (struct pn533_cmd_jump_dep_response *) params;
-       cmd = (struct pn533_cmd_jump_dep *) arg;
        rc = resp->status & PN533_CMD_RET_MASK;
        if (rc != PN533_CMD_RET_SUCCESS) {
                nfc_dev_err(&dev->interface->dev,
@@ -1734,7 +1737,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg,
        if (rc == 0)
                rc = nfc_dep_link_is_up(dev->nfc_dev,
                                                dev->nfc_dev->targets[0].idx,
-                                               !cmd->active, NFC_RF_INITIATOR);
+                                               !active, NFC_RF_INITIATOR);
 
        return 0;
 }
@@ -1819,12 +1822,8 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target,
        rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame,
                                dev->in_maxlen, pn533_in_dep_link_up_complete,
                                cmd, GFP_KERNEL);
-       if (rc)
-               goto out;
-
-
-out:
-       kfree(cmd);
+       if (rc < 0)
+               kfree(cmd);
 
        return rc;
 }
@@ -2078,8 +2077,12 @@ error:
 static int pn533_tm_send_complete(struct pn533 *dev, void *arg,
                                  u8 *params, int params_len)
 {
+       struct sk_buff *skb_out = arg;
+
        nfc_dev_dbg(&dev->interface->dev, "%s", __func__);
 
+       dev_kfree_skb(skb_out);
+
        if (params_len < 0) {
                nfc_dev_err(&dev->interface->dev,
                            "Error %d when sending data",
@@ -2117,7 +2120,7 @@ static int pn533_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb)
 
        rc = pn533_send_cmd_frame_async(dev, out_frame, dev->in_frame,
                                        dev->in_maxlen, pn533_tm_send_complete,
-                                       NULL, GFP_KERNEL);
+                                       skb, GFP_KERNEL);
        if (rc) {
                nfc_dev_err(&dev->interface->dev,
                            "Error %d when trying to send data", rc);
index d96caefd914a90d2db11f05278f565a7e7cc79ee..aeecf0f72cad50c633953e4ffd9617709239095b 100644 (file)
@@ -178,7 +178,7 @@ config PINCTRL_COH901
          ports of 8 GPIO pins each.
 
 config PINCTRL_SAMSUNG
-       bool "Samsung pinctrl driver"
+       bool
        depends on OF && GPIOLIB
        select PINMUX
        select PINCONF
index c17ae22567e0494c381bf023c13e48dfc729aa8b..0c6fcb461faf7bb10df865bd3e49a5bd905313df 100644 (file)
@@ -401,7 +401,7 @@ EXPORT_SYMBOL_GPL(rio_release_inb_pwrite);
 /**
  * rio_map_inb_region -- Map inbound memory region.
  * @mport: Master port.
- * @lstart: physical address of memory region to be mapped
+ * @local: physical address of memory region to be mapped
  * @rbase: RIO base address assigned to this window
  * @size: Size of the memory region
  * @rflags: Flags for mapping.
index 1c5ab0172ea282c73b0835d07be67e4172a8a6af..2b557119adad4b11d63ec345c96b425183e691f3 100644 (file)
@@ -394,7 +394,7 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev,
 #define pm8607_regulator_dt_init(x, y, z)      (-1)
 #endif
 
-static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
+static int pm8607_regulator_probe(struct platform_device *pdev)
 {
        struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
        struct pm8607_regulator_info *info = NULL;
@@ -454,7 +454,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit pm8607_regulator_remove(struct platform_device *pdev)
+static int pm8607_regulator_remove(struct platform_device *pdev)
 {
        struct pm8607_regulator_info *info = platform_get_drvdata(pdev);
 
@@ -481,7 +481,7 @@ static struct platform_driver pm8607_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = pm8607_regulator_probe,
-       .remove         = __devexit_p(pm8607_regulator_remove),
+       .remove         = pm8607_regulator_remove,
        .id_table       = pm8607_regulator_driver_ids,
 };
 
index 67d47b59a66d878c9188afaaa62b92f255d657bb..551a22b075387a0641d37ff9dc1a34e25b65ee9d 100644 (file)
@@ -109,6 +109,16 @@ config REGULATOR_DA9052
          This driver supports the voltage regulators of DA9052-BC and
          DA9053-AA/Bx PMIC.
 
+config REGULATOR_DA9055
+       tristate "Dialog Semiconductor DA9055 regulators"
+       depends on MFD_DA9055
+       help
+         Say y here to support the BUCKs and LDOs regulators found on
+         Dialog Semiconductor DA9055 PMIC.
+
+         This driver can also be built as a module. If so, the module
+         will be called da9055-regulator.
+
 config REGULATOR_FAN53555
        tristate "Fairchild FAN53555 Regulator"
        depends on I2C
@@ -204,6 +214,16 @@ config REGULATOR_MAX8952
          via I2C bus. Maxim 8952 has one voltage output and supports 4 DVS
          modes ranging from 0.77V to 1.40V by 0.01V steps.
 
+config REGULATOR_MAX8973
+       tristate "Maxim MAX8973 voltage regulator "
+       depends on I2C
+       select REGMAP_I2C
+       help
+         The MAXIM MAX8973 high-efficiency. three phase, DC-DC step-down
+         switching regulator delievers up to 9A of output current. Each
+         phase operates at a 2MHz fixed frequency with a 120 deg shift
+         from the adjacent phase, allowing the use of small magnetic component.
+
 config REGULATOR_MAX8997
        tristate "Maxim 8997/8966 regulator"
        depends on MFD_MAX8997
@@ -335,6 +355,17 @@ config REGULATOR_PALMAS
          on the muxing. This is handled automatically in the driver by
          reading the mux info from OTP.
 
+config REGULATOR_TPS51632
+       tristate "TI TPS51632 Power Regulator"
+       depends on I2C
+       select REGMAP_I2C
+       help
+         This driver supports TPS51632 voltage regulator chip.
+         The TPS51632 is 3-2-1 Phase D-Cap+ Step Down Driverless Controller
+         with Serial VID control and DVFS.
+         The voltage output can be configure through I2C interface or PWM
+         interface.
+
 config REGULATOR_TPS6105X
        tristate "TI TPS6105X Power regulators"
        depends on TPS6105X
@@ -415,6 +446,15 @@ config REGULATOR_TPS65912
        help
            This driver supports TPS65912 voltage regulator chip.
 
+config REGULATOR_TPS80031
+       tristate "TI TPS80031/TPS80032 power regualtor driver"
+       depends on MFD_TPS80031
+       help
+         TPS80031/ TPS80032 Fully Integrated Power Management with Power
+         Path and Battery Charger. It has 5 configurable step-down
+         converters, 11 general purpose LDOs, VBUS generator and digital
+         output to control regulators.
+
 config REGULATOR_TWL4030
        bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 PMIC"
        depends on TWL4030_CORE
@@ -422,6 +462,13 @@ config REGULATOR_TWL4030
          This driver supports the voltage regulators provided by
          this family of companion chips.
 
+config REGULATOR_VEXPRESS
+       tristate "Versatile Express regulators"
+       depends on VEXPRESS_CONFIG
+       help
+         This driver provides support for voltage regulators available
+         on the ARM Ltd's Versatile Express platform.
+
 config REGULATOR_WM831X
        tristate "Wolfson Microelectronics WM831x PMIC regulators"
        depends on MFD_WM831X
@@ -450,5 +497,12 @@ config REGULATOR_WM8994
          This driver provides support for the voltage regulators on the
          WM8994 CODEC.
 
+config REGULATOR_AS3711
+       tristate "AS3711 PMIC"
+       depends on MFD_AS3711
+       help
+         This driver provides support for the voltage regulators on the
+         AS3711 PMIC
+
 endif
 
index e431eed8a8782f2f49fc1869365b76929dc52001..b802b0c7fb02d7d7bb3bf3c1fa72b95aed899ce4 100644 (file)
@@ -16,8 +16,10 @@ obj-$(CONFIG_REGULATOR_AB8500)       += ab8500.o
 obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
 obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
 obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
+obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
 obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
 obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
+obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o
 obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
 obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
 obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
@@ -34,6 +36,7 @@ obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
 obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o
 obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
 obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
+obj-$(CONFIG_REGULATOR_MAX8973) += max8973-regulator.o
 obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
 obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
 obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o
@@ -41,6 +44,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
 obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
 obj-$(CONFIG_REGULATOR_MC13XXX_CORE) +=  mc13xxx-regulator-core.o
 obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
+obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
 obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
 obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
 obj-$(CONFIG_REGULATOR_RC5T583)  += rc5t583-regulator.o
@@ -56,7 +60,9 @@ obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
+obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
+obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
index 167c93f21981a0178a9bd9d47ba879604ed7fb4a..8b5876356db97da46cd5ac0dd59dccb4b2521361 100644 (file)
@@ -187,7 +187,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit aat2870_regulator_remove(struct platform_device *pdev)
+static int aat2870_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -201,7 +201,7 @@ static struct platform_driver aat2870_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = aat2870_regulator_probe,
-       .remove = __devexit_p(aat2870_regulator_remove),
+       .remove = aat2870_regulator_remove,
 };
 
 static int __init aat2870_regulator_init(void)
index df4ad8927f0ce88257cb70db8fdfed535f8d17f2..111ec69a3e9454a40fa96091e4a7bc679cfa5dd1 100644 (file)
@@ -494,7 +494,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
  * for all the different regulators.
  */
 
-static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
+static int ab3100_regulators_probe(struct platform_device *pdev)
 {
        struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
        struct regulator_config config = { };
@@ -571,7 +571,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit ab3100_regulators_remove(struct platform_device *pdev)
+static int ab3100_regulators_remove(struct platform_device *pdev)
 {
        int i;
 
@@ -589,7 +589,7 @@ static struct platform_driver ab3100_regulators_driver = {
                .owner = THIS_MODULE,
        },
        .probe = ab3100_regulators_probe,
-       .remove = __devexit_p(ab3100_regulators_remove),
+       .remove = ab3100_regulators_remove,
 };
 
 static __init int ab3100_regulators_init(void)
index e3d1d063025a45b12179e0712ea0d2599bfcb21c..09014f38a9481f8afb630ce8a5c5fdb513100380 100644 (file)
@@ -641,7 +641,7 @@ static struct ab8500_reg_init ab8500_reg_init[] = {
        REG_INIT(AB8500_REGUCTRLDISCH2,         0x04, 0x44, 0x16),
 };
 
-static __devinit int
+static int
 ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
 {
        int err;
@@ -676,7 +676,7 @@ ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
        return 0;
 }
 
-static __devinit int ab8500_regulator_register(struct platform_device *pdev,
+static int ab8500_regulator_register(struct platform_device *pdev,
                                        struct regulator_init_data *init_data,
                                        int id,
                                        struct device_node *np)
@@ -735,7 +735,7 @@ static struct of_regulator_match ab8500_regulator_matches[] = {
        { .name = "ab8500_ldo_ana",     .driver_data = (void *) AB8500_LDO_ANA, },
 };
 
-static __devinit int
+static int
 ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
 {
        int err, i;
@@ -751,7 +751,7 @@ ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
        return 0;
 }
 
-static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
+static int ab8500_regulator_probe(struct platform_device *pdev)
 {
        struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
        struct ab8500_platform_data *pdata;
@@ -817,7 +817,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
+static int ab8500_regulator_remove(struct platform_device *pdev)
 {
        int i;
 
@@ -836,7 +836,7 @@ static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
 
 static struct platform_driver ab8500_regulator_driver = {
        .probe = ab8500_regulator_probe,
-       .remove = __devexit_p(ab8500_regulator_remove),
+       .remove = ab8500_regulator_remove,
        .driver         = {
                .name   = "ab8500-regulator",
                .owner  = THIS_MODULE,
index f123f7e3b7525acd164ed639e022f25dc46711cf..6b981b5faa7015c53f10a463d7a53097edeab075 100644 (file)
@@ -211,7 +211,7 @@ static const struct i2c_device_id ad5398_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, ad5398_id);
 
-static int __devinit ad5398_probe(struct i2c_client *client,
+static int ad5398_probe(struct i2c_client *client,
                                const struct i2c_device_id *id)
 {
        struct regulator_init_data *init_data = client->dev.platform_data;
@@ -256,7 +256,7 @@ err:
        return ret;
 }
 
-static int __devexit ad5398_remove(struct i2c_client *client)
+static int ad5398_remove(struct i2c_client *client)
 {
        struct ad5398_chip_info *chip = i2c_get_clientdata(client);
 
@@ -266,7 +266,7 @@ static int __devexit ad5398_remove(struct i2c_client *client)
 
 static struct i2c_driver ad5398_driver = {
        .probe = ad5398_probe,
-       .remove = __devexit_p(ad5398_remove),
+       .remove = ad5398_remove,
        .driver         = {
                .name   = "ad5398",
        },
index 1af97686f4448864d92b7dbfdf58e79c883edbb8..0199eeea63b13f6d770b49897d14bb3da1173290 100644 (file)
@@ -48,36 +48,21 @@ static int anatop_regmap_set_voltage_sel(struct regulator_dev *reg,
                                        unsigned selector)
 {
        struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
-       u32 val, mask;
 
        if (!anatop_reg->control_reg)
                return -ENOTSUPP;
 
-       val = anatop_reg->min_bit_val + selector;
-       dev_dbg(&reg->dev, "%s: calculated val %d\n", __func__, val);
-       mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
-               anatop_reg->vol_bit_shift;
-       val <<= anatop_reg->vol_bit_shift;
-       regmap_update_bits(anatop_reg->anatop, anatop_reg->control_reg,
-                               mask, val);
-
-       return 0;
+       return regulator_set_voltage_sel_regmap(reg, selector);
 }
 
 static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg)
 {
        struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
-       u32 val, mask;
 
        if (!anatop_reg->control_reg)
                return -ENOTSUPP;
 
-       regmap_read(anatop_reg->anatop, anatop_reg->control_reg, &val);
-       mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
-               anatop_reg->vol_bit_shift;
-       val = (val & mask) >> anatop_reg->vol_bit_shift;
-
-       return val - anatop_reg->min_bit_val;
+       return regulator_get_voltage_sel_regmap(reg);
 }
 
 static struct regulator_ops anatop_rops = {
@@ -87,7 +72,7 @@ static struct regulator_ops anatop_rops = {
        .map_voltage = regulator_map_voltage_linear,
 };
 
-static int __devinit anatop_regulator_probe(struct platform_device *pdev)
+static int anatop_regulator_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct device_node *np = dev->of_node;
@@ -158,15 +143,20 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev)
                goto anatop_probe_end;
        }
 
-       rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage)
-               / 25000 + 1;
+       rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage) / 25000 + 1
+                           + sreg->min_bit_val;
        rdesc->min_uV = sreg->min_voltage;
        rdesc->uV_step = 25000;
+       rdesc->linear_min_sel = sreg->min_bit_val;
+       rdesc->vsel_reg = sreg->control_reg;
+       rdesc->vsel_mask = ((1 << sreg->vol_bit_width) - 1) <<
+                          sreg->vol_bit_shift;
 
        config.dev = &pdev->dev;
        config.init_data = initdata;
        config.driver_data = sreg;
        config.of_node = pdev->dev.of_node;
+       config.regmap = sreg->anatop;
 
        /* register regulator */
        rdev = regulator_register(rdesc, &config);
@@ -186,7 +176,7 @@ anatop_probe_end:
        return ret;
 }
 
-static int __devexit anatop_regulator_remove(struct platform_device *pdev)
+static int anatop_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
        struct anatop_regulator *sreg = rdev_get_drvdata(rdev);
@@ -210,7 +200,7 @@ static struct platform_driver anatop_regulator_driver = {
                .of_match_table = of_anatop_regulator_match_tbl,
        },
        .probe  = anatop_regulator_probe,
-       .remove = __devexit_p(anatop_regulator_remove),
+       .remove = anatop_regulator_remove,
 };
 
 static int __init anatop_regulator_init(void)
index d184aa35abcb45a91795aeed9de35ad8f7d1a75a..ed7beec53af85505b49815d97d94947d0d311efb 100644 (file)
@@ -34,6 +34,108 @@ struct arizona_ldo1 {
        struct regulator_init_data init_data;
 };
 
+static int arizona_ldo1_hc_list_voltage(struct regulator_dev *rdev,
+                                       unsigned int selector)
+{
+       if (selector >= rdev->desc->n_voltages)
+               return -EINVAL;
+
+       if (selector == rdev->desc->n_voltages - 1)
+               return 1800000;
+       else
+               return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
+}
+
+static int arizona_ldo1_hc_map_voltage(struct regulator_dev *rdev,
+                                      int min_uV, int max_uV)
+{
+       int sel;
+
+       sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
+       if (sel >= rdev->desc->n_voltages)
+               sel = rdev->desc->n_voltages - 1;
+
+       return sel;
+}
+
+static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev,
+                                          unsigned sel)
+{
+       struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev);
+       struct regmap *regmap = ldo->arizona->regmap;
+       unsigned int val;
+       int ret;
+
+       if (sel == rdev->desc->n_voltages - 1)
+               val = ARIZONA_LDO1_HI_PWR;
+       else
+               val = 0;
+
+       ret = regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_2,
+                                ARIZONA_LDO1_HI_PWR, val);
+       if (ret != 0)
+               return ret;
+
+       ret = regmap_update_bits(regmap, ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
+                                ARIZONA_SUBSYS_MAX_FREQ, val);
+       if (ret != 0)
+               return ret;
+
+       if (val)
+               return 0;
+
+       val = sel << ARIZONA_LDO1_VSEL_SHIFT;
+
+       return regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_1,
+                                 ARIZONA_LDO1_VSEL_MASK, val);
+}
+
+static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev);
+       struct regmap *regmap = ldo->arizona->regmap;
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_2, &val);
+       if (ret != 0)
+               return ret;
+
+       if (val & ARIZONA_LDO1_HI_PWR)
+               return rdev->desc->n_voltages - 1;
+
+       ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_1, &val);
+       if (ret != 0)
+               return ret;
+
+       return (val & ARIZONA_LDO1_VSEL_MASK) >> ARIZONA_LDO1_VSEL_SHIFT;
+}
+
+static struct regulator_ops arizona_ldo1_hc_ops = {
+       .list_voltage = arizona_ldo1_hc_list_voltage,
+       .map_voltage = arizona_ldo1_hc_map_voltage,
+       .get_voltage_sel = arizona_ldo1_hc_get_voltage_sel,
+       .set_voltage_sel = arizona_ldo1_hc_set_voltage_sel,
+       .get_bypass = regulator_get_bypass_regmap,
+       .set_bypass = regulator_set_bypass_regmap,
+};
+
+static const struct regulator_desc arizona_ldo1_hc = {
+       .name = "LDO1",
+       .supply_name = "LDOVDD",
+       .type = REGULATOR_VOLTAGE,
+       .ops = &arizona_ldo1_hc_ops,
+
+       .bypass_reg = ARIZONA_LDO1_CONTROL_1,
+       .bypass_mask = ARIZONA_LDO1_BYPASS,
+       .min_uV = 900000,
+       .uV_step = 50000,
+       .n_voltages = 8,
+       .enable_time = 500,
+
+       .owner = THIS_MODULE,
+};
+
 static struct regulator_ops arizona_ldo1_ops = {
        .list_voltage = regulator_list_voltage_linear,
        .map_voltage = regulator_map_voltage_linear,
@@ -55,11 +157,22 @@ static const struct regulator_desc arizona_ldo1 = {
        .bypass_mask = ARIZONA_LDO1_BYPASS,
        .min_uV = 900000,
        .uV_step = 50000,
-       .n_voltages = 6,
+       .n_voltages = 7,
+       .enable_time = 500,
 
        .owner = THIS_MODULE,
 };
 
+static const struct regulator_init_data arizona_ldo1_dvfs = {
+       .constraints = {
+               .min_uV = 1200000,
+               .max_uV = 1800000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS |
+                                 REGULATOR_CHANGE_VOLTAGE,
+       },
+       .num_consumer_supplies = 1,
+};
+
 static const struct regulator_init_data arizona_ldo1_default = {
        .constraints = {
                .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -67,9 +180,10 @@ static const struct regulator_init_data arizona_ldo1_default = {
        .num_consumer_supplies = 1,
 };
 
-static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
+static int arizona_ldo1_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+       const struct regulator_desc *desc;
        struct regulator_config config = { };
        struct arizona_ldo1 *ldo1;
        int ret;
@@ -87,7 +201,17 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
         * default init_data for it.  This will be overridden with
         * platform data if provided.
         */
-       ldo1->init_data = arizona_ldo1_default;
+       switch (arizona->type) {
+       case WM5102:
+               desc = &arizona_ldo1_hc;
+               ldo1->init_data = arizona_ldo1_dvfs;
+               break;
+       default:
+               desc = &arizona_ldo1;
+               ldo1->init_data = arizona_ldo1_default;
+               break;
+       }
+
        ldo1->init_data.consumer_supplies = &ldo1->supply;
        ldo1->supply.supply = "DCVDD";
        ldo1->supply.dev_name = dev_name(arizona->dev);
@@ -102,7 +226,7 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
        else
                config.init_data = &ldo1->init_data;
 
-       ldo1->regulator = regulator_register(&arizona_ldo1, &config);
+       ldo1->regulator = regulator_register(desc, &config);
        if (IS_ERR(ldo1->regulator)) {
                ret = PTR_ERR(ldo1->regulator);
                dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n",
@@ -115,7 +239,7 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
        return 0;
 }
 
-static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
+static int arizona_ldo1_remove(struct platform_device *pdev)
 {
        struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev);
 
@@ -126,7 +250,7 @@ static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
 
 static struct platform_driver arizona_ldo1_driver = {
        .probe = arizona_ldo1_probe,
-       .remove = __devexit_p(arizona_ldo1_remove),
+       .remove = arizona_ldo1_remove,
        .driver         = {
                .name   = "arizona-ldo1",
                .owner  = THIS_MODULE,
index d9b1f82cc5bd80939206025432f2602072dfe244..a6d040cbf8ac1dade86099eb0a71df4c2f94c4c8 100644 (file)
@@ -101,6 +101,8 @@ static const struct regulator_desc arizona_micsupp = {
        .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1,
        .bypass_mask = ARIZONA_CPMIC_BYPASS,
 
+       .enable_time = 3000,
+
        .owner = THIS_MODULE,
 };
 
@@ -115,7 +117,7 @@ static const struct regulator_init_data arizona_micsupp_default = {
        .num_consumer_supplies = 1,
 };
 
-static __devinit int arizona_micsupp_probe(struct platform_device *pdev)
+static int arizona_micsupp_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
        struct regulator_config config = { };
@@ -166,7 +168,7 @@ static __devinit int arizona_micsupp_probe(struct platform_device *pdev)
        return 0;
 }
 
-static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
+static int arizona_micsupp_remove(struct platform_device *pdev)
 {
        struct arizona_micsupp *micsupp = platform_get_drvdata(pdev);
 
@@ -177,7 +179,7 @@ static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
 
 static struct platform_driver arizona_micsupp_driver = {
        .probe = arizona_micsupp_probe,
-       .remove = __devexit_p(arizona_micsupp_remove),
+       .remove = arizona_micsupp_remove,
        .driver         = {
                .name   = "arizona-micsupp",
                .owner  = THIS_MODULE,
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c
new file mode 100644 (file)
index 0000000..2f1341d
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * AS3711 PMIC regulator driver, using DCDC Step Down and LDO supplies
+ *
+ * Copyright (C) 2012 Renesas Electronics Corporation
+ * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License as
+ * published by the Free Software Foundation
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/mfd/as3711.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/slab.h>
+
+struct as3711_regulator_info {
+       struct regulator_desc   desc;
+       unsigned int            max_uV;
+};
+
+struct as3711_regulator {
+       struct as3711_regulator_info *reg_info;
+       struct regulator_dev *rdev;
+};
+
+static int as3711_list_voltage_sd(struct regulator_dev *rdev,
+                                 unsigned int selector)
+{
+       if (selector >= rdev->desc->n_voltages)
+               return -EINVAL;
+
+       if (!selector)
+               return 0;
+       if (selector < 0x41)
+               return 600000 + selector * 12500;
+       if (selector < 0x71)
+               return 1400000 + (selector - 0x40) * 25000;
+       return 2600000 + (selector - 0x70) * 50000;
+}
+
+static int as3711_list_voltage_aldo(struct regulator_dev *rdev,
+                                   unsigned int selector)
+{
+       if (selector >= rdev->desc->n_voltages)
+               return -EINVAL;
+
+       if (selector < 0x10)
+               return 1200000 + selector * 50000;
+       return 1800000 + (selector - 0x10) * 100000;
+}
+
+static int as3711_list_voltage_dldo(struct regulator_dev *rdev,
+                                   unsigned int selector)
+{
+       if (selector >= rdev->desc->n_voltages ||
+           (selector > 0x10 && selector < 0x20))
+               return -EINVAL;
+
+       if (selector < 0x11)
+               return 900000 + selector * 50000;
+       return 1750000 + (selector - 0x20) * 50000;
+}
+
+static int as3711_bound_check(struct regulator_dev *rdev,
+                             int *min_uV, int *max_uV)
+{
+       struct as3711_regulator *reg = rdev_get_drvdata(rdev);
+       struct as3711_regulator_info *info = reg->reg_info;
+
+       dev_dbg(&rdev->dev, "%s(), %d, %d, %d\n", __func__,
+               *min_uV, rdev->desc->min_uV, info->max_uV);
+
+       if (*max_uV < *min_uV ||
+           *min_uV > info->max_uV || rdev->desc->min_uV > *max_uV)
+               return -EINVAL;
+
+       if (rdev->desc->n_voltages == 1)
+               return 0;
+
+       if (*max_uV > info->max_uV)
+               *max_uV = info->max_uV;
+
+       if (*min_uV < rdev->desc->min_uV)
+               *min_uV = rdev->desc->min_uV;
+
+       return *min_uV;
+}
+
+static int as3711_sel_check(int min, int max, int bottom, int step)
+{
+       int sel, voltage;
+
+       /* Round up min, when dividing: keeps us within the range */
+       sel = DIV_ROUND_UP(min - bottom, step);
+       voltage = sel * step + bottom;
+       pr_debug("%s(): select %d..%d in %d+N*%d: %d\n", __func__,
+              min, max, bottom, step, sel);
+       if (voltage > max)
+               return -EINVAL;
+
+       return sel;
+}
+
+static int as3711_map_voltage_sd(struct regulator_dev *rdev,
+                                int min_uV, int max_uV)
+{
+       int ret;
+
+       ret = as3711_bound_check(rdev, &min_uV, &max_uV);
+       if (ret <= 0)
+               return ret;
+
+       if (min_uV <= 1400000)
+               return as3711_sel_check(min_uV, max_uV, 600000, 12500);
+
+       if (min_uV <= 2600000)
+               return as3711_sel_check(min_uV, max_uV, 1400000, 25000) + 0x40;
+
+       return as3711_sel_check(min_uV, max_uV, 2600000, 50000) + 0x70;
+}
+
+/*
+ * The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and
+ * STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes:
+ * FAST:       sdX_fast=1
+ * NORMAL:     low_noise=1
+ * IDLE:       low_noise=0
+ */
+
+static int as3711_set_mode_sd(struct regulator_dev *rdev, unsigned int mode)
+{
+       unsigned int fast_bit = rdev->desc->enable_mask,
+               low_noise_bit = fast_bit << 4;
+       u8 val;
+
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               val = fast_bit | low_noise_bit;
+               break;
+       case REGULATOR_MODE_NORMAL:
+               val = low_noise_bit;
+               break;
+       case REGULATOR_MODE_IDLE:
+               val = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return regmap_update_bits(rdev->regmap, AS3711_SD_CONTROL_1,
+                                 low_noise_bit | fast_bit, val);
+}
+
+static unsigned int as3711_get_mode_sd(struct regulator_dev *rdev)
+{
+       unsigned int fast_bit = rdev->desc->enable_mask,
+               low_noise_bit = fast_bit << 4, mask = fast_bit | low_noise_bit;
+       unsigned int val;
+       int ret = regmap_read(rdev->regmap, AS3711_SD_CONTROL_1, &val);
+
+       if (ret < 0)
+               return ret;
+
+       if ((val & mask) == mask)
+               return REGULATOR_MODE_FAST;
+
+       if ((val & mask) == low_noise_bit)
+               return REGULATOR_MODE_NORMAL;
+
+       if (!(val & mask))
+               return REGULATOR_MODE_IDLE;
+
+       return -EINVAL;
+}
+
+static int as3711_map_voltage_aldo(struct regulator_dev *rdev,
+                                 int min_uV, int max_uV)
+{
+       int ret;
+
+       ret = as3711_bound_check(rdev, &min_uV, &max_uV);
+       if (ret <= 0)
+               return ret;
+
+       if (min_uV <= 1800000)
+               return as3711_sel_check(min_uV, max_uV, 1200000, 50000);
+
+       return as3711_sel_check(min_uV, max_uV, 1800000, 100000) + 0x10;
+}
+
+static int as3711_map_voltage_dldo(struct regulator_dev *rdev,
+                                 int min_uV, int max_uV)
+{
+       int ret;
+
+       ret = as3711_bound_check(rdev, &min_uV, &max_uV);
+       if (ret <= 0)
+               return ret;
+
+       if (min_uV <= 1700000)
+               return as3711_sel_check(min_uV, max_uV, 900000, 50000);
+
+       return as3711_sel_check(min_uV, max_uV, 1750000, 50000) + 0x20;
+}
+
+static struct regulator_ops as3711_sd_ops = {
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .list_voltage           = as3711_list_voltage_sd,
+       .map_voltage            = as3711_map_voltage_sd,
+       .get_mode               = as3711_get_mode_sd,
+       .set_mode               = as3711_set_mode_sd,
+};
+
+static struct regulator_ops as3711_aldo_ops = {
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .list_voltage           = as3711_list_voltage_aldo,
+       .map_voltage            = as3711_map_voltage_aldo,
+};
+
+static struct regulator_ops as3711_dldo_ops = {
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .list_voltage           = as3711_list_voltage_dldo,
+       .map_voltage            = as3711_map_voltage_dldo,
+};
+
+#define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx)     \
+       [AS3711_REGULATOR_ ## _id] = {                                                  \
+       .desc = {                                                                       \
+               .name = "as3711-regulator-" # _id,                                      \
+               .id = AS3711_REGULATOR_ ## _id,                                         \
+               .n_voltages = (_vmask + 1),                                             \
+               .ops = &as3711_ ## _sfx ## _ops,                                        \
+               .type = REGULATOR_VOLTAGE,                                              \
+               .owner = THIS_MODULE,                                                   \
+               .vsel_reg = AS3711_ ## _id ## _VOLTAGE,                                 \
+               .vsel_mask = _vmask << _vshift,                                         \
+               .enable_reg = AS3711_ ## _en_reg,                                       \
+               .enable_mask = BIT(_en_bit),                                            \
+               .min_uV = _min_uV,                                                      \
+       },                                                                              \
+       .max_uV = _max_uV,                                                              \
+}
+
+static struct as3711_regulator_info as3711_reg_info[] = {
+       AS3711_REG(SD_1, SD_CONTROL, 0, 0x7f, 0, 612500, 3350000, sd),
+       AS3711_REG(SD_2, SD_CONTROL, 1, 0x7f, 0, 612500, 3350000, sd),
+       AS3711_REG(SD_3, SD_CONTROL, 2, 0x7f, 0, 612500, 3350000, sd),
+       AS3711_REG(SD_4, SD_CONTROL, 3, 0x7f, 0, 612500, 3350000, sd),
+       AS3711_REG(LDO_1, LDO_1_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo),
+       AS3711_REG(LDO_2, LDO_2_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo),
+       AS3711_REG(LDO_3, LDO_3_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       AS3711_REG(LDO_4, LDO_4_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       AS3711_REG(LDO_5, LDO_5_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       AS3711_REG(LDO_6, LDO_6_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       AS3711_REG(LDO_7, LDO_7_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       AS3711_REG(LDO_8, LDO_8_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       /* StepUp output voltage depends on supplying regulator */
+};
+
+#define AS3711_REGULATOR_NUM ARRAY_SIZE(as3711_reg_info)
+
+static int as3711_regulator_probe(struct platform_device *pdev)
+{
+       struct as3711_regulator_pdata *pdata = dev_get_platdata(&pdev->dev);
+       struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent);
+       struct regulator_init_data *reg_data;
+       struct regulator_config config = {.dev = &pdev->dev,};
+       struct as3711_regulator *reg = NULL;
+       struct as3711_regulator *regs;
+       struct regulator_dev *rdev;
+       struct as3711_regulator_info *ri;
+       int ret;
+       int id;
+
+       if (!pdata)
+               dev_dbg(&pdev->dev, "No platform data...\n");
+
+       regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM *
+                       sizeof(struct as3711_regulator), GFP_KERNEL);
+       if (!regs) {
+               dev_err(&pdev->dev, "Memory allocation failed exiting..\n");
+               return -ENOMEM;
+       }
+
+       for (id = 0, ri = as3711_reg_info; id < AS3711_REGULATOR_NUM; ++id, ri++) {
+               reg_data = pdata ? pdata->init_data[id] : NULL;
+
+               /* No need to register if there is no regulator data */
+               if (!ri->desc.name)
+                       continue;
+
+               reg = &regs[id];
+               reg->reg_info = ri;
+
+               config.init_data = reg_data;
+               config.driver_data = reg;
+               config.regmap = as3711->regmap;
+
+               rdev = regulator_register(&ri->desc, &config);
+               if (IS_ERR(rdev)) {
+                       dev_err(&pdev->dev, "Failed to register regulator %s\n",
+                               ri->desc.name);
+                       ret = PTR_ERR(rdev);
+                       goto eregreg;
+               }
+               reg->rdev = rdev;
+       }
+       platform_set_drvdata(pdev, regs);
+       return 0;
+
+eregreg:
+       while (--id >= 0)
+               regulator_unregister(regs[id].rdev);
+
+       return ret;
+}
+
+static int as3711_regulator_remove(struct platform_device *pdev)
+{
+       struct as3711_regulator *regs = platform_get_drvdata(pdev);
+       int id;
+
+       for (id = 0; id < AS3711_REGULATOR_NUM; ++id)
+               regulator_unregister(regs[id].rdev);
+       return 0;
+}
+
+static struct platform_driver as3711_regulator_driver = {
+       .driver = {
+               .name   = "as3711-regulator",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = as3711_regulator_probe,
+       .remove         = as3711_regulator_remove,
+};
+
+static int __init as3711_regulator_init(void)
+{
+       return platform_driver_register(&as3711_regulator_driver);
+}
+subsys_initcall(as3711_regulator_init);
+
+static void __exit as3711_regulator_exit(void)
+{
+       platform_driver_unregister(&as3711_regulator_driver);
+}
+module_exit(as3711_regulator_exit);
+
+MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
+MODULE_DESCRIPTION("AS3711 regulator driver");
+MODULE_ALIAS("platform:as3711-regulator");
+MODULE_LICENSE("GPL v2");
index 5c4829cba6a62de6168c6bb3c4913812e5e8b4e1..cd1b201c91e2e8faacff620a5686f9efd9dc9ddf 100644 (file)
@@ -199,8 +199,11 @@ static int regulator_check_consumers(struct regulator_dev *rdev,
                        *min_uV = regulator->min_uV;
        }
 
-       if (*min_uV > *max_uV)
+       if (*min_uV > *max_uV) {
+               dev_err(regulator->dev, "Restricting voltage, %u-%uuV\n",
+                       regulator->min_uV, regulator->max_uV);
                return -EINVAL;
+       }
 
        return 0;
 }
@@ -880,7 +883,9 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
 
                /* final: [min_uV..max_uV] valid iff constraints valid */
                if (max_uV < min_uV) {
-                       rdev_err(rdev, "unsupportable voltage constraints\n");
+                       rdev_err(rdev,
+                                "unsupportable voltage constraints %u-%uuV\n",
+                                min_uV, max_uV);
                        return -EINVAL;
                }
 
@@ -1381,22 +1386,14 @@ struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
 }
 EXPORT_SYMBOL_GPL(regulator_get_exclusive);
 
-/**
- * regulator_put - "free" the regulator source
- * @regulator: regulator source
- *
- * Note: drivers must ensure that all regulator_enable calls made on this
- * regulator source are balanced by regulator_disable calls prior to calling
- * this function.
- */
-void regulator_put(struct regulator *regulator)
+/* Locks held by regulator_put() */
+static void _regulator_put(struct regulator *regulator)
 {
        struct regulator_dev *rdev;
 
        if (regulator == NULL || IS_ERR(regulator))
                return;
 
-       mutex_lock(&regulator_list_mutex);
        rdev = regulator->rdev;
 
        debugfs_remove_recursive(regulator->debugfs);
@@ -1412,6 +1409,20 @@ void regulator_put(struct regulator *regulator)
        rdev->exclusive = 0;
 
        module_put(rdev->owner);
+}
+
+/**
+ * regulator_put - "free" the regulator source
+ * @regulator: regulator source
+ *
+ * Note: drivers must ensure that all regulator_enable calls made on this
+ * regulator source are balanced by regulator_disable calls prior to calling
+ * this function.
+ */
+void regulator_put(struct regulator *regulator)
+{
+       mutex_lock(&regulator_list_mutex);
+       _regulator_put(regulator);
        mutex_unlock(&regulator_list_mutex);
 }
 EXPORT_SYMBOL_GPL(regulator_put);
@@ -1860,6 +1871,28 @@ int regulator_is_enabled(struct regulator *regulator)
 }
 EXPORT_SYMBOL_GPL(regulator_is_enabled);
 
+/**
+ * regulator_can_change_voltage - check if regulator can change voltage
+ * @regulator: regulator source
+ *
+ * Returns positive if the regulator driver backing the source/client
+ * can change its voltage, false otherwise. Usefull for detecting fixed
+ * or dummy regulators and disabling voltage change logic in the client
+ * driver.
+ */
+int regulator_can_change_voltage(struct regulator *regulator)
+{
+       struct regulator_dev    *rdev = regulator->rdev;
+
+       if (rdev->constraints &&
+           rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE &&
+           rdev->desc->n_voltages > 1)
+               return 1;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(regulator_can_change_voltage);
+
 /**
  * regulator_count_voltages - count regulator_list_voltage() selectors
  * @regulator: regulator source
@@ -1891,6 +1924,10 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev,
 {
        if (selector >= rdev->desc->n_voltages)
                return -EINVAL;
+       if (selector < rdev->desc->linear_min_sel)
+               return 0;
+
+       selector -= rdev->desc->linear_min_sel;
 
        return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
 }
@@ -1974,11 +2011,16 @@ int regulator_is_supported_voltage(struct regulator *regulator,
        if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
                ret = regulator_get_voltage(regulator);
                if (ret >= 0)
-                       return (min_uV >= ret && ret <= max_uV);
+                       return (min_uV <= ret && ret <= max_uV);
                else
                        return ret;
        }
 
+       /* Any voltage within constrains range is fine? */
+       if (rdev->desc->continuous_voltage_range)
+               return min_uV >= rdev->constraints->min_uV &&
+                               max_uV <= rdev->constraints->max_uV;
+
        ret = regulator_count_voltages(regulator);
        if (ret < 0)
                return ret;
@@ -2114,6 +2156,8 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev,
        if (ret < 0)
                return ret;
 
+       ret += rdev->desc->linear_min_sel;
+
        /* Map back into a voltage to verify we're still in bounds */
        voltage = rdev->desc->ops->list_voltage(rdev, ret);
        if (voltage < min_uV || voltage > max_uV)
@@ -3365,7 +3409,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
                if (ret != 0) {
                        rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
                                 config->ena_gpio, ret);
-                       goto clean;
+                       goto wash;
                }
 
                rdev->ena_gpio = config->ena_gpio;
@@ -3445,10 +3489,11 @@ unset_supplies:
 
 scrub:
        if (rdev->supply)
-               regulator_put(rdev->supply);
+               _regulator_put(rdev->supply);
        if (rdev->ena_gpio)
                gpio_free(rdev->ena_gpio);
        kfree(rdev->constraints);
+wash:
        device_unregister(&rdev->dev);
        /* device core frees rdev */
        rdev = ERR_PTR(ret);
index 36c5b92fe0af26487cb093234800d534061c41f6..2afa5730f324ba1ef1bb068b5f63c79e41c11a8f 100644 (file)
@@ -460,7 +460,7 @@ static inline struct da903x_regulator_info *find_regulator_info(int id)
        return NULL;
 }
 
-static int __devinit da903x_regulator_probe(struct platform_device *pdev)
+static int da903x_regulator_probe(struct platform_device *pdev)
 {
        struct da903x_regulator_info *ri = NULL;
        struct regulator_dev *rdev;
@@ -499,7 +499,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit da903x_regulator_remove(struct platform_device *pdev)
+static int da903x_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -513,7 +513,7 @@ static struct platform_driver da903x_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = da903x_regulator_probe,
-       .remove         = __devexit_p(da903x_regulator_remove),
+       .remove         = da903x_regulator_remove,
 };
 
 static int __init da903x_regulator_init(void)
index 27355b1199e571ed090f24c5799dce5511d2cc94..d0963090442d220f69ebecb8c6dbbf22866b62f8 100644 (file)
@@ -129,17 +129,17 @@ static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA,
        else if (offset == 0)
                row = 1;
 
-       if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] ||
-           max_uA < da9052_current_limits[row][DA9052_MIN_UA])
-               return -EINVAL;
-
        for (i = DA9052_CURRENT_RANGE - 1; i >= 0; i--) {
-               if (da9052_current_limits[row][i] <= max_uA) {
+               if ((min_uA <= da9052_current_limits[row][i]) &&
+                   (da9052_current_limits[row][i] <= max_uA)) {
                        reg_val = i;
                        break;
                }
        }
 
+       if (i < 0)
+               return -EINVAL;
+
        /* Determine the even or odd position of the buck current limit
         * register field
        */
@@ -365,7 +365,7 @@ static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
        return NULL;
 }
 
-static int __devinit da9052_regulator_probe(struct platform_device *pdev)
+static int da9052_regulator_probe(struct platform_device *pdev)
 {
        struct regulator_config config = { };
        struct da9052_regulator *regulator;
@@ -430,7 +430,7 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit da9052_regulator_remove(struct platform_device *pdev)
+static int da9052_regulator_remove(struct platform_device *pdev)
 {
        struct da9052_regulator *regulator = platform_get_drvdata(pdev);
 
@@ -440,7 +440,7 @@ static int __devexit da9052_regulator_remove(struct platform_device *pdev)
 
 static struct platform_driver da9052_regulator_driver = {
        .probe = da9052_regulator_probe,
-       .remove = __devexit_p(da9052_regulator_remove),
+       .remove = da9052_regulator_remove,
        .driver = {
                .name = "da9052-regulator",
                .owner = THIS_MODULE,
diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c
new file mode 100644 (file)
index 0000000..a4b9cb8
--- /dev/null
@@ -0,0 +1,641 @@
+/*
+* Regulator driver for DA9055 PMIC
+*
+* Copyright(c) 2012 Dialog Semiconductor Ltd.
+*
+* Author: David Dajun Chen <dchen@diasemi.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 <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/reg.h>
+#include <linux/mfd/da9055/pdata.h>
+
+#define DA9055_MIN_UA          0
+#define DA9055_MAX_UA          3
+
+#define DA9055_LDO_MODE_SYNC   0
+#define DA9055_LDO_MODE_SLEEP  1
+
+#define DA9055_BUCK_MODE_SLEEP 1
+#define DA9055_BUCK_MODE_SYNC  2
+#define DA9055_BUCK_MODE_AUTO  3
+
+/* DA9055 REGULATOR IDs */
+#define DA9055_ID_BUCK1        0
+#define DA9055_ID_BUCK2        1
+#define DA9055_ID_LDO1         2
+#define DA9055_ID_LDO2         3
+#define DA9055_ID_LDO3         4
+#define DA9055_ID_LDO4         5
+#define DA9055_ID_LDO5         6
+#define DA9055_ID_LDO6         7
+
+/* DA9055 BUCK current limit */
+static const int da9055_current_limits[] = { 500000, 600000, 700000, 800000 };
+
+struct da9055_conf_reg {
+       int reg;
+       int sel_mask;
+       int en_mask;
+};
+
+struct da9055_volt_reg {
+       int reg_a;
+       int reg_b;
+       int sl_shift;
+       int v_mask;
+       int v_shift;
+};
+
+struct da9055_mode_reg {
+       int reg;
+       int mask;
+       int shift;
+};
+
+struct da9055_regulator_info {
+       struct regulator_desc reg_desc;
+       struct da9055_conf_reg conf;
+       struct da9055_volt_reg volt;
+       struct da9055_mode_reg mode;
+};
+
+struct da9055_regulator {
+       struct da9055 *da9055;
+       struct da9055_regulator_info *info;
+       struct regulator_dev *rdev;
+       enum gpio_select reg_rselect;
+};
+
+static unsigned int da9055_buck_get_mode(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int ret, mode = 0;
+
+       ret = da9055_reg_read(regulator->da9055, info->mode.reg);
+       if (ret < 0)
+               return ret;
+
+       switch ((ret & info->mode.mask) >> info->mode.shift) {
+       case DA9055_BUCK_MODE_SYNC:
+               mode = REGULATOR_MODE_FAST;
+               break;
+       case DA9055_BUCK_MODE_AUTO:
+               mode = REGULATOR_MODE_NORMAL;
+               break;
+       case DA9055_BUCK_MODE_SLEEP:
+               mode = REGULATOR_MODE_STANDBY;
+               break;
+       }
+
+       return mode;
+}
+
+static int da9055_buck_set_mode(struct regulator_dev *rdev,
+                                       unsigned int mode)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int val = 0;
+
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               val = DA9055_BUCK_MODE_SYNC << info->mode.shift;
+               break;
+       case REGULATOR_MODE_NORMAL:
+               val = DA9055_BUCK_MODE_AUTO << info->mode.shift;
+               break;
+       case REGULATOR_MODE_STANDBY:
+               val = DA9055_BUCK_MODE_SLEEP << info->mode.shift;
+               break;
+       }
+
+       return da9055_reg_update(regulator->da9055, info->mode.reg,
+                                info->mode.mask, val);
+}
+
+static unsigned int da9055_ldo_get_mode(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int ret;
+
+       ret = da9055_reg_read(regulator->da9055, info->volt.reg_b);
+       if (ret < 0)
+               return ret;
+
+       if (ret >> info->volt.sl_shift)
+               return REGULATOR_MODE_STANDBY;
+       else
+               return REGULATOR_MODE_NORMAL;
+}
+
+static int da9055_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       struct da9055_volt_reg volt = info->volt;
+       int val = 0;
+
+       switch (mode) {
+       case REGULATOR_MODE_NORMAL:
+       case REGULATOR_MODE_FAST:
+               val = DA9055_LDO_MODE_SYNC;
+               break;
+       case REGULATOR_MODE_STANDBY:
+               val = DA9055_LDO_MODE_SLEEP;
+               break;
+       }
+
+       return da9055_reg_update(regulator->da9055, volt.reg_b,
+                                1 << volt.sl_shift,
+                                val << volt.sl_shift);
+}
+
+static int da9055_buck_get_current_limit(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int ret;
+
+       ret = da9055_reg_read(regulator->da9055, DA9055_REG_BUCK_LIM);
+       if (ret < 0)
+               return ret;
+
+       ret &= info->mode.mask;
+       return da9055_current_limits[ret >> info->mode.shift];
+}
+
+static int da9055_buck_set_current_limit(struct regulator_dev *rdev, int min_uA,
+                                        int max_uA)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int i;
+
+       for (i = ARRAY_SIZE(da9055_current_limits) - 1; i >= 0; i--) {
+               if ((min_uA <= da9055_current_limits[i]) &&
+                   (da9055_current_limits[i] <= max_uA))
+                       return da9055_reg_update(regulator->da9055,
+                                                DA9055_REG_BUCK_LIM,
+                                                info->mode.mask,
+                                                i << info->mode.shift);
+       }
+
+       return -EINVAL;
+}
+
+static int da9055_regulator_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       struct da9055_volt_reg volt = info->volt;
+       int ret, sel;
+
+       /*
+        * There are two voltage register set A & B for voltage ramping but
+        * either one of then can be active therefore we first determine
+        * the active register set.
+        */
+       ret = da9055_reg_read(regulator->da9055, info->conf.reg);
+       if (ret < 0)
+               return ret;
+
+       ret &= info->conf.sel_mask;
+
+       /* Get the voltage for the active register set A/B */
+       if (ret == DA9055_REGUALTOR_SET_A)
+               ret = da9055_reg_read(regulator->da9055, volt.reg_a);
+       else
+               ret = da9055_reg_read(regulator->da9055, volt.reg_b);
+
+       if (ret < 0)
+               return ret;
+
+       sel = (ret & volt.v_mask);
+       return sel;
+}
+
+static int da9055_regulator_set_voltage_sel(struct regulator_dev *rdev,
+                                           unsigned int selector)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int ret;
+
+       /*
+        * Regulator register set A/B is not selected through GPIO therefore
+        * we use default register set A for voltage ramping.
+        */
+       if (regulator->reg_rselect == NO_GPIO) {
+               /* Select register set A */
+               ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       info->conf.sel_mask, DA9055_SEL_REG_A);
+               if (ret < 0)
+                       return ret;
+
+               /* Set the voltage */
+               return da9055_reg_update(regulator->da9055, info->volt.reg_a,
+                                        info->volt.v_mask, selector);
+       }
+
+       /*
+        * Here regulator register set A/B is selected through GPIO.
+        * Therefore we first determine the selected register set A/B and
+        * then set the desired voltage for that register set A/B.
+        */
+       ret = da9055_reg_read(regulator->da9055, info->conf.reg);
+       if (ret < 0)
+               return ret;
+
+       ret &= info->conf.sel_mask;
+
+       /* Set the voltage */
+       if (ret == DA9055_REGUALTOR_SET_A)
+               return da9055_reg_update(regulator->da9055, info->volt.reg_a,
+                                        info->volt.v_mask, selector);
+       else
+               return da9055_reg_update(regulator->da9055, info->volt.reg_b,
+                                        info->volt.v_mask, selector);
+}
+
+static int da9055_regulator_set_suspend_voltage(struct regulator_dev *rdev,
+                                               int uV)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int ret;
+
+       /* Select register set B for suspend voltage ramping. */
+       if (regulator->reg_rselect == NO_GPIO) {
+               ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       info->conf.sel_mask, DA9055_SEL_REG_B);
+               if (ret < 0)
+                       return ret;
+       }
+
+       ret = regulator_map_voltage_linear(rdev, uV, uV);
+       if (ret < 0)
+               return ret;
+
+       return da9055_reg_update(regulator->da9055, info->volt.reg_b,
+                                info->volt.v_mask, ret);
+}
+
+static int da9055_suspend_enable(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+
+       /* Select register set B for voltage ramping. */
+       if (regulator->reg_rselect == NO_GPIO)
+               return da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       info->conf.sel_mask, DA9055_SEL_REG_B);
+       else
+               return 0;
+}
+
+static int da9055_suspend_disable(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+
+       /* Diselect register set B. */
+       if (regulator->reg_rselect == NO_GPIO)
+               return da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       info->conf.sel_mask, DA9055_SEL_REG_A);
+       else
+               return 0;
+}
+
+static struct regulator_ops da9055_buck_ops = {
+       .get_mode = da9055_buck_get_mode,
+       .set_mode = da9055_buck_set_mode,
+
+       .get_current_limit = da9055_buck_get_current_limit,
+       .set_current_limit = da9055_buck_set_current_limit,
+
+       .get_voltage_sel = da9055_regulator_get_voltage_sel,
+       .set_voltage_sel = da9055_regulator_set_voltage_sel,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+
+       .set_suspend_voltage = da9055_regulator_set_suspend_voltage,
+       .set_suspend_enable = da9055_suspend_enable,
+       .set_suspend_disable = da9055_suspend_disable,
+       .set_suspend_mode = da9055_buck_set_mode,
+};
+
+static struct regulator_ops da9055_ldo_ops = {
+       .get_mode = da9055_ldo_get_mode,
+       .set_mode = da9055_ldo_set_mode,
+
+       .get_voltage_sel = da9055_regulator_get_voltage_sel,
+       .set_voltage_sel = da9055_regulator_set_voltage_sel,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+
+       .set_suspend_voltage = da9055_regulator_set_suspend_voltage,
+       .set_suspend_enable = da9055_suspend_enable,
+       .set_suspend_disable = da9055_suspend_disable,
+       .set_suspend_mode = da9055_ldo_set_mode,
+
+};
+
+#define DA9055_LDO(_id, step, min, max, vbits, voffset) \
+{\
+       .reg_desc = {\
+               .name = #_id,\
+               .ops = &da9055_ldo_ops,\
+               .type = REGULATOR_VOLTAGE,\
+               .id = DA9055_ID_##_id,\
+               .n_voltages = (max - min) / step + 1 + (voffset), \
+               .enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+               .enable_mask = 1, \
+               .min_uV = (min) * 1000,\
+               .uV_step = (step) * 1000,\
+               .linear_min_sel = (voffset),\
+               .owner = THIS_MODULE,\
+       },\
+       .conf = {\
+               .reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+               .sel_mask = (1 << 4),\
+               .en_mask = 1,\
+       },\
+       .volt = {\
+               .reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \
+               .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \
+               .sl_shift = 7,\
+               .v_mask = (1 << (vbits)) - 1,\
+               .v_shift = (vbits),\
+       },\
+}
+
+#define DA9055_BUCK(_id, step, min, max, vbits, voffset, mbits, sbits) \
+{\
+       .reg_desc = {\
+               .name = #_id,\
+               .ops = &da9055_buck_ops,\
+               .type = REGULATOR_VOLTAGE,\
+               .id = DA9055_ID_##_id,\
+               .n_voltages = (max - min) / step + 1 + (voffset), \
+               .enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+               .enable_mask = 1,\
+               .min_uV = (min) * 1000,\
+               .uV_step = (step) * 1000,\
+               .linear_min_sel = (voffset),\
+               .owner = THIS_MODULE,\
+       },\
+       .conf = {\
+               .reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+               .sel_mask = (1 << 4),\
+               .en_mask = 1,\
+       },\
+       .volt = {\
+               .reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \
+               .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \
+               .sl_shift = 7,\
+               .v_mask = (1 << (vbits)) - 1,\
+               .v_shift = (vbits),\
+       },\
+       .mode = {\
+               .reg = DA9055_REG_BCORE_MODE,\
+               .mask = (mbits),\
+               .shift = (sbits),\
+       },\
+}
+
+static struct da9055_regulator_info da9055_regulator_info[] = {
+       DA9055_BUCK(BUCK1, 25, 725, 2075, 6, 9, 0xc, 2),
+       DA9055_BUCK(BUCK2, 25, 925, 2500, 6, 0, 3, 0),
+       DA9055_LDO(LDO1, 50, 900, 3300, 6, 2),
+       DA9055_LDO(LDO2, 50, 900, 3300, 6, 3),
+       DA9055_LDO(LDO3, 50, 900, 3300, 6, 2),
+       DA9055_LDO(LDO4, 50, 900, 3300, 6, 2),
+       DA9055_LDO(LDO5, 50, 900, 2750, 6, 2),
+       DA9055_LDO(LDO6, 20, 900, 3300, 7, 0),
+};
+
+/*
+ * Configures regulator to be controlled either through GPIO 1 or 2.
+ * GPIO can control regulator state and/or select the regulator register
+ * set A/B for voltage ramping.
+ */
+static __devinit int da9055_gpio_init(struct da9055_regulator *regulator,
+                                     struct regulator_config *config,
+                                     struct da9055_pdata *pdata, int id)
+{
+       struct da9055_regulator_info *info = regulator->info;
+       int ret = 0;
+
+       if (pdata->gpio_ren && pdata->gpio_ren[id]) {
+               char name[18];
+               int gpio_mux = pdata->gpio_ren[id];
+
+               config->ena_gpio = pdata->ena_gpio[id];
+               config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
+               config->ena_gpio_invert = 1;
+
+               /*
+                * GPI pin is muxed with regulator to control the
+                * regulator state.
+                */
+               sprintf(name, "DA9055 GPI %d", gpio_mux);
+               ret = devm_gpio_request_one(config->dev, gpio_mux, GPIOF_DIR_IN,
+                                           name);
+               if (ret < 0)
+                       goto err;
+
+               /*
+                * Let the regulator know that its state is controlled
+                * through GPI.
+                */
+               ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       DA9055_E_GPI_MASK,
+                                       pdata->reg_ren[id]
+                                       << DA9055_E_GPI_SHIFT);
+               if (ret < 0)
+                       goto err;
+       }
+
+       if (pdata->gpio_rsel && pdata->gpio_rsel[id]) {
+               char name[18];
+               int gpio_mux = pdata->gpio_rsel[id];
+
+               regulator->reg_rselect = pdata->reg_rsel[id];
+
+               /*
+                * GPI pin is muxed with regulator to select the
+                * regulator register set A/B for voltage ramping.
+                */
+               sprintf(name, "DA9055 GPI %d", gpio_mux);
+               ret = devm_gpio_request_one(config->dev, gpio_mux, GPIOF_DIR_IN,
+                                           name);
+               if (ret < 0)
+                       goto err;
+
+               /*
+                * Let the regulator know that its register set A/B
+                * will be selected through GPI for voltage ramping.
+                */
+               ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       DA9055_V_GPI_MASK,
+                                       pdata->reg_rsel[id]
+                                       << DA9055_V_GPI_SHIFT);
+       }
+
+err:
+       return ret;
+}
+
+static irqreturn_t da9055_ldo5_6_oc_irq(int irq, void *data)
+{
+       struct da9055_regulator *regulator = data;
+
+       regulator_notifier_call_chain(regulator->rdev,
+                                     REGULATOR_EVENT_OVER_CURRENT, NULL);
+
+       return IRQ_HANDLED;
+}
+
+static inline struct da9055_regulator_info *find_regulator_info(int id)
+{
+       struct da9055_regulator_info *info;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(da9055_regulator_info); i++) {
+               info = &da9055_regulator_info[i];
+               if (info->reg_desc.id == id)
+                       return info;
+       }
+
+       return NULL;
+}
+
+static int __devinit da9055_regulator_probe(struct platform_device *pdev)
+{
+       struct regulator_config config = { };
+       struct da9055_regulator *regulator;
+       struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent);
+       struct da9055_pdata *pdata = da9055->dev->platform_data;
+       int ret, irq;
+
+       if (pdata == NULL || pdata->regulators[pdev->id] == NULL)
+               return -ENODEV;
+
+       regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9055_regulator),
+                                GFP_KERNEL);
+       if (!regulator)
+               return -ENOMEM;
+
+       regulator->info = find_regulator_info(pdev->id);
+       if (regulator->info == NULL) {
+               dev_err(&pdev->dev, "invalid regulator ID specified\n");
+               return -EINVAL;
+       }
+
+       regulator->da9055 = da9055;
+       config.dev = &pdev->dev;
+       config.driver_data = regulator;
+       config.regmap = da9055->regmap;
+
+       if (pdata && pdata->regulators)
+               config.init_data = pdata->regulators[pdev->id];
+
+       ret = da9055_gpio_init(regulator, &config, pdata, pdev->id);
+       if (ret < 0)
+               return ret;
+
+       regulator->rdev = regulator_register(&regulator->info->reg_desc,
+                                            &config);
+       if (IS_ERR(regulator->rdev)) {
+               dev_err(&pdev->dev, "Failed to register regulator %s\n",
+                       regulator->info->reg_desc.name);
+               ret = PTR_ERR(regulator->rdev);
+               return ret;
+       }
+
+       /* Only LDO 5 and 6 has got the over current interrupt */
+       if (pdev->id == DA9055_ID_LDO5 || pdev->id ==  DA9055_ID_LDO6) {
+               irq = platform_get_irq_byname(pdev, "REGULATOR");
+               irq = regmap_irq_get_virq(da9055->irq_data, irq);
+               ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                               da9055_ldo5_6_oc_irq,
+                                               IRQF_TRIGGER_HIGH |
+                                               IRQF_ONESHOT |
+                                               IRQF_PROBE_SHARED,
+                                               pdev->name, regulator);
+               if (ret != 0) {
+                       if (ret != -EBUSY) {
+                               dev_err(&pdev->dev,
+                               "Failed to request Regulator IRQ %d: %d\n",
+                               irq, ret);
+                               goto err_regulator;
+                       }
+               }
+       }
+
+       platform_set_drvdata(pdev, regulator);
+
+       return 0;
+
+err_regulator:
+       regulator_unregister(regulator->rdev);
+       return ret;
+}
+
+static int __devexit da9055_regulator_remove(struct platform_device *pdev)
+{
+       struct da9055_regulator *regulator = platform_get_drvdata(pdev);
+
+       regulator_unregister(regulator->rdev);
+
+       return 0;
+}
+
+static struct platform_driver da9055_regulator_driver = {
+       .probe = da9055_regulator_probe,
+       .remove = __devexit_p(da9055_regulator_remove),
+       .driver = {
+               .name = "da9055-regulator",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init da9055_regulator_init(void)
+{
+       return platform_driver_register(&da9055_regulator_driver);
+}
+subsys_initcall(da9055_regulator_init);
+
+static void __exit da9055_regulator_exit(void)
+{
+       platform_driver_unregister(&da9055_regulator_driver);
+}
+module_exit(da9055_regulator_exit);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9055 PMIC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9055-regulator");
index 359f8d18fc3f35f03f0314661aba33def33846f7..219d162b651e3c75f2077517e5b3e0b69c28100f 100644 (file)
@@ -412,7 +412,7 @@ dbx500_regulator_info[DB8500_NUM_REGULATORS] = {
        },
 };
 
-static __devinit int db8500_regulator_register(struct platform_device *pdev,
+static int db8500_regulator_register(struct platform_device *pdev,
                                        struct regulator_init_data *init_data,
                                        int id,
                                        struct device_node *np)
@@ -474,7 +474,7 @@ static struct of_regulator_match db8500_regulator_matches[] = {
        { .name = "db8500_esram34_ret",   .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM34RET, },
 };
 
-static __devinit int
+static int
 db8500_regulator_of_probe(struct platform_device *pdev,
                        struct device_node *np)
 {
@@ -491,7 +491,7 @@ db8500_regulator_of_probe(struct platform_device *pdev,
        return 0;
 }
 
-static int __devinit db8500_regulator_probe(struct platform_device *pdev)
+static int db8500_regulator_probe(struct platform_device *pdev)
 {
        struct regulator_init_data *db8500_init_data =
                                        dev_get_platdata(&pdev->dev);
index f2e5ecdc586424ba1f92947ee5c31f1ce3268cad..261f3d2299bc0a5d2d074824211172be7a6b8448 100644 (file)
@@ -173,7 +173,7 @@ int __attribute__((weak)) dbx500_regulator_testcase(
        return 0;
 }
 
-int __devinit
+int
 ux500_regulator_debug_init(struct platform_device *pdev,
        struct dbx500_regulator_info *regulator_info,
        int num_regulators)
@@ -230,7 +230,7 @@ exit_no_debugfs:
        return -ENOMEM;
 }
 
-int __devexit ux500_regulator_debug_exit(void)
+int ux500_regulator_debug_exit(void)
 {
        debugfs_remove_recursive(rdebug.dir);
        kfree(rdebug.state_after_suspend);
index 03a1d7c11ef2b5c9ce0d07c91517673cf83d30bb..df9f42524abb3fd1164f61e7bee4065985d59d24 100644 (file)
@@ -37,7 +37,7 @@ static struct regulator_desc dummy_desc = {
        .ops = &dummy_ops,
 };
 
-static int __devinit dummy_regulator_probe(struct platform_device *pdev)
+static int dummy_regulator_probe(struct platform_device *pdev)
 {
        struct regulator_config config = { };
        int ret;
index 339f4d732e973e5c4ca543d869da368af80a90c3..9165b0c40ed32a6b4e8a851e5c81f9b1f68f8be0 100644 (file)
@@ -230,7 +230,7 @@ static struct regmap_config fan53555_regmap_config = {
        .val_bits = 8,
 };
 
-static int __devinit fan53555_regulator_probe(struct i2c_client *client,
+static int fan53555_regulator_probe(struct i2c_client *client,
                                const struct i2c_device_id *id)
 {
        struct fan53555_device_info *di;
@@ -293,7 +293,7 @@ static int __devinit fan53555_regulator_probe(struct i2c_client *client,
 
 }
 
-static int __devexit fan53555_regulator_remove(struct i2c_client *client)
+static int fan53555_regulator_remove(struct i2c_client *client)
 {
        struct fan53555_device_info *di = i2c_get_clientdata(client);
 
@@ -311,7 +311,7 @@ static struct i2c_driver fan53555_regulator_driver = {
                .name = "fan53555-regulator",
        },
        .probe = fan53555_regulator_probe,
-       .remove = __devexit_p(fan53555_regulator_remove),
+       .remove = fan53555_regulator_remove,
        .id_table = fan53555_id,
 };
 
index 185468c4d38fcbe691c7842ca9a0f50068ca5e25..48d5b7608b00bd519cbb4c2434721335c91fa4d4 100644 (file)
@@ -134,7 +134,7 @@ static struct regulator_ops fixed_voltage_ops = {
        .list_voltage = fixed_voltage_list_voltage,
 };
 
-static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
+static int reg_fixed_voltage_probe(struct platform_device *pdev)
 {
        struct fixed_voltage_config *config;
        struct fixed_voltage_data *drvdata;
@@ -234,7 +234,7 @@ err:
        return ret;
 }
 
-static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev)
+static int reg_fixed_voltage_remove(struct platform_device *pdev)
 {
        struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev);
 
@@ -255,7 +255,7 @@ MODULE_DEVICE_TABLE(of, fixed_of_match);
 
 static struct platform_driver regulator_fixed_voltage_driver = {
        .probe          = reg_fixed_voltage_probe,
-       .remove         = __devexit_p(reg_fixed_voltage_remove),
+       .remove         = reg_fixed_voltage_remove,
        .driver         = {
                .name           = "reg-fixed-voltage",
                .owner          = THIS_MODULE,
index 8b5944f2d7d1ddd36e82e92d786770e469743dfe..2cfd9d3079e80ede35a5c61ff8314b820e8e2800 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
 #include <linux/regulator/gpio-regulator.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 
 struct gpio_regulator_data {
        struct regulator_desc desc;
@@ -129,18 +132,108 @@ static struct regulator_ops gpio_regulator_voltage_ops = {
        .list_voltage = gpio_regulator_list_voltage,
 };
 
+struct gpio_regulator_config *
+of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
+{
+       struct gpio_regulator_config *config;
+       struct property *prop;
+       const char *regtype;
+       int proplen, gpio, i;
+
+       config = devm_kzalloc(dev,
+                       sizeof(struct gpio_regulator_config),
+                       GFP_KERNEL);
+       if (!config)
+               return ERR_PTR(-ENOMEM);
+
+       config->init_data = of_get_regulator_init_data(dev, np);
+       if (!config->init_data)
+               return ERR_PTR(-EINVAL);
+
+       config->supply_name = config->init_data->constraints.name;
+
+       if (of_property_read_bool(np, "enable-active-high"))
+               config->enable_high = true;
+
+       if (of_property_read_bool(np, "enable-at-boot"))
+               config->enabled_at_boot = true;
+
+       of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
+
+       config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
+
+       /* Fetch GPIOs. */
+       for (i = 0; ; i++)
+               if (of_get_named_gpio(np, "gpios", i) < 0)
+                       break;
+       config->nr_gpios = i;
+
+       config->gpios = devm_kzalloc(dev,
+                               sizeof(struct gpio) * config->nr_gpios,
+                               GFP_KERNEL);
+       if (!config->gpios)
+               return ERR_PTR(-ENOMEM);
+
+       for (i = 0; config->nr_gpios; i++) {
+               gpio = of_get_named_gpio(np, "gpios", i);
+               if (gpio < 0)
+                       break;
+               config->gpios[i].gpio = gpio;
+       }
+
+       /* Fetch states. */
+       prop = of_find_property(np, "states", NULL);
+       if (!prop) {
+               dev_err(dev, "No 'states' property found\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       proplen = prop->length / sizeof(int);
+
+       config->states = devm_kzalloc(dev,
+                               sizeof(struct gpio_regulator_state)
+                               * (proplen / 2),
+                               GFP_KERNEL);
+       if (!config->states)
+               return ERR_PTR(-ENOMEM);
+
+       for (i = 0; i < proplen / 2; i++) {
+               config->states[i].value =
+                       be32_to_cpup((int *)prop->value + (i * 2));
+               config->states[i].gpios =
+                       be32_to_cpup((int *)prop->value + (i * 2 + 1));
+       }
+       config->nr_states = i;
+
+       of_property_read_string(np, "regulator-type", &regtype);
+
+       if (!strncmp("voltage", regtype, 7))
+               config->type = REGULATOR_VOLTAGE;
+       else if (!strncmp("current", regtype, 7))
+               config->type = REGULATOR_CURRENT;
+
+       return config;
+}
+
 static struct regulator_ops gpio_regulator_current_ops = {
        .get_current_limit = gpio_regulator_get_value,
        .set_current_limit = gpio_regulator_set_current_limit,
 };
 
-static int __devinit gpio_regulator_probe(struct platform_device *pdev)
+static int gpio_regulator_probe(struct platform_device *pdev)
 {
        struct gpio_regulator_config *config = pdev->dev.platform_data;
+       struct device_node *np = pdev->dev.of_node;
        struct gpio_regulator_data *drvdata;
        struct regulator_config cfg = { };
        int ptr, ret, state;
 
+       if (np) {
+               config = of_get_gpio_regulator_config(&pdev->dev, np);
+               if (IS_ERR(config))
+                       return PTR_ERR(config);
+       }
+
        drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data),
                               GFP_KERNEL);
        if (drvdata == NULL) {
@@ -215,6 +308,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
        cfg.dev = &pdev->dev;
        cfg.init_data = config->init_data;
        cfg.driver_data = drvdata;
+       cfg.of_node = np;
 
        if (config->enable_gpio >= 0)
                cfg.ena_gpio = config->enable_gpio;
@@ -254,7 +348,7 @@ err:
        return ret;
 }
 
-static int __devexit gpio_regulator_remove(struct platform_device *pdev)
+static int gpio_regulator_remove(struct platform_device *pdev)
 {
        struct gpio_regulator_data *drvdata = platform_get_drvdata(pdev);
 
@@ -270,12 +364,20 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev)
        return 0;
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id regulator_gpio_of_match[] __devinitconst = {
+       { .compatible = "regulator-gpio", },
+       {},
+};
+#endif
+
 static struct platform_driver gpio_regulator_driver = {
        .probe          = gpio_regulator_probe,
-       .remove         = __devexit_p(gpio_regulator_remove),
+       .remove         = gpio_regulator_remove,
        .driver         = {
                .name           = "gpio-regulator",
                .owner          = THIS_MODULE,
+               .of_match_table = of_match_ptr(regulator_gpio_of_match),
        },
 };
 
index d8ecf49a5777e383876aae1f5894adc43d0bf741..d1e5bee2a26b210685290f7bb98d0a5138315a87 100644 (file)
@@ -106,7 +106,7 @@ static const struct regulator_desc isl_rd[] = {
        },
 };
 
-static int __devinit isl6271a_probe(struct i2c_client *i2c,
+static int isl6271a_probe(struct i2c_client *i2c,
                                     const struct i2c_device_id *id)
 {
        struct regulator_config config = { };
@@ -151,7 +151,7 @@ error:
        return err;
 }
 
-static int __devexit isl6271a_remove(struct i2c_client *i2c)
+static int isl6271a_remove(struct i2c_client *i2c)
 {
        struct isl_pmic *pmic = i2c_get_clientdata(i2c);
        int i;
@@ -174,7 +174,7 @@ static struct i2c_driver isl6271a_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = isl6271a_probe,
-       .remove = __devexit_p(isl6271a_remove),
+       .remove = isl6271a_remove,
        .id_table = isl6271a_id,
 };
 
index 7c6e3b8ff484ad03ab60fd25d07f74d80395a65f..5f68ff11a2985bb6519d0b5d4f2a8c1e89ce9e05 100644 (file)
@@ -386,7 +386,7 @@ static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val)
        return ret;
 }
 
-static int __devinit setup_regulators(struct lp3971 *lp3971,
+static int setup_regulators(struct lp3971 *lp3971,
                                      struct lp3971_platform_data *pdata)
 {
        int i, err;
@@ -429,7 +429,7 @@ err_nomem:
        return err;
 }
 
-static int __devinit lp3971_i2c_probe(struct i2c_client *i2c,
+static int lp3971_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct lp3971 *lp3971;
@@ -472,7 +472,7 @@ err_detect:
        return ret;
 }
 
-static int __devexit lp3971_i2c_remove(struct i2c_client *i2c)
+static int lp3971_i2c_remove(struct i2c_client *i2c)
 {
        struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
        int i;
@@ -498,7 +498,7 @@ static struct i2c_driver lp3971_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe    = lp3971_i2c_probe,
-       .remove   = __devexit_p(lp3971_i2c_remove),
+       .remove   = lp3971_i2c_remove,
        .id_table = lp3971_i2c_id,
 };
 
index 3cdc755d9b225774aabf25a1101f4aeeae591cec..69c42c318b87c5506a4f1c9548bf1a303ddc3ae3 100644 (file)
@@ -481,7 +481,7 @@ static const struct regulator_desc regulators[] = {
        },
 };
 
-static int __devinit setup_regulators(struct lp3972 *lp3972,
+static int setup_regulators(struct lp3972 *lp3972,
        struct lp3972_platform_data *pdata)
 {
        int i, err;
@@ -523,7 +523,7 @@ err_nomem:
        return err;
 }
 
-static int __devinit lp3972_i2c_probe(struct i2c_client *i2c,
+static int lp3972_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct lp3972 *lp3972;
@@ -569,7 +569,7 @@ err_detect:
        return ret;
 }
 
-static int __devexit lp3972_i2c_remove(struct i2c_client *i2c)
+static int lp3972_i2c_remove(struct i2c_client *i2c)
 {
        struct lp3972 *lp3972 = i2c_get_clientdata(i2c);
        int i;
@@ -594,7 +594,7 @@ static struct i2c_driver lp3972_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe    = lp3972_i2c_probe,
-       .remove   = __devexit_p(lp3972_i2c_remove),
+       .remove   = lp3972_i2c_remove,
        .id_table = lp3972_i2c_id,
 };
 
index 708f4b6a17dcb02ee45b26223db11fc78b3319e3..9289ead715cab59d749c56222f605195051395db 100644 (file)
@@ -893,7 +893,7 @@ err_dev:
        return ret;
 }
 
-static int __devexit lp872x_remove(struct i2c_client *cl)
+static int lp872x_remove(struct i2c_client *cl)
 {
        struct lp872x *lp = i2c_get_clientdata(cl);
 
@@ -914,7 +914,7 @@ static struct i2c_driver lp872x_driver = {
                .owner = THIS_MODULE,
        },
        .probe = lp872x_probe,
-       .remove = __devexit_p(lp872x_remove),
+       .remove = lp872x_remove,
        .id_table = lp872x_ids,
 };
 
index ba3e0aa402de84a67cfcb3ac15ee8c0555f2eb1b..aef3f2b0c5ea433e45647f1c10a7a429d416a234 100644 (file)
@@ -429,18 +429,6 @@ static struct regulator_desc lp8788_buck_desc[] = {
        },
 };
 
-static int _gpio_request(struct lp8788_buck *buck, int gpio, char *name)
-{
-       struct device *dev = buck->lp->dev;
-
-       if (!gpio_is_valid(gpio)) {
-               dev_err(dev, "invalid gpio: %d\n", gpio);
-               return -EINVAL;
-       }
-
-       return devm_gpio_request_one(dev, gpio, DVS_LOW, name);
-}
-
 static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
                                enum lp8788_buck_id id)
 {
@@ -452,7 +440,8 @@ static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
        switch (id) {
        case BUCK1:
                gpio = pdata->buck1_dvs->gpio;
-               ret = _gpio_request(buck, gpio, b1_name);
+               ret = devm_gpio_request_one(buck->lp->dev, gpio, DVS_LOW,
+                                           b1_name);
                if (ret)
                        return ret;
 
@@ -461,7 +450,8 @@ static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
        case BUCK2:
                for (i = 0 ; i < LP8788_NUM_BUCK2_DVS ; i++) {
                        gpio = pdata->buck2_dvs->gpio[i];
-                       ret = _gpio_request(buck, gpio, b2_name[i]);
+                       ret = devm_gpio_request_one(buck->lp->dev, gpio,
+                                                   DVS_LOW, b2_name[i]);
                        if (ret)
                                return ret;
                }
@@ -504,7 +494,7 @@ set_default_dvs_mode:
                                  default_dvs_mode[id]);
 }
 
-static __devinit int lp8788_buck_probe(struct platform_device *pdev)
+static int lp8788_buck_probe(struct platform_device *pdev)
 {
        struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
        int id = pdev->id;
@@ -542,7 +532,7 @@ static __devinit int lp8788_buck_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit lp8788_buck_remove(struct platform_device *pdev)
+static int lp8788_buck_remove(struct platform_device *pdev)
 {
        struct lp8788_buck *buck = platform_get_drvdata(pdev);
 
@@ -554,7 +544,7 @@ static int __devexit lp8788_buck_remove(struct platform_device *pdev)
 
 static struct platform_driver lp8788_buck_driver = {
        .probe = lp8788_buck_probe,
-       .remove = __devexit_p(lp8788_buck_remove),
+       .remove = lp8788_buck_remove,
        .driver = {
                .name = LP8788_DEV_BUCK,
                .owner = THIS_MODULE,
index 6796eeb47dc6f65b1997f75cacc1f04cb8e7d6cf..3792741708ce65b4b0bbb3449643baef4a21b22c 100644 (file)
@@ -126,7 +126,7 @@ struct lp8788_ldo {
 };
 
 /* DLDO 1, 2, 3, 9 voltage table */
-const int lp8788_dldo1239_vtbl[] = {
+static const int lp8788_dldo1239_vtbl[] = {
        1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
        2600000, 2700000, 2800000, 2900000, 3000000, 2850000, 2850000, 2850000,
        2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
@@ -662,14 +662,6 @@ static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo,
                [EN_DLDO7]   = LP8788_EN_SEL_DLDO7_M,
                [EN_DLDO911] = LP8788_EN_SEL_DLDO911_M,
        };
-       u8 val[] = {
-               [EN_ALDO1]   = 0 << 5,
-               [EN_ALDO234] = 0 << 4,
-               [EN_ALDO5]   = 0 << 3,
-               [EN_ALDO7]   = 0 << 2,
-               [EN_DLDO7]   = 0 << 1,
-               [EN_DLDO911] = 0 << 0,
-       };
 
        switch (id) {
        case DLDO7:
@@ -708,11 +700,10 @@ static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo,
        return ret;
 
 set_default_ldo_enable_mode:
-       return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id],
-                               val[enable_id]);
+       return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id], 0);
 }
 
-static __devinit int lp8788_dldo_probe(struct platform_device *pdev)
+static int lp8788_dldo_probe(struct platform_device *pdev)
 {
        struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
        int id = pdev->id;
@@ -749,7 +740,7 @@ static __devinit int lp8788_dldo_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
+static int lp8788_dldo_remove(struct platform_device *pdev)
 {
        struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -761,14 +752,14 @@ static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
 
 static struct platform_driver lp8788_dldo_driver = {
        .probe = lp8788_dldo_probe,
-       .remove = __devexit_p(lp8788_dldo_remove),
+       .remove = lp8788_dldo_remove,
        .driver = {
                .name = LP8788_DEV_DLDO,
                .owner = THIS_MODULE,
        },
 };
 
-static __devinit int lp8788_aldo_probe(struct platform_device *pdev)
+static int lp8788_aldo_probe(struct platform_device *pdev)
 {
        struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
        int id = pdev->id;
@@ -805,7 +796,7 @@ static __devinit int lp8788_aldo_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
+static int lp8788_aldo_remove(struct platform_device *pdev)
 {
        struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -817,7 +808,7 @@ static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
 
 static struct platform_driver lp8788_aldo_driver = {
        .probe = lp8788_aldo_probe,
-       .remove = __devexit_p(lp8788_aldo_remove),
+       .remove = lp8788_aldo_remove,
        .driver = {
                .name = LP8788_DEV_ALDO,
                .owner = THIS_MODULE,
index f67af3c1b9638636f5bdde781d15b79d516b89e8..8c5a54f541b50964567ba739a128b0ae59ec286a 100644 (file)
@@ -44,6 +44,9 @@ struct max1586_data {
        unsigned int min_uV;
        unsigned int max_uV;
 
+       unsigned int v3_curr_sel;
+       unsigned int v6_curr_sel;
+
        struct regulator_dev *rdev[0];
 };
 
@@ -63,31 +66,60 @@ static int v6_voltages_uv[] = { 1, 1800000, 2500000, 3000000 };
  * R24 and R25=100kOhm as described in the data sheet.
  * The gain is approximately: 1 + R24/R25 + R24/185.5kOhm
  */
+static int max1586_v3_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct max1586_data *max1586 = rdev_get_drvdata(rdev);
+
+       return max1586->v3_curr_sel;
+}
+
 static int max1586_v3_set_voltage_sel(struct regulator_dev *rdev,
                                      unsigned selector)
 {
        struct max1586_data *max1586 = rdev_get_drvdata(rdev);
        struct i2c_client *client = max1586->client;
+       int ret;
        u8 v3_prog;
 
        dev_dbg(&client->dev, "changing voltage v3 to %dmv\n",
                regulator_list_voltage_linear(rdev, selector) / 1000);
 
        v3_prog = I2C_V3_SELECT | (u8) selector;
-       return i2c_smbus_write_byte(client, v3_prog);
+       ret = i2c_smbus_write_byte(client, v3_prog);
+       if (ret)
+               return ret;
+
+       max1586->v3_curr_sel = selector;
+
+       return 0;
+}
+
+static int max1586_v6_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct max1586_data *max1586 = rdev_get_drvdata(rdev);
+
+       return max1586->v6_curr_sel;
 }
 
 static int max1586_v6_set_voltage_sel(struct regulator_dev *rdev,
                                      unsigned int selector)
 {
-       struct i2c_client *client = rdev_get_drvdata(rdev);
+       struct max1586_data *max1586 = rdev_get_drvdata(rdev);
+       struct i2c_client *client = max1586->client;
        u8 v6_prog;
+       int ret;
 
        dev_dbg(&client->dev, "changing voltage v6 to %dmv\n",
                rdev->desc->volt_table[selector] / 1000);
 
        v6_prog = I2C_V6_SELECT | (u8) selector;
-       return i2c_smbus_write_byte(client, v6_prog);
+       ret = i2c_smbus_write_byte(client, v6_prog);
+       if (ret)
+               return ret;
+
+       max1586->v6_curr_sel = selector;
+
+       return 0;
 }
 
 /*
@@ -95,12 +127,14 @@ static int max1586_v6_set_voltage_sel(struct regulator_dev *rdev,
  * the set up value.
  */
 static struct regulator_ops max1586_v3_ops = {
+       .get_voltage_sel = max1586_v3_get_voltage_sel,
        .set_voltage_sel = max1586_v3_set_voltage_sel,
        .list_voltage = regulator_list_voltage_linear,
        .map_voltage = regulator_map_voltage_linear,
 };
 
 static struct regulator_ops max1586_v6_ops = {
+       .get_voltage_sel = max1586_v6_get_voltage_sel,
        .set_voltage_sel = max1586_v6_set_voltage_sel,
        .list_voltage = regulator_list_voltage_table,
 };
@@ -125,7 +159,7 @@ static struct regulator_desc max1586_reg[] = {
        },
 };
 
-static int __devinit max1586_pmic_probe(struct i2c_client *client,
+static int max1586_pmic_probe(struct i2c_client *client,
                                        const struct i2c_device_id *i2c_id)
 {
        struct regulator_dev **rdev;
@@ -148,6 +182,10 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client,
        max1586->min_uV = MAX1586_V3_MIN_UV / 1000 * pdata->v3_gain / 1000;
        max1586->max_uV = MAX1586_V3_MAX_UV / 1000 * pdata->v3_gain / 1000;
 
+       /* Set curr_sel to default voltage on power-up */
+       max1586->v3_curr_sel = 24; /* 1.3V */
+       max1586->v6_curr_sel = 0;
+
        rdev = max1586->rdev;
        for (i = 0; i < pdata->num_subdevs && i <= MAX1586_V6; i++) {
                id = pdata->subdevs[i].id;
@@ -188,7 +226,7 @@ err:
        return ret;
 }
 
-static int __devexit max1586_pmic_remove(struct i2c_client *client)
+static int max1586_pmic_remove(struct i2c_client *client)
 {
        struct max1586_data *max1586 = i2c_get_clientdata(client);
        int i;
@@ -207,7 +245,7 @@ MODULE_DEVICE_TABLE(i2c, max1586_id);
 
 static struct i2c_driver max1586_pmic_driver = {
        .probe = max1586_pmic_probe,
-       .remove = __devexit_p(max1586_pmic_remove),
+       .remove = max1586_pmic_remove,
        .driver         = {
                .name   = "max1586",
                .owner  = THIS_MODULE,
index 2a67d08658add7dfcabbc1c00d4a0a02b9b70a0d..b85040caaea318b13154927bc1beb0e13aef6ad4 100644 (file)
@@ -67,8 +67,94 @@ enum max77686_ramp_rate {
 
 struct max77686_data {
        struct regulator_dev *rdev[MAX77686_REGULATORS];
+       unsigned int opmode[MAX77686_REGULATORS];
 };
 
+/* Some BUCKS supports Normal[ON/OFF] mode during suspend */
+static int max77686_buck_set_suspend_disable(struct regulator_dev *rdev)
+{
+       unsigned int val;
+       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+
+       if (rdev->desc->id == MAX77686_BUCK1)
+               val = 0x1;
+       else
+               val = 0x1 << MAX77686_OPMODE_BUCK234_SHIFT;
+
+       max77686->opmode[rdev->desc->id] = val;
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask,
+                                 val);
+}
+
+/* Some LDOs supports [LPM/Normal]ON mode during suspend state */
+static int max77686_set_suspend_mode(struct regulator_dev *rdev,
+                                    unsigned int mode)
+{
+       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+       unsigned int val;
+
+       /* BUCK[5-9] doesn't support this feature */
+       if (rdev->desc->id >= MAX77686_BUCK5)
+               return 0;
+
+       switch (mode) {
+       case REGULATOR_MODE_IDLE:                       /* ON in LP Mode */
+               val = 0x2 << MAX77686_OPMODE_SHIFT;
+               break;
+       case REGULATOR_MODE_NORMAL:                     /* ON in Normal Mode */
+               val = 0x3 << MAX77686_OPMODE_SHIFT;
+               break;
+       default:
+               pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
+                       rdev->desc->name, mode);
+               return -EINVAL;
+       }
+
+       max77686->opmode[rdev->desc->id] = val;
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask,
+                                 val);
+}
+
+/* Some LDOs supports LPM-ON/OFF/Normal-ON mode during suspend state */
+static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev,
+                                    unsigned int mode)
+{
+       unsigned int val;
+       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+
+       switch (mode) {
+       case REGULATOR_MODE_STANDBY:                    /* switch off */
+               val = 0x1 << MAX77686_OPMODE_SHIFT;
+               break;
+       case REGULATOR_MODE_IDLE:                       /* ON in LP Mode */
+               val = 0x2 << MAX77686_OPMODE_SHIFT;
+               break;
+       case REGULATOR_MODE_NORMAL:                     /* ON in Normal Mode */
+               val = 0x3 << MAX77686_OPMODE_SHIFT;
+               break;
+       default:
+               pr_warn("%s: regulator_suspend_mode : 0x%x not supported\n",
+                       rdev->desc->name, mode);
+               return -EINVAL;
+       }
+
+       max77686->opmode[rdev->desc->id] = val;
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask,
+                                 val);
+}
+
+static int max77686_enable(struct regulator_dev *rdev)
+{
+       struct max77686_data *max77686 = rdev_get_drvdata(rdev);
+
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 rdev->desc->enable_mask,
+                                 max77686->opmode[rdev->desc->id]);
+}
+
 static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
 {
        unsigned int ramp_value = RAMP_RATE_NO_CTRL;
@@ -98,23 +184,49 @@ static struct regulator_ops max77686_ops = {
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
        .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = regulator_enable_regmap,
+       .enable                 = max77686_enable,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_suspend_mode       = max77686_set_suspend_mode,
+};
+
+static struct regulator_ops max77686_ldo_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = max77686_enable,
        .disable                = regulator_disable_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_suspend_mode       = max77686_ldo_set_suspend_mode,
+};
+
+static struct regulator_ops max77686_buck1_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = max77686_enable,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_suspend_disable    = max77686_buck_set_suspend_disable,
 };
 
 static struct regulator_ops max77686_buck_dvs_ops = {
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
        .is_enabled             = regulator_is_enabled_regmap,
-       .enable                 = regulator_enable_regmap,
+       .enable                 = max77686_enable,
        .disable                = regulator_disable_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .set_voltage_time_sel   = regulator_set_voltage_time_sel,
        .set_ramp_delay         = max77686_set_ramp_delay,
+       .set_suspend_disable    = max77686_buck_set_suspend_disable,
 };
 
 #define regulator_desc_ldo(num)                {                               \
@@ -133,7 +245,39 @@ static struct regulator_ops max77686_buck_dvs_ops = {
        .enable_mask    = MAX77686_OPMODE_MASK                          \
                        << MAX77686_OPMODE_SHIFT,                       \
 }
+#define regulator_desc_lpm_ldo(num)    {                               \
+       .name           = "LDO"#num,                                    \
+       .id             = MAX77686_LDO##num,                            \
+       .ops            = &max77686_ldo_ops,                            \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_LDO_MINUV,                           \
+       .uV_step        = MAX77686_LDO_UVSTEP,                          \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_SHIFT,                       \
+}
 #define regulator_desc_ldo_low(num)            {                       \
+       .name           = "LDO"#num,                                    \
+       .id             = MAX77686_LDO##num,                            \
+       .ops            = &max77686_ldo_ops,                            \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_LDO_LOW_MINUV,                       \
+       .uV_step        = MAX77686_LDO_LOW_UVSTEP,                      \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_SHIFT,                       \
+}
+#define regulator_desc_ldo1_low(num)           {                       \
        .name           = "LDO"#num,                                    \
        .id             = MAX77686_LDO##num,                            \
        .ops            = &max77686_ops,                                \
@@ -167,7 +311,7 @@ static struct regulator_ops max77686_buck_dvs_ops = {
 #define regulator_desc_buck1(num)              {                       \
        .name           = "BUCK"#num,                                   \
        .id             = MAX77686_BUCK##num,                           \
-       .ops            = &max77686_ops,                                \
+       .ops            = &max77686_buck1_ops,                          \
        .type           = REGULATOR_VOLTAGE,                            \
        .owner          = THIS_MODULE,                                  \
        .min_uV         = MAX77686_BUCK_MINUV,                          \
@@ -197,7 +341,7 @@ static struct regulator_ops max77686_buck_dvs_ops = {
 }
 
 static struct regulator_desc regulators[] = {
-       regulator_desc_ldo_low(1),
+       regulator_desc_ldo1_low(1),
        regulator_desc_ldo_low(2),
        regulator_desc_ldo(3),
        regulator_desc_ldo(4),
@@ -206,13 +350,13 @@ static struct regulator_desc regulators[] = {
        regulator_desc_ldo_low(7),
        regulator_desc_ldo_low(8),
        regulator_desc_ldo(9),
-       regulator_desc_ldo(10),
-       regulator_desc_ldo(11),
-       regulator_desc_ldo(12),
+       regulator_desc_lpm_ldo(10),
+       regulator_desc_lpm_ldo(11),
+       regulator_desc_lpm_ldo(12),
        regulator_desc_ldo(13),
-       regulator_desc_ldo(14),
+       regulator_desc_lpm_ldo(14),
        regulator_desc_ldo_low(15),
-       regulator_desc_ldo(16),
+       regulator_desc_lpm_ldo(16),
        regulator_desc_ldo(17),
        regulator_desc_ldo(18),
        regulator_desc_ldo(19),
@@ -280,7 +424,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
 }
 #endif /* CONFIG_OF */
 
-static __devinit int max77686_pmic_probe(struct platform_device *pdev)
+static int max77686_pmic_probe(struct platform_device *pdev)
 {
        struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -314,12 +458,14 @@ static __devinit int max77686_pmic_probe(struct platform_device *pdev)
 
        config.dev = &pdev->dev;
        config.regmap = iodev->regmap;
+       config.driver_data = max77686;
        platform_set_drvdata(pdev, max77686);
 
        for (i = 0; i < MAX77686_REGULATORS; i++) {
                config.init_data = pdata->regulators[i].initdata;
                config.of_node = pdata->regulators[i].of_node;
 
+               max77686->opmode[i] = regulators[i].enable_mask;
                max77686->rdev[i] = regulator_register(&regulators[i], &config);
                if (IS_ERR(max77686->rdev[i])) {
                        ret = PTR_ERR(max77686->rdev[i]);
@@ -337,7 +483,7 @@ err:
        return ret;
 }
 
-static int __devexit max77686_pmic_remove(struct platform_device *pdev)
+static int max77686_pmic_remove(struct platform_device *pdev)
 {
        struct max77686_data *max77686 = platform_get_drvdata(pdev);
        int i;
@@ -360,7 +506,7 @@ static struct platform_driver max77686_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max77686_pmic_probe,
-       .remove = __devexit_p(max77686_pmic_remove),
+       .remove = max77686_pmic_remove,
        .id_table = max77686_pmic_id,
 };
 
index 9d540cd02dab5f4de264dc35599322b773d6c484..3ca14380f22db06aba4338544cf62967d48fa900 100644 (file)
@@ -176,7 +176,7 @@ static struct regmap_config max8649_regmap_config = {
        .val_bits = 8,
 };
 
-static int __devinit max8649_regulator_probe(struct i2c_client *client,
+static int max8649_regulator_probe(struct i2c_client *client,
                                             const struct i2c_device_id *id)
 {
        struct max8649_platform_data *pdata = client->dev.platform_data;
@@ -271,7 +271,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit max8649_regulator_remove(struct i2c_client *client)
+static int max8649_regulator_remove(struct i2c_client *client)
 {
        struct max8649_regulator_info *info = i2c_get_clientdata(client);
 
@@ -291,7 +291,7 @@ MODULE_DEVICE_TABLE(i2c, max8649_id);
 
 static struct i2c_driver max8649_driver = {
        .probe          = max8649_regulator_probe,
-       .remove         = __devexit_p(max8649_regulator_remove),
+       .remove         = max8649_regulator_remove,
        .driver         = {
                .name   = "max8649",
        },
index 8d531742f593616d1145fef2aa00fd22e13f4b32..4d7c635c36c2d6cc92b1ecd8fafb9d533213ae21 100644 (file)
@@ -305,7 +305,7 @@ static const struct regulator_desc max8660_reg[] = {
        },
 };
 
-static int __devinit max8660_probe(struct i2c_client *client,
+static int max8660_probe(struct i2c_client *client,
                                   const struct i2c_device_id *i2c_id)
 {
        struct regulator_dev **rdev;
@@ -420,7 +420,7 @@ err_out:
        return ret;
 }
 
-static int __devexit max8660_remove(struct i2c_client *client)
+static int max8660_remove(struct i2c_client *client)
 {
        struct max8660 *max8660 = i2c_get_clientdata(client);
        int i;
@@ -440,7 +440,7 @@ MODULE_DEVICE_TABLE(i2c, max8660_id);
 
 static struct i2c_driver max8660_driver = {
        .probe = max8660_probe,
-       .remove = __devexit_p(max8660_remove),
+       .remove = max8660_remove,
        .driver         = {
                .name   = "max8660",
                .owner  = THIS_MODULE,
index af7607515ab951e2b688b31e0a1cffef8b8bc396..d1a77512d83e69501c2a4a3a3e8c3f09b75f7ba6 100644 (file)
@@ -275,7 +275,7 @@ static inline struct device_node *match_of_node(int index)
 }
 #endif
 
-static __devinit int max8907_regulator_probe(struct platform_device *pdev)
+static int max8907_regulator_probe(struct platform_device *pdev)
 {
        struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
        struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev);
@@ -368,7 +368,7 @@ err_unregister_regulator:
        return ret;
 }
 
-static __devexit int max8907_regulator_remove(struct platform_device *pdev)
+static int max8907_regulator_remove(struct platform_device *pdev)
 {
        struct max8907_regulator *pmic = platform_get_drvdata(pdev);
        int i;
@@ -385,7 +385,7 @@ static struct platform_driver max8907_regulator_driver = {
                   .owner = THIS_MODULE,
                   },
        .probe = max8907_regulator_probe,
-       .remove = __devexit_p(max8907_regulator_remove),
+       .remove = max8907_regulator_remove,
 };
 
 static int __init max8907_regulator_init(void)
index 9bb0be37495f417d65728720f2d13217d51962d5..446a854455535b4603fa2584f09498b0e557cc0e 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/max8925.h>
+#include <linux/of.h>
+#include <linux/regulator/of_regulator.h>
 
 #define SD1_DVM_VMIN           850000
 #define SD1_DVM_VMAX           1000000
@@ -187,6 +189,34 @@ static struct regulator_ops max8925_regulator_ldo_ops = {
        .enable_reg     = MAX8925_LDOCTL##_id,                  \
 }
 
+#ifdef CONFIG_OF
+static struct of_regulator_match max8925_regulator_matches[] = {
+       { .name = "SDV1",},
+       { .name = "SDV2",},
+       { .name = "SDV3",},
+       { .name = "LDO1",},
+       { .name = "LDO2",},
+       { .name = "LDO3",},
+       { .name = "LDO4",},
+       { .name = "LDO5",},
+       { .name = "LDO6",},
+       { .name = "LDO7",},
+       { .name = "LDO8",},
+       { .name = "LDO9",},
+       { .name = "LDO10",},
+       { .name = "LDO11",},
+       { .name = "LDO12",},
+       { .name = "LDO13",},
+       { .name = "LDO14",},
+       { .name = "LDO15",},
+       { .name = "LDO16",},
+       { .name = "LDO17",},
+       { .name = "LDO18",},
+       { .name = "LDO19",},
+       { .name = "LDO20",},
+};
+#endif
+
 static struct max8925_regulator_info max8925_regulator_info[] = {
        MAX8925_SDV(1, 637.5, 1425, 12.5),
        MAX8925_SDV(2,   650, 2225,   25),
@@ -214,7 +244,37 @@ static struct max8925_regulator_info max8925_regulator_info[] = {
        MAX8925_LDO(20, 750, 3900, 50),
 };
 
-static int __devinit max8925_regulator_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static int max8925_regulator_dt_init(struct platform_device *pdev,
+                                   struct max8925_regulator_info *info,
+                                   struct regulator_config *config,
+                                   int ridx)
+{
+       struct device_node *nproot, *np;
+       int rcount;
+       nproot = pdev->dev.parent->of_node;
+       if (!nproot)
+               return -ENODEV;
+       np = of_find_node_by_name(nproot, "regulators");
+       if (!np) {
+               dev_err(&pdev->dev, "failed to find regulators node\n");
+               return -ENODEV;
+       }
+
+       rcount = of_regulator_match(&pdev->dev, np,
+                               &max8925_regulator_matches[ridx], 1);
+       if (rcount < 0)
+               return -ENODEV;
+       config->init_data =     max8925_regulator_matches[ridx].init_data;
+       config->of_node = max8925_regulator_matches[ridx].of_node;
+
+       return 0;
+}
+#else
+#define max8925_regulator_dt_init(w, x, y, z)  (-1)
+#endif
+
+static int max8925_regulator_probe(struct platform_device *pdev)
 {
        struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
        struct regulator_init_data *pdata = pdev->dev.platform_data;
@@ -222,7 +282,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
        struct max8925_regulator_info *ri;
        struct resource *res;
        struct regulator_dev *rdev;
-       int i;
+       int i, regulator_idx;
 
        res = platform_get_resource(pdev, IORESOURCE_REG, 0);
        if (!res) {
@@ -231,9 +291,12 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
        }
        for (i = 0; i < ARRAY_SIZE(max8925_regulator_info); i++) {
                ri = &max8925_regulator_info[i];
-               if (ri->vol_reg == res->start)
+               if (ri->vol_reg == res->start) {
+                       regulator_idx = i;
                        break;
+               }
        }
+
        if (i == ARRAY_SIZE(max8925_regulator_info)) {
                dev_err(&pdev->dev, "Failed to find regulator %llu\n",
                        (unsigned long long)res->start);
@@ -243,9 +306,12 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
        ri->chip = chip;
 
        config.dev = &pdev->dev;
-       config.init_data = pdata;
        config.driver_data = ri;
 
+       if (max8925_regulator_dt_init(pdev, ri, &config, regulator_idx))
+               if (pdata)
+                       config.init_data = pdata;
+
        rdev = regulator_register(&ri->desc, &config);
        if (IS_ERR(rdev)) {
                dev_err(&pdev->dev, "failed to register regulator %s\n",
@@ -257,7 +323,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit max8925_regulator_remove(struct platform_device *pdev)
+static int max8925_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -273,7 +339,7 @@ static struct platform_driver max8925_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = max8925_regulator_probe,
-       .remove         = __devexit_p(max8925_regulator_remove),
+       .remove         = max8925_regulator_remove,
 };
 
 static int __init max8925_regulator_init(void)
index 355ca7bad9d59a9583cdda44ee986ced030ab5fa..fc7935a19e3a143f996aeeb4879d4d8ba75f0e9b 100644 (file)
@@ -126,7 +126,7 @@ static const struct regulator_desc regulator = {
        .owner          = THIS_MODULE,
 };
 
-static int __devinit max8952_pmic_probe(struct i2c_client *client,
+static int max8952_pmic_probe(struct i2c_client *client,
                const struct i2c_device_id *i2c_id)
 {
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@@ -247,7 +247,7 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit max8952_pmic_remove(struct i2c_client *client)
+static int max8952_pmic_remove(struct i2c_client *client)
 {
        struct max8952_data *max8952 = i2c_get_clientdata(client);
        struct max8952_platform_data *pdata = max8952->pdata;
@@ -268,7 +268,7 @@ MODULE_DEVICE_TABLE(i2c, max8952_ids);
 
 static struct i2c_driver max8952_pmic_driver = {
        .probe          = max8952_pmic_probe,
-       .remove         = __devexit_p(max8952_pmic_remove),
+       .remove         = max8952_pmic_remove,
        .driver         = {
                .name   = "max8952",
        },
diff --git a/drivers/regulator/max8973-regulator.c b/drivers/regulator/max8973-regulator.c
new file mode 100644 (file)
index 0000000..3ee2638
--- /dev/null
@@ -0,0 +1,505 @@
+/*
+ * max8973-regulator.c -- Maxim max8973
+ *
+ * Regulator driver for MAXIM 8973 DC-DC step-down switching regulator.
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * 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 <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/max8973-regulator.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+
+/* Register definitions */
+#define MAX8973_VOUT                                   0x0
+#define MAX8973_VOUT_DVS                               0x1
+#define MAX8973_CONTROL1                               0x2
+#define MAX8973_CONTROL2                               0x3
+#define MAX8973_CHIPID1                                        0x4
+#define MAX8973_CHIPID2                                        0x5
+
+#define MAX8973_MAX_VOUT_REG                           2
+
+/* MAX8973_VOUT */
+#define MAX8973_VOUT_ENABLE                            BIT(7)
+#define MAX8973_VOUT_MASK                              0x7F
+
+/* MAX8973_VOUT_DVS */
+#define MAX8973_DVS_VOUT_MASK                          0x7F
+
+/* MAX8973_CONTROL1 */
+#define MAX8973_SNS_ENABLE                             BIT(7)
+#define MAX8973_FPWM_EN_M                              BIT(6)
+#define MAX8973_NFSR_ENABLE                            BIT(5)
+#define MAX8973_AD_ENABLE                              BIT(4)
+#define MAX8973_BIAS_ENABLE                            BIT(3)
+#define MAX8973_FREQSHIFT_9PER                         BIT(2)
+
+#define MAX8973_RAMP_12mV_PER_US                       0x0
+#define MAX8973_RAMP_25mV_PER_US                       0x1
+#define MAX8973_RAMP_50mV_PER_US                       0x2
+#define MAX8973_RAMP_200mV_PER_US                      0x3
+
+/* MAX8973_CONTROL2 */
+#define MAX8973_WDTMR_ENABLE                           BIT(6)
+#define MAX8973_DISCH_ENBABLE                          BIT(5)
+#define MAX8973_FT_ENABLE                              BIT(4)
+
+#define MAX8973_CKKADV_TRIP_DISABLE                    0xC
+#define MAX8973_CKKADV_TRIP_75mV_PER_US                        0x0
+#define MAX8973_CKKADV_TRIP_150mV_PER_US               0x4
+#define MAX8973_CKKADV_TRIP_75mV_PER_US_HIST_DIS       0x8
+#define MAX8973_CONTROL_CLKADV_TRIP_MASK               0x00030000
+
+#define MAX8973_INDUCTOR_MIN_30_PER                    0x0
+#define MAX8973_INDUCTOR_NOMINAL                       0x1
+#define MAX8973_INDUCTOR_PLUS_30_PER                   0x2
+#define MAX8973_INDUCTOR_PLUS_60_PER                   0x3
+#define MAX8973_CONTROL_INDUCTOR_VALUE_MASK            0x00300000
+
+#define MAX8973_MIN_VOLATGE                            606250
+#define MAX8973_MAX_VOLATGE                            1400000
+#define MAX8973_VOLATGE_STEP                           6250
+#define MAX8973_BUCK_N_VOLTAGE                         0x80
+
+/* Maxim 8973 chip information */
+struct max8973_chip {
+       struct device *dev;
+       struct regulator_desc desc;
+       struct regulator_dev *rdev;
+       struct regmap *regmap;
+       bool enable_external_control;
+       int dvs_gpio;
+       int lru_index[MAX8973_MAX_VOUT_REG];
+       int curr_vout_val[MAX8973_MAX_VOUT_REG];
+       int curr_vout_reg;
+       int curr_gpio_val;
+       bool valid_dvs_gpio;
+};
+
+/*
+ * find_voltage_set_register: Find new voltage configuration register (VOUT).
+ * The finding of the new VOUT register will be based on the LRU mechanism.
+ * Each VOUT register will have different voltage configured . This
+ * Function will look if any of the VOUT register have requested voltage set
+ * or not.
+ *     - If it is already there then it will make that register as most
+ *       recently used and return as found so that caller need not to set
+ *       the VOUT register but need to set the proper gpios to select this
+ *       VOUT register.
+ *     - If requested voltage is not found then it will use the least
+ *       recently mechanism to get new VOUT register for new configuration
+ *       and will return not_found so that caller need to set new VOUT
+ *       register and then gpios (both).
+ */
+static bool find_voltage_set_register(struct max8973_chip *tps,
+               int req_vsel, int *vout_reg, int *gpio_val)
+{
+       int i;
+       bool found = false;
+       int new_vout_reg = tps->lru_index[MAX8973_MAX_VOUT_REG - 1];
+       int found_index = MAX8973_MAX_VOUT_REG - 1;
+
+       for (i = 0; i < MAX8973_MAX_VOUT_REG; ++i) {
+               if (tps->curr_vout_val[tps->lru_index[i]] == req_vsel) {
+                       new_vout_reg = tps->lru_index[i];
+                       found_index = i;
+                       found = true;
+                       goto update_lru_index;
+               }
+       }
+
+update_lru_index:
+       for (i = found_index; i > 0; i--)
+               tps->lru_index[i] = tps->lru_index[i - 1];
+
+       tps->lru_index[0] = new_vout_reg;
+       *gpio_val = new_vout_reg;
+       *vout_reg = MAX8973_VOUT + new_vout_reg;
+       return found;
+}
+
+static int max8973_dcdc_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct max8973_chip *max = rdev_get_drvdata(rdev);
+       unsigned int data;
+       int ret;
+
+       ret = regmap_read(max->regmap, max->curr_vout_reg, &data);
+       if (ret < 0) {
+               dev_err(max->dev, "register %d read failed, err = %d\n",
+                       max->curr_vout_reg, ret);
+               return ret;
+       }
+       return data & MAX8973_VOUT_MASK;
+}
+
+static int max8973_dcdc_set_voltage_sel(struct regulator_dev *rdev,
+            unsigned vsel)
+{
+       struct max8973_chip *max = rdev_get_drvdata(rdev);
+       int ret;
+       bool found = false;
+       int vout_reg = max->curr_vout_reg;
+       int gpio_val = max->curr_gpio_val;
+
+       /*
+        * If gpios are available to select the VOUT register then least
+        * recently used register for new configuration.
+        */
+       if (max->valid_dvs_gpio)
+               found = find_voltage_set_register(max, vsel,
+                                       &vout_reg, &gpio_val);
+
+       if (!found) {
+               ret = regmap_update_bits(max->regmap, vout_reg,
+                                       MAX8973_VOUT_MASK, vsel);
+               if (ret < 0) {
+                       dev_err(max->dev, "register %d update failed, err %d\n",
+                                vout_reg, ret);
+                       return ret;
+               }
+               max->curr_vout_reg = vout_reg;
+               max->curr_vout_val[gpio_val] = vsel;
+       }
+
+       /* Select proper VOUT register vio gpios */
+       if (max->valid_dvs_gpio) {
+               gpio_set_value_cansleep(max->dvs_gpio, gpio_val & 0x1);
+               max->curr_gpio_val = gpio_val;
+       }
+       return 0;
+}
+
+static int max8973_dcdc_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+       struct max8973_chip *max = rdev_get_drvdata(rdev);
+       int ret;
+       int pwm;
+
+       /* Enable force PWM mode in FAST mode only. */
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               pwm = MAX8973_FPWM_EN_M;
+               break;
+
+       case REGULATOR_MODE_NORMAL:
+               pwm = 0;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       ret = regmap_update_bits(max->regmap, MAX8973_CONTROL1,
+                               MAX8973_FPWM_EN_M, pwm);
+       if (ret < 0)
+               dev_err(max->dev, "register %d update failed, err %d\n",
+                               MAX8973_CONTROL1, ret);
+       return ret;
+}
+
+static unsigned int max8973_dcdc_get_mode(struct regulator_dev *rdev)
+{
+       struct max8973_chip *max = rdev_get_drvdata(rdev);
+       unsigned int data;
+       int ret;
+
+       ret = regmap_read(max->regmap, MAX8973_CONTROL1, &data);
+       if (ret < 0) {
+               dev_err(max->dev, "register %d read failed, err %d\n",
+                               MAX8973_CONTROL1, ret);
+               return ret;
+       }
+       return (data & MAX8973_FPWM_EN_M) ?
+               REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
+}
+
+static struct regulator_ops max8973_dcdc_ops = {
+       .get_voltage_sel        = max8973_dcdc_get_voltage_sel,
+       .set_voltage_sel        = max8973_dcdc_set_voltage_sel,
+       .list_voltage           = regulator_list_voltage_linear,
+       .set_mode               = max8973_dcdc_set_mode,
+       .get_mode               = max8973_dcdc_get_mode,
+};
+
+static int __devinit max8973_init_dcdc(struct max8973_chip *max,
+               struct max8973_regulator_platform_data *pdata)
+{
+       int ret;
+       uint8_t control1 = 0;
+       uint8_t control2 = 0;
+
+       if (pdata->control_flags & MAX8973_CONTROL_REMOTE_SENSE_ENABLE)
+               control1 |= MAX8973_SNS_ENABLE;
+
+       if (!(pdata->control_flags & MAX8973_CONTROL_FALLING_SLEW_RATE_ENABLE))
+               control1 |= MAX8973_NFSR_ENABLE;
+
+       if (pdata->control_flags & MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE)
+               control1 |= MAX8973_AD_ENABLE;
+
+       if (pdata->control_flags & MAX8973_CONTROL_BIAS_ENABLE)
+               control1 |= MAX8973_BIAS_ENABLE;
+
+       if (pdata->control_flags & MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE)
+               control1 |= MAX8973_FREQSHIFT_9PER;
+
+       /* Set ramp delay */
+       if (pdata->reg_init_data &&
+                       pdata->reg_init_data->constraints.ramp_delay) {
+               if (pdata->reg_init_data->constraints.ramp_delay < 25000)
+                       control1 = MAX8973_RAMP_12mV_PER_US;
+               else if (pdata->reg_init_data->constraints.ramp_delay < 50000)
+                       control1 = MAX8973_RAMP_25mV_PER_US;
+               else if (pdata->reg_init_data->constraints.ramp_delay < 200000)
+                       control1 = MAX8973_RAMP_50mV_PER_US;
+               else
+                       control1 = MAX8973_RAMP_200mV_PER_US;
+       } else {
+               control1 = MAX8973_RAMP_12mV_PER_US;
+               max->desc.ramp_delay = 12500;
+       }
+
+       if (!(pdata->control_flags & MAX8973_CONTROL_PULL_DOWN_ENABLE))
+               control2 |= MAX8973_DISCH_ENBABLE;
+
+       /*  Clock advance trip configuration */
+       switch (pdata->control_flags & MAX8973_CONTROL_CLKADV_TRIP_MASK) {
+       case MAX8973_CONTROL_CLKADV_TRIP_DISABLED:
+               control2 |= MAX8973_CKKADV_TRIP_DISABLE;
+               break;
+
+       case MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US:
+               control2 |= MAX8973_CKKADV_TRIP_75mV_PER_US;
+               break;
+
+       case MAX8973_CONTROL_CLKADV_TRIP_150mV_PER_US:
+               control2 |= MAX8973_CKKADV_TRIP_150mV_PER_US;
+               break;
+
+       case MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US_HIST_DIS:
+               control2 |= MAX8973_CKKADV_TRIP_75mV_PER_US_HIST_DIS;
+               break;
+       }
+
+       /* Configure inductor value */
+       switch (pdata->control_flags & MAX8973_CONTROL_INDUCTOR_VALUE_MASK) {
+       case MAX8973_CONTROL_INDUCTOR_VALUE_NOMINAL:
+               control2 |= MAX8973_INDUCTOR_NOMINAL;
+               break;
+
+       case MAX8973_CONTROL_INDUCTOR_VALUE_MINUS_30_PER:
+               control2 |= MAX8973_INDUCTOR_MIN_30_PER;
+               break;
+
+       case MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_30_PER:
+               control2 |= MAX8973_INDUCTOR_PLUS_30_PER;
+               break;
+
+       case MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_60_PER:
+               control2 |= MAX8973_INDUCTOR_PLUS_60_PER;
+               break;
+       }
+
+       ret = regmap_write(max->regmap, MAX8973_CONTROL1, control1);
+       if (ret < 0) {
+               dev_err(max->dev, "register %d write failed, err = %d",
+                               MAX8973_CONTROL1, ret);
+               return ret;
+       }
+
+       ret = regmap_write(max->regmap, MAX8973_CONTROL2, control2);
+       if (ret < 0) {
+               dev_err(max->dev, "register %d write failed, err = %d",
+                               MAX8973_CONTROL2, ret);
+               return ret;
+       }
+
+       /* If external control is enabled then disable EN bit */
+       if (max->enable_external_control) {
+               ret = regmap_update_bits(max->regmap, MAX8973_VOUT,
+                                               MAX8973_VOUT_ENABLE, 0);
+               if (ret < 0)
+                       dev_err(max->dev, "register %d update failed, err = %d",
+                               MAX8973_VOUT, ret);
+       }
+       return ret;
+}
+
+static const struct regmap_config max8973_regmap_config = {
+       .reg_bits               = 8,
+       .val_bits               = 8,
+       .max_register           = MAX8973_CHIPID2,
+       .cache_type             = REGCACHE_RBTREE,
+};
+
+static int __devinit max8973_probe(struct i2c_client *client,
+                                    const struct i2c_device_id *id)
+{
+       struct max8973_regulator_platform_data *pdata;
+       struct regulator_config config = { };
+       struct regulator_dev *rdev;
+       struct max8973_chip *max;
+       int ret;
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->dev, "No Platform data");
+               return -EIO;
+       }
+
+       max = devm_kzalloc(&client->dev, sizeof(*max), GFP_KERNEL);
+       if (!max) {
+               dev_err(&client->dev, "Memory allocation for max failed\n");
+               return -ENOMEM;
+       }
+
+       max->regmap = devm_regmap_init_i2c(client, &max8973_regmap_config);
+       if (IS_ERR(max->regmap)) {
+               ret = PTR_ERR(max->regmap);
+               dev_err(&client->dev, "regmap init failed, err %d\n", ret);
+               return ret;
+       }
+
+       i2c_set_clientdata(client, max);
+       max->dev = &client->dev;
+       max->desc.name = id->name;
+       max->desc.id = 0;
+       max->desc.ops = &max8973_dcdc_ops;
+       max->desc.type = REGULATOR_VOLTAGE;
+       max->desc.owner = THIS_MODULE;
+       max->desc.min_uV = MAX8973_MIN_VOLATGE;
+       max->desc.uV_step = MAX8973_VOLATGE_STEP;
+       max->desc.n_voltages = MAX8973_BUCK_N_VOLTAGE;
+
+       if (!pdata->enable_ext_control) {
+               max->desc.enable_reg = MAX8973_VOUT;
+               max->desc.enable_mask = MAX8973_VOUT_ENABLE;
+               max8973_dcdc_ops.enable = regulator_enable_regmap;
+               max8973_dcdc_ops.disable = regulator_disable_regmap;
+               max8973_dcdc_ops.is_enabled = regulator_is_enabled_regmap;
+       }
+
+       max->enable_external_control = pdata->enable_ext_control;
+       max->dvs_gpio = pdata->dvs_gpio;
+       max->curr_gpio_val = pdata->dvs_def_state;
+       max->curr_vout_reg = MAX8973_VOUT + pdata->dvs_def_state;
+       max->lru_index[0] = max->curr_vout_reg;
+       max->valid_dvs_gpio = false;
+
+       if (gpio_is_valid(max->dvs_gpio)) {
+               int gpio_flags;
+               int i;
+
+               gpio_flags = (pdata->dvs_def_state) ?
+                               GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+               ret = devm_gpio_request_one(&client->dev, max->dvs_gpio,
+                               gpio_flags, "max8973-dvs");
+               if (ret) {
+                       dev_err(&client->dev,
+                               "gpio_request for gpio %d failed, err = %d\n",
+                               max->dvs_gpio, ret);
+                       return ret;
+               }
+               max->valid_dvs_gpio = true;
+
+               /*
+                * Initialize the lru index with vout_reg id
+                * The index 0 will be most recently used and
+                * set with the max->curr_vout_reg */
+               for (i = 0; i < MAX8973_MAX_VOUT_REG; ++i)
+                       max->lru_index[i] = i;
+               max->lru_index[0] = max->curr_vout_reg;
+               max->lru_index[max->curr_vout_reg] = 0;
+       }
+
+       ret = max8973_init_dcdc(max, pdata);
+       if (ret < 0) {
+               dev_err(max->dev, "Max8973 Init failed, err = %d\n", ret);
+               return ret;
+       }
+
+       config.dev = &client->dev;
+       config.init_data = pdata->reg_init_data;
+       config.driver_data = max;
+       config.of_node = client->dev.of_node;
+       config.regmap = max->regmap;
+
+       /* Register the regulators */
+       rdev = regulator_register(&max->desc, &config);
+       if (IS_ERR(rdev)) {
+               ret = PTR_ERR(rdev);
+               dev_err(max->dev, "regulator register failed, err %d\n", ret);
+               return ret;
+       }
+
+       max->rdev = rdev;
+       return 0;
+}
+
+static int __devexit max8973_remove(struct i2c_client *client)
+{
+       struct max8973_chip *max = i2c_get_clientdata(client);
+
+       regulator_unregister(max->rdev);
+       return 0;
+}
+
+static const struct i2c_device_id max8973_id[] = {
+       {.name = "max8973",},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, max8973_id);
+
+static struct i2c_driver max8973_i2c_driver = {
+       .driver = {
+               .name = "max8973",
+               .owner = THIS_MODULE,
+       },
+       .probe = max8973_probe,
+       .remove = __devexit_p(max8973_remove),
+       .id_table = max8973_id,
+};
+
+static int __init max8973_init(void)
+{
+       return i2c_add_driver(&max8973_i2c_driver);
+}
+subsys_initcall(max8973_init);
+
+static void __exit max8973_cleanup(void)
+{
+       i2c_del_driver(&max8973_i2c_driver);
+}
+module_exit(max8973_cleanup);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("MAX8973 voltage regulator driver");
+MODULE_LICENSE("GPL v2");
index e39a0c7260dca5b7fe13098dbfd06d98c4b0b3e5..df0eafb0dc7e63a1f4a9e8bfb989d91caa1d9f63 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/bug.h>
 #include <linux/err.h>
 #include <linux/gpio.h>
+#include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
@@ -31,6 +32,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/mfd/max8997.h>
 #include <linux/mfd/max8997-private.h>
+#include <linux/regulator/of_regulator.h>
 
 struct max8997_data {
        struct device *dev;
@@ -933,22 +935,163 @@ static struct regulator_desc regulators[] = {
                                  max8997_charger_fixedstate_ops),
 };
 
-static __devinit int max8997_pmic_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev,
+                       struct max8997_platform_data *pdata,
+                       struct device_node *pmic_np)
+{
+       int i, gpio;
+
+       for (i = 0; i < 3; i++) {
+               gpio = of_get_named_gpio(pmic_np,
+                                       "max8997,pmic-buck125-dvs-gpios", i);
+               if (!gpio_is_valid(gpio)) {
+                       dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio);
+                       return -EINVAL;
+               }
+               pdata->buck125_gpios[i] = gpio;
+       }
+       return 0;
+}
+
+static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
+                                       struct max8997_platform_data *pdata)
+{
+       struct device_node *pmic_np, *regulators_np, *reg_np;
+       struct max8997_regulator_data *rdata;
+       unsigned int i, dvs_voltage_nr = 1, ret;
+
+       pmic_np = iodev->dev->of_node;
+       if (!pmic_np) {
+               dev_err(iodev->dev, "could not find pmic sub-node\n");
+               return -ENODEV;
+       }
+
+       regulators_np = of_find_node_by_name(pmic_np, "regulators");
+       if (!regulators_np) {
+               dev_err(iodev->dev, "could not find regulators sub-node\n");
+               return -EINVAL;
+       }
+
+       /* count the number of regulators to be supported in pmic */
+       pdata->num_regulators = 0;
+       for_each_child_of_node(regulators_np, reg_np)
+               pdata->num_regulators++;
+
+       rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
+                               pdata->num_regulators, GFP_KERNEL);
+       if (!rdata) {
+               dev_err(iodev->dev, "could not allocate memory for "
+                                               "regulator data\n");
+               return -ENOMEM;
+       }
+
+       pdata->regulators = rdata;
+       for_each_child_of_node(regulators_np, reg_np) {
+               for (i = 0; i < ARRAY_SIZE(regulators); i++)
+                       if (!of_node_cmp(reg_np->name, regulators[i].name))
+                               break;
+
+               if (i == ARRAY_SIZE(regulators)) {
+                       dev_warn(iodev->dev, "don't know how to configure "
+                               "regulator %s\n", reg_np->name);
+                       continue;
+               }
+
+               rdata->id = i;
+               rdata->initdata = of_get_regulator_init_data(
+                                               iodev->dev, reg_np);
+               rdata->reg_node = reg_np;
+               rdata++;
+       }
+
+       if (of_get_property(pmic_np, "max8997,pmic-buck1-uses-gpio-dvs", NULL))
+               pdata->buck1_gpiodvs = true;
+
+       if (of_get_property(pmic_np, "max8997,pmic-buck2-uses-gpio-dvs", NULL))
+               pdata->buck2_gpiodvs = true;
+
+       if (of_get_property(pmic_np, "max8997,pmic-buck5-uses-gpio-dvs", NULL))
+               pdata->buck5_gpiodvs = true;
+
+       if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
+                                               pdata->buck5_gpiodvs) {
+               ret = max8997_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
+               if (ret)
+                       return -EINVAL;
+
+               if (of_property_read_u32(pmic_np,
+                               "max8997,pmic-buck125-default-dvs-idx",
+                               &pdata->buck125_default_idx)) {
+                       pdata->buck125_default_idx = 0;
+               } else {
+                       if (pdata->buck125_default_idx >= 8) {
+                               pdata->buck125_default_idx = 0;
+                               dev_info(iodev->dev, "invalid value for "
+                               "default dvs index, using 0 instead\n");
+                       }
+               }
+
+               if (of_get_property(pmic_np,
+                       "max8997,pmic-ignore-gpiodvs-side-effect", NULL))
+                       pdata->ignore_gpiodvs_side_effect = true;
+
+               dvs_voltage_nr = 8;
+       }
+
+       if (of_property_read_u32_array(pmic_np,
+                               "max8997,pmic-buck1-dvs-voltage",
+                               pdata->buck1_voltage, dvs_voltage_nr)) {
+               dev_err(iodev->dev, "buck1 voltages not specified\n");
+               return -EINVAL;
+       }
+
+       if (of_property_read_u32_array(pmic_np,
+                               "max8997,pmic-buck2-dvs-voltage",
+                               pdata->buck2_voltage, dvs_voltage_nr)) {
+               dev_err(iodev->dev, "buck2 voltages not specified\n");
+               return -EINVAL;
+       }
+
+       if (of_property_read_u32_array(pmic_np,
+                               "max8997,pmic-buck5-dvs-voltage",
+                               pdata->buck5_voltage, dvs_voltage_nr)) {
+               dev_err(iodev->dev, "buck5 voltages not specified\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+#else
+static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev,
+                                       struct max8997_platform_data *pdata)
+{
+       return 0;
+}
+#endif /* CONFIG_OF */
+
+static int max8997_pmic_probe(struct platform_device *pdev)
 {
        struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
-       struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
+       struct max8997_platform_data *pdata = iodev->pdata;
        struct regulator_config config = { };
        struct regulator_dev **rdev;
        struct max8997_data *max8997;
        struct i2c_client *i2c;
-       int i, ret, size;
+       int i, ret, size, nr_dvs;
        u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0;
 
-       if (!pdata) {
+       if (IS_ERR_OR_NULL(pdata)) {
                dev_err(pdev->dev.parent, "No platform init data supplied.\n");
                return -ENODEV;
        }
 
+       if (iodev->dev->of_node) {
+               ret = max8997_pmic_dt_parse_pdata(iodev, pdata);
+               if (ret)
+                       return ret;
+       }
+
        max8997 = devm_kzalloc(&pdev->dev, sizeof(struct max8997_data),
                               GFP_KERNEL);
        if (!max8997)
@@ -973,7 +1116,10 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
        memcpy(max8997->buck125_gpios, pdata->buck125_gpios, sizeof(int) * 3);
        max8997->ignore_gpiodvs_side_effect = pdata->ignore_gpiodvs_side_effect;
 
-       for (i = 0; i < 8; i++) {
+       nr_dvs = (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
+                       pdata->buck5_gpiodvs) ? 8 : 1;
+
+       for (i = 0; i < nr_dvs; i++) {
                max8997->buck1_vol[i] = ret =
                        max8997_get_voltage_proper_val(
                                        &buck1245_voltage_map_desc,
@@ -1019,6 +1165,19 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
                                max_buck5, 0x3f);
        }
 
+       /* Initialize all the DVS related BUCK registers */
+       for (i = 0; i < nr_dvs; i++) {
+               max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
+                               max8997->buck1_vol[i],
+                               0x3f);
+               max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
+                               max8997->buck2_vol[i],
+                               0x3f);
+               max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
+                               max8997->buck5_vol[i],
+                               0x3f);
+       }
+
        /*
         * If buck 1, 2, and 5 do not care DVS GPIO settings, ignore them.
         * If at least one of them cares, set gpios.
@@ -1068,19 +1227,6 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
        max8997_update_reg(i2c, MAX8997_REG_BUCK5CTRL, (pdata->buck5_gpiodvs) ?
                        (1 << 1) : (0 << 1), 1 << 1);
 
-       /* Initialize all the DVS related BUCK registers */
-       for (i = 0; i < 8; i++) {
-               max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS1 + i,
-                               max8997->buck1_vol[i],
-                               0x3f);
-               max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS1 + i,
-                               max8997->buck2_vol[i],
-                               0x3f);
-               max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS1 + i,
-                               max8997->buck5_vol[i],
-                               0x3f);
-       }
-
        /* Misc Settings */
        max8997->ramp_delay = 10; /* set 10mV/us, which is the default */
        max8997_write_reg(i2c, MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9);
@@ -1101,6 +1247,7 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
                config.dev = max8997->dev;
                config.init_data = pdata->regulators[i].initdata;
                config.driver_data = max8997;
+               config.of_node = pdata->regulators[i].reg_node;
 
                rdev[i] = regulator_register(&regulators[id], &config);
                if (IS_ERR(rdev[i])) {
@@ -1120,7 +1267,7 @@ err_out:
        return ret;
 }
 
-static int __devexit max8997_pmic_remove(struct platform_device *pdev)
+static int max8997_pmic_remove(struct platform_device *pdev)
 {
        struct max8997_data *max8997 = platform_get_drvdata(pdev);
        struct regulator_dev **rdev = max8997->rdev;
@@ -1143,7 +1290,7 @@ static struct platform_driver max8997_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max8997_pmic_probe,
-       .remove = __devexit_p(max8997_pmic_remove),
+       .remove = max8997_pmic_remove,
        .id_table = max8997_pmic_id,
 };
 
index 5dfa920ff0c8873c91e8c02176af4d722f3c3659..b821d08eb64ae84b643f2cfe93cd0764738d21c9 100644 (file)
@@ -633,7 +633,7 @@ static struct regulator_desc regulators[] = {
        }
 };
 
-static __devinit int max8998_pmic_probe(struct platform_device *pdev)
+static int max8998_pmic_probe(struct platform_device *pdev)
 {
        struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -818,7 +818,7 @@ err_out:
        return ret;
 }
 
-static int __devexit max8998_pmic_remove(struct platform_device *pdev)
+static int max8998_pmic_remove(struct platform_device *pdev)
 {
        struct max8998_data *max8998 = platform_get_drvdata(pdev);
        struct regulator_dev **rdev = max8998->rdev;
@@ -842,7 +842,7 @@ static struct platform_driver max8998_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max8998_pmic_probe,
-       .remove = __devexit_p(max8998_pmic_remove),
+       .remove = max8998_pmic_remove,
        .id_table = max8998_pmic_id,
 };
 
index 0801a6d0c122e7e7b94e75b797497728ef2a7d36..c46c6705cd74538af5b30c2c112cde1cedad4df2 100644 (file)
@@ -392,7 +392,7 @@ static struct regulator_ops mc13783_gpo_regulator_ops = {
        .set_voltage = mc13xxx_fixed_regulator_set_voltage,
 };
 
-static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
+static int mc13783_regulator_probe(struct platform_device *pdev)
 {
        struct mc13xxx_regulator_priv *priv;
        struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
@@ -445,7 +445,7 @@ err:
        return ret;
 }
 
-static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
+static int mc13783_regulator_remove(struct platform_device *pdev)
 {
        struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
        struct mc13xxx_regulator_platform_data *pdata =
@@ -465,7 +465,7 @@ static struct platform_driver mc13783_regulator_driver = {
                .name   = "mc13783-regulator",
                .owner  = THIS_MODULE,
        },
-       .remove         = __devexit_p(mc13783_regulator_remove),
+       .remove         = mc13783_regulator_remove,
        .probe          = mc13783_regulator_probe,
 };
 
index 1fa63812f7ace6070dcfda38a14cd5aab0466b69..0d84b1f33199ca5251c425ba898ffad4296da88f 100644 (file)
@@ -486,7 +486,7 @@ static unsigned int mc13892_vcam_get_mode(struct regulator_dev *rdev)
 }
 
 
-static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
+static int mc13892_regulator_probe(struct platform_device *pdev)
 {
        struct mc13xxx_regulator_priv *priv;
        struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent);
@@ -588,7 +588,7 @@ err_unlock:
        return ret;
 }
 
-static int __devexit mc13892_regulator_remove(struct platform_device *pdev)
+static int mc13892_regulator_remove(struct platform_device *pdev)
 {
        struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
        int i;
@@ -606,7 +606,7 @@ static struct platform_driver mc13892_regulator_driver = {
                .name   = "mc13892-regulator",
                .owner  = THIS_MODULE,
        },
-       .remove = __devexit_p(mc13892_regulator_remove),
+       .remove = mc13892_regulator_remove,
        .probe  = mc13892_regulator_probe,
 };
 
index 88cbb832d555207b4e7fc124aa05b4afcbcbb3f1..4ed89c6541100e838e8d6c3afb5aea3e0ad5bebf 100644 (file)
@@ -162,7 +162,7 @@ struct regulator_ops mc13xxx_fixed_regulator_ops = {
 EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops);
 
 #ifdef CONFIG_OF
-int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
+int mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
 {
        struct device_node *parent, *child;
        int num = 0;
@@ -179,7 +179,7 @@ int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
 }
 EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt);
 
-struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt(
+struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
        struct platform_device *pdev, struct mc13xxx_regulator *regulators,
        int num_regulators)
 {
index 07aee694ba92abc4c8eab282b519a89dbff69ff1..e915629a25cf64ed660e9ac9f2b2112b1ea228e9 100644 (file)
@@ -309,68 +309,22 @@ static int palmas_list_voltage_smps(struct regulator_dev *dev,
        int id = rdev_get_id(dev);
        int mult = 1;
 
-       if (!selector)
-               return 0;
-
        /* Read the multiplier set in VSEL register to return
         * the correct voltage.
         */
        if (pmic->range[id])
                mult = 2;
 
-       /* Voltage is (0.49V + (selector * 0.01V)) * RANGE
-        * as defined in data sheet. RANGE is either x1 or x2
-        */
-       return  (490000 + (selector * 10000)) * mult;
-}
-
-static int palmas_get_voltage_smps_sel(struct regulator_dev *dev)
-{
-       struct palmas_pmic *pmic = rdev_get_drvdata(dev);
-       int id = rdev_get_id(dev);
-       int selector;
-       unsigned int reg;
-       unsigned int addr;
-
-       addr = palmas_regs_info[id].vsel_addr;
-
-       palmas_smps_read(pmic->palmas, addr, &reg);
-
-       selector = reg & PALMAS_SMPS12_VOLTAGE_VSEL_MASK;
-
-       /* Adjust selector to match list_voltage ranges */
-       if ((selector > 0) && (selector < 6))
-               selector = 6;
-       if (!selector)
-               selector = 5;
-       if (selector > 121)
-               selector = 121;
-       selector -= 5;
-
-       return selector;
-}
-
-static int palmas_set_voltage_smps_sel(struct regulator_dev *dev,
-               unsigned selector)
-{
-       struct palmas_pmic *pmic = rdev_get_drvdata(dev);
-       int id = rdev_get_id(dev);
-       unsigned int reg = 0;
-       unsigned int addr;
-
-       addr = palmas_regs_info[id].vsel_addr;
-
-       /* Make sure we don't change the value of RANGE */
-       if (pmic->range[id])
-               reg |= PALMAS_SMPS12_VOLTAGE_RANGE;
-
-       /* Adjust the linux selector into range used in VSEL register */
-       if (selector)
-               reg |= selector + 5;
-
-       palmas_smps_write(pmic->palmas, addr, reg);
-
-       return 0;
+       if (selector == 0)
+               return 0;
+       else if (selector < 6)
+               return 500000 * mult;
+       else
+               /* Voltage is linear mapping starting from selector 6,
+                * volt = (0.49V + ((selector - 5) * 0.01V)) * RANGE
+                * RANGE is either x1 or x2
+                */
+               return (490000 + ((selector - 5) * 10000)) * mult;
 }
 
 static int palmas_map_voltage_smps(struct regulator_dev *rdev,
@@ -386,11 +340,11 @@ static int palmas_map_voltage_smps(struct regulator_dev *rdev,
        if (pmic->range[id]) { /* RANGE is x2 */
                if (min_uV < 1000000)
                        min_uV = 1000000;
-               ret = DIV_ROUND_UP(min_uV - 1000000, 20000) + 1;
+               ret = DIV_ROUND_UP(min_uV - 1000000, 20000) + 6;
        } else {                /* RANGE is x1 */
                if (min_uV < 500000)
                        min_uV = 500000;
-               ret = DIV_ROUND_UP(min_uV - 500000, 10000) + 1;
+               ret = DIV_ROUND_UP(min_uV - 500000, 10000) + 6;
        }
 
        /* Map back into a voltage to verify we're still in bounds */
@@ -407,8 +361,8 @@ static struct regulator_ops palmas_ops_smps = {
        .disable                = palmas_disable_smps,
        .set_mode               = palmas_set_mode_smps,
        .get_mode               = palmas_get_mode_smps,
-       .get_voltage_sel        = palmas_get_voltage_smps_sel,
-       .set_voltage_sel        = palmas_set_voltage_smps_sel,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .list_voltage           = palmas_list_voltage_smps,
        .map_voltage            = palmas_map_voltage_smps,
 };
@@ -436,44 +390,14 @@ static int palmas_is_enabled_ldo(struct regulator_dev *dev)
        return !!(reg);
 }
 
-static int palmas_list_voltage_ldo(struct regulator_dev *dev,
-                                       unsigned selector)
-{
-       if (!selector)
-               return 0;
-
-       /* voltage is 0.85V + (selector * 0.05v) */
-       return  850000 + (selector * 50000);
-}
-
-static int palmas_map_voltage_ldo(struct regulator_dev *rdev,
-               int min_uV, int max_uV)
-{
-       int ret, voltage;
-
-       if (min_uV == 0)
-               return 0;
-
-       if (min_uV < 900000)
-               min_uV = 900000;
-       ret = DIV_ROUND_UP(min_uV - 900000, 50000) + 1;
-
-       /* Map back into a voltage to verify we're still in bounds */
-       voltage = palmas_list_voltage_ldo(rdev, ret);
-       if (voltage < min_uV || voltage > max_uV)
-               return -EINVAL;
-
-       return ret;
-}
-
 static struct regulator_ops palmas_ops_ldo = {
        .is_enabled             = palmas_is_enabled_ldo,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
-       .list_voltage           = palmas_list_voltage_ldo,
-       .map_voltage            = palmas_map_voltage_ldo,
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
 };
 
 /*
@@ -595,7 +519,7 @@ static struct of_regulator_match palmas_matches[] = {
        { .name = "ldousb", },
 };
 
-static void __devinit palmas_dt_to_pdata(struct device *dev,
+static void palmas_dt_to_pdata(struct device *dev,
                struct device_node *node,
                struct palmas_pmic_platform_data *pdata)
 {
@@ -663,7 +587,7 @@ static void __devinit palmas_dt_to_pdata(struct device *dev,
 }
 
 
-static __devinit int palmas_probe(struct platform_device *pdev)
+static int palmas_probe(struct platform_device *pdev)
 {
        struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
        struct palmas_pmic_platform_data *pdata = pdev->dev.platform_data;
@@ -733,6 +657,14 @@ static __devinit int palmas_probe(struct platform_device *pdev)
                                continue;
                }
 
+               /* Initialise sleep/init values from platform data */
+               if (pdata && pdata->reg_init[id]) {
+                       reg_init = pdata->reg_init[id];
+                       ret = palmas_smps_init(palmas, id, reg_init);
+                       if (ret)
+                               goto err_unregister_regulator;
+               }
+
                /* Register the regulators */
                pmic->desc[id].name = palmas_regs_info[id].name;
                pmic->desc[id].id = id;
@@ -753,29 +685,11 @@ static __devinit int palmas_probe(struct platform_device *pdev)
                        pmic->desc[id].uV_step = 1250000;
                        break;
                default:
-                       pmic->desc[id].ops = &palmas_ops_smps;
-                       pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
-               }
-
-               pmic->desc[id].type = REGULATOR_VOLTAGE;
-               pmic->desc[id].owner = THIS_MODULE;
-
-               /* Initialise sleep/init values from platform data */
-               if (pdata) {
-                       reg_init = pdata->reg_init[id];
-                       if (reg_init) {
-                               ret = palmas_smps_init(palmas, id, reg_init);
-                               if (ret)
-                                       goto err_unregister_regulator;
-                       }
-               }
-
-               /*
-                * read and store the RANGE bit for later use
-                * This must be done before regulator is probed otherwise
-                * we error in probe with unsuportable ranges.
-                */
-               if (id != PALMAS_REG_SMPS10) {
+                       /*
+                        * Read and store the RANGE bit for later use
+                        * This must be done before regulator is probed,
+                        * otherwise we error in probe with unsupportable ranges.
+                        */
                        addr = palmas_regs_info[id].vsel_addr;
 
                        ret = palmas_smps_read(pmic->palmas, addr, &reg);
@@ -783,8 +697,19 @@ static __devinit int palmas_probe(struct platform_device *pdev)
                                goto err_unregister_regulator;
                        if (reg & PALMAS_SMPS12_VOLTAGE_RANGE)
                                pmic->range[id] = 1;
+
+                       pmic->desc[id].ops = &palmas_ops_smps;
+                       pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
+                       pmic->desc[id].vsel_reg =
+                                       PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
+                                               palmas_regs_info[id].vsel_addr);
+                       pmic->desc[id].vsel_mask =
+                                       PALMAS_SMPS12_VOLTAGE_VSEL_MASK;
                }
 
+               pmic->desc[id].type = REGULATOR_VOLTAGE;
+               pmic->desc[id].owner = THIS_MODULE;
+
                if (pdata)
                        config.init_data = pdata->reg_data[id];
                else
@@ -821,6 +746,9 @@ static __devinit int palmas_probe(struct platform_device *pdev)
 
                pmic->desc[id].type = REGULATOR_VOLTAGE;
                pmic->desc[id].owner = THIS_MODULE;
+               pmic->desc[id].min_uV = 900000;
+               pmic->desc[id].uV_step = 50000;
+               pmic->desc[id].linear_min_sel = 1;
                pmic->desc[id].vsel_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE,
                                                palmas_regs_info[id].vsel_addr);
                pmic->desc[id].vsel_mask = PALMAS_LDO1_VOLTAGE_VSEL_MASK;
@@ -868,7 +796,7 @@ err_unregister_regulator:
        return ret;
 }
 
-static int __devexit palmas_remove(struct platform_device *pdev)
+static int palmas_remove(struct platform_device *pdev)
 {
        struct palmas_pmic *pmic = platform_get_drvdata(pdev);
        int id;
@@ -890,7 +818,7 @@ static struct platform_driver palmas_driver = {
                .owner = THIS_MODULE,
        },
        .probe = palmas_probe,
-       .remove = __devexit_p(palmas_remove),
+       .remove = palmas_remove,
 };
 
 static int __init palmas_init(void)
index 68777acc099fb6da2d0d4f1428b11ef1d704f9a3..4899342f1fc12cba02790a094c4be82f5ec30b15 100644 (file)
@@ -236,7 +236,7 @@ static const struct regulator_desc pcap_regulators[] = {
        VREG(VAUX4), VREG(VSIM), VREG(VSIM2), VREG(VVIB), VREG(SW1), VREG(SW2),
 };
 
-static int __devinit pcap_regulator_probe(struct platform_device *pdev)
+static int pcap_regulator_probe(struct platform_device *pdev)
 {
        struct regulator_dev *rdev;
        void *pcap = dev_get_drvdata(pdev->dev.parent);
@@ -255,7 +255,7 @@ static int __devinit pcap_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit pcap_regulator_remove(struct platform_device *pdev)
+static int pcap_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -271,7 +271,7 @@ static struct platform_driver pcap_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = pcap_regulator_probe,
-       .remove = __devexit_p(pcap_regulator_remove),
+       .remove = pcap_regulator_remove,
 };
 
 static int __init pcap_regulator_init(void)
index 092e5cb848a1e3b0e30736bf6fe08823220f77aa..534075e13d6dba59e5f21b4db91fb3b0d9acdb25 100644 (file)
 #include <linux/mfd/pcf50633/core.h>
 #include <linux/mfd/pcf50633/pmic.h>
 
-#define PCF50633_REGULATOR(_name, _id, _n)                     \
+#define PCF50633_REGULATOR(_name, _id, _min_uV, _uV_step, _min_sel, _n) \
        {                                                       \
                .name = _name,                                  \
                .id = PCF50633_REGULATOR_##_id,                 \
                .ops = &pcf50633_regulator_ops,                 \
                .n_voltages = _n,                               \
+               .min_uV = _min_uV,                              \
+               .uV_step = _uV_step,                            \
+               .linear_min_sel = _min_sel,                     \
                .type = REGULATOR_VOLTAGE,                      \
                .owner = THIS_MODULE,                           \
                .vsel_reg = PCF50633_REG_##_id##OUT,            \
                .enable_mask = PCF50633_REGULATOR_ON,           \
        }
 
-/* Bits from voltage value */
-static u8 auto_voltage_bits(unsigned int millivolts)
-{
-       if (millivolts < 1800)
-               return 0x2f;
-       if (millivolts > 3800)
-               return 0xff;
-
-       millivolts -= 625;
-
-       return millivolts / 25;
-}
-
-static u8 down_voltage_bits(unsigned int millivolts)
-{
-       if (millivolts < 625)
-               return 0;
-       else if (millivolts > 3000)
-               return 0xff;
-
-       millivolts -= 625;
-
-       return millivolts / 25;
-}
-
-static u8 ldo_voltage_bits(unsigned int millivolts)
-{
-       if (millivolts < 900)
-               return 0;
-       else if (millivolts > 3600)
-               return 0x1f;
-
-       millivolts -= 900;
-       return millivolts / 100;
-}
-
-/* Obtain voltage value from bits */
-static unsigned int auto_voltage_value(u8 bits)
-{
-       /* AUTOOUT: 00000000 to 00101110 are reserved.
-        * Return 0 for bits in reserved range, which means this selector code
-        * can't be used on this system */
-       if (bits < 0x2f)
-               return 0;
-
-       return 625 + (bits * 25);
-}
-
-
-static unsigned int down_voltage_value(u8 bits)
-{
-       return 625 + (bits * 25);
-}
-
-
-static unsigned int ldo_voltage_value(u8 bits)
-{
-       bits &= 0x1f;
-
-       return 900 + (bits * 100);
-}
-
-static int pcf50633_regulator_map_voltage(struct regulator_dev *rdev,
-                                         int min_uV, int max_uV)
-{
-       struct pcf50633 *pcf;
-       int regulator_id, millivolts;
-       u8 volt_bits;
-
-       pcf = rdev_get_drvdata(rdev);
-
-       regulator_id = rdev_get_id(rdev);
-       if (regulator_id >= PCF50633_NUM_REGULATORS)
-               return -EINVAL;
-
-       millivolts = min_uV / 1000;
-
-       switch (regulator_id) {
-       case PCF50633_REGULATOR_AUTO:
-               volt_bits = auto_voltage_bits(millivolts);
-               break;
-       case PCF50633_REGULATOR_DOWN1:
-       case PCF50633_REGULATOR_DOWN2:
-               volt_bits = down_voltage_bits(millivolts);
-               break;
-       case PCF50633_REGULATOR_LDO1:
-       case PCF50633_REGULATOR_LDO2:
-       case PCF50633_REGULATOR_LDO3:
-       case PCF50633_REGULATOR_LDO4:
-       case PCF50633_REGULATOR_LDO5:
-       case PCF50633_REGULATOR_LDO6:
-       case PCF50633_REGULATOR_HCLDO:
-       case PCF50633_REGULATOR_MEMLDO:
-               volt_bits = ldo_voltage_bits(millivolts);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return volt_bits;
-}
-
-static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
-                                               unsigned int index)
-{
-       int regulator_id = rdev_get_id(rdev);
-
-       int millivolts;
-
-       switch (regulator_id) {
-       case PCF50633_REGULATOR_AUTO:
-               millivolts = auto_voltage_value(index);
-               break;
-       case PCF50633_REGULATOR_DOWN1:
-       case PCF50633_REGULATOR_DOWN2:
-               millivolts = down_voltage_value(index);
-               break;
-       case PCF50633_REGULATOR_LDO1:
-       case PCF50633_REGULATOR_LDO2:
-       case PCF50633_REGULATOR_LDO3:
-       case PCF50633_REGULATOR_LDO4:
-       case PCF50633_REGULATOR_LDO5:
-       case PCF50633_REGULATOR_LDO6:
-       case PCF50633_REGULATOR_HCLDO:
-       case PCF50633_REGULATOR_MEMLDO:
-               millivolts = ldo_voltage_value(index);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return millivolts * 1000;
-}
-
 static struct regulator_ops pcf50633_regulator_ops = {
        .set_voltage_sel = regulator_set_voltage_sel_regmap,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
-       .list_voltage = pcf50633_regulator_list_voltage,
-       .map_voltage = pcf50633_regulator_map_voltage,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
        .enable = regulator_enable_regmap,
        .disable = regulator_disable_regmap,
        .is_enabled = regulator_is_enabled_regmap,
 };
 
 static const struct regulator_desc regulators[] = {
-       [PCF50633_REGULATOR_AUTO] = PCF50633_REGULATOR("auto", AUTO, 128),
-       [PCF50633_REGULATOR_DOWN1] = PCF50633_REGULATOR("down1", DOWN1, 96),
-       [PCF50633_REGULATOR_DOWN2] = PCF50633_REGULATOR("down2", DOWN2, 96),
-       [PCF50633_REGULATOR_LDO1] = PCF50633_REGULATOR("ldo1", LDO1, 28),
-       [PCF50633_REGULATOR_LDO2] = PCF50633_REGULATOR("ldo2", LDO2, 28),
-       [PCF50633_REGULATOR_LDO3] = PCF50633_REGULATOR("ldo3", LDO3, 28),
-       [PCF50633_REGULATOR_LDO4] = PCF50633_REGULATOR("ldo4", LDO4, 28),
-       [PCF50633_REGULATOR_LDO5] = PCF50633_REGULATOR("ldo5", LDO5, 28),
-       [PCF50633_REGULATOR_LDO6] = PCF50633_REGULATOR("ldo6", LDO6, 28),
-       [PCF50633_REGULATOR_HCLDO] = PCF50633_REGULATOR("hcldo", HCLDO, 28),
-       [PCF50633_REGULATOR_MEMLDO] = PCF50633_REGULATOR("memldo", MEMLDO, 28),
+       [PCF50633_REGULATOR_AUTO] =
+               PCF50633_REGULATOR("auto", AUTO, 1800000, 25000, 0x2f, 128),
+       [PCF50633_REGULATOR_DOWN1] =
+               PCF50633_REGULATOR("down1", DOWN1, 625000, 25000, 0, 96),
+       [PCF50633_REGULATOR_DOWN2] =
+               PCF50633_REGULATOR("down2", DOWN2, 625000, 25000, 0, 96),
+       [PCF50633_REGULATOR_LDO1] =
+               PCF50633_REGULATOR("ldo1", LDO1, 900000, 100000, 0, 28),
+       [PCF50633_REGULATOR_LDO2] =
+               PCF50633_REGULATOR("ldo2", LDO2, 900000, 100000, 0, 28),
+       [PCF50633_REGULATOR_LDO3] =
+               PCF50633_REGULATOR("ldo3", LDO3, 900000, 100000, 0, 28),
+       [PCF50633_REGULATOR_LDO4] =
+               PCF50633_REGULATOR("ldo4", LDO4, 900000, 100000, 0, 28),
+       [PCF50633_REGULATOR_LDO5] =
+               PCF50633_REGULATOR("ldo5", LDO5, 900000, 100000, 0, 28),
+       [PCF50633_REGULATOR_LDO6] =
+               PCF50633_REGULATOR("ldo6", LDO6, 900000, 100000, 0, 28),
+       [PCF50633_REGULATOR_HCLDO] =
+               PCF50633_REGULATOR("hcldo", HCLDO, 900000, 100000, 0, 28),
+       [PCF50633_REGULATOR_MEMLDO] =
+               PCF50633_REGULATOR("memldo", MEMLDO, 900000, 100000, 0, 28),
 };
 
-static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
+static int pcf50633_regulator_probe(struct platform_device *pdev)
 {
        struct regulator_dev *rdev;
        struct pcf50633 *pcf;
@@ -222,7 +102,7 @@ static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit pcf50633_regulator_remove(struct platform_device *pdev)
+static int pcf50633_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -237,7 +117,7 @@ static struct platform_driver pcf50633_regulator_driver = {
                .name = "pcf50633-regltr",
        },
        .probe = pcf50633_regulator_probe,
-       .remove = __devexit_p(pcf50633_regulator_remove),
+       .remove = pcf50633_regulator_remove,
 };
 
 static int __init pcf50633_regulator_init(void)
index 8bf4e8c9de9a2a811622ff0e8986a8fea9de2735..9e6f78694bf16d66d13e9ea95e160ed631603742 100644 (file)
@@ -119,7 +119,7 @@ static struct rc5t583_regulator_info rc5t583_reg_info[RC5T583_REGULATOR_MAX] = {
        RC5T583_REG(LDO9, LDOEN1, 1, LDODIS1, 1, 0x7F, 900, 3400, 25000, 133),
 };
 
-static int __devinit rc5t583_regulator_probe(struct platform_device *pdev)
+static int rc5t583_regulator_probe(struct platform_device *pdev)
 {
        struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
        struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
@@ -198,7 +198,7 @@ clean_exit:
        return ret;
 }
 
-static int __devexit rc5t583_regulator_remove(struct platform_device *pdev)
+static int rc5t583_regulator_remove(struct platform_device *pdev)
 {
        struct rc5t583_regulator *regs = platform_get_drvdata(pdev);
        int id;
@@ -214,7 +214,7 @@ static struct platform_driver rc5t583_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = rc5t583_regulator_probe,
-       .remove         = __devexit_p(rc5t583_regulator_remove),
+       .remove         = rc5t583_regulator_remove,
 };
 
 static int __init rc5t583_regulator_init(void)
index 926f9c8f2facde5b415b0e4bdc71b5fd2dc53fe6..bd062a2ffbe235cb9e4c4636b59b8676738676e8 100644 (file)
@@ -231,7 +231,7 @@ static struct regulator_desc regulators[] = {
        regulator_desc_buck10,
 };
 
-static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
+static int s2mps11_pmic_probe(struct platform_device *pdev)
 {
        struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -269,16 +269,16 @@ static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
 
        if (ramp_enable) {
                if (s2mps11->buck2_ramp)
-                       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) >> 6;
+                       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) << 6;
                if (s2mps11->buck3_ramp || s2mps11->buck4_ramp)
-                       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) >> 4;
+                       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) << 4;
                sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable);
        }
 
        ramp_reg &= 0x00;
-       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) >> 6;
-       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) >> 4;
-       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) >> 2;
+       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) << 6;
+       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) << 4;
+       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) << 2;
        ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9);
        sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg);
 
@@ -307,7 +307,7 @@ err:
        return ret;
 }
 
-static int __devexit s2mps11_pmic_remove(struct platform_device *pdev)
+static int s2mps11_pmic_remove(struct platform_device *pdev)
 {
        struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev);
        int i;
@@ -330,7 +330,7 @@ static struct platform_driver s2mps11_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = s2mps11_pmic_probe,
-       .remove = __devexit_p(s2mps11_pmic_remove),
+       .remove = s2mps11_pmic_remove,
        .id_table = s2mps11_pmic_id,
 };
 
index abe64a32aedf3a4b38ee05ea7c59849b4959642c..2b822bec3c2decf898d22371d67918c5d85db10e 100644 (file)
@@ -499,7 +499,7 @@ static struct regulator_desc regulators[] = {
        s5m8767_regulator_desc(BUCK9),
 };
 
-static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
+static int s5m8767_pmic_probe(struct platform_device *pdev)
 {
        struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -773,7 +773,7 @@ err:
        return ret;
 }
 
-static int __devexit s5m8767_pmic_remove(struct platform_device *pdev)
+static int s5m8767_pmic_remove(struct platform_device *pdev)
 {
        struct s5m8767_info *s5m8767 = platform_get_drvdata(pdev);
        struct regulator_dev **rdev = s5m8767->rdev;
@@ -798,7 +798,7 @@ static struct platform_driver s5m8767_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = s5m8767_pmic_probe,
-       .remove = __devexit_p(s5m8767_pmic_remove),
+       .remove = s5m8767_pmic_remove,
        .id_table = s5m8767_pmic_id,
 };
 
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
new file mode 100644 (file)
index 0000000..ab21133
--- /dev/null
@@ -0,0 +1,342 @@
+/*
+ * tps51632-regulator.c -- TI TPS51632
+ *
+ * Regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down Driverless
+ * Controller with serial VID control and DVFS.
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * 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 <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/tps51632-regulator.h>
+#include <linux/slab.h>
+
+/* Register definitions */
+#define TPS51632_VOLTAGE_SELECT_REG            0x0
+#define TPS51632_VOLTAGE_BASE_REG              0x1
+#define TPS51632_OFFSET_REG                    0x2
+#define TPS51632_IMON_REG                      0x3
+#define TPS51632_VMAX_REG                      0x4
+#define TPS51632_DVFS_CONTROL_REG              0x5
+#define TPS51632_POWER_STATE_REG               0x6
+#define TPS51632_SLEW_REGS                     0x7
+#define TPS51632_FAULT_REG                     0x14
+
+#define TPS51632_MAX_REG                       0x15
+
+#define TPS51632_VOUT_MASK                     0x7F
+#define TPS51632_VOUT_OFFSET_MASK              0x1F
+#define TPS51632_VMAX_MASK                     0x7F
+#define TPS51632_VMAX_LOCK                     0x80
+
+/* TPS51632_DVFS_CONTROL_REG */
+#define TPS51632_DVFS_PWMEN                    0x1
+#define TPS51632_DVFS_STEP_20                  0x2
+#define TPS51632_DVFS_VMAX_PG                  0x4
+#define TPS51632_DVFS_PWMRST                   0x8
+#define TPS51632_DVFS_OCA_EN                   0x10
+#define TPS51632_DVFS_FCCM                     0x20
+
+/* TPS51632_POWER_STATE_REG */
+#define TPS51632_POWER_STATE_MASK              0x03
+#define TPS51632_POWER_STATE_MULTI_PHASE_CCM   0x0
+#define TPS51632_POWER_STATE_SINGLE_PHASE_CCM  0x1
+#define TPS51632_POWER_STATE_SINGLE_PHASE_DCM  0x2
+
+#define TPS51632_MIN_VOLATGE                   500000
+#define TPS51632_MAX_VOLATGE                   1520000
+#define TPS51632_VOLATGE_STEP_10mV             10000
+#define TPS51632_VOLATGE_STEP_20mV             20000
+#define TPS51632_MAX_VSEL                      0x7F
+#define TPS51632_MIN_VSEL                      0x19
+#define TPS51632_DEFAULT_RAMP_DELAY            6000
+#define TPS51632_VOLT_VSEL(uV)                                 \
+               (DIV_ROUND_UP(uV - TPS51632_MIN_VOLATGE,        \
+                       TPS51632_VOLATGE_STEP_10mV) +           \
+                       TPS51632_MIN_VSEL)
+
+/* TPS51632 chip information */
+struct tps51632_chip {
+       struct device *dev;
+       struct regulator_desc desc;
+       struct regulator_dev *rdev;
+       struct regmap *regmap;
+       bool enable_pwm_dvfs;
+};
+
+static int tps51632_dcdc_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+       unsigned int data;
+       int ret;
+       unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
+       int vsel;
+
+       if (tps->enable_pwm_dvfs)
+               reg = TPS51632_VOLTAGE_BASE_REG;
+
+       ret = regmap_read(tps->regmap, reg, &data);
+       if (ret < 0) {
+               dev_err(tps->dev, "reg read failed, err %d\n", ret);
+               return ret;
+       }
+
+       vsel = data & TPS51632_VOUT_MASK;
+       return vsel;
+}
+
+static int tps51632_dcdc_set_voltage_sel(struct regulator_dev *rdev,
+               unsigned selector)
+{
+       struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+       int ret;
+       unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
+
+       if (tps->enable_pwm_dvfs)
+               reg = TPS51632_VOLTAGE_BASE_REG;
+
+       if (selector > TPS51632_MAX_VSEL)
+               return -EINVAL;
+
+       ret = regmap_write(tps->regmap, reg, selector);
+       if (ret < 0)
+               dev_err(tps->dev, "reg write failed, err %d\n", ret);
+       return ret;
+}
+
+static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev,
+               int ramp_delay)
+{
+       struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+       int bit = ramp_delay/6000;
+       int ret;
+
+       if (bit)
+               bit--;
+       ret = regmap_write(tps->regmap, TPS51632_SLEW_REGS, BIT(bit));
+       if (ret < 0)
+               dev_err(tps->dev, "SLEW reg write failed, err %d\n", ret);
+       return ret;
+}
+
+static struct regulator_ops tps51632_dcdc_ops = {
+       .get_voltage_sel        = tps51632_dcdc_get_voltage_sel,
+       .set_voltage_sel        = tps51632_dcdc_set_voltage_sel,
+       .list_voltage           = regulator_list_voltage_linear,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_ramp_delay         = tps51632_dcdc_set_ramp_delay,
+};
+
+static int tps51632_init_dcdc(struct tps51632_chip *tps,
+               struct tps51632_regulator_platform_data *pdata)
+{
+       int ret;
+       uint8_t control = 0;
+       int vsel;
+
+       if (!pdata->enable_pwm_dvfs)
+               goto skip_pwm_config;
+
+       control |= TPS51632_DVFS_PWMEN;
+       tps->enable_pwm_dvfs = pdata->enable_pwm_dvfs;
+       vsel = TPS51632_VOLT_VSEL(pdata->base_voltage_uV);
+       ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_BASE_REG, vsel);
+       if (ret < 0) {
+               dev_err(tps->dev, "BASE reg write failed, err %d\n", ret);
+               return ret;
+       }
+
+       if (pdata->dvfs_step_20mV)
+               control |= TPS51632_DVFS_STEP_20;
+
+       if (pdata->max_voltage_uV) {
+               unsigned int vmax;
+               /**
+                * TPS51632 hw behavior: VMAX register can be write only
+                * once as it get locked after first write. The lock get
+                * reset only when device is power-reset.
+                * Write register only when lock bit is not enabled.
+                */
+               ret = regmap_read(tps->regmap, TPS51632_VMAX_REG, &vmax);
+               if (ret < 0) {
+                       dev_err(tps->dev, "VMAX read failed, err %d\n", ret);
+                       return ret;
+               }
+               if (!(vmax & TPS51632_VMAX_LOCK)) {
+                       vsel = TPS51632_VOLT_VSEL(pdata->max_voltage_uV);
+                       ret = regmap_write(tps->regmap, TPS51632_VMAX_REG,
+                                       vsel);
+                       if (ret < 0) {
+                               dev_err(tps->dev,
+                                       "VMAX write failed, err %d\n", ret);
+                               return ret;
+                       }
+               }
+       }
+
+skip_pwm_config:
+       ret = regmap_write(tps->regmap, TPS51632_DVFS_CONTROL_REG, control);
+       if (ret < 0)
+               dev_err(tps->dev, "DVFS reg write failed, err %d\n", ret);
+       return ret;
+}
+
+static bool rd_wr_reg(struct device *dev, unsigned int reg)
+{
+       if ((reg >= 0x8) && (reg <= 0x10))
+               return false;
+       return true;
+}
+
+static const struct regmap_config tps51632_regmap_config = {
+       .reg_bits               = 8,
+       .val_bits               = 8,
+       .writeable_reg          = rd_wr_reg,
+       .readable_reg           = rd_wr_reg,
+       .max_register           = TPS51632_MAX_REG - 1,
+       .cache_type             = REGCACHE_RBTREE,
+};
+
+static int tps51632_probe(struct i2c_client *client,
+                               const struct i2c_device_id *id)
+{
+       struct tps51632_regulator_platform_data *pdata;
+       struct regulator_dev *rdev;
+       struct tps51632_chip *tps;
+       int ret;
+       struct regulator_config config = { };
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->dev, "No Platform data\n");
+               return -EINVAL;
+       }
+
+       if (pdata->enable_pwm_dvfs) {
+               if ((pdata->base_voltage_uV < TPS51632_MIN_VOLATGE) ||
+                   (pdata->base_voltage_uV > TPS51632_MAX_VOLATGE)) {
+                       dev_err(&client->dev, "Invalid base_voltage_uV setting\n");
+                       return -EINVAL;
+               }
+
+               if ((pdata->max_voltage_uV) &&
+                   ((pdata->max_voltage_uV < TPS51632_MIN_VOLATGE) ||
+                    (pdata->max_voltage_uV > TPS51632_MAX_VOLATGE))) {
+                       dev_err(&client->dev, "Invalid max_voltage_uV setting\n");
+                       return -EINVAL;
+               }
+       }
+
+       tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+       if (!tps) {
+               dev_err(&client->dev, "Memory allocation failed\n");
+               return -ENOMEM;
+       }
+
+       tps->dev = &client->dev;
+       tps->desc.name = id->name;
+       tps->desc.id = 0;
+       tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY;
+       tps->desc.min_uV = TPS51632_MIN_VOLATGE;
+       tps->desc.uV_step = TPS51632_VOLATGE_STEP_10mV;
+       tps->desc.linear_min_sel = TPS51632_MIN_VSEL;
+       tps->desc.n_voltages = TPS51632_MAX_VSEL + 1;
+       tps->desc.ops = &tps51632_dcdc_ops;
+       tps->desc.type = REGULATOR_VOLTAGE;
+       tps->desc.owner = THIS_MODULE;
+
+       tps->regmap = devm_regmap_init_i2c(client, &tps51632_regmap_config);
+       if (IS_ERR(tps->regmap)) {
+               ret = PTR_ERR(tps->regmap);
+               dev_err(&client->dev, "regmap init failed, err %d\n", ret);
+               return ret;
+       }
+       i2c_set_clientdata(client, tps);
+
+       ret = tps51632_init_dcdc(tps, pdata);
+       if (ret < 0) {
+               dev_err(tps->dev, "Init failed, err = %d\n", ret);
+               return ret;
+       }
+
+       /* Register the regulators */
+       config.dev = &client->dev;
+       config.init_data = pdata->reg_init_data;
+       config.driver_data = tps;
+       config.regmap = tps->regmap;
+       config.of_node = client->dev.of_node;
+
+       rdev = regulator_register(&tps->desc, &config);
+       if (IS_ERR(rdev)) {
+               dev_err(tps->dev, "regulator register failed\n");
+               return PTR_ERR(rdev);
+       }
+
+       tps->rdev = rdev;
+       return 0;
+}
+
+static int tps51632_remove(struct i2c_client *client)
+{
+       struct tps51632_chip *tps = i2c_get_clientdata(client);
+
+       regulator_unregister(tps->rdev);
+       return 0;
+}
+
+static const struct i2c_device_id tps51632_id[] = {
+       {.name = "tps51632",},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, tps51632_id);
+
+static struct i2c_driver tps51632_i2c_driver = {
+       .driver = {
+               .name = "tps51632",
+               .owner = THIS_MODULE,
+       },
+       .probe = tps51632_probe,
+       .remove = tps51632_remove,
+       .id_table = tps51632_id,
+};
+
+static int __init tps51632_init(void)
+{
+       return i2c_add_driver(&tps51632_i2c_driver);
+}
+subsys_initcall(tps51632_init);
+
+static void __exit tps51632_cleanup(void)
+{
+       i2c_del_driver(&tps51632_i2c_driver);
+}
+module_exit(tps51632_cleanup);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("TPS51632 voltage regulator driver");
+MODULE_LICENSE("GPL v2");
index 1378409efaec70170b8a3c70eeb09e1402abec33..ec9453ffb77fd561ec1c2d6c3591b7302bc16b5f 100644 (file)
@@ -127,7 +127,7 @@ static const struct regulator_desc tps6105x_regulator_desc = {
 /*
  * Registers the chip as a voltage regulator
  */
-static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
+static int tps6105x_regulator_probe(struct platform_device *pdev)
 {
        struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
        struct tps6105x_platform_data *pdata = tps6105x->pdata;
@@ -159,7 +159,7 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit tps6105x_regulator_remove(struct platform_device *pdev)
+static int tps6105x_regulator_remove(struct platform_device *pdev)
 {
        struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
        regulator_unregister(tps6105x->regulator);
@@ -172,7 +172,7 @@ static struct platform_driver tps6105x_regulator_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps6105x_regulator_probe,
-       .remove = __devexit_p(tps6105x_regulator_remove),
+       .remove = tps6105x_regulator_remove,
 };
 
 static __init int tps6105x_regulator_init(void)
index 68729a7c8709fbcbc8e88e8cf99924afc2e69f18..acbd63fde4153fb7ffe9cf3a8b22dd25aad43383 100644 (file)
@@ -243,7 +243,7 @@ static struct regulator_ops tps62360_dcdc_ops = {
        .get_mode               = tps62360_get_mode,
 };
 
-static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps,
+static int tps62360_init_dcdc(struct tps62360_chip *tps,
                struct tps62360_regulator_platform_data *pdata)
 {
        int ret;
@@ -339,7 +339,7 @@ static const struct of_device_id tps62360_of_match[] = {
 MODULE_DEVICE_TABLE(of, tps62360_of_match);
 #endif
 
-static int __devinit tps62360_probe(struct i2c_client *client,
+static int tps62360_probe(struct i2c_client *client,
                                     const struct i2c_device_id *id)
 {
        struct regulator_config config = { };
@@ -490,7 +490,7 @@ static int __devinit tps62360_probe(struct i2c_client *client,
  *
  * Unregister TPS driver as an i2c client device driver
  */
-static int __devexit tps62360_remove(struct i2c_client *client)
+static int tps62360_remove(struct i2c_client *client)
 {
        struct tps62360_chip *tps = i2c_get_clientdata(client);
 
@@ -531,7 +531,7 @@ static struct i2c_driver tps62360_i2c_driver = {
                .of_match_table = of_match_ptr(tps62360_of_match),
        },
        .probe = tps62360_probe,
-       .remove = __devexit_p(tps62360_remove),
+       .remove = tps62360_remove,
        .shutdown = tps62360_shutdown,
        .id_table = tps62360_id,
 };
index 6998d579d07b424891a79d09e62406a6b7e38d74..9b9af6d889c83214b06e9aa6b54767ede61289b1 100644 (file)
@@ -219,7 +219,7 @@ static struct regmap_config tps65023_regmap_config = {
        .val_bits = 8,
 };
 
-static int __devinit tps_65023_probe(struct i2c_client *client,
+static int tps_65023_probe(struct i2c_client *client,
                                     const struct i2c_device_id *id)
 {
        const struct tps_driver_data *drv_data = (void *)id->driver_data;
@@ -319,7 +319,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
        return error;
 }
 
-static int __devexit tps_65023_remove(struct i2c_client *client)
+static int tps_65023_remove(struct i2c_client *client)
 {
        struct tps_pmic *tps = i2c_get_clientdata(client);
        int i;
@@ -446,7 +446,7 @@ static struct i2c_driver tps_65023_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps_65023_probe,
-       .remove = __devexit_p(tps_65023_remove),
+       .remove = tps_65023_remove,
        .id_table = tps_65023_id,
 };
 
index 07d01ccdf308fdf2a6871ce60f6d60f380d4060c..0233cfb5656058a57ccd0dce40591701c16ce8b6 100644 (file)
@@ -356,7 +356,7 @@ static struct regulator_ops tps6507x_pmic_ops = {
        .list_voltage = regulator_list_voltage_table,
 };
 
-static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
+static int tps6507x_pmic_probe(struct platform_device *pdev)
 {
        struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
        struct tps_info *info = &tps6507x_pmic_regs[0];
@@ -439,7 +439,7 @@ fail:
        return error;
 }
 
-static int __devexit tps6507x_pmic_remove(struct platform_device *pdev)
+static int tps6507x_pmic_remove(struct platform_device *pdev)
 {
        struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
        struct tps6507x_pmic *tps = tps6507x_dev->pmic;
@@ -456,7 +456,7 @@ static struct platform_driver tps6507x_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps6507x_pmic_probe,
-       .remove = __devexit_p(tps6507x_pmic_remove),
+       .remove = tps6507x_pmic_remove,
 };
 
 static int __init tps6507x_pmic_init(void)
index 001ad554ac62634c6a77897ffc9a92cf641c2abf..41c391789c9790a59678dc1232bf0938e978a47e 100644 (file)
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/tps65090.h>
-#include <linux/regulator/tps65090-regulator.h>
 
 struct tps65090_regulator {
-       int             id;
-       /* used by regulator core */
-       struct regulator_desc   desc;
-
-       /* Device */
        struct device           *dev;
+       struct regulator_desc   *desc;
+       struct regulator_dev    *rdev;
+};
+
+static struct regulator_ops tps65090_ext_control_ops = {
+};
+
+static struct regulator_ops tps65090_reg_contol_ops = {
+       .enable         = regulator_enable_regmap,
+       .disable        = regulator_disable_regmap,
+       .is_enabled     = regulator_is_enabled_regmap,
 };
 
-static struct regulator_ops tps65090_ops = {
-       .enable = regulator_enable_regmap,
-       .disable = regulator_disable_regmap,
-       .is_enabled = regulator_is_enabled_regmap,
+static struct regulator_ops tps65090_ldo_ops = {
 };
 
-#define tps65090_REG(_id)                              \
+#define tps65090_REG_DESC(_id, _sname, _en_reg, _ops)  \
 {                                                      \
-       .id             = TPS65090_ID_##_id,            \
-       .desc = {                                       \
-               .name = tps65090_rails(_id),            \
-               .id = TPS65090_ID_##_id,                \
-               .ops = &tps65090_ops,                   \
-               .type = REGULATOR_VOLTAGE,              \
-               .owner = THIS_MODULE,                   \
-               .enable_reg = (TPS65090_ID_##_id) + 12, \
-               .enable_mask = BIT(0),                  \
-       },                                              \
+       .name = "TPS65090_RAILS"#_id,                   \
+       .supply_name = _sname,                          \
+       .id = TPS65090_REGULATOR_##_id,                 \
+       .ops = &_ops,                                   \
+       .enable_reg = _en_reg,                          \
+       .enable_mask = BIT(0),                          \
+       .type = REGULATOR_VOLTAGE,                      \
+       .owner = THIS_MODULE,                           \
 }
 
-static struct tps65090_regulator TPS65090_regulator[] = {
-       tps65090_REG(DCDC1),
-       tps65090_REG(DCDC2),
-       tps65090_REG(DCDC3),
-       tps65090_REG(FET1),
-       tps65090_REG(FET2),
-       tps65090_REG(FET3),
-       tps65090_REG(FET4),
-       tps65090_REG(FET5),
-       tps65090_REG(FET6),
-       tps65090_REG(FET7),
+static struct regulator_desc tps65090_regulator_desc[] = {
+       tps65090_REG_DESC(DCDC1, "vsys1",   0x0C, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(DCDC2, "vsys2",   0x0D, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(DCDC3, "vsys3",   0x0E, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET1,  "infet1",  0x0F, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET2,  "infet2",  0x10, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET3,  "infet3",  0x11, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET4,  "infet4",  0x12, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET5,  "infet5",  0x13, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET6,  "infet6",  0x14, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET7,  "infet7",  0x15, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(LDO1,  "vsys_l1", 0,    tps65090_ldo_ops),
+       tps65090_REG_DESC(LDO2,  "vsys_l2", 0,    tps65090_ldo_ops),
 };
 
-static inline struct tps65090_regulator *find_regulator_info(int id)
+static inline bool is_dcdc(int id)
 {
-       struct tps65090_regulator *ri;
-       int i;
+       switch (id) {
+       case TPS65090_REGULATOR_DCDC1:
+       case TPS65090_REGULATOR_DCDC2:
+       case TPS65090_REGULATOR_DCDC3:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static int tps65090_config_ext_control(
+       struct tps65090_regulator *ri, bool enable)
+{
+       int ret;
+       struct device *parent = ri->dev->parent;
+       unsigned int reg_en_reg = ri->desc->enable_reg;
+
+       if (enable)
+               ret = tps65090_set_bits(parent, reg_en_reg, 1);
+       else
+               ret =  tps65090_clr_bits(parent, reg_en_reg, 1);
+       if (ret < 0)
+               dev_err(ri->dev, "Error in updating reg 0x%x\n", reg_en_reg);
+       return ret;
+}
+
+static int tps65090_regulator_disable_ext_control(
+               struct tps65090_regulator *ri,
+               struct tps65090_regulator_plat_data *tps_pdata)
+{
+       int ret = 0;
+       struct device *parent = ri->dev->parent;
+       unsigned int reg_en_reg = ri->desc->enable_reg;
+
+       /*
+        * First enable output for internal control if require.
+        * And then disable external control.
+        */
+       if (tps_pdata->reg_init_data->constraints.always_on ||
+                       tps_pdata->reg_init_data->constraints.boot_on) {
+               ret =  tps65090_set_bits(parent, reg_en_reg, 0);
+               if (ret < 0) {
+                       dev_err(ri->dev, "Error in set reg 0x%x\n", reg_en_reg);
+                       return ret;
+               }
+       }
+       return tps65090_config_ext_control(ri, false);
+}
+
+static void tps65090_configure_regulator_config(
+               struct tps65090_regulator_plat_data *tps_pdata,
+               struct regulator_config *config)
+{
+       if (gpio_is_valid(tps_pdata->gpio)) {
+               int gpio_flag = GPIOF_OUT_INIT_LOW;
+
+               if (tps_pdata->reg_init_data->constraints.always_on ||
+                               tps_pdata->reg_init_data->constraints.boot_on)
+                       gpio_flag = GPIOF_OUT_INIT_HIGH;
 
-       for (i = 0; i < ARRAY_SIZE(TPS65090_regulator); i++) {
-               ri = &TPS65090_regulator[i];
-               if (ri->desc.id == id)
-                       return ri;
+               config->ena_gpio = tps_pdata->gpio;
+               config->ena_gpio_flags = gpio_flag;
        }
-       return NULL;
 }
 
-static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
+static int tps65090_regulator_probe(struct platform_device *pdev)
 {
        struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent);
        struct tps65090_regulator *ri = NULL;
        struct regulator_config config = { };
        struct regulator_dev *rdev;
-       struct tps65090_regulator_platform_data *tps_pdata;
-       int id = pdev->id;
+       struct tps65090_regulator_plat_data *tps_pdata;
+       struct tps65090_regulator *pmic;
+       struct tps65090_platform_data *tps65090_pdata;
+       int num;
+       int ret;
 
-       dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
+       dev_dbg(&pdev->dev, "Probing regulator\n");
 
-       ri = find_regulator_info(id);
-       if (ri == NULL) {
-               dev_err(&pdev->dev, "invalid regulator ID specified\n");
+       tps65090_pdata = dev_get_platdata(pdev->dev.parent);
+       if (!tps65090_pdata) {
+               dev_err(&pdev->dev, "Platform data missing\n");
                return -EINVAL;
        }
-       tps_pdata = pdev->dev.platform_data;
-       ri->dev = &pdev->dev;
-
-       config.dev = &pdev->dev;
-       config.init_data = &tps_pdata->regulator;
-       config.driver_data = ri;
-       config.regmap = tps65090_mfd->rmap;
-
-       rdev = regulator_register(&ri->desc, &config);
-       if (IS_ERR(rdev)) {
-               dev_err(&pdev->dev, "failed to register regulator %s\n",
-                               ri->desc.name);
-               return PTR_ERR(rdev);
+
+       pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic),
+                       GFP_KERNEL);
+       if (!pmic) {
+               dev_err(&pdev->dev, "mem alloc for pmic failed\n");
+               return -ENOMEM;
+       }
+
+       for (num = 0; num < TPS65090_REGULATOR_MAX; num++) {
+               tps_pdata = tps65090_pdata->reg_pdata[num];
+
+               ri = &pmic[num];
+               ri->dev = &pdev->dev;
+               ri->desc = &tps65090_regulator_desc[num];
+
+               /*
+                * TPS5090 DCDC support the control from external digital input.
+                * Configure it as per platform data.
+                */
+               if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data) {
+                       if (tps_pdata->enable_ext_control) {
+                               tps65090_configure_regulator_config(
+                                               tps_pdata, &config);
+                               ri->desc->ops = &tps65090_ext_control_ops;
+                       } else {
+                               ret = tps65090_regulator_disable_ext_control(
+                                               ri, tps_pdata);
+                               if (ret < 0) {
+                                       dev_err(&pdev->dev,
+                                               "failed disable ext control\n");
+                                       goto scrub;
+                               }
+                       }
+               }
+
+               config.dev = &pdev->dev;
+               config.driver_data = ri;
+               config.regmap = tps65090_mfd->rmap;
+               if (tps_pdata)
+                       config.init_data = tps_pdata->reg_init_data;
+               else
+                       config.init_data = NULL;
+
+               rdev = regulator_register(ri->desc, &config);
+               if (IS_ERR(rdev)) {
+                       dev_err(&pdev->dev, "failed to register regulator %s\n",
+                               ri->desc->name);
+                       ret = PTR_ERR(rdev);
+                       goto scrub;
+               }
+               ri->rdev = rdev;
+
+               /* Enable external control if it is require */
+               if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data &&
+                               tps_pdata->enable_ext_control) {
+                       ret = tps65090_config_ext_control(ri, true);
+                       if (ret < 0) {
+                               /* Increment num to get unregister rdev */
+                               num++;
+                               goto scrub;
+                       }
+               }
        }
 
-       platform_set_drvdata(pdev, rdev);
+       platform_set_drvdata(pdev, pmic);
        return 0;
+
+scrub:
+       while (--num >= 0) {
+               ri = &pmic[num];
+               regulator_unregister(ri->rdev);
+       }
+       return ret;
 }
 
-static int __devexit tps65090_regulator_remove(struct platform_device *pdev)
+static int tps65090_regulator_remove(struct platform_device *pdev)
 {
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
+       struct tps65090_regulator *pmic = platform_get_drvdata(pdev);
+       struct tps65090_regulator *ri;
+       int num;
 
-       regulator_unregister(rdev);
+       for (num = 0; num < TPS65090_REGULATOR_MAX; ++num) {
+               ri = &pmic[num];
+               regulator_unregister(ri->rdev);
+       }
        return 0;
 }
 
 static struct platform_driver tps65090_regulator_driver = {
        .driver = {
-               .name   = "tps65090-regulator",
+               .name   = "tps65090-pmic",
                .owner  = THIS_MODULE,
        },
        .probe          = tps65090_regulator_probe,
-       .remove         = __devexit_p(tps65090_regulator_remove),
+       .remove         = tps65090_regulator_remove,
 };
 
 static int __init tps65090_regulator_init(void)
@@ -148,3 +269,4 @@ module_exit(tps65090_regulator_exit);
 MODULE_DESCRIPTION("tps65090 regulator driver");
 MODULE_AUTHOR("Venu Byravarasu <vbyravarasu@nvidia.com>");
 MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:tps65090-pmic");
index ab00cab905b730459c6e752907f1139aaec9ee57..73dce76641265590179cb2440e75ad71ffd722d0 100644 (file)
@@ -332,7 +332,7 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev)
 }
 #endif
 
-static int __devinit tps65217_regulator_probe(struct platform_device *pdev)
+static int tps65217_regulator_probe(struct platform_device *pdev)
 {
        struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
        struct tps65217_board *pdata = dev_get_platdata(tps->dev);
@@ -397,7 +397,7 @@ err_unregister_regulator:
        return ret;
 }
 
-static int __devexit tps65217_regulator_remove(struct platform_device *pdev)
+static int tps65217_regulator_remove(struct platform_device *pdev)
 {
        struct tps65217 *tps = platform_get_drvdata(pdev);
        unsigned int i;
@@ -415,7 +415,7 @@ static struct platform_driver tps65217_regulator_driver = {
                .name = "tps65217-pmic",
        },
        .probe = tps65217_regulator_probe,
-       .remove = __devexit_p(tps65217_regulator_remove),
+       .remove = tps65217_regulator_remove,
 };
 
 static int __init tps65217_regulator_init(void)
index 058d2f2675e902c8d2856b83b3ee5a6b4c7c5503..843ee0a9bb92ce2a23e7a2209590b99cfa13e76c 100644 (file)
@@ -592,7 +592,7 @@ static int pmic_remove(struct spi_device *spi)
        return 0;
 }
 
-static int __devinit pmic_probe(struct spi_device *spi)
+static int pmic_probe(struct spi_device *spi)
 {
        struct tps6524x *hw;
        struct device *dev = &spi->dev;
@@ -649,7 +649,7 @@ fail:
 
 static struct spi_driver pmic_driver = {
        .probe          = pmic_probe,
-       .remove         = __devexit_p(pmic_remove),
+       .remove         = pmic_remove,
        .driver         = {
                .name   = "tps6524x",
                .owner  = THIS_MODULE,
index c3e0c9730cdaafb3ce82bf62710ba245511bf488..f86da672c758b4ab1070facacdf291cabc482c66 100644 (file)
@@ -378,7 +378,7 @@ static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
 }
 #endif
 
-static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
+static int tps6586x_regulator_probe(struct platform_device *pdev)
 {
        struct tps6586x_regulator *ri = NULL;
        struct regulator_config config = { };
@@ -461,7 +461,7 @@ fail:
        return err;
 }
 
-static int __devexit tps6586x_regulator_remove(struct platform_device *pdev)
+static int tps6586x_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev **rdev = platform_get_drvdata(pdev);
        int id = TPS6586X_ID_MAX_REGULATOR;
@@ -478,7 +478,7 @@ static struct platform_driver tps6586x_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = tps6586x_regulator_probe,
-       .remove         = __devexit_p(tps6586x_regulator_remove),
+       .remove         = tps6586x_regulator_remove,
 };
 
 static int __init tps6586x_regulator_init(void)
index 793adda560c3c3364c2053cdb152974fc2a2f02b..6b77bbf32ebcf7db26e1b1d85d05268efd7fa1eb 100644 (file)
@@ -1026,7 +1026,7 @@ static inline struct tps65910_board *tps65910_parse_dt_reg_data(
 }
 #endif
 
-static __devinit int tps65910_probe(struct platform_device *pdev)
+static int tps65910_probe(struct platform_device *pdev)
 {
        struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
        struct regulator_config config = { };
@@ -1184,7 +1184,7 @@ err_unregister_regulator:
        return err;
 }
 
-static int __devexit tps65910_remove(struct platform_device *pdev)
+static int tps65910_remove(struct platform_device *pdev)
 {
        struct tps65910_reg *pmic = platform_get_drvdata(pdev);
        int i;
@@ -1231,7 +1231,7 @@ static struct platform_driver tps65910_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps65910_probe,
-       .remove = __devexit_p(tps65910_remove),
+       .remove = tps65910_remove,
        .shutdown = tps65910_shutdown,
 };
 
index 18b2a1dcb4b5d6ba189fa74dfe4c8f2d23fbe1d8..17e994e47dc139c3117a8affe76eef64b5e092e1 100644 (file)
@@ -459,7 +459,7 @@ static struct regulator_ops tps65912_ops_ldo = {
        .list_voltage = tps65912_list_voltage,
 };
 
-static __devinit int tps65912_probe(struct platform_device *pdev)
+static int tps65912_probe(struct platform_device *pdev)
 {
        struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
        struct regulator_config config = { };
@@ -525,7 +525,7 @@ err:
        return err;
 }
 
-static int __devexit tps65912_remove(struct platform_device *pdev)
+static int tps65912_remove(struct platform_device *pdev)
 {
        struct tps65912_reg *tps65912_reg = platform_get_drvdata(pdev);
        int i;
@@ -541,7 +541,7 @@ static struct platform_driver tps65912_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps65912_probe,
-       .remove = __devexit_p(tps65912_remove),
+       .remove = tps65912_remove,
 };
 
 static int __init tps65912_init(void)
diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c
new file mode 100644 (file)
index 0000000..127d175
--- /dev/null
@@ -0,0 +1,793 @@
+/*
+ * tps80031-regulator.c -- TI TPS80031 regulator driver.
+ *
+ * Regulator driver for TITPS80031/TPS80032 Fully Integrated Power
+ * Management with Power Path and Battery Charger.
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * Author: Laxman Dewangan <ldewangan@nvidia.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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * 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 <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mfd/tps80031.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/slab.h>
+
+/* Flags for DCDC Voltage reading */
+#define DCDC_OFFSET_EN         BIT(0)
+#define DCDC_EXTENDED_EN       BIT(1)
+#define TRACK_MODE_ENABLE      BIT(2)
+
+#define SMPS_MULTOFFSET_VIO    BIT(1)
+#define SMPS_MULTOFFSET_SMPS1  BIT(3)
+#define SMPS_MULTOFFSET_SMPS2  BIT(4)
+#define SMPS_MULTOFFSET_SMPS3  BIT(6)
+#define SMPS_MULTOFFSET_SMPS4  BIT(0)
+
+#define SMPS_CMD_MASK          0xC0
+#define SMPS_VSEL_MASK         0x3F
+#define LDO_VSEL_MASK          0x1F
+#define LDO_TRACK_VSEL_MASK    0x3F
+
+#define MISC2_LDOUSB_IN_VSYS   BIT(4)
+#define MISC2_LDOUSB_IN_PMID   BIT(3)
+#define MISC2_LDOUSB_IN_MASK   0x18
+
+#define MISC2_LDO3_SEL_VIB_VAL BIT(0)
+#define MISC2_LDO3_SEL_VIB_MASK        0x1
+
+#define BOOST_HW_PWR_EN                BIT(5)
+#define BOOST_HW_PWR_EN_MASK   BIT(5)
+
+#define OPA_MODE_EN            BIT(6)
+#define OPA_MODE_EN_MASK       BIT(6)
+
+#define USB_VBUS_CTRL_SET      0x04
+#define USB_VBUS_CTRL_CLR      0x05
+#define VBUS_DISCHRG           0x20
+
+struct tps80031_regulator_info {
+       /* Regulator register address.*/
+       u8              trans_reg;
+       u8              state_reg;
+       u8              force_reg;
+       u8              volt_reg;
+       u8              volt_id;
+
+       /*Power request bits */
+       int             preq_bit;
+
+       /* used by regulator core */
+       struct regulator_desc   desc;
+
+};
+
+struct tps80031_regulator {
+       struct device                   *dev;
+       struct regulator_dev            *rdev;
+       struct tps80031_regulator_info  *rinfo;
+
+       u8                              device_flags;
+       unsigned int                    config_flags;
+       unsigned int                    ext_ctrl_flag;
+};
+
+static inline struct device *to_tps80031_dev(struct regulator_dev *rdev)
+{
+       return rdev_get_dev(rdev)->parent->parent;
+}
+
+static int tps80031_reg_is_enabled(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       u8 reg_val;
+       int ret;
+
+       if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
+               return true;
+
+       ret = tps80031_read(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
+                               &reg_val);
+       if (ret < 0) {
+               dev_err(&rdev->dev, "Reg 0x%02x read failed, err = %d\n",
+                       ri->rinfo->state_reg, ret);
+               return ret;
+       }
+       return ((reg_val & TPS80031_STATE_MASK) == TPS80031_STATE_ON);
+}
+
+static int tps80031_reg_enable(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret;
+
+       if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
+               return 0;
+
+       ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
+                       TPS80031_STATE_ON, TPS80031_STATE_MASK);
+       if (ret < 0) {
+               dev_err(&rdev->dev, "Reg 0x%02x update failed, err = %d\n",
+                       ri->rinfo->state_reg, ret);
+               return ret;
+       }
+       return ret;
+}
+
+static int tps80031_reg_disable(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret;
+
+       if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
+               return 0;
+
+       ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
+                       TPS80031_STATE_OFF, TPS80031_STATE_MASK);
+       if (ret < 0)
+               dev_err(&rdev->dev, "Reg 0x%02x update failed, err = %d\n",
+                       ri->rinfo->state_reg, ret);
+       return ret;
+}
+
+/* DCDC voltages for the selector of 58 to 63 */
+static int tps80031_dcdc_voltages[4][5] = {
+       { 1350, 1500, 1800, 1900, 2100},
+       { 1350, 1500, 1800, 1900, 2100},
+       { 2084, 2315, 2778, 2932, 3241},
+       { 4167, 2315, 2778, 2932, 3241},
+};
+
+static int tps80031_dcdc_list_voltage(struct regulator_dev *rdev, unsigned sel)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       int volt_index = ri->device_flags & 0x3;
+
+       if (sel == 0)
+               return 0;
+       else if (sel < 58)
+               return regulator_list_voltage_linear(rdev, sel - 1);
+       else
+               return tps80031_dcdc_voltages[volt_index][sel - 58] * 1000;
+}
+
+static int tps80031_dcdc_set_voltage_sel(struct regulator_dev *rdev,
+               unsigned vsel)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret;
+       u8 reg_val;
+
+       if (ri->rinfo->force_reg) {
+               ret = tps80031_read(parent, ri->rinfo->volt_id,
+                                               ri->rinfo->force_reg, &reg_val);
+               if (ret < 0) {
+                       dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                               ri->rinfo->force_reg, ret);
+                       return ret;
+               }
+               if (!(reg_val & SMPS_CMD_MASK)) {
+                       ret = tps80031_update(parent, ri->rinfo->volt_id,
+                               ri->rinfo->force_reg, vsel, SMPS_VSEL_MASK);
+                       if (ret < 0)
+                               dev_err(ri->dev,
+                                       "reg 0x%02x update failed, e = %d\n",
+                                       ri->rinfo->force_reg, ret);
+                       return ret;
+               }
+       }
+       ret = tps80031_update(parent, ri->rinfo->volt_id,
+                       ri->rinfo->volt_reg, vsel, SMPS_VSEL_MASK);
+       if (ret < 0)
+               dev_err(ri->dev, "reg 0x%02x update failed, e = %d\n",
+                       ri->rinfo->volt_reg, ret);
+       return ret;
+}
+
+static int tps80031_dcdc_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       uint8_t vsel = 0;
+       int ret;
+
+       if (ri->rinfo->force_reg) {
+               ret = tps80031_read(parent, ri->rinfo->volt_id,
+                                               ri->rinfo->force_reg, &vsel);
+               if (ret < 0) {
+                       dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                                       ri->rinfo->force_reg, ret);
+                       return ret;
+               }
+
+               if (!(vsel & SMPS_CMD_MASK))
+                       return vsel & SMPS_VSEL_MASK;
+       }
+       ret = tps80031_read(parent, ri->rinfo->volt_id,
+                               ri->rinfo->volt_reg, &vsel);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                       ri->rinfo->volt_reg, ret);
+               return ret;
+       }
+       return vsel & SMPS_VSEL_MASK;
+}
+
+static int tps80031_ldo_set_voltage_sel(struct regulator_dev *rdev,
+               unsigned sel)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret;
+
+       /* Check for valid setting for TPS80031 or TPS80032-ES1.0 */
+       if ((ri->rinfo->desc.id == TPS80031_REGULATOR_LDO2) &&
+                       (ri->device_flags & TRACK_MODE_ENABLE)) {
+               unsigned nvsel = (sel) & 0x1F;
+               if (((tps80031_get_chip_info(parent) == TPS80031) ||
+                       ((tps80031_get_chip_info(parent) == TPS80032) &&
+                       (tps80031_get_pmu_version(parent) == 0x0))) &&
+                       ((nvsel == 0x0) || (nvsel >= 0x19 && nvsel <= 0x1F))) {
+                               dev_err(ri->dev,
+                                       "Invalid sel %d in track mode LDO2\n",
+                                       nvsel);
+                               return -EINVAL;
+               }
+       }
+
+       ret = tps80031_write(parent, ri->rinfo->volt_id,
+                       ri->rinfo->volt_reg, sel);
+       if (ret < 0)
+               dev_err(ri->dev, "Error in writing reg 0x%02x, e = %d\n",
+                       ri->rinfo->volt_reg, ret);
+       return ret;
+}
+
+static int tps80031_ldo_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       uint8_t vsel;
+       int ret;
+
+       ret = tps80031_read(parent, ri->rinfo->volt_id,
+                               ri->rinfo->volt_reg, &vsel);
+       if (ret < 0) {
+               dev_err(ri->dev, "Error in writing the Voltage register\n");
+               return ret;
+       }
+       return vsel & rdev->desc->vsel_mask;
+}
+
+static int tps80031_ldo_list_voltage(struct regulator_dev *rdev, unsigned sel)
+{
+       if (sel == 0)
+               return 0;
+       else
+               return regulator_list_voltage_linear(rdev, sel - 1);
+}
+
+static int tps80031_vbus_is_enabled(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret = -EIO;
+       uint8_t ctrl1 = 0;
+       uint8_t ctrl3 = 0;
+
+       ret = tps80031_read(parent, TPS80031_SLAVE_ID2,
+                       TPS80031_CHARGERUSB_CTRL1, &ctrl1);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                       TPS80031_CHARGERUSB_CTRL1, ret);
+               return ret;
+       }
+       ret = tps80031_read(parent, TPS80031_SLAVE_ID2,
+                               TPS80031_CHARGERUSB_CTRL3, &ctrl3);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                       TPS80031_CHARGERUSB_CTRL1, ret);
+               return ret;
+       }
+       if ((ctrl1 & OPA_MODE_EN) && (ctrl3 & BOOST_HW_PWR_EN))
+               return 1;
+       return ret;
+}
+
+static int tps80031_vbus_enable(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret;
+
+       ret = tps80031_set_bits(parent, TPS80031_SLAVE_ID2,
+                               TPS80031_CHARGERUSB_CTRL1, OPA_MODE_EN);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                                       TPS80031_CHARGERUSB_CTRL1, ret);
+               return ret;
+       }
+
+       ret = tps80031_set_bits(parent, TPS80031_SLAVE_ID2,
+                               TPS80031_CHARGERUSB_CTRL3, BOOST_HW_PWR_EN);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                       TPS80031_CHARGERUSB_CTRL3, ret);
+               return ret;
+       }
+       return ret;
+}
+
+static int tps80031_vbus_disable(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret = 0;
+
+       if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) {
+               ret = tps80031_write(parent, TPS80031_SLAVE_ID2,
+                       USB_VBUS_CTRL_SET, VBUS_DISCHRG);
+               if (ret < 0) {
+                       dev_err(ri->dev, "reg 0x%02x write failed, e = %d\n",
+                               USB_VBUS_CTRL_SET, ret);
+                       return ret;
+               }
+       }
+
+       ret = tps80031_clr_bits(parent, TPS80031_SLAVE_ID2,
+                       TPS80031_CHARGERUSB_CTRL1,  OPA_MODE_EN);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x clearbit failed, e = %d\n",
+                               TPS80031_CHARGERUSB_CTRL1, ret);
+               return ret;
+       }
+
+       ret = tps80031_clr_bits(parent, TPS80031_SLAVE_ID2,
+                               TPS80031_CHARGERUSB_CTRL3, BOOST_HW_PWR_EN);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x clearbit failed, e = %d\n",
+                               TPS80031_CHARGERUSB_CTRL3, ret);
+               return ret;
+       }
+
+       mdelay(DIV_ROUND_UP(ri->rinfo->desc.enable_time, 1000));
+       if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) {
+               ret = tps80031_write(parent, TPS80031_SLAVE_ID2,
+                       USB_VBUS_CTRL_CLR, VBUS_DISCHRG);
+               if (ret < 0) {
+                       dev_err(ri->dev, "reg 0x%02x write failed, e = %d\n",
+                                       USB_VBUS_CTRL_CLR, ret);
+                       return ret;
+               }
+       }
+       return ret;
+}
+
+static struct regulator_ops tps80031_dcdc_ops = {
+       .list_voltage           = tps80031_dcdc_list_voltage,
+       .set_voltage_sel        = tps80031_dcdc_set_voltage_sel,
+       .get_voltage_sel        = tps80031_dcdc_get_voltage_sel,
+       .enable         = tps80031_reg_enable,
+       .disable        = tps80031_reg_disable,
+       .is_enabled     = tps80031_reg_is_enabled,
+};
+
+static struct regulator_ops tps80031_ldo_ops = {
+       .list_voltage           = tps80031_ldo_list_voltage,
+       .set_voltage_sel        = tps80031_ldo_set_voltage_sel,
+       .get_voltage_sel        = tps80031_ldo_get_voltage_sel,
+       .enable                 = tps80031_reg_enable,
+       .disable                = tps80031_reg_disable,
+       .is_enabled             = tps80031_reg_is_enabled,
+};
+
+static struct regulator_ops tps80031_vbus_sw_ops = {
+       .enable         = tps80031_vbus_enable,
+       .disable        = tps80031_vbus_disable,
+       .is_enabled     = tps80031_vbus_is_enabled,
+};
+
+static struct regulator_ops tps80031_vbus_hw_ops = {
+};
+
+static struct regulator_ops tps80031_ext_reg_ops = {
+       .enable         = tps80031_reg_enable,
+       .disable        = tps80031_reg_disable,
+       .is_enabled     = tps80031_reg_is_enabled,
+};
+
+/* Non-exiting default definition for some register */
+#define TPS80031_SMPS3_CFG_FORCE       0
+#define TPS80031_SMPS4_CFG_FORCE       0
+
+#define TPS80031_VBUS_CFG_TRANS                0
+#define TPS80031_VBUS_CFG_STATE                0
+
+#define TPS80031_REG_SMPS(_id, _volt_id, _pbit)        \
+{                                                              \
+       .trans_reg = TPS80031_##_id##_CFG_TRANS,                \
+       .state_reg = TPS80031_##_id##_CFG_STATE,                \
+       .force_reg = TPS80031_##_id##_CFG_FORCE,                \
+       .volt_reg = TPS80031_##_id##_CFG_VOLTAGE,               \
+       .volt_id = TPS80031_SLAVE_##_volt_id,                   \
+       .preq_bit = _pbit,                                      \
+       .desc = {                                               \
+               .name = "tps80031_"#_id,                        \
+               .id = TPS80031_REGULATOR_##_id,                 \
+               .n_voltages = 63,                               \
+               .ops = &tps80031_dcdc_ops,                      \
+               .type = REGULATOR_VOLTAGE,                      \
+               .owner = THIS_MODULE,                           \
+               .enable_time = 500,                             \
+       },                                                      \
+}
+
+#define TPS80031_REG_LDO(_id, _preq_bit)                       \
+{                                                              \
+       .trans_reg = TPS80031_##_id##_CFG_TRANS,                \
+       .state_reg = TPS80031_##_id##_CFG_STATE,                \
+       .volt_reg = TPS80031_##_id##_CFG_VOLTAGE,               \
+       .volt_id = TPS80031_SLAVE_ID1,                          \
+       .preq_bit = _preq_bit,                                  \
+       .desc = {                                               \
+               .owner = THIS_MODULE,                           \
+               .name = "tps80031_"#_id,                        \
+               .id = TPS80031_REGULATOR_##_id,                 \
+               .ops = &tps80031_ldo_ops,                       \
+               .type = REGULATOR_VOLTAGE,                      \
+               .min_uV = 1000000,                              \
+               .uV_step = 100000,                              \
+               .n_voltages = 25,                               \
+               .vsel_mask = LDO_VSEL_MASK,                     \
+               .enable_time = 500,                             \
+       },                                                      \
+}
+
+#define TPS80031_REG_FIXED(_id, max_mV, _ops, _delay, _pbit)   \
+{                                                              \
+       .trans_reg = TPS80031_##_id##_CFG_TRANS,                \
+       .state_reg = TPS80031_##_id##_CFG_STATE,                \
+       .volt_id = TPS80031_SLAVE_ID1,                          \
+       .preq_bit = _pbit,                                      \
+       .desc = {                                               \
+               .name = "tps80031_"#_id,                        \
+               .id = TPS80031_REGULATOR_##_id,                 \
+               .n_voltages = 2,                                \
+               .ops = &_ops,                                   \
+               .type = REGULATOR_VOLTAGE,                      \
+               .owner = THIS_MODULE,                           \
+               .enable_time = _delay,                          \
+       },                                                      \
+}
+
+static struct tps80031_regulator_info tps80031_rinfo[TPS80031_REGULATOR_MAX] = {
+       TPS80031_REG_SMPS(VIO,   ID0, 4),
+       TPS80031_REG_SMPS(SMPS1, ID0, 0),
+       TPS80031_REG_SMPS(SMPS2, ID0, 1),
+       TPS80031_REG_SMPS(SMPS3, ID1, 2),
+       TPS80031_REG_SMPS(SMPS4, ID1, 3),
+       TPS80031_REG_LDO(VANA,   -1),
+       TPS80031_REG_LDO(LDO1,   8),
+       TPS80031_REG_LDO(LDO2,   9),
+       TPS80031_REG_LDO(LDO3,   10),
+       TPS80031_REG_LDO(LDO4,   11),
+       TPS80031_REG_LDO(LDO5,   12),
+       TPS80031_REG_LDO(LDO6,   13),
+       TPS80031_REG_LDO(LDO7,   14),
+       TPS80031_REG_LDO(LDOLN,  15),
+       TPS80031_REG_LDO(LDOUSB, 5),
+       TPS80031_REG_FIXED(VBUS,   5000, tps80031_vbus_hw_ops, 100000, -1),
+       TPS80031_REG_FIXED(REGEN1, 3300, tps80031_ext_reg_ops, 0, 16),
+       TPS80031_REG_FIXED(REGEN2, 3300, tps80031_ext_reg_ops, 0, 17),
+       TPS80031_REG_FIXED(SYSEN,  3300, tps80031_ext_reg_ops, 0, 18),
+};
+
+static int tps80031_power_req_config(struct device *parent,
+               struct tps80031_regulator *ri,
+               struct tps80031_regulator_platform_data *tps80031_pdata)
+{
+       int ret = 0;
+
+       if (ri->rinfo->preq_bit < 0)
+               goto skip_pwr_req_config;
+
+       ret = tps80031_ext_power_req_config(parent, ri->ext_ctrl_flag,
+                       ri->rinfo->preq_bit, ri->rinfo->state_reg,
+                       ri->rinfo->trans_reg);
+       if (ret < 0) {
+               dev_err(ri->dev, "ext powerreq config failed, err = %d\n", ret);
+               return ret;
+       }
+
+skip_pwr_req_config:
+       if (tps80031_pdata->ext_ctrl_flag & TPS80031_PWR_ON_ON_SLEEP) {
+               ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
+                               ri->rinfo->trans_reg, TPS80031_TRANS_SLEEP_ON,
+                               TPS80031_TRANS_SLEEP_MASK);
+               if (ret < 0) {
+                       dev_err(ri->dev, "Reg 0x%02x update failed, e %d\n",
+                                       ri->rinfo->trans_reg, ret);
+                       return ret;
+               }
+       }
+       return ret;
+}
+
+static int tps80031_regulator_config(struct device *parent,
+               struct tps80031_regulator *ri,
+               struct tps80031_regulator_platform_data *tps80031_pdata)
+{
+       int ret = 0;
+
+       switch (ri->rinfo->desc.id) {
+       case TPS80031_REGULATOR_LDOUSB:
+               if (ri->config_flags & (TPS80031_USBLDO_INPUT_VSYS |
+                       TPS80031_USBLDO_INPUT_PMID)) {
+                       unsigned val = 0;
+                       if (ri->config_flags & TPS80031_USBLDO_INPUT_VSYS)
+                               val = MISC2_LDOUSB_IN_VSYS;
+                       else
+                               val = MISC2_LDOUSB_IN_PMID;
+
+                       ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
+                               TPS80031_MISC2, val,
+                               MISC2_LDOUSB_IN_MASK);
+                       if (ret < 0) {
+                               dev_err(ri->dev,
+                                       "LDOUSB config failed, e= %d\n", ret);
+                               return ret;
+                       }
+               }
+               break;
+
+       case TPS80031_REGULATOR_LDO3:
+               if (ri->config_flags & TPS80031_LDO3_OUTPUT_VIB) {
+                       ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
+                               TPS80031_MISC2, MISC2_LDO3_SEL_VIB_VAL,
+                               MISC2_LDO3_SEL_VIB_MASK);
+                       if (ret < 0) {
+                               dev_err(ri->dev,
+                                       "LDO3 config failed, e = %d\n", ret);
+                               return ret;
+                       }
+               }
+               break;
+
+       case TPS80031_REGULATOR_VBUS:
+               /* Provide SW control Ops if VBUS is SW control */
+               if (!(ri->config_flags & TPS80031_VBUS_SW_ONLY))
+                       ri->rinfo->desc.ops = &tps80031_vbus_sw_ops;
+               break;
+       default:
+               break;
+       }
+
+       /* Configure Active state to ON, SLEEP to OFF and OFF_state to OFF */
+       ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->trans_reg,
+               TPS80031_TRANS_ACTIVE_ON | TPS80031_TRANS_SLEEP_OFF |
+               TPS80031_TRANS_OFF_OFF, TPS80031_TRANS_ACTIVE_MASK |
+               TPS80031_TRANS_SLEEP_MASK | TPS80031_TRANS_OFF_MASK);
+       if (ret < 0) {
+               dev_err(ri->dev, "trans reg update failed, e %d\n", ret);
+               return ret;
+       }
+
+       return ret;
+}
+
+static int check_smps_mode_mult(struct device *parent,
+       struct tps80031_regulator *ri)
+{
+       int mult_offset;
+       int ret;
+       u8 smps_offset;
+       u8 smps_mult;
+
+       ret = tps80031_read(parent, TPS80031_SLAVE_ID1,
+                       TPS80031_SMPS_OFFSET, &smps_offset);
+       if (ret < 0) {
+               dev_err(parent, "Error in reading smps offset register\n");
+               return ret;
+       }
+
+       ret = tps80031_read(parent, TPS80031_SLAVE_ID1,
+                       TPS80031_SMPS_MULT, &smps_mult);
+       if (ret < 0) {
+               dev_err(parent, "Error in reading smps mult register\n");
+               return ret;
+       }
+
+       switch (ri->rinfo->desc.id) {
+       case TPS80031_REGULATOR_VIO:
+               mult_offset = SMPS_MULTOFFSET_VIO;
+               break;
+       case TPS80031_REGULATOR_SMPS1:
+               mult_offset = SMPS_MULTOFFSET_SMPS1;
+               break;
+       case TPS80031_REGULATOR_SMPS2:
+               mult_offset = SMPS_MULTOFFSET_SMPS2;
+               break;
+       case TPS80031_REGULATOR_SMPS3:
+               mult_offset = SMPS_MULTOFFSET_SMPS3;
+               break;
+       case TPS80031_REGULATOR_SMPS4:
+               mult_offset = SMPS_MULTOFFSET_SMPS4;
+               break;
+       case TPS80031_REGULATOR_LDO2:
+               ri->device_flags = smps_mult & BIT(5) ? TRACK_MODE_ENABLE : 0;
+               /* TRACK mode the ldo2 varies from 600mV to 1300mV */
+               if (ri->device_flags & TRACK_MODE_ENABLE) {
+                       ri->rinfo->desc.min_uV = 600000;
+                       ri->rinfo->desc.uV_step = 12500;
+                       ri->rinfo->desc.n_voltages = 57;
+                       ri->rinfo->desc.vsel_mask = LDO_TRACK_VSEL_MASK;
+               }
+               return 0;
+       default:
+               return 0;
+       }
+
+       ri->device_flags = (smps_offset & mult_offset) ? DCDC_OFFSET_EN : 0;
+       ri->device_flags |= (smps_mult & mult_offset) ? DCDC_EXTENDED_EN : 0;
+       switch (ri->device_flags) {
+       case 0:
+               ri->rinfo->desc.min_uV = 607700;
+               ri->rinfo->desc.uV_step = 12660;
+               break;
+       case DCDC_OFFSET_EN:
+               ri->rinfo->desc.min_uV = 700000;
+               ri->rinfo->desc.uV_step = 12500;
+               break;
+       case DCDC_EXTENDED_EN:
+               ri->rinfo->desc.min_uV = 1852000;
+               ri->rinfo->desc.uV_step = 38600;
+               break;
+       case DCDC_OFFSET_EN | DCDC_EXTENDED_EN:
+               ri->rinfo->desc.min_uV = 2161000;
+               ri->rinfo->desc.uV_step = 38600;
+               break;
+       }
+       return 0;
+}
+
+static int tps80031_regulator_probe(struct platform_device *pdev)
+{
+       struct tps80031_platform_data *pdata;
+       struct tps80031_regulator_platform_data *tps_pdata;
+       struct tps80031_regulator_info *rinfo;
+       struct tps80031_regulator *ri;
+       struct tps80031_regulator *pmic;
+       struct regulator_dev *rdev;
+       struct regulator_config config = { };
+       int ret;
+       int num;
+
+       pdata = dev_get_platdata(pdev->dev.parent);
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "No platform data\n");
+               return -EINVAL;
+       }
+
+       pmic = devm_kzalloc(&pdev->dev,
+                       TPS80031_REGULATOR_MAX * sizeof(*pmic), GFP_KERNEL);
+       if (!pmic) {
+               dev_err(&pdev->dev, "mem alloc for pmic failed\n");
+               return -ENOMEM;
+       }
+
+       for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) {
+               tps_pdata = pdata->regulator_pdata[num];
+               rinfo = &tps80031_rinfo[num];
+               ri = &pmic[num];
+               ri->rinfo = rinfo;
+               ri->dev = &pdev->dev;
+
+               check_smps_mode_mult(pdev->dev.parent, ri);
+               config.dev = &pdev->dev;
+               config.init_data = NULL;
+               config.driver_data = ri;
+               if (tps_pdata) {
+                       config.init_data = tps_pdata->reg_init_data;
+                       ri->config_flags = tps_pdata->config_flags;
+                       ri->ext_ctrl_flag = tps_pdata->ext_ctrl_flag;
+                       ret = tps80031_regulator_config(pdev->dev.parent,
+                                       ri, tps_pdata);
+                       if (ret < 0) {
+                               dev_err(&pdev->dev,
+                                       "regulator config failed, e %d\n", ret);
+                               goto fail;
+                       }
+
+                       ret = tps80031_power_req_config(pdev->dev.parent,
+                                       ri, tps_pdata);
+                       if (ret < 0) {
+                               dev_err(&pdev->dev,
+                                       "pwr_req config failed, err %d\n", ret);
+                               goto fail;
+                       }
+               }
+               rdev = regulator_register(&ri->rinfo->desc, &config);
+               if (IS_ERR_OR_NULL(rdev)) {
+                       dev_err(&pdev->dev,
+                               "register regulator failed %s\n",
+                                       ri->rinfo->desc.name);
+                       ret = PTR_ERR(rdev);
+                       goto fail;
+               }
+               ri->rdev = rdev;
+       }
+
+       platform_set_drvdata(pdev, pmic);
+       return 0;
+fail:
+       while (--num >= 0) {
+               ri = &pmic[num];
+               regulator_unregister(ri->rdev);
+       }
+       return ret;
+}
+
+static int tps80031_regulator_remove(struct platform_device *pdev)
+{
+       struct tps80031_regulator *pmic = platform_get_drvdata(pdev);
+       struct tps80031_regulator *ri = NULL;
+       int num;
+
+       for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) {
+               ri = &pmic[num];
+               regulator_unregister(ri->rdev);
+       }
+       return 0;
+}
+
+static struct platform_driver tps80031_regulator_driver = {
+       .driver = {
+               .name   = "tps80031-pmic",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = tps80031_regulator_probe,
+       .remove         = tps80031_regulator_remove,
+};
+
+static int __init tps80031_regulator_init(void)
+{
+       return platform_driver_register(&tps80031_regulator_driver);
+}
+subsys_initcall(tps80031_regulator_init);
+
+static void __exit tps80031_regulator_exit(void)
+{
+       platform_driver_unregister(&tps80031_regulator_driver);
+}
+module_exit(tps80031_regulator_exit);
+
+MODULE_ALIAS("platform:tps80031-regulator");
+MODULE_DESCRIPTION("Regulator Driver for TI TPS80031 PMIC");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL v2");
index 7eb986a4074678cb58118577544a10838b8a185a..493c8c6a241f41b1820786b993b342816002bc1c 100644 (file)
@@ -1116,7 +1116,7 @@ static const struct of_device_id twl_of_match[] __devinitconst = {
 };
 MODULE_DEVICE_TABLE(of, twl_of_match);
 
-static int __devinit twlreg_probe(struct platform_device *pdev)
+static int twlreg_probe(struct platform_device *pdev)
 {
        int                             i, id;
        struct twlreg_info              *info;
@@ -1241,7 +1241,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit twlreg_remove(struct platform_device *pdev)
+static int twlreg_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
        struct twlreg_info *info = rdev->reg_data;
@@ -1255,7 +1255,7 @@ MODULE_ALIAS("platform:twl_reg");
 
 static struct platform_driver twlreg_driver = {
        .probe          = twlreg_probe,
-       .remove         = __devexit_p(twlreg_remove),
+       .remove         = twlreg_remove,
        /* NOTE: short name, to work around driver model truncation of
         * "twl_regulator.12" (and friends) to "twl_regulator.1".
         */
diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c
new file mode 100644 (file)
index 0000000..4668c7f
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#define DRVNAME "vexpress-regulator"
+#define pr_fmt(fmt) DRVNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/vexpress.h>
+
+struct vexpress_regulator {
+       struct regulator_desc desc;
+       struct regulator_dev *regdev;
+       struct vexpress_config_func *func;
+};
+
+static int vexpress_regulator_get_voltage(struct regulator_dev *regdev)
+{
+       struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
+       u32 uV;
+       int err = vexpress_config_read(reg->func, 0, &uV);
+
+       return err ? err : uV;
+}
+
+static int vexpress_regulator_set_voltage(struct regulator_dev *regdev,
+               int min_uV, int max_uV, unsigned *selector)
+{
+       struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
+
+       return vexpress_config_write(reg->func, 0, min_uV);
+}
+
+static struct regulator_ops vexpress_regulator_ops_ro = {
+       .get_voltage = vexpress_regulator_get_voltage,
+};
+
+static struct regulator_ops vexpress_regulator_ops = {
+       .get_voltage = vexpress_regulator_get_voltage,
+       .set_voltage = vexpress_regulator_set_voltage,
+};
+
+static int vexpress_regulator_probe(struct platform_device *pdev)
+{
+       int err;
+       struct vexpress_regulator *reg;
+       struct regulator_init_data *init_data;
+       struct regulator_config config = { };
+
+       reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL);
+       if (!reg) {
+               err = -ENOMEM;
+               goto error_kzalloc;
+       }
+
+       reg->func = vexpress_config_func_get_by_dev(&pdev->dev);
+       if (!reg->func) {
+               err = -ENXIO;
+               goto error_get_func;
+       }
+
+       reg->desc.name = dev_name(&pdev->dev);
+       reg->desc.type = REGULATOR_VOLTAGE;
+       reg->desc.owner = THIS_MODULE;
+       reg->desc.continuous_voltage_range = true;
+
+       init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
+       if (!init_data) {
+               err = -EINVAL;
+               goto error_get_regulator_init_data;
+       }
+
+       init_data->constraints.apply_uV = 0;
+       if (init_data->constraints.min_uV && init_data->constraints.max_uV)
+               reg->desc.ops = &vexpress_regulator_ops;
+       else
+               reg->desc.ops = &vexpress_regulator_ops_ro;
+
+       config.dev = &pdev->dev;
+       config.init_data = init_data;
+       config.driver_data = reg;
+       config.of_node = pdev->dev.of_node;
+
+       reg->regdev = regulator_register(&reg->desc, &config);
+       if (IS_ERR(reg->regdev)) {
+               err = PTR_ERR(reg->regdev);
+               goto error_regulator_register;
+       }
+
+       platform_set_drvdata(pdev, reg);
+
+       return 0;
+
+error_regulator_register:
+error_get_regulator_init_data:
+       vexpress_config_func_put(reg->func);
+error_get_func:
+error_kzalloc:
+       return err;
+}
+
+static int vexpress_regulator_remove(struct platform_device *pdev)
+{
+       struct vexpress_regulator *reg = platform_get_drvdata(pdev);
+
+       vexpress_config_func_put(reg->func);
+       regulator_unregister(reg->regdev);
+
+       return 0;
+}
+
+static struct of_device_id vexpress_regulator_of_match[] = {
+       { .compatible = "arm,vexpress-volt", },
+       { }
+};
+
+static struct platform_driver vexpress_regulator_driver = {
+       .probe = vexpress_regulator_probe,
+       .remove = vexpress_regulator_remove,
+       .driver = {
+               .name = DRVNAME,
+               .owner = THIS_MODULE,
+               .of_match_table = vexpress_regulator_of_match,
+       },
+};
+
+module_platform_driver(vexpress_regulator_driver);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_DESCRIPTION("Versatile Express regulator");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:vexpress-regulator");
index c038e74225381ea760f9e3984d62eb802af86814..01c66e9712a4aa236ba36ed409abbbce51cd66f2 100644 (file)
@@ -285,7 +285,7 @@ static const struct attribute_group regulator_virtual_attr_group = {
        .attrs  = regulator_virtual_attributes,
 };
 
-static int __devinit regulator_virtual_probe(struct platform_device *pdev)
+static int regulator_virtual_probe(struct platform_device *pdev)
 {
        char *reg_id = pdev->dev.platform_data;
        struct virtual_consumer_data *drvdata;
@@ -321,7 +321,7 @@ static int __devinit regulator_virtual_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit regulator_virtual_remove(struct platform_device *pdev)
+static int regulator_virtual_remove(struct platform_device *pdev)
 {
        struct virtual_consumer_data *drvdata = platform_get_drvdata(pdev);
 
@@ -337,7 +337,7 @@ static int __devexit regulator_virtual_remove(struct platform_device *pdev)
 
 static struct platform_driver regulator_virtual_consumer_driver = {
        .probe          = regulator_virtual_probe,
-       .remove         = __devexit_p(regulator_virtual_remove),
+       .remove         = regulator_virtual_remove,
        .driver         = {
                .name           = "reg-virt-consumer",
                .owner          = THIS_MODULE,
index 782c228a19bd503ccda868ac67f46cce7fbba2e7..bce25658e12eed041634ec513aab391636b47b83 100644 (file)
@@ -290,7 +290,7 @@ static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev,
        if (vsel > dcdc->dvs_vsel) {
                ret = wm831x_set_bits(wm831x, dvs_reg,
                                      WM831X_DC1_DVS_VSEL_MASK,
-                                     dcdc->dvs_vsel);
+                                     vsel);
                if (ret == 0)
                        dcdc->dvs_vsel = vsel;
                else
@@ -387,7 +387,7 @@ static struct regulator_ops wm831x_buckv_ops = {
  * Set up DVS control.  We just log errors since we can still run
  * (with reduced performance) if we fail.
  */
-static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
+static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
                                            struct wm831x_buckv_pdata *pdata)
 {
        struct wm831x *wm831x = dcdc->wm831x;
@@ -448,7 +448,7 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
        }
 }
 
-static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
+static int wm831x_buckv_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -562,7 +562,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
+static int wm831x_buckv_remove(struct platform_device *pdev)
 {
        struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
        struct wm831x *wm831x = dcdc->wm831x;
@@ -582,7 +582,7 @@ static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_buckv_driver = {
        .probe = wm831x_buckv_probe,
-       .remove = __devexit_p(wm831x_buckv_remove),
+       .remove = wm831x_buckv_remove,
        .driver         = {
                .name   = "wm831x-buckv",
                .owner  = THIS_MODULE,
@@ -623,7 +623,7 @@ static struct regulator_ops wm831x_buckp_ops = {
        .set_suspend_mode = wm831x_dcdc_set_suspend_mode,
 };
 
-static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
+static int wm831x_buckp_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -710,7 +710,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
+static int wm831x_buckp_remove(struct platform_device *pdev)
 {
        struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 
@@ -725,7 +725,7 @@ static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_buckp_driver = {
        .probe = wm831x_buckp_probe,
-       .remove = __devexit_p(wm831x_buckp_remove),
+       .remove = wm831x_buckp_remove,
        .driver         = {
                .name   = "wm831x-buckp",
                .owner  = THIS_MODULE,
@@ -771,7 +771,7 @@ static struct regulator_ops wm831x_boostp_ops = {
        .disable = regulator_disable_regmap,
 };
 
-static __devinit int wm831x_boostp_probe(struct platform_device *pdev)
+static int wm831x_boostp_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -845,7 +845,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
+static int wm831x_boostp_remove(struct platform_device *pdev)
 {
        struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 
@@ -860,7 +860,7 @@ static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_boostp_driver = {
        .probe = wm831x_boostp_probe,
-       .remove = __devexit_p(wm831x_boostp_remove),
+       .remove = wm831x_boostp_remove,
        .driver         = {
                .name   = "wm831x-boostp",
                .owner  = THIS_MODULE,
@@ -883,7 +883,7 @@ static struct regulator_ops wm831x_epe_ops = {
        .get_status = wm831x_dcdc_get_status,
 };
 
-static __devinit int wm831x_epe_probe(struct platform_device *pdev)
+static int wm831x_epe_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -936,7 +936,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_epe_remove(struct platform_device *pdev)
+static int wm831x_epe_remove(struct platform_device *pdev)
 {
        struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 
@@ -948,7 +948,7 @@ static __devexit int wm831x_epe_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_epe_driver = {
        .probe = wm831x_epe_probe,
-       .remove = __devexit_p(wm831x_epe_remove),
+       .remove = wm831x_epe_remove,
        .driver         = {
                .name   = "wm831x-epe",
                .owner  = THIS_MODULE,
index 2646a1902b33fe6287ee4bfea055c5c0d952fba5..68586ee3e1cb18197f64ea68d7cbee9e963408fc 100644 (file)
@@ -148,7 +148,7 @@ static irqreturn_t wm831x_isink_irq(int irq, void *data)
 }
 
 
-static __devinit int wm831x_isink_probe(struct platform_device *pdev)
+static int wm831x_isink_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -221,7 +221,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_isink_remove(struct platform_device *pdev)
+static int wm831x_isink_remove(struct platform_device *pdev)
 {
        struct wm831x_isink *isink = platform_get_drvdata(pdev);
 
@@ -236,7 +236,7 @@ static __devexit int wm831x_isink_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_isink_driver = {
        .probe = wm831x_isink_probe,
-       .remove = __devexit_p(wm831x_isink_remove),
+       .remove = wm831x_isink_remove,
        .driver         = {
                .name   = "wm831x-isink",
                .owner  = THIS_MODULE,
index c2dc03993dc7011d5ce9c87726cea6f25579d8c3..1ec379a9a95c88807c9987b23568e892b14bdc1a 100644 (file)
@@ -247,7 +247,7 @@ static struct regulator_ops wm831x_gp_ldo_ops = {
        .disable = regulator_disable_regmap,
 };
 
-static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
+static int wm831x_gp_ldo_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -334,7 +334,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
+static int wm831x_gp_ldo_remove(struct platform_device *pdev)
 {
        struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -349,7 +349,7 @@ static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_gp_ldo_driver = {
        .probe = wm831x_gp_ldo_probe,
-       .remove = __devexit_p(wm831x_gp_ldo_remove),
+       .remove = wm831x_gp_ldo_remove,
        .driver         = {
                .name   = "wm831x-ldo",
                .owner  = THIS_MODULE,
@@ -504,7 +504,7 @@ static struct regulator_ops wm831x_aldo_ops = {
        .disable = regulator_disable_regmap,
 };
 
-static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
+static int wm831x_aldo_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -590,7 +590,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
+static int wm831x_aldo_remove(struct platform_device *pdev)
 {
        struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -603,7 +603,7 @@ static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_aldo_driver = {
        .probe = wm831x_aldo_probe,
-       .remove = __devexit_p(wm831x_aldo_remove),
+       .remove = wm831x_aldo_remove,
        .driver         = {
                .name   = "wm831x-aldo",
                .owner  = THIS_MODULE,
@@ -660,7 +660,7 @@ static struct regulator_ops wm831x_alive_ldo_ops = {
        .disable = regulator_disable_regmap,
 };
 
-static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
+static int wm831x_alive_ldo_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -737,7 +737,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
+static int wm831x_alive_ldo_remove(struct platform_device *pdev)
 {
        struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -748,7 +748,7 @@ static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_alive_ldo_driver = {
        .probe = wm831x_alive_ldo_probe,
-       .remove = __devexit_p(wm831x_alive_ldo_remove),
+       .remove = wm831x_alive_ldo_remove,
        .driver         = {
                .name   = "wm831x-alive-ldo",
                .owner  = THIS_MODULE,
index 27c746ef06364d2f02e95b8928ed748a31de6b1d..c6a32ea80b9d2aa063408f6ac38d11622253f477 100644 (file)
@@ -226,7 +226,7 @@ static struct regulator_desc regulators[] = {
        },
 };
 
-static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
+static int wm8400_regulator_probe(struct platform_device *pdev)
 {
        struct wm8400 *wm8400 = container_of(pdev, struct wm8400, regulators[pdev->id]);
        struct regulator_config config = { };
@@ -246,7 +246,7 @@ static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit wm8400_regulator_remove(struct platform_device *pdev)
+static int wm8400_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -261,7 +261,7 @@ static struct platform_driver wm8400_regulator_driver = {
                .name = "wm8400-regulator",
        },
        .probe = wm8400_regulator_probe,
-       .remove = __devexit_p(wm8400_regulator_remove),
+       .remove = wm8400_regulator_remove,
 };
 
 /**
index 86bb48db149ed3d2bb1285f9dd4a24fb28a531f2..6ff872342648cc2cacbf23565826715b0d3bbff7 100644 (file)
@@ -99,7 +99,7 @@ static const struct regulator_desc wm8994_ldo_desc[] = {
        },
 };
 
-static __devinit int wm8994_ldo_probe(struct platform_device *pdev)
+static int wm8994_ldo_probe(struct platform_device *pdev)
 {
        struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
        struct wm8994_pdata *pdata = wm8994->dev->platform_data;
@@ -142,7 +142,7 @@ err:
        return ret;
 }
 
-static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
+static int wm8994_ldo_remove(struct platform_device *pdev)
 {
        struct wm8994_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -155,7 +155,7 @@ static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
 
 static struct platform_driver wm8994_ldo_driver = {
        .probe = wm8994_ldo_probe,
-       .remove = __devexit_p(wm8994_ldo_remove),
+       .remove = wm8994_ldo_remove,
        .driver         = {
                .name   = "wm8994-ldo",
                .owner  = THIS_MODULE,
index 9ffb6d5f17aa0523473215db57edeccda1391a70..4ed343e4eb4155718cc31084eb6902a2ee84f570 100644 (file)
@@ -44,7 +44,6 @@
 #define RAW3215_NR_CCWS            3
 #define RAW3215_TIMEOUT            HZ/10     /* time for delayed output */
 
-#define RAW3215_FIXED      1         /* 3215 console device is not be freed */
 #define RAW3215_WORKING            4         /* set if a request is being worked on */
 #define RAW3215_THROTTLED   8        /* set if reading is disabled */
 #define RAW3215_STOPPED            16        /* set if writing is disabled */
@@ -339,8 +338,10 @@ static void raw3215_wakeup(unsigned long data)
        struct tty_struct *tty;
 
        tty = tty_port_tty_get(&raw->port);
-       tty_wakeup(tty);
-       tty_kref_put(tty);
+       if (tty) {
+               tty_wakeup(tty);
+               tty_kref_put(tty);
+       }
 }
 
 /*
@@ -629,8 +630,7 @@ static void raw3215_shutdown(struct raw3215_info *raw)
        DECLARE_WAITQUEUE(wait, current);
        unsigned long flags;
 
-       if (!(raw->port.flags & ASYNC_INITIALIZED) ||
-                       (raw->flags & RAW3215_FIXED))
+       if (!(raw->port.flags & ASYNC_INITIALIZED))
                return;
        /* Wait for outstanding requests, then free irq */
        spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
@@ -926,8 +926,6 @@ static int __init con3215_init(void)
        dev_set_drvdata(&cdev->dev, raw);
        cdev->handler = raw3215_irq;
 
-       raw->flags |= RAW3215_FIXED;
-
        /* Request the console irq */
        if (raw3215_startup(raw) != 0) {
                raw3215_free_info(raw);
index 3e25d31504560a79b75b782a45153190a7694ffa..4d6ba00d00472055f56afe7ad2b4f651d7f6fe26 100644 (file)
@@ -2942,13 +2942,33 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,
        QETH_DBF_TEXT(SETUP, 2, "qipasscb");
 
        cmd = (struct qeth_ipa_cmd *) data;
+
+       switch (cmd->hdr.return_code) {
+       case IPA_RC_NOTSUPP:
+       case IPA_RC_L2_UNSUPPORTED_CMD:
+               QETH_DBF_TEXT(SETUP, 2, "ipaunsup");
+               card->options.ipa4.supported_funcs |= IPA_SETADAPTERPARMS;
+               card->options.ipa6.supported_funcs |= IPA_SETADAPTERPARMS;
+               return -0;
+       default:
+               if (cmd->hdr.return_code) {
+                       QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Unhandled "
+                                               "rc=%d\n",
+                                               dev_name(&card->gdev->dev),
+                                               cmd->hdr.return_code);
+                       return 0;
+               }
+       }
+
        if (cmd->hdr.prot_version == QETH_PROT_IPV4) {
                card->options.ipa4.supported_funcs = cmd->hdr.ipa_supported;
                card->options.ipa4.enabled_funcs = cmd->hdr.ipa_enabled;
-       } else {
+       } else if (cmd->hdr.prot_version == QETH_PROT_IPV6) {
                card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;
                card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;
-       }
+       } else
+               QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Flawed LIC detected"
+                                       "\n", dev_name(&card->gdev->dev));
        QETH_DBF_TEXT(SETUP, 2, "suppenbl");
        QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_supported);
        QETH_DBF_TEXT_(SETUP, 2, "%08x", (__u32)cmd->hdr.ipa_enabled);
index e67e0258aec582a8d441e3eff5591c1eec2058ec..fddb62654b6a6cabeaf4e168951a305cddce1abd 100644 (file)
@@ -626,10 +626,13 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)
        QETH_DBF_TEXT(SETUP, 2, "doL2init");
        QETH_DBF_TEXT_(SETUP, 2, "doL2%s", CARD_BUS_ID(card));
 
-       rc = qeth_query_setadapterparms(card);
-       if (rc) {
-               QETH_DBF_MESSAGE(2, "could not query adapter parameters on "
-                       "device %s: x%x\n", CARD_BUS_ID(card), rc);
+       if (qeth_is_supported(card, IPA_SETADAPTERPARMS)) {
+               rc = qeth_query_setadapterparms(card);
+               if (rc) {
+                       QETH_DBF_MESSAGE(2, "could not query adapter "
+                               "parameters on device %s: x%x\n",
+                               CARD_BUS_ID(card), rc);
+               }
        }
 
        if (card->info.type == QETH_CARD_TYPE_IQD ||
@@ -676,7 +679,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p)
                return -ERESTARTSYS;
        }
        rc = qeth_l2_send_delmac(card, &card->dev->dev_addr[0]);
-       if (!rc)
+       if (!rc || (rc == IPA_RC_L2_MAC_NOT_FOUND))
                rc = qeth_l2_send_setmac(card, addr->sa_data);
        return rc ? -EINVAL : 0;
 }
index c1bafc3f3fb19bad3a1587c85345ef2c4fa9545f..9594ab62702b1786d51d7ac80f7e10b365b6ce61 100644 (file)
@@ -1972,7 +1972,7 @@ sci_io_request_frame_handler(struct isci_request *ireq,
                                                                      frame_index,
                                                                      (void **)&frame_buffer);
 
-                       sci_controller_copy_sata_response(&ireq->stp.req,
+                       sci_controller_copy_sata_response(&ireq->stp.rsp,
                                                               frame_header,
                                                               frame_buffer);
 
index 2936b447cae93bc544fc054c862ecd6d1abb92c6..2c0d0ec8150b62d62d8ca3ca9ecc777a950a7c0a 100644 (file)
@@ -55,6 +55,7 @@
 #include <linux/cpu.h>
 #include <linux/mutex.h>
 #include <linux/async.h>
+#include <asm/unaligned.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
@@ -1061,6 +1062,50 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf,
 }
 EXPORT_SYMBOL_GPL(scsi_get_vpd_page);
 
+/**
+ * scsi_report_opcode - Find out if a given command opcode is supported
+ * @sdev:      scsi device to query
+ * @buffer:    scratch buffer (must be at least 20 bytes long)
+ * @len:       length of buffer
+ * @opcode:    opcode for command to look up
+ *
+ * Uses the REPORT SUPPORTED OPERATION CODES to look up the given
+ * opcode. Returns 0 if RSOC fails or if the command opcode is
+ * unsupported. Returns 1 if the device claims to support the command.
+ */
+int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
+                      unsigned int len, unsigned char opcode)
+{
+       unsigned char cmd[16];
+       struct scsi_sense_hdr sshdr;
+       int result;
+
+       if (sdev->no_report_opcodes || sdev->scsi_level < SCSI_SPC_3)
+               return 0;
+
+       memset(cmd, 0, 16);
+       cmd[0] = MAINTENANCE_IN;
+       cmd[1] = MI_REPORT_SUPPORTED_OPERATION_CODES;
+       cmd[2] = 1;             /* One command format */
+       cmd[3] = opcode;
+       put_unaligned_be32(len, &cmd[6]);
+       memset(buffer, 0, len);
+
+       result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len,
+                                 &sshdr, 30 * HZ, 3, NULL);
+
+       if (result && scsi_sense_valid(&sshdr) &&
+           sshdr.sense_key == ILLEGAL_REQUEST &&
+           (sshdr.asc == 0x20 || sshdr.asc == 0x24) && sshdr.ascq == 0x00)
+               return 0;
+
+       if ((buffer[1] & 3) == 3) /* Command supported */
+               return 1;
+
+       return 0;
+}
+EXPORT_SYMBOL(scsi_report_opcode);
+
 /**
  * scsi_device_get  -  get an additional reference to a scsi_device
  * @sdev:      device to get a reference to
index da36a3a81a9ee2206f753a04d4fbbe91b883e00a..9032e910bca3044055ed23310b38c126318736bb 100644 (file)
@@ -900,11 +900,23 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                                action = ACTION_FAIL;
                                error = -EILSEQ;
                        /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
-                       } else if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
-                                  (cmd->cmnd[0] == UNMAP ||
-                                   cmd->cmnd[0] == WRITE_SAME_16 ||
-                                   cmd->cmnd[0] == WRITE_SAME)) {
-                               description = "Discard failure";
+                       } else if (sshdr.asc == 0x20 || sshdr.asc == 0x24) {
+                               switch (cmd->cmnd[0]) {
+                               case UNMAP:
+                                       description = "Discard failure";
+                                       break;
+                               case WRITE_SAME:
+                               case WRITE_SAME_16:
+                                       if (cmd->cmnd[1] & 0x8)
+                                               description = "Discard failure";
+                                       else
+                                               description =
+                                                       "Write same failure";
+                                       break;
+                               default:
+                                       description = "Invalid command failure";
+                                       break;
+                               }
                                action = ACTION_FAIL;
                                error = -EREMOTEIO;
                        } else
index 12f6fdfc11474a9363ae6c641959832d2c1d6440..352bc77b7c886fb80c057019c3edc2d5b95b7d7e 100644 (file)
@@ -99,6 +99,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
 #endif
 
 static void sd_config_discard(struct scsi_disk *, unsigned int);
+static void sd_config_write_same(struct scsi_disk *);
 static int  sd_revalidate_disk(struct gendisk *);
 static void sd_unlock_native_capacity(struct gendisk *disk);
 static int  sd_probe(struct device *);
@@ -395,6 +396,45 @@ sd_store_max_medium_access_timeouts(struct device *dev,
        return err ? err : count;
 }
 
+static ssize_t
+sd_show_write_same_blocks(struct device *dev, struct device_attribute *attr,
+                         char *buf)
+{
+       struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+       return snprintf(buf, 20, "%u\n", sdkp->max_ws_blocks);
+}
+
+static ssize_t
+sd_store_write_same_blocks(struct device *dev, struct device_attribute *attr,
+                          const char *buf, size_t count)
+{
+       struct scsi_disk *sdkp = to_scsi_disk(dev);
+       struct scsi_device *sdp = sdkp->device;
+       unsigned long max;
+       int err;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EACCES;
+
+       if (sdp->type != TYPE_DISK)
+               return -EINVAL;
+
+       err = kstrtoul(buf, 10, &max);
+
+       if (err)
+               return err;
+
+       if (max == 0)
+               sdp->no_write_same = 1;
+       else if (max <= SD_MAX_WS16_BLOCKS)
+               sdkp->max_ws_blocks = max;
+
+       sd_config_write_same(sdkp);
+
+       return count;
+}
+
 static struct device_attribute sd_disk_attrs[] = {
        __ATTR(cache_type, S_IRUGO|S_IWUSR, sd_show_cache_type,
               sd_store_cache_type),
@@ -410,6 +450,8 @@ static struct device_attribute sd_disk_attrs[] = {
        __ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL),
        __ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode,
               sd_store_provisioning_mode),
+       __ATTR(max_write_same_blocks, S_IRUGO|S_IWUSR,
+              sd_show_write_same_blocks, sd_store_write_same_blocks),
        __ATTR(max_medium_access_timeouts, S_IRUGO|S_IWUSR,
               sd_show_max_medium_access_timeouts,
               sd_store_max_medium_access_timeouts),
@@ -561,19 +603,23 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
                return;
 
        case SD_LBP_UNMAP:
-               max_blocks = min_not_zero(sdkp->max_unmap_blocks, 0xffffffff);
+               max_blocks = min_not_zero(sdkp->max_unmap_blocks,
+                                         (u32)SD_MAX_WS16_BLOCKS);
                break;
 
        case SD_LBP_WS16:
-               max_blocks = min_not_zero(sdkp->max_ws_blocks, 0xffffffff);
+               max_blocks = min_not_zero(sdkp->max_ws_blocks,
+                                         (u32)SD_MAX_WS16_BLOCKS);
                break;
 
        case SD_LBP_WS10:
-               max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
+               max_blocks = min_not_zero(sdkp->max_ws_blocks,
+                                         (u32)SD_MAX_WS10_BLOCKS);
                break;
 
        case SD_LBP_ZERO:
-               max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
+               max_blocks = min_not_zero(sdkp->max_ws_blocks,
+                                         (u32)SD_MAX_WS10_BLOCKS);
                q->limits.discard_zeroes_data = 1;
                break;
        }
@@ -583,29 +629,26 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
 }
 
 /**
- * scsi_setup_discard_cmnd - unmap blocks on thinly provisioned device
+ * sd_setup_discard_cmnd - unmap blocks on thinly provisioned device
  * @sdp: scsi device to operate one
  * @rq: Request to prepare
  *
  * Will issue either UNMAP or WRITE SAME(16) depending on preference
  * indicated by target device.
  **/
-static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
+static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
 {
        struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
-       struct bio *bio = rq->bio;
-       sector_t sector = bio->bi_sector;
-       unsigned int nr_sectors = bio_sectors(bio);
+       sector_t sector = blk_rq_pos(rq);
+       unsigned int nr_sectors = blk_rq_sectors(rq);
+       unsigned int nr_bytes = blk_rq_bytes(rq);
        unsigned int len;
        int ret;
        char *buf;
        struct page *page;
 
-       if (sdkp->device->sector_size == 4096) {
-               sector >>= 3;
-               nr_sectors >>= 3;
-       }
-
+       sector >>= ilog2(sdp->sector_size) - 9;
+       nr_sectors >>= ilog2(sdp->sector_size) - 9;
        rq->timeout = SD_TIMEOUT;
 
        memset(rq->cmd, 0, rq->cmd_len);
@@ -660,6 +703,7 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq)
        blk_add_request_payload(rq, page, len);
        ret = scsi_setup_blk_pc_cmnd(sdp, rq);
        rq->buffer = page_address(page);
+       rq->__data_len = nr_bytes;
 
 out:
        if (ret != BLKPREP_OK) {
@@ -669,6 +713,83 @@ out:
        return ret;
 }
 
+static void sd_config_write_same(struct scsi_disk *sdkp)
+{
+       struct request_queue *q = sdkp->disk->queue;
+       unsigned int logical_block_size = sdkp->device->sector_size;
+       unsigned int blocks = 0;
+
+       if (sdkp->device->no_write_same) {
+               sdkp->max_ws_blocks = 0;
+               goto out;
+       }
+
+       /* Some devices can not handle block counts above 0xffff despite
+        * supporting WRITE SAME(16). Consequently we default to 64k
+        * blocks per I/O unless the device explicitly advertises a
+        * bigger limit.
+        */
+       if (sdkp->max_ws_blocks == 0)
+               sdkp->max_ws_blocks = SD_MAX_WS10_BLOCKS;
+
+       if (sdkp->ws16 || sdkp->max_ws_blocks > SD_MAX_WS10_BLOCKS)
+               blocks = min_not_zero(sdkp->max_ws_blocks,
+                                     (u32)SD_MAX_WS16_BLOCKS);
+       else
+               blocks = min_not_zero(sdkp->max_ws_blocks,
+                                     (u32)SD_MAX_WS10_BLOCKS);
+
+out:
+       blk_queue_max_write_same_sectors(q, blocks * (logical_block_size >> 9));
+}
+
+/**
+ * sd_setup_write_same_cmnd - write the same data to multiple blocks
+ * @sdp: scsi device to operate one
+ * @rq: Request to prepare
+ *
+ * Will issue either WRITE SAME(10) or WRITE SAME(16) depending on
+ * preference indicated by target device.
+ **/
+static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq)
+{
+       struct scsi_disk *sdkp = scsi_disk(rq->rq_disk);
+       struct bio *bio = rq->bio;
+       sector_t sector = blk_rq_pos(rq);
+       unsigned int nr_sectors = blk_rq_sectors(rq);
+       unsigned int nr_bytes = blk_rq_bytes(rq);
+       int ret;
+
+       if (sdkp->device->no_write_same)
+               return BLKPREP_KILL;
+
+       BUG_ON(bio_offset(bio) || bio_iovec(bio)->bv_len != sdp->sector_size);
+
+       sector >>= ilog2(sdp->sector_size) - 9;
+       nr_sectors >>= ilog2(sdp->sector_size) - 9;
+
+       rq->__data_len = sdp->sector_size;
+       rq->timeout = SD_WRITE_SAME_TIMEOUT;
+       memset(rq->cmd, 0, rq->cmd_len);
+
+       if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff) {
+               rq->cmd_len = 16;
+               rq->cmd[0] = WRITE_SAME_16;
+               put_unaligned_be64(sector, &rq->cmd[2]);
+               put_unaligned_be32(nr_sectors, &rq->cmd[10]);
+       } else {
+               rq->cmd_len = 10;
+               rq->cmd[0] = WRITE_SAME;
+               put_unaligned_be32(sector, &rq->cmd[2]);
+               put_unaligned_be16(nr_sectors, &rq->cmd[7]);
+       }
+
+       ret = scsi_setup_blk_pc_cmnd(sdp, rq);
+       rq->__data_len = nr_bytes;
+
+       return ret;
+}
+
 static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq)
 {
        rq->timeout = SD_FLUSH_TIMEOUT;
@@ -712,7 +833,10 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq)
         * block PC requests to make life easier.
         */
        if (rq->cmd_flags & REQ_DISCARD) {
-               ret = scsi_setup_discard_cmnd(sdp, rq);
+               ret = sd_setup_discard_cmnd(sdp, rq);
+               goto out;
+       } else if (rq->cmd_flags & REQ_WRITE_SAME) {
+               ret = sd_setup_write_same_cmnd(sdp, rq);
                goto out;
        } else if (rq->cmd_flags & REQ_FLUSH) {
                ret = scsi_setup_flush_cmnd(sdp, rq);
@@ -1482,12 +1606,21 @@ static int sd_done(struct scsi_cmnd *SCpnt)
        unsigned int good_bytes = result ? 0 : scsi_bufflen(SCpnt);
        struct scsi_sense_hdr sshdr;
        struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk);
+       struct request *req = SCpnt->request;
        int sense_valid = 0;
        int sense_deferred = 0;
        unsigned char op = SCpnt->cmnd[0];
+       unsigned char unmap = SCpnt->cmnd[1] & 8;
 
-       if ((SCpnt->request->cmd_flags & REQ_DISCARD) && !result)
-               scsi_set_resid(SCpnt, 0);
+       if (req->cmd_flags & REQ_DISCARD || req->cmd_flags & REQ_WRITE_SAME) {
+               if (!result) {
+                       good_bytes = blk_rq_bytes(req);
+                       scsi_set_resid(SCpnt, 0);
+               } else {
+                       good_bytes = 0;
+                       scsi_set_resid(SCpnt, blk_rq_bytes(req));
+               }
+       }
 
        if (result) {
                sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr);
@@ -1536,9 +1669,25 @@ static int sd_done(struct scsi_cmnd *SCpnt)
                if (sshdr.asc == 0x10)  /* DIX: Host detected corruption */
                        good_bytes = sd_completed_bytes(SCpnt);
                /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
-               if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
-                   (op == UNMAP || op == WRITE_SAME_16 || op == WRITE_SAME))
-                       sd_config_discard(sdkp, SD_LBP_DISABLE);
+               if (sshdr.asc == 0x20 || sshdr.asc == 0x24) {
+                       switch (op) {
+                       case UNMAP:
+                               sd_config_discard(sdkp, SD_LBP_DISABLE);
+                               break;
+                       case WRITE_SAME_16:
+                       case WRITE_SAME:
+                               if (unmap)
+                                       sd_config_discard(sdkp, SD_LBP_DISABLE);
+                               else {
+                                       sdkp->device->no_write_same = 1;
+                                       sd_config_write_same(sdkp);
+
+                                       good_bytes = 0;
+                                       req->__data_len = blk_rq_bytes(req);
+                                       req->cmd_flags |= REQ_QUIET;
+                               }
+                       }
+               }
                break;
        default:
                break;
@@ -2374,9 +2523,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)
        if (buffer[3] == 0x3c) {
                unsigned int lba_count, desc_count;
 
-               sdkp->max_ws_blocks =
-                       (u32) min_not_zero(get_unaligned_be64(&buffer[36]),
-                                          (u64)0xffffffff);
+               sdkp->max_ws_blocks = (u32)get_unaligned_be64(&buffer[36]);
 
                if (!sdkp->lbpme)
                        goto out;
@@ -2469,6 +2616,13 @@ static void sd_read_block_provisioning(struct scsi_disk *sdkp)
        kfree(buffer);
 }
 
+static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer)
+{
+       if (scsi_report_opcode(sdkp->device, buffer, SD_BUF_SIZE,
+                              WRITE_SAME_16))
+               sdkp->ws16 = 1;
+}
+
 static int sd_try_extended_inquiry(struct scsi_device *sdp)
 {
        /*
@@ -2528,6 +2682,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
                sd_read_write_protect_flag(sdkp, buffer);
                sd_read_cache_type(sdkp, buffer);
                sd_read_app_tag_own(sdkp, buffer);
+               sd_read_write_same(sdkp, buffer);
        }
 
        sdkp->first_scan = 0;
@@ -2545,6 +2700,7 @@ static int sd_revalidate_disk(struct gendisk *disk)
        blk_queue_flush(sdkp->disk->queue, flush);
 
        set_capacity(disk, sdkp->capacity);
+       sd_config_write_same(sdkp);
        kfree(buffer);
 
  out:
index 47c52a6d733c0f757b4ef42236e89fba172b857c..74a1e4ca5401f9a58e6e705bb2fc8a99fcd04a0f 100644 (file)
@@ -14,6 +14,7 @@
 #define SD_TIMEOUT             (30 * HZ)
 #define SD_MOD_TIMEOUT         (75 * HZ)
 #define SD_FLUSH_TIMEOUT       (60 * HZ)
+#define SD_WRITE_SAME_TIMEOUT  (120 * HZ)
 
 /*
  * Number of allowed retries
@@ -38,6 +39,11 @@ enum {
        SD_MEMPOOL_SIZE = 2,    /* CDB pool size */
 };
 
+enum {
+       SD_MAX_WS10_BLOCKS = 0xffff,
+       SD_MAX_WS16_BLOCKS = 0x7fffff,
+};
+
 enum {
        SD_LBP_FULL = 0,        /* Full logical block provisioning */
        SD_LBP_UNMAP,           /* Use UNMAP command */
@@ -77,6 +83,7 @@ struct scsi_disk {
        unsigned        lbpws : 1;
        unsigned        lbpws10 : 1;
        unsigned        lbpvpd : 1;
+       unsigned        ws16 : 1;
 };
 #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
 
index f2ffd963f1c348e3986f761b1d2d2b7b75b361e2..d0cafd6371996c75e3ee094b2be3168ad14d38b7 100644 (file)
@@ -51,12 +51,10 @@ enum android_alarm_return_flags {
 #define ANDROID_ALARM_WAIT                  _IO('a', 1)
 
 #define ALARM_IOW(c, type, size)            _IOW('a', (c) | ((type) << 4), size)
-#define ALARM_IOR(c, type, size)            _IOR('a', (c) | ((type) << 4), size)
-
 /* Set alarm */
 #define ANDROID_ALARM_SET(type)             ALARM_IOW(2, type, struct timespec)
 #define ANDROID_ALARM_SET_AND_WAIT(type)    ALARM_IOW(3, type, struct timespec)
-#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOR(4, type, struct timespec)
+#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOW(4, type, struct timespec)
 #define ANDROID_ALARM_SET_RTC               _IOW('a', 5, struct timespec)
 #define ANDROID_ALARM_BASE_CMD(cmd)         (cmd & ~(_IOC(0, 0, 0xf0, 0)))
 #define ANDROID_ALARM_IOCTL_TO_TYPE(cmd)    (_IOC_NR(cmd) >> 4)
index a5dec1ca1b826bad18d9a1bf5c69eae17bfba423..13ee53bd0bf66869c201e901d3bf16ff35039e17 100644 (file)
@@ -424,7 +424,6 @@ static void hvc_hangup(struct tty_struct *tty)
 {
        struct hvc_struct *hp = tty->driver_data;
        unsigned long flags;
-       int temp_open_count;
 
        if (!hp)
                return;
@@ -444,7 +443,6 @@ static void hvc_hangup(struct tty_struct *tty)
                return;
        }
 
-       temp_open_count = hp->port.count;
        hp->port.count = 0;
        spin_unlock_irqrestore(&hp->port.lock, flags);
        tty_port_tty_set(&hp->port, NULL);
@@ -453,11 +451,6 @@ static void hvc_hangup(struct tty_struct *tty)
 
        if (hp->ops->notifier_hangup)
                hp->ops->notifier_hangup(hp, hp->data);
-
-       while(temp_open_count) {
-               --temp_open_count;
-               tty_port_put(&hp->port);
-       }
 }
 
 /*
index 2bc28a59d38514f762718d19a8ebe50851311b49..1ab1d2c66de43ad749772c240f4f4c6944783e22 100644 (file)
@@ -1239,6 +1239,7 @@ static int __devexit max310x_remove(struct spi_device *spi)
 static const struct spi_device_id max310x_id_table[] = {
        { "max3107",    MAX310X_TYPE_MAX3107 },
        { "max3108",    MAX310X_TYPE_MAX3108 },
+       { }
 };
 MODULE_DEVICE_TABLE(spi, max310x_id_table);
 
index 1e741bca02652e8f4ed2b027654abc3ac9d16a4f..f034716190ff425c89b007e2e10e4cd98ca6cb61 100644 (file)
@@ -2151,8 +2151,15 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum);
 irqreturn_t usb_hcd_irq (int irq, void *__hcd)
 {
        struct usb_hcd          *hcd = __hcd;
+       unsigned long           flags;
        irqreturn_t             rc;
 
+       /* IRQF_DISABLED doesn't work correctly with shared IRQs
+        * when the first handler doesn't use it.  So let's just
+        * assume it's never used.
+        */
+       local_irq_save(flags);
+
        if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd)))
                rc = IRQ_NONE;
        else if (hcd->driver->irq(hcd) == IRQ_NONE)
@@ -2160,6 +2167,7 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
        else
                rc = IRQ_HANDLED;
 
+       local_irq_restore(flags);
        return rc;
 }
 EXPORT_SYMBOL_GPL(usb_hcd_irq);
@@ -2347,6 +2355,14 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd,
        int retval;
 
        if (hcd->driver->irq) {
+
+               /* IRQF_DISABLED doesn't work as advertised when used together
+                * with IRQF_SHARED. As usb_hcd_irq() will always disable
+                * interrupts we can remove it here.
+                */
+               if (irqflags & IRQF_SHARED)
+                       irqflags &= ~IRQF_DISABLED;
+
                snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d",
                                hcd->driver->description, hcd->self.busnum);
                retval = request_irq(irqnum, &usb_hcd_irq, irqflags,
index e426ad626d7498bf5e6537ac100c7a508979066a..4bfa78af379cff63e1e74fa57453d7f55c96fb5e 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/usb/ehci_def.h>
 #include <linux/delay.h>
 #include <linux/serial_core.h>
+#include <linux/kconfig.h>
 #include <linux/kgdb.h>
 #include <linux/kthread.h>
 #include <asm/io.h>
@@ -614,12 +615,6 @@ err:
        return -ENODEV;
 }
 
-int dbgp_external_startup(struct usb_hcd *hcd)
-{
-       return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
-}
-EXPORT_SYMBOL_GPL(dbgp_external_startup);
-
 static int ehci_reset_port(int port)
 {
        u32 portsc;
@@ -979,6 +974,7 @@ struct console early_dbgp_console = {
        .index =        -1,
 };
 
+#if IS_ENABLED(CONFIG_USB_EHCI_HCD)
 int dbgp_reset_prep(struct usb_hcd *hcd)
 {
        int ret = xen_dbgp_reset_prep(hcd);
@@ -1007,6 +1003,13 @@ int dbgp_reset_prep(struct usb_hcd *hcd)
 }
 EXPORT_SYMBOL_GPL(dbgp_reset_prep);
 
+int dbgp_external_startup(struct usb_hcd *hcd)
+{
+       return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup();
+}
+EXPORT_SYMBOL_GPL(dbgp_external_startup);
+#endif /* USB_EHCI_HCD */
+
 #ifdef CONFIG_KGDB
 
 static char kgdbdbgp_buf[DBGP_MAX_PACKET];
index ca759652626bcf5f823a32bf9e6640acda23a02b..aa0f328922dfad88495b919a84d82abd3a494ac9 100644 (file)
@@ -113,7 +113,7 @@ static int ehci_hcd_ls1x_probe(struct platform_device *pdev)
                goto err_put_hcd;
        }
 
-       ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
        if (ret)
                goto err_put_hcd;
 
index 84201cd1a472cd5b00bd959b28bcf35af24137e6..41e378f17c66ac453f2aabfd25640c8e77120224 100644 (file)
@@ -56,7 +56,7 @@ static int ohci_xls_probe_internal(const struct hc_driver *driver,
                goto err3;
        }
 
-       retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
+       retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
        if (retval != 0)
                goto err4;
        return retval;
index d0b87e7b4abfd98b232c135df7661d6dbe0bfe90..b6b84dacc7917070fb20503243ac51098c927631 100644 (file)
@@ -707,11 +707,12 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                fifo_count = musb_readw(epio, MUSB_RXCOUNT);
 
                /*
-                *  use mode 1 only if we expect data of at least ep packet_sz
-                *  and have not yet received a short packet
+                * Enable Mode 1 on RX transfers only when short_not_ok flag
+                * is set. Currently short_not_ok flag is set only from
+                * file_storage and f_mass_storage drivers
                 */
-               if ((request->length - request->actual >= musb_ep->packet_sz) &&
-                       (fifo_count >= musb_ep->packet_sz))
+
+               if (request->short_not_ok && fifo_count == musb_ep->packet_sz)
                        use_mode_1 = 1;
                else
                        use_mode_1 = 0;
@@ -727,6 +728,27 @@ static void rxstate(struct musb *musb, struct musb_request *req)
                                c = musb->dma_controller;
                                channel = musb_ep->dma;
 
+       /* We use DMA Req mode 0 in rx_csr, and DMA controller operates in
+        * mode 0 only. So we do not get endpoint interrupts due to DMA
+        * completion. We only get interrupts from DMA controller.
+        *
+        * We could operate in DMA mode 1 if we knew the size of the tranfer
+        * in advance. For mass storage class, request->length = what the host
+        * sends, so that'd work.  But for pretty much everything else,
+        * request->length is routinely more than what the host sends. For
+        * most these gadgets, end of is signified either by a short packet,
+        * or filling the last byte of the buffer.  (Sending extra data in
+        * that last pckate should trigger an overflow fault.)  But in mode 1,
+        * we don't get DMA completion interrupt for short packets.
+        *
+        * Theoretically, we could enable DMAReq irq (MUSB_RXCSR_DMAMODE = 1),
+        * to get endpoint interrupt on every DMA req, but that didn't seem
+        * to work reliably.
+        *
+        * REVISIT an updated g_file_storage can set req->short_not_ok, which
+        * then becomes usable as a runtime "use mode 1" hint...
+        */
+
                                /* Experimental: Mode1 works with mass storage use cases */
                                if (use_mode_1) {
                                        csr |= MUSB_RXCSR_AUTOCLEAR;
index d62a91fedc221c02774de2c8b9c9e66c3a880ade..0e62f504410eaaf1120edb49ef40381eb7d41d59 100644 (file)
@@ -65,7 +65,7 @@ static int __devinit ux500_probe(struct platform_device *pdev)
        struct platform_device          *musb;
        struct ux500_glue               *glue;
        struct clk                      *clk;
-
+       int                             musbid;
        int                             ret = -ENOMEM;
 
        glue = kzalloc(sizeof(*glue), GFP_KERNEL);
index d8c8a42bff3eb0bb9187849e8136a6ba358a92cf..6223062d5d1b5487534dc29724508d2e5df68793 100644 (file)
@@ -58,7 +58,7 @@ config USB_ULPI_VIEWPORT
 
 config TWL4030_USB
        tristate "TWL4030 USB Transceiver Driver"
-       depends on TWL4030_CORE && REGULATOR_TWL4030
+       depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS
        select USB_OTG_UTILS
        help
          Enable this to support the USB OTG transceiver on TWL4030
@@ -68,7 +68,7 @@ config TWL4030_USB
 
 config TWL6030_USB
        tristate "TWL6030 USB Transceiver Driver"
-       depends on TWL4030_CORE && OMAP_USB2
+       depends on TWL4030_CORE && OMAP_USB2 && USB_MUSB_OMAP2PLUS
        select USB_OTG_UTILS
        help
          Enable this to support the USB OTG transceiver on TWL6030
index 7179b0c5f8148e183219b2a71c34d6d7bf7494a6..cff8dd5b462d0c35a264ef850c0b7877f9702afa 100644 (file)
@@ -2430,7 +2430,7 @@ static void keyspan_release(struct usb_serial *serial)
 static int keyspan_port_probe(struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
-       struct keyspan_port_private *s_priv;
+       struct keyspan_serial_private *s_priv;
        struct keyspan_port_private *p_priv;
        const struct keyspan_device_details *d_details;
        struct callbacks *cback;
@@ -2445,7 +2445,6 @@ static int keyspan_port_probe(struct usb_serial_port *port)
        if (!p_priv)
                return -ENOMEM;
 
-       s_priv = usb_get_serial_data(port->serial);
        p_priv->device_details = d_details;
 
        /* Setup values for the various callback routines */
index 5dee7d61241e2269d6453a0c5693af3a354e8a0e..edc64bb6f457e45408f2c360dfc6de4500108499 100644 (file)
@@ -158,6 +158,7 @@ static void option_instat_callback(struct urb *urb);
 #define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED        0x8001
 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED        0x9000
 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED        0x9001
+#define NOVATELWIRELESS_PRODUCT_E362           0x9010
 #define NOVATELWIRELESS_PRODUCT_G1             0xA001
 #define NOVATELWIRELESS_PRODUCT_G1_M           0xA002
 #define NOVATELWIRELESS_PRODUCT_G2             0xA010
@@ -193,6 +194,9 @@ static void option_instat_callback(struct urb *urb);
 #define DELL_PRODUCT_5730_MINICARD_TELUS       0x8181
 #define DELL_PRODUCT_5730_MINICARD_VZW         0x8182
 
+#define DELL_PRODUCT_5800_MINICARD_VZW         0x8195  /* Novatel E362 */
+#define DELL_PRODUCT_5800_V2_MINICARD_VZW      0x8196  /* Novatel E362 */
+
 #define KYOCERA_VENDOR_ID                      0x0c88
 #define KYOCERA_PRODUCT_KPC650                 0x17da
 #define KYOCERA_PRODUCT_KPC680                 0x180a
@@ -283,6 +287,7 @@ static void option_instat_callback(struct urb *urb);
 /* ALCATEL PRODUCTS */
 #define ALCATEL_VENDOR_ID                      0x1bbb
 #define ALCATEL_PRODUCT_X060S_X200             0x0000
+#define ALCATEL_PRODUCT_X220_X500D             0x0017
 
 #define PIRELLI_VENDOR_ID                      0x1266
 #define PIRELLI_PRODUCT_C100_1                 0x1002
@@ -706,6 +711,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) },
        /* Novatel Ovation MC551 a.k.a. Verizon USB551L */
        { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) },
 
        { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) },
        { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) },
@@ -728,6 +734,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) },      /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
        { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) },       /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
        { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) },         /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */
+       { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_MINICARD_VZW, 0xff, 0xff, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_V2_MINICARD_VZW, 0xff, 0xff, 0xff) },
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) },   /* ADU-E100, ADU-310 */
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) },
        { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) },
@@ -1157,6 +1165,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
          .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
        },
+       { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) },
        { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
        { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
        { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
index 61a73ad1a1877c4558444a34884e236a8352e0d9..a3e9c095f0d83a39738ef74b9e3a9ef7b41a2d6e 100644 (file)
@@ -455,9 +455,6 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
        struct usb_serial *serial = port->serial;
        struct urb *urb;
 
-       if (endpoint == -1)
-               return NULL;    /* endpoint not needed */
-
        urb = usb_alloc_urb(0, GFP_KERNEL);     /* No ISO */
        if (urb == NULL) {
                dev_dbg(&serial->interface->dev,
@@ -489,6 +486,9 @@ int usb_wwan_port_probe(struct usb_serial_port *port)
        init_usb_anchor(&portdata->delayed);
 
        for (i = 0; i < N_IN_URB; i++) {
+               if (!port->bulk_in_size)
+                       break;
+
                buffer = (u8 *)__get_free_page(GFP_KERNEL);
                if (!buffer)
                        goto bail_out_error;
@@ -502,8 +502,8 @@ int usb_wwan_port_probe(struct usb_serial_port *port)
        }
 
        for (i = 0; i < N_OUT_URB; i++) {
-               if (port->bulk_out_endpointAddress == -1)
-                       continue;
+               if (!port->bulk_out_size)
+                       break;
 
                buffer = kmalloc(OUT_BUFLEN, GFP_KERNEL);
                if (!buffer)
index a3d54366afccde598a4ba5f3240909044f975266..92f35abee92d281990e17ccdb4f388d33ed67f0e 100644 (file)
@@ -186,6 +186,12 @@ static int slave_configure(struct scsi_device *sdev)
                /* Some devices don't handle VPD pages correctly */
                sdev->skip_vpd_pages = 1;
 
+               /* Do not attempt to use REPORT SUPPORTED OPERATION CODES */
+               sdev->no_report_opcodes = 1;
+
+               /* Do not attempt to use WRITE SAME */
+               sdev->no_write_same = 1;
+
                /* Some disks return the total number of blocks in response
                 * to READ CAPACITY rather than the highest block number.
                 * If this device makes that mistake, tell the sd driver. */
index d64ac3842884f4e9eac994dd03fdc311646d27b9..bee92846cfab930f6304a9ebb4316b25b8780bc7 100644 (file)
@@ -365,11 +365,20 @@ struct platform_device *dsi_get_dsidev_from_id(int module)
        struct omap_dss_output *out;
        enum omap_dss_output_id id;
 
-       id = module == 0 ? OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2;
+       switch (module) {
+       case 0:
+               id = OMAP_DSS_OUTPUT_DSI1;
+               break;
+       case 1:
+               id = OMAP_DSS_OUTPUT_DSI2;
+               break;
+       default:
+               return NULL;
+       }
 
        out = omap_dss_get_output(id);
 
-       return out->pdev;
+       return out ? out->pdev : NULL;
 }
 
 static inline void dsi_write_reg(struct platform_device *dsidev,
index 2ab1c3e96553d81297ad5f942eed2cfb76a5064b..5f6eea801b064a37949b3cc66bf9ca5f2dde3431 100644 (file)
@@ -697,11 +697,15 @@ static int dss_get_clocks(void)
 
        dss.dss_clk = clk;
 
-       clk = clk_get(NULL, dss.feat->clk_name);
-       if (IS_ERR(clk)) {
-               DSSERR("Failed to get %s\n", dss.feat->clk_name);
-               r = PTR_ERR(clk);
-               goto err;
+       if (dss.feat->clk_name) {
+               clk = clk_get(NULL, dss.feat->clk_name);
+               if (IS_ERR(clk)) {
+                       DSSERR("Failed to get %s\n", dss.feat->clk_name);
+                       r = PTR_ERR(clk);
+                       goto err;
+               }
+       } else {
+               clk = NULL;
        }
 
        dss.dpll4_m4_ck = clk;
@@ -805,10 +809,10 @@ static int __init dss_init_features(struct device *dev)
 
        if (cpu_is_omap24xx())
                src = &omap24xx_dss_feats;
-       else if (cpu_is_omap34xx())
-               src = &omap34xx_dss_feats;
        else if (cpu_is_omap3630())
                src = &omap3630_dss_feats;
+       else if (cpu_is_omap34xx())
+               src = &omap34xx_dss_feats;
        else if (cpu_is_omap44xx())
                src = &omap44xx_dss_feats;
        else if (soc_is_omap54xx())
index a48a7dd75b3303a3bba28e10b01e4c1f133c00d3..8c9b8b3b7f773cd41c00f78b923070f87c325f70 100644 (file)
@@ -644,8 +644,10 @@ static void hdmi_dump_regs(struct seq_file *s)
 {
        mutex_lock(&hdmi.lock);
 
-       if (hdmi_runtime_get())
+       if (hdmi_runtime_get()) {
+               mutex_unlock(&hdmi.lock);
                return;
+       }
 
        hdmi.ip_data.ops->dump_wrapper(&hdmi.ip_data, s);
        hdmi.ip_data.ops->dump_pll(&hdmi.ip_data, s);
index 606b89f12351d4e1cc2cb234fd4e5c481bf82cda..d630b26a005c7ae2e0bea55b1c0a644fc64ad1e9 100644 (file)
@@ -787,7 +787,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
 
        case OMAPFB_WAITFORVSYNC:
                DBG("ioctl WAITFORVSYNC\n");
-               if (!display && !display->output && !display->output->manager) {
+               if (!display || !display->output || !display->output->manager) {
                        r = -EINVAL;
                        break;
                }
index 8adb9cc267f96e201ade041441ef8a317ce336d8..71f5c459b088aa5e21066b77adbcb5f34f7b9843 100644 (file)
@@ -361,13 +361,13 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
        down_write(&mm->mmap_sem);
 
        vma = find_vma(mm, m.addr);
-       ret = -EINVAL;
        if (!vma ||
            vma->vm_ops != &privcmd_vm_ops ||
            (m.addr != vma->vm_start) ||
            ((m.addr + (nr_pages << PAGE_SHIFT)) != vma->vm_end) ||
            !privcmd_enforce_singleshot_mapping(vma)) {
                up_write(&mm->mmap_sem);
+               ret = -EINVAL;
                goto out;
        }
 
@@ -383,12 +383,16 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version)
 
        up_write(&mm->mmap_sem);
 
-       if (state.global_error && (version == 1)) {
-               /* Write back errors in second pass. */
-               state.user_mfn = (xen_pfn_t *)m.arr;
-               state.err      = err_array;
-               ret = traverse_pages(m.num, sizeof(xen_pfn_t),
-                                    &pagelist, mmap_return_errors_v1, &state);
+       if (version == 1) {
+               if (state.global_error) {
+                       /* Write back errors in second pass. */
+                       state.user_mfn = (xen_pfn_t *)m.arr;
+                       state.err      = err_array;
+                       ret = traverse_pages(m.num, sizeof(xen_pfn_t),
+                                            &pagelist, mmap_return_errors_v1, &state);
+               } else
+                       ret = 0;
+
        } else if (version == 2) {
                ret = __copy_to_user(m.err, err_array, m.num * sizeof(int));
                if (ret)
index 7320a66e958f8d45e796c796ee150b786c3f7f8e..22548f56197b52cf06b343285b7e7beb7d74cb10 100644 (file)
@@ -2101,8 +2101,9 @@ int ext3_trim_fs(struct super_block *sb, struct fstrim_range *range)
        end = start + (range->len >> sb->s_blocksize_bits) - 1;
        minlen = range->minlen >> sb->s_blocksize_bits;
 
-       if (unlikely(minlen > EXT3_BLOCKS_PER_GROUP(sb)) ||
-           unlikely(start >= max_blks))
+       if (minlen > EXT3_BLOCKS_PER_GROUP(sb) ||
+           start >= max_blks ||
+           range->len < sb->s_blocksize)
                return -EINVAL;
        if (end >= max_blks)
                end = max_blks - 1;
index 708d997a77485989d53583084a3e1b99354fb407..7cb71b99260340fe7302d2a8c5dc4f84f8029aff 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -685,7 +685,6 @@ void do_close_on_exec(struct files_struct *files)
        struct fdtable *fdt;
 
        /* exec unshares first */
-       BUG_ON(atomic_read(&files->count) != 1);
        spin_lock(&files->file_lock);
        for (i = 0; ; i++) {
                unsigned long set;
index 60ef3fb707ffbfc6a77f1257efc82544cf0f9489..1506673c087e11ae820245baadc8ae74cb9f01b2 100644 (file)
@@ -138,33 +138,39 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
        struct page *pg;
        struct inode *inode = mapping->host;
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+       struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+       struct jffs2_raw_inode ri;
+       uint32_t alloc_len = 0;
        pgoff_t index = pos >> PAGE_CACHE_SHIFT;
        uint32_t pageofs = index << PAGE_CACHE_SHIFT;
        int ret = 0;
 
+       jffs2_dbg(1, "%s()\n", __func__);
+
+       if (pageofs > inode->i_size) {
+               ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
+                                         ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
+               if (ret)
+                       return ret;
+       }
+
+       mutex_lock(&f->sem);
        pg = grab_cache_page_write_begin(mapping, index, flags);
-       if (!pg)
+       if (!pg) {
+               if (alloc_len)
+                       jffs2_complete_reservation(c);
+               mutex_unlock(&f->sem);
                return -ENOMEM;
+       }
        *pagep = pg;
 
-       jffs2_dbg(1, "%s()\n", __func__);
-
-       if (pageofs > inode->i_size) {
+       if (alloc_len) {
                /* Make new hole frag from old EOF to new page */
-               struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
-               struct jffs2_raw_inode ri;
                struct jffs2_full_dnode *fn;
-               uint32_t alloc_len;
 
                jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n",
                          (unsigned int)inode->i_size, pageofs);
 
-               ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
-                                         ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
-               if (ret)
-                       goto out_page;
-
-               mutex_lock(&f->sem);
                memset(&ri, 0, sizeof(ri));
 
                ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
@@ -191,7 +197,6 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
                if (IS_ERR(fn)) {
                        ret = PTR_ERR(fn);
                        jffs2_complete_reservation(c);
-                       mutex_unlock(&f->sem);
                        goto out_page;
                }
                ret = jffs2_add_full_dnode_to_inode(c, f, fn);
@@ -206,12 +211,10 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
                        jffs2_mark_node_obsolete(c, fn->raw);
                        jffs2_free_full_dnode(fn);
                        jffs2_complete_reservation(c);
-                       mutex_unlock(&f->sem);
                        goto out_page;
                }
                jffs2_complete_reservation(c);
                inode->i_size = pageofs;
-               mutex_unlock(&f->sem);
        }
 
        /*
@@ -220,18 +223,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping,
         * case of a short-copy.
         */
        if (!PageUptodate(pg)) {
-               mutex_lock(&f->sem);
                ret = jffs2_do_readpage_nolock(inode, pg);
-               mutex_unlock(&f->sem);
                if (ret)
                        goto out_page;
        }
+       mutex_unlock(&f->sem);
        jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags);
        return ret;
 
 out_page:
        unlock_page(pg);
        page_cache_release(pg);
+       mutex_unlock(&f->sem);
        return ret;
 }
 
index 721d692fa8d4a20dd5bf593d3f732d8b3f913261..6fcaeb8c902e4c3bc862c6c81db0a884068274b7 100644 (file)
@@ -258,7 +258,8 @@ static ssize_t copy_event_to_user(struct fsnotify_group *group,
        if (ret)
                goto out_close_fd;
 
-       fd_install(fd, f);
+       if (fd != FAN_NOFD)
+               fd_install(fd, f);
        return fanotify_event_metadata.event_len;
 
 out_close_fd:
index 144a96732dd7d602df0d5f8a504e435cfdb07229..3c231adf845088ee51517c1f7fd0745284d88be2 100644 (file)
@@ -873,6 +873,113 @@ static const struct file_operations proc_environ_operations = {
        .release        = mem_release,
 };
 
+static ssize_t oom_adj_read(struct file *file, char __user *buf, size_t count,
+                           loff_t *ppos)
+{
+       struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
+       char buffer[PROC_NUMBUF];
+       int oom_adj = OOM_ADJUST_MIN;
+       size_t len;
+       unsigned long flags;
+
+       if (!task)
+               return -ESRCH;
+       if (lock_task_sighand(task, &flags)) {
+               if (task->signal->oom_score_adj == OOM_SCORE_ADJ_MAX)
+                       oom_adj = OOM_ADJUST_MAX;
+               else
+                       oom_adj = (task->signal->oom_score_adj * -OOM_DISABLE) /
+                                 OOM_SCORE_ADJ_MAX;
+               unlock_task_sighand(task, &flags);
+       }
+       put_task_struct(task);
+       len = snprintf(buffer, sizeof(buffer), "%d\n", oom_adj);
+       return simple_read_from_buffer(buf, count, ppos, buffer, len);
+}
+
+static ssize_t oom_adj_write(struct file *file, const char __user *buf,
+                            size_t count, loff_t *ppos)
+{
+       struct task_struct *task;
+       char buffer[PROC_NUMBUF];
+       int oom_adj;
+       unsigned long flags;
+       int err;
+
+       memset(buffer, 0, sizeof(buffer));
+       if (count > sizeof(buffer) - 1)
+               count = sizeof(buffer) - 1;
+       if (copy_from_user(buffer, buf, count)) {
+               err = -EFAULT;
+               goto out;
+       }
+
+       err = kstrtoint(strstrip(buffer), 0, &oom_adj);
+       if (err)
+               goto out;
+       if ((oom_adj < OOM_ADJUST_MIN || oom_adj > OOM_ADJUST_MAX) &&
+            oom_adj != OOM_DISABLE) {
+               err = -EINVAL;
+               goto out;
+       }
+
+       task = get_proc_task(file->f_path.dentry->d_inode);
+       if (!task) {
+               err = -ESRCH;
+               goto out;
+       }
+
+       task_lock(task);
+       if (!task->mm) {
+               err = -EINVAL;
+               goto err_task_lock;
+       }
+
+       if (!lock_task_sighand(task, &flags)) {
+               err = -ESRCH;
+               goto err_task_lock;
+       }
+
+       /*
+        * Scale /proc/pid/oom_score_adj appropriately ensuring that a maximum
+        * value is always attainable.
+        */
+       if (oom_adj == OOM_ADJUST_MAX)
+               oom_adj = OOM_SCORE_ADJ_MAX;
+       else
+               oom_adj = (oom_adj * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE;
+
+       if (oom_adj < task->signal->oom_score_adj &&
+           !capable(CAP_SYS_RESOURCE)) {
+               err = -EACCES;
+               goto err_sighand;
+       }
+
+       /*
+        * /proc/pid/oom_adj is provided for legacy purposes, ask users to use
+        * /proc/pid/oom_score_adj instead.
+        */
+       printk_once(KERN_WARNING "%s (%d): /proc/%d/oom_adj is deprecated, please use /proc/%d/oom_score_adj instead.\n",
+                 current->comm, task_pid_nr(current), task_pid_nr(task),
+                 task_pid_nr(task));
+
+       task->signal->oom_score_adj = oom_adj;
+       trace_oom_score_adj_update(task);
+err_sighand:
+       unlock_task_sighand(task, &flags);
+err_task_lock:
+       task_unlock(task);
+       put_task_struct(task);
+out:
+       return err < 0 ? err : count;
+}
+
+static const struct file_operations proc_oom_adj_operations = {
+       .read           = oom_adj_read,
+       .write          = oom_adj_write,
+       .llseek         = generic_file_llseek,
+};
+
 static ssize_t oom_score_adj_read(struct file *file, char __user *buf,
                                        size_t count, loff_t *ppos)
 {
@@ -2598,6 +2705,7 @@ static const struct pid_entry tgid_base_stuff[] = {
        REG("cgroup",  S_IRUGO, proc_cgroup_operations),
 #endif
        INF("oom_score",  S_IRUGO, proc_oom_score),
+       REG("oom_adj",    S_IRUGO|S_IWUSR, proc_oom_adj_operations),
        REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
 #ifdef CONFIG_AUDITSYSCALL
        REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
@@ -2964,6 +3072,7 @@ static const struct pid_entry tid_base_stuff[] = {
        REG("cgroup",  S_IRUGO, proc_cgroup_operations),
 #endif
        INF("oom_score", S_IRUGO, proc_oom_score),
+       REG("oom_adj",   S_IRUGO|S_IWUSR, proc_oom_adj_operations),
        REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
 #ifdef CONFIG_AUDITSYSCALL
        REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
index a40da07e93d68a88e670b5256a1c22c4badeb634..947fbe06c3b1f2ed0948b8fb050b43f2c48ff591 100644 (file)
@@ -161,6 +161,7 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
 
        while (s < e) {
                unsigned long flags;
+               u64 id;
 
                if (c > psinfo->bufsize)
                        c = psinfo->bufsize;
@@ -172,7 +173,7 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
                        spin_lock_irqsave(&psinfo->buf_lock, flags);
                }
                memcpy(psinfo->buf, s, c);
-               psinfo->write(PSTORE_TYPE_CONSOLE, 0, NULL, 0, c, psinfo);
+               psinfo->write(PSTORE_TYPE_CONSOLE, 0, &id, 0, c, psinfo);
                spin_unlock_irqrestore(&psinfo->buf_lock, flags);
                s += c;
                c = e - s;
index f27f01a98aa2c9573c6cc61fe093c821ce6e107c..d83736fbc26cb4679cf074ee33263f125f13afa7 100644 (file)
@@ -1782,8 +1782,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 
        BUG_ON(!th->t_trans_id);
 
-       dquot_initialize(inode);
+       reiserfs_write_unlock(inode->i_sb);
        err = dquot_alloc_inode(inode);
+       reiserfs_write_lock(inode->i_sb);
        if (err)
                goto out_end_trans;
        if (!dir->i_nlink) {
@@ -1979,8 +1980,10 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
 
       out_end_trans:
        journal_end(th, th->t_super, th->t_blocks_allocated);
+       reiserfs_write_unlock(inode->i_sb);
        /* Drop can be outside and it needs more credits so it's better to have it outside */
        dquot_drop(inode);
+       reiserfs_write_lock(inode->i_sb);
        inode->i_flags |= S_NOQUOTA;
        make_bad_inode(inode);
 
@@ -3103,10 +3106,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
        /* must be turned off for recursive notify_change calls */
        ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID);
 
-       depth = reiserfs_write_lock_once(inode->i_sb);
        if (is_quota_modification(inode, attr))
                dquot_initialize(inode);
-
+       depth = reiserfs_write_lock_once(inode->i_sb);
        if (attr->ia_valid & ATTR_SIZE) {
                /* version 2 items will be caught by the s_maxbytes check
                 ** done for us in vmtruncate
@@ -3170,7 +3172,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr)
                error = journal_begin(&th, inode->i_sb, jbegin_count);
                if (error)
                        goto out;
+               reiserfs_write_unlock_once(inode->i_sb, depth);
                error = dquot_transfer(inode, attr);
+               depth = reiserfs_write_lock_once(inode->i_sb);
                if (error) {
                        journal_end(&th, inode->i_sb, jbegin_count);
                        goto out;
index f8afa4b162b8f026da18b1cf2364e7d1cd6f5116..2f40a4c70a4d9667ca34e00ef2b31888255276c2 100644 (file)
@@ -1968,7 +1968,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree
                       key2type(&(key->on_disk_key)));
 #endif
 
+       reiserfs_write_unlock(inode->i_sb);
        retval = dquot_alloc_space_nodirty(inode, pasted_size);
+       reiserfs_write_lock(inode->i_sb);
        if (retval) {
                pathrelse(search_path);
                return retval;
@@ -2061,9 +2063,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th,
                               "reiserquota insert_item(): allocating %u id=%u type=%c",
                               quota_bytes, inode->i_uid, head2type(ih));
 #endif
+               reiserfs_write_unlock(inode->i_sb);
                /* We can't dirty inode here. It would be immediately written but
                 * appropriate stat item isn't inserted yet... */
                retval = dquot_alloc_space_nodirty(inode, quota_bytes);
+               reiserfs_write_lock(inode->i_sb);
                if (retval) {
                        pathrelse(path);
                        return retval;
index 1078ae179993bb12f105d39fb1d847eb84c12414..418bdc3a57da4e11092477fa1b3cbf2e37f71422 100644 (file)
@@ -298,7 +298,9 @@ static int finish_unfinished(struct super_block *s)
                        retval = remove_save_link_only(s, &save_link_key, 0);
                        continue;
                }
+               reiserfs_write_unlock(s);
                dquot_initialize(inode);
+               reiserfs_write_lock(s);
 
                if (truncate && S_ISDIR(inode->i_mode)) {
                        /* We got a truncate request for a dir which is impossible.
@@ -1335,7 +1337,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                                kfree(qf_names[i]);
 #endif
                err = -EINVAL;
-               goto out_err;
+               goto out_unlock;
        }
 #ifdef CONFIG_QUOTA
        handle_quota_files(s, qf_names, &qfmt);
@@ -1379,7 +1381,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        if (blocks) {
                err = reiserfs_resize(s, blocks);
                if (err != 0)
-                       goto out_err;
+                       goto out_unlock;
        }
 
        if (*mount_flags & MS_RDONLY) {
@@ -1389,9 +1391,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                        /* it is read-only already */
                        goto out_ok;
 
+               /*
+                * Drop write lock. Quota will retake it when needed and lock
+                * ordering requires calling dquot_suspend() without it.
+                */
+               reiserfs_write_unlock(s);
                err = dquot_suspend(s, -1);
                if (err < 0)
                        goto out_err;
+               reiserfs_write_lock(s);
 
                /* try to remount file system with read-only permissions */
                if (sb_umount_state(rs) == REISERFS_VALID_FS
@@ -1401,7 +1409,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
 
                err = journal_begin(&th, s, 10);
                if (err)
-                       goto out_err;
+                       goto out_unlock;
 
                /* Mounting a rw partition read-only. */
                reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
@@ -1416,7 +1424,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
 
                if (reiserfs_is_journal_aborted(journal)) {
                        err = journal->j_errno;
-                       goto out_err;
+                       goto out_unlock;
                }
 
                handle_data_mode(s, mount_options);
@@ -1425,7 +1433,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
                s->s_flags &= ~MS_RDONLY;       /* now it is safe to call journal_begin */
                err = journal_begin(&th, s, 10);
                if (err)
-                       goto out_err;
+                       goto out_unlock;
 
                /* Mount a partition which is read-only, read-write */
                reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1);
@@ -1442,10 +1450,16 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg)
        SB_JOURNAL(s)->j_must_wait = 1;
        err = journal_end(&th, s, 10);
        if (err)
-               goto out_err;
+               goto out_unlock;
 
        if (!(*mount_flags & MS_RDONLY)) {
+               /*
+                * Drop write lock. Quota will retake it when needed and lock
+                * ordering requires calling dquot_resume() without it.
+                */
+               reiserfs_write_unlock(s);
                dquot_resume(s, -1);
+               reiserfs_write_lock(s);
                finish_unfinished(s);
                reiserfs_xattr_init(s, *mount_flags);
        }
@@ -1455,9 +1469,10 @@ out_ok:
        reiserfs_write_unlock(s);
        return 0;
 
+out_unlock:
+       reiserfs_write_unlock(s);
 out_err:
        kfree(new_opts);
-       reiserfs_write_unlock(s);
        return err;
 }
 
@@ -2095,13 +2110,15 @@ static int reiserfs_write_dquot(struct dquot *dquot)
                          REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
        if (ret)
                goto out;
+       reiserfs_write_unlock(dquot->dq_sb);
        ret = dquot_commit(dquot);
+       reiserfs_write_lock(dquot->dq_sb);
        err =
            journal_end(&th, dquot->dq_sb,
                        REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb));
        if (!ret && err)
                ret = err;
-      out:
+out:
        reiserfs_write_unlock(dquot->dq_sb);
        return ret;
 }
@@ -2117,13 +2134,15 @@ static int reiserfs_acquire_dquot(struct dquot *dquot)
                          REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
        if (ret)
                goto out;
+       reiserfs_write_unlock(dquot->dq_sb);
        ret = dquot_acquire(dquot);
+       reiserfs_write_lock(dquot->dq_sb);
        err =
            journal_end(&th, dquot->dq_sb,
                        REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb));
        if (!ret && err)
                ret = err;
-      out:
+out:
        reiserfs_write_unlock(dquot->dq_sb);
        return ret;
 }
@@ -2137,19 +2156,21 @@ static int reiserfs_release_dquot(struct dquot *dquot)
        ret =
            journal_begin(&th, dquot->dq_sb,
                          REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
+       reiserfs_write_unlock(dquot->dq_sb);
        if (ret) {
                /* Release dquot anyway to avoid endless cycle in dqput() */
                dquot_release(dquot);
                goto out;
        }
        ret = dquot_release(dquot);
+       reiserfs_write_lock(dquot->dq_sb);
        err =
            journal_end(&th, dquot->dq_sb,
                        REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb));
        if (!ret && err)
                ret = err;
-      out:
        reiserfs_write_unlock(dquot->dq_sb);
+out:
        return ret;
 }
 
@@ -2174,11 +2195,13 @@ static int reiserfs_write_info(struct super_block *sb, int type)
        ret = journal_begin(&th, sb, 2);
        if (ret)
                goto out;
+       reiserfs_write_unlock(sb);
        ret = dquot_commit_info(sb, type);
+       reiserfs_write_lock(sb);
        err = journal_end(&th, sb, 2);
        if (!ret && err)
                ret = err;
-      out:
+out:
        reiserfs_write_unlock(sb);
        return ret;
 }
@@ -2203,8 +2226,11 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
        struct reiserfs_transaction_handle th;
        int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA;
 
-       if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt)))
-               return -EINVAL;
+       reiserfs_write_lock(sb);
+       if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) {
+               err = -EINVAL;
+               goto out;
+       }
 
        /* Quotafile not on the same filesystem? */
        if (path->dentry->d_sb != sb) {
@@ -2246,8 +2272,10 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id,
                if (err)
                        goto out;
        }
-       err = dquot_quota_on(sb, type, format_id, path);
+       reiserfs_write_unlock(sb);
+       return dquot_quota_on(sb, type, format_id, path);
 out:
+       reiserfs_write_unlock(sb);
        return err;
 }
 
@@ -2320,7 +2348,9 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
                tocopy = sb->s_blocksize - offset < towrite ?
                    sb->s_blocksize - offset : towrite;
                tmp_bh.b_state = 0;
+               reiserfs_write_lock(sb);
                err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE);
+               reiserfs_write_unlock(sb);
                if (err)
                        goto out;
                if (offset || tocopy != sb->s_blocksize)
@@ -2336,10 +2366,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type,
                flush_dcache_page(bh->b_page);
                set_buffer_uptodate(bh);
                unlock_buffer(bh);
+               reiserfs_write_lock(sb);
                reiserfs_prepare_for_journal(sb, bh, 1);
                journal_mark_dirty(current->journal_info, sb, bh);
                if (!journal_quota)
                        reiserfs_add_ordered_list(inode, bh);
+               reiserfs_write_unlock(sb);
                brelse(bh);
                offset = 0;
                towrite -= tocopy;
index 28ec13af28d91c360c89c68f7af0f1957e79477a..2dcf3d473fec1d406bf0fc2d14d73828ff81f662 100644 (file)
@@ -681,8 +681,16 @@ int ubifs_find_free_leb_for_idx(struct ubifs_info *c)
        if (!lprops) {
                lprops = ubifs_fast_find_freeable(c);
                if (!lprops) {
-                       ubifs_assert(c->freeable_cnt == 0);
-                       if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
+                       /*
+                        * The first condition means the following: go scan the
+                        * LPT if there are uncategorized lprops, which means
+                        * there may be freeable LEBs there (UBIFS does not
+                        * store the information about freeable LEBs in the
+                        * master node).
+                        */
+                       if (c->in_a_category_cnt != c->main_lebs ||
+                           c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) {
+                               ubifs_assert(c->freeable_cnt == 0);
                                lprops = scan_for_leb_for_idx(c);
                                if (IS_ERR(lprops)) {
                                        err = PTR_ERR(lprops);
index e5a2a35a46dcc1fc3fb9178704cec947458bda2e..46190a7c42a6c113bcffe4f170800b98a22eaf01 100644 (file)
@@ -300,8 +300,11 @@ void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops,
        default:
                ubifs_assert(0);
        }
+
        lprops->flags &= ~LPROPS_CAT_MASK;
        lprops->flags |= cat;
+       c->in_a_category_cnt += 1;
+       ubifs_assert(c->in_a_category_cnt <= c->main_lebs);
 }
 
 /**
@@ -334,6 +337,9 @@ static void ubifs_remove_from_cat(struct ubifs_info *c,
        default:
                ubifs_assert(0);
        }
+
+       c->in_a_category_cnt -= 1;
+       ubifs_assert(c->in_a_category_cnt >= 0);
 }
 
 /**
index 5486346d0a3f9ec63ce10f9296ee0fbdec8732f1..d133c276fe05d526c647756c704ef37a8438612e 100644 (file)
@@ -1183,6 +1183,8 @@ struct ubifs_debug_info;
  * @freeable_list: list of freeable non-index LEBs (free + dirty == @leb_size)
  * @frdi_idx_list: list of freeable index LEBs (free + dirty == @leb_size)
  * @freeable_cnt: number of freeable LEBs in @freeable_list
+ * @in_a_category_cnt: count of lprops which are in a certain category, which
+ *                     basically meants that they were loaded from the flash
  *
  * @ltab_lnum: LEB number of LPT's own lprops table
  * @ltab_offs: offset of LPT's own lprops table
@@ -1412,6 +1414,7 @@ struct ubifs_info {
        struct list_head freeable_list;
        struct list_head frdi_idx_list;
        int freeable_cnt;
+       int in_a_category_cnt;
 
        int ltab_lnum;
        int ltab_offs;
index e562dd43f41fe762eb4d49c7814f1f002fe965c9..e57e2daa357c34fc9634871a1d41dd76569cf871 100644 (file)
@@ -481,11 +481,17 @@ static inline int bio_add_buffer(struct bio *bio, struct buffer_head *bh)
  *
  * The fix is two passes across the ioend list - one to start writeback on the
  * buffer_heads, and then submit them for I/O on the second pass.
+ *
+ * If @fail is non-zero, it means that we have a situation where some part of
+ * the submission process has failed after we have marked paged for writeback
+ * and unlocked them. In this situation, we need to fail the ioend chain rather
+ * than submit it to IO. This typically only happens on a filesystem shutdown.
  */
 STATIC void
 xfs_submit_ioend(
        struct writeback_control *wbc,
-       xfs_ioend_t             *ioend)
+       xfs_ioend_t             *ioend,
+       int                     fail)
 {
        xfs_ioend_t             *head = ioend;
        xfs_ioend_t             *next;
@@ -506,6 +512,18 @@ xfs_submit_ioend(
                next = ioend->io_list;
                bio = NULL;
 
+               /*
+                * If we are failing the IO now, just mark the ioend with an
+                * error and finish it. This will run IO completion immediately
+                * as there is only one reference to the ioend at this point in
+                * time.
+                */
+               if (fail) {
+                       ioend->io_error = -fail;
+                       xfs_finish_ioend(ioend);
+                       continue;
+               }
+
                for (bh = ioend->io_buffer_head; bh; bh = bh->b_private) {
 
                        if (!bio) {
@@ -1060,7 +1078,18 @@ xfs_vm_writepage(
 
        xfs_start_page_writeback(page, 1, count);
 
-       if (ioend && imap_valid) {
+       /* if there is no IO to be submitted for this page, we are done */
+       if (!ioend)
+               return 0;
+
+       ASSERT(iohead);
+
+       /*
+        * Any errors from this point onwards need tobe reported through the IO
+        * completion path as we have marked the initial page as under writeback
+        * and unlocked it.
+        */
+       if (imap_valid) {
                xfs_off_t               end_index;
 
                end_index = imap.br_startoff + imap.br_blockcount;
@@ -1079,20 +1108,15 @@ xfs_vm_writepage(
                                  wbc, end_index);
        }
 
-       if (iohead) {
-               /*
-                * Reserve log space if we might write beyond the on-disk
-                * inode size.
-                */
-               if (ioend->io_type != XFS_IO_UNWRITTEN &&
-                   xfs_ioend_is_append(ioend)) {
-                       err = xfs_setfilesize_trans_alloc(ioend);
-                       if (err)
-                               goto error;
-               }
 
-               xfs_submit_ioend(wbc, iohead);
-       }
+       /*
+        * Reserve log space if we might write beyond the on-disk inode size.
+        */
+       err = 0;
+       if (ioend->io_type != XFS_IO_UNWRITTEN && xfs_ioend_is_append(ioend))
+               err = xfs_setfilesize_trans_alloc(ioend);
+
+       xfs_submit_ioend(wbc, iohead, err);
 
        return 0;
 
index d330111ca738eef9ff86b5fd28723c0b63a9b379..70eec1829776309b3cba83e9a660aa6de5ad9693 100644 (file)
@@ -1291,6 +1291,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
        leaf2 = blk2->bp->b_addr;
        ASSERT(leaf1->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
        ASSERT(leaf2->hdr.info.magic == cpu_to_be16(XFS_ATTR_LEAF_MAGIC));
+       ASSERT(leaf2->hdr.count == 0);
        args = state->args;
 
        trace_xfs_attr_leaf_rebalance(args);
@@ -1361,6 +1362,7 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
                 * I assert that since all callers pass in an empty
                 * second buffer, this code should never execute.
                 */
+               ASSERT(0);
 
                /*
                 * Figure the total bytes to be added to the destination leaf.
@@ -1422,10 +1424,24 @@ xfs_attr_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1,
                        args->index2 = 0;
                        args->blkno2 = blk2->blkno;
                } else {
+                       /*
+                        * On a double leaf split, the original attr location
+                        * is already stored in blkno2/index2, so don't
+                        * overwrite it overwise we corrupt the tree.
+                        */
                        blk2->index = blk1->index
                                    - be16_to_cpu(leaf1->hdr.count);
-                       args->index = args->index2 = blk2->index;
-                       args->blkno = args->blkno2 = blk2->blkno;
+                       args->index = blk2->index;
+                       args->blkno = blk2->blkno;
+                       if (!state->extravalid) {
+                               /*
+                                * set the new attr location to match the old
+                                * one and let the higher level split code
+                                * decide where in the leaf to place it.
+                                */
+                               args->index2 = blk2->index;
+                               args->blkno2 = blk2->blkno;
+                       }
                }
        } else {
                ASSERT(state->inleaf == 1);
index 933b7930b8636da970a627d571388b11e8dabde7..4b0b8dd1b7b0ea2bbc431ef523ec5412eb4fd584 100644 (file)
@@ -1197,9 +1197,14 @@ xfs_buf_bio_end_io(
 {
        xfs_buf_t               *bp = (xfs_buf_t *)bio->bi_private;
 
-       xfs_buf_ioerror(bp, -error);
+       /*
+        * don't overwrite existing errors - otherwise we can lose errors on
+        * buffers that require multiple bios to complete.
+        */
+       if (!bp->b_error)
+               xfs_buf_ioerror(bp, -error);
 
-       if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
+       if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ))
                invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp));
 
        _xfs_buf_ioend(bp, 1);
@@ -1279,6 +1284,11 @@ next_chunk:
                if (size)
                        goto next_chunk;
        } else {
+               /*
+                * This is guaranteed not to be the last io reference count
+                * because the caller (xfs_buf_iorequest) holds a count itself.
+                */
+               atomic_dec(&bp->b_io_remaining);
                xfs_buf_ioerror(bp, EIO);
                bio_put(bio);
        }
index af1cbaf535edeb395954583d1d1c1cd0c255c64c..c5c35e629426b506d2e7d00fe876f2e528a48f80 100644 (file)
        {0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x679B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x679E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x679F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
index c127315829208046fbd9327488dfc258cc1d0372..f9f5e9eeb9dd1f37f59cc95cf1da0cdbd91b7001 100644 (file)
@@ -335,8 +335,8 @@ const char *__clk_get_name(struct clk *clk);
 struct clk_hw *__clk_get_hw(struct clk *clk);
 u8 __clk_get_num_parents(struct clk *clk);
 struct clk *__clk_get_parent(struct clk *clk);
-inline int __clk_get_enable_count(struct clk *clk);
-inline int __clk_get_prepare_count(struct clk *clk);
+int __clk_get_enable_count(struct clk *clk);
+int __clk_get_prepare_count(struct clk *clk);
 unsigned long __clk_get_rate(struct clk *clk);
 unsigned long __clk_get_flags(struct clk *clk);
 int __clk_is_enabled(struct clk *clk);
index df804ba73e0b2ae97d935ba2c3797cd36b1499de..92a0dc75bc74661541e5b5c15f4cdd095c922b38 100644 (file)
@@ -34,6 +34,7 @@ struct omap_i2c_bus_platform_data {
        u32             clkrate;
        u32             rev;
        u32             flags;
+       void            (*set_mpu_wkup_lat)(struct device *dev, long set);
 };
 
 #endif
index 7671a287dfee4f592e909c15bcc0c14cac47bb7a..ba26e99c388d0a7f6105ce9181cdc0f94e42736a 100644 (file)
@@ -76,6 +76,7 @@
 #define ARIZONA_RATE_ESTIMATOR_3                 0x154
 #define ARIZONA_RATE_ESTIMATOR_4                 0x155
 #define ARIZONA_RATE_ESTIMATOR_5                 0x156
+#define ARIZONA_DYNAMIC_FREQUENCY_SCALING_1      0x161
 #define ARIZONA_FLL1_CONTROL_1                   0x171
 #define ARIZONA_FLL1_CONTROL_2                   0x172
 #define ARIZONA_FLL1_CONTROL_3                   0x173
 #define ARIZONA_FLL2_GPIO_CLOCK                  0x1AA
 #define ARIZONA_MIC_CHARGE_PUMP_1                0x200
 #define ARIZONA_LDO1_CONTROL_1                   0x210
+#define ARIZONA_LDO1_CONTROL_2                   0x212
 #define ARIZONA_LDO2_CONTROL_1                   0x213
 #define ARIZONA_MIC_BIAS_CTRL_1                  0x218
 #define ARIZONA_MIC_BIAS_CTRL_2                  0x219
 #define ARIZONA_SAMPLE_RATE_DETECT_D_SHIFT            0  /* SAMPLE_RATE_DETECT_D - [4:0] */
 #define ARIZONA_SAMPLE_RATE_DETECT_D_WIDTH            5  /* SAMPLE_RATE_DETECT_D - [4:0] */
 
+/*
+ * R353 (0x161) - Dynamic Frequency Scaling 1
+ */
+#define ARIZONA_SUBSYS_MAX_FREQ                  0x0001  /* SUBSYS_MAX_FREQ */
+#define ARIZONA_SUBSYS_MAX_FREQ_SHIFT                 0  /* SUBSYS_MAX_FREQ */
+#define ARIZONA_SUBSYS_MAX_FREQ_WIDTH                 1  /* SUBSYS_MAX_FREQ */
+
 /*
  * R369 (0x171) - FLL1 Control 1
  */
 #define ARIZONA_LDO1_ENA_SHIFT                        0  /* LDO1_ENA */
 #define ARIZONA_LDO1_ENA_WIDTH                        1  /* LDO1_ENA */
 
+/*
+ * R530 (0x212) - LDO1 Control 2
+ */
+#define ARIZONA_LDO1_HI_PWR                      0x0001  /* LDO1_HI_PWR */
+#define ARIZONA_LDO1_HI_PWR_SHIFT                     0  /* LDO1_HI_PWR */
+#define ARIZONA_LDO1_HI_PWR_WIDTH                     1  /* LDO1_HI_PWR */
+
 /*
  * R531 (0x213) - LDO2 Control 1
  */
index 147293b4471d6811248388c3932e89e65a3b844b..f87a6c172a917f860976e90a62ddd8c790e4266e 100644 (file)
@@ -25,8 +25,29 @@ struct da9055_pdata {
        int gpio_base;
 
        struct regulator_init_data *regulators[DA9055_MAX_REGULATORS];
-       bool reset_enable;              /* Enable RTC in RESET Mode */
-       enum gpio_select *gpio_rsel;    /* Select regulator set thru GPIO 1/2 */
-       enum gpio_select *gpio_ren;     /* Enable regulator thru GPIO 1/2 */
+       /* Enable RTC in RESET Mode */
+       bool reset_enable;
+       /*
+        * GPI muxed pin to control
+        * regulator state A/B, 0 if not available.
+        */
+       int *gpio_ren;
+       /*
+        * GPI muxed pin to control
+        * regulator set, 0 if not available.
+        */
+       int *gpio_rsel;
+       /*
+        * Regulator mode control bits value (GPI offset) that
+        * that controls the regulator state, 0 if not available.
+        */
+       enum gpio_select *reg_ren;
+       /*
+        * Regulator mode control bits value (GPI offset) that
+        * controls the regulator set A/B, 0 if  not available.
+        */
+       enum gpio_select *reg_rsel;
+       /* GPIOs to enable regulator, 0 if not available */
+       int *ena_gpio;
 };
 #endif /* __DA9055_PDATA_H */
index 830152cfae339727ad1d70875a61dbdaa34a6c67..6ae21bf47d644fe8424587b31afd880701720434 100644 (file)
@@ -316,6 +316,7 @@ enum max8997_irq {
 #define MAX8997_NUM_GPIO       12
 struct max8997_dev {
        struct device *dev;
+       struct max8997_platform_data *pdata;
        struct i2c_client *i2c; /* 0xcc / PMIC, Battery Control, and FLASH */
        struct i2c_client *rtc; /* slave addr 0x0c */
        struct i2c_client *haptic; /* slave addr 0x90 */
index 328d8e24b533acaf524746d01dbf1cba76656782..1d4a4fe6ac33e9341f8b90bb0a0f32a015b490b5 100644 (file)
@@ -75,6 +75,7 @@ enum max8998_regulators {
 struct max8997_regulator_data {
        int id;
        struct regulator_init_data *initdata;
+       struct device_node *reg_node;
 };
 
 enum max8997_muic_usb_type {
index 6bc31d854626b26f62994f0810a143ee00027e17..804e280c1e1d9a2a18157b377bfef9f622834cc7 100644 (file)
 
 #include <linux/irq.h>
 
+/* TPS65090 Regulator ID */
+enum {
+       TPS65090_REGULATOR_DCDC1,
+       TPS65090_REGULATOR_DCDC2,
+       TPS65090_REGULATOR_DCDC3,
+       TPS65090_REGULATOR_FET1,
+       TPS65090_REGULATOR_FET2,
+       TPS65090_REGULATOR_FET3,
+       TPS65090_REGULATOR_FET4,
+       TPS65090_REGULATOR_FET5,
+       TPS65090_REGULATOR_FET6,
+       TPS65090_REGULATOR_FET7,
+       TPS65090_REGULATOR_LDO1,
+       TPS65090_REGULATOR_LDO2,
+
+       /* Last entry for maximum ID */
+       TPS65090_REGULATOR_MAX,
+};
+
 struct tps65090 {
        struct mutex            lock;
        struct device           *dev;
@@ -41,10 +60,26 @@ struct tps65090_subdev_info {
        void            *platform_data;
 };
 
+/*
+ * struct tps65090_regulator_plat_data
+ *
+ * @reg_init_data: The regulator init data.
+ * @enable_ext_control: Enable extrenal control or not. Only available for
+ *     DCDC1, DCDC2 and DCDC3.
+ * @gpio: Gpio number if external control is enabled and controlled through
+ *     gpio.
+ */
+struct tps65090_regulator_plat_data {
+       struct regulator_init_data *reg_init_data;
+       bool enable_ext_control;
+       int gpio;
+};
+
 struct tps65090_platform_data {
        int irq_base;
        int num_subdevs;
        struct tps65090_subdev_info *subdevs;
+       struct tps65090_regulator_plat_data *reg_pdata[TPS65090_REGULATOR_MAX];
 };
 
 /*
index fa068040273893c27d71461e459e2eb268739396..bcaab4e6fe913ac6e3f2ef0a6c83ea24d8972867 100644 (file)
@@ -1684,9 +1684,5 @@ static inline unsigned int debug_guardpage_minorder(void) { return 0; }
 static inline bool page_is_guard(struct page *page) { return false; }
 #endif /* CONFIG_DEBUG_PAGEALLOC */
 
-extern void reset_zone_present_pages(void);
-extern void fixup_zone_present_pages(int nid, unsigned long start_pfn,
-                               unsigned long end_pfn);
-
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MM_H */
index 50aaca81f63d6db3914b7858f0209fed036a5971..a23923ba8263b18dac16ec73971d19bed719d015 100644 (file)
@@ -752,7 +752,7 @@ extern int init_currently_empty_zone(struct zone *zone, unsigned long start_pfn,
                                     unsigned long size,
                                     enum memmap_context context);
 
-extern void lruvec_init(struct lruvec *lruvec, struct zone *zone);
+extern void lruvec_init(struct lruvec *lruvec);
 
 static inline struct zone *lruvec_zone(struct lruvec *lruvec)
 {
index e20e3af68fb6acbaf6a51c5aec465bb753a54968..0506eb53519b635286be2b2c54b8a4c7e524a3d7 100644 (file)
@@ -42,10 +42,12 @@ static inline struct device_node *of_find_matching_node_by_address(
 {
        return NULL;
 }
+#ifndef of_iomap
 static inline void __iomem *of_iomap(struct device_node *device, int index)
 {
        return NULL;
 }
+#endif
 static inline const __be32 *of_get_address(struct device_node *dev, int index,
                                        u64 *size, unsigned int *flags)
 {
diff --git a/include/linux/platform_data/omap_ocp2scp.h b/include/linux/platform_data/omap_ocp2scp.h
new file mode 100644 (file)
index 0000000..5c6c393
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * omap_ocp2scp.h -- ocp2scp header file
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.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.
+ *
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * 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 __DRIVERS_OMAP_OCP2SCP_H
+#define __DRIVERS_OMAP_OCP2SCP_H
+
+struct omap_ocp2scp_dev {
+       const char                      *drv_name;
+       struct resource                 *res;
+};
+
+struct omap_ocp2scp_platform_data {
+       int                             dev_cnt;
+       struct omap_ocp2scp_dev         **devices;
+};
+#endif /* __DRIVERS_OMAP_OCP2SCP_H */
index c43cd3556b1f5b789bae79de586f7e85a4cafacc..7bc732ce6e50c5793f3db777d07a2ced422f91ef 100644 (file)
@@ -160,6 +160,7 @@ int regulator_bulk_force_disable(int num_consumers,
 void regulator_bulk_free(int num_consumers,
                         struct regulator_bulk_data *consumers);
 
+int regulator_can_change_voltage(struct regulator *regulator);
 int regulator_count_voltages(struct regulator *regulator);
 int regulator_list_voltage(struct regulator *regulator, unsigned selector);
 int regulator_is_supported_voltage(struct regulator *regulator,
@@ -358,6 +359,10 @@ static inline void regulator_set_drvdata(struct regulator *regulator,
 {
 }
 
+static inline int regulator_count_voltages(struct regulator *regulator)
+{
+       return 0;
+}
 #endif
 
 static inline int regulator_set_voltage_tol(struct regulator *regulator,
@@ -367,4 +372,12 @@ static inline int regulator_set_voltage_tol(struct regulator *regulator,
                                     new_uV - tol_uV, new_uV + tol_uV);
 }
 
+static inline int regulator_is_supported_voltage_tol(struct regulator *regulator,
+                                                    int target_uV, int tol_uV)
+{
+       return regulator_is_supported_voltage(regulator,
+                                             target_uV - tol_uV,
+                                             target_uV + tol_uV);
+}
+
 #endif
index 7932a3bf21bdba89f84275b7b990bcaa3a5773b0..d10bb0f39c5e72fd6bb7747e47761d062f75c981 100644 (file)
@@ -181,10 +181,13 @@ enum regulator_type {
  * @type: Indicates if the regulator is a voltage or current regulator.
  * @owner: Module providing the regulator, used for refcounting.
  *
+ * @continuous_voltage_range: Indicates if the regulator can set any
+ *                            voltage within constrains range.
  * @n_voltages: Number of selectors available for ops.list_voltage().
  *
  * @min_uV: Voltage given by the lowest selector (if linear mapping)
  * @uV_step: Voltage increase with each selector (if linear mapping)
+ * @linear_min_sel: Minimal selector for starting linear mapping
  * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
  * @volt_table: Voltage mapping table (if table based mapping)
  *
@@ -199,6 +202,7 @@ struct regulator_desc {
        const char *name;
        const char *supply_name;
        int id;
+       bool continuous_voltage_range;
        unsigned n_voltages;
        struct regulator_ops *ops;
        int irq;
@@ -207,6 +211,7 @@ struct regulator_desc {
 
        unsigned int min_uV;
        unsigned int uV_step;
+       unsigned int linear_min_sel;
        unsigned int ramp_delay;
 
        const unsigned int *volt_table;
diff --git a/include/linux/regulator/max8973-regulator.h b/include/linux/regulator/max8973-regulator.h
new file mode 100644 (file)
index 0000000..f8acc05
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * max8973-regulator.h -- MAXIM 8973 regulator
+ *
+ * Interface for regulator driver for MAXIM 8973 DC-DC step-down
+ * switching regulator.
+ *
+ * Copyright (C) 2012 NVIDIA Corporation
+
+ * Author: Laxman Dewangan <ldewangan@nvidia.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.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __LINUX_REGULATOR_MAX8973_H
+#define __LINUX_REGULATOR_MAX8973_H
+
+/*
+ * Control flags for configuration of the device.
+ * Client need to pass this information with ORed
+ */
+#define MAX8973_CONTROL_REMOTE_SENSE_ENABLE                    0x00000001
+#define MAX8973_CONTROL_FALLING_SLEW_RATE_ENABLE               0x00000002
+#define MAX8973_CONTROL_OUTPUT_ACTIVE_DISCH_ENABLE             0x00000004
+#define MAX8973_CONTROL_BIAS_ENABLE                            0x00000008
+#define MAX8973_CONTROL_PULL_DOWN_ENABLE                       0x00000010
+#define MAX8973_CONTROL_FREQ_SHIFT_9PER_ENABLE                 0x00000020
+
+#define MAX8973_CONTROL_CLKADV_TRIP_DISABLED                   0x00000000
+#define MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US                        0x00010000
+#define MAX8973_CONTROL_CLKADV_TRIP_150mV_PER_US               0x00020000
+#define MAX8973_CONTROL_CLKADV_TRIP_75mV_PER_US_HIST_DIS       0x00030000
+
+#define MAX8973_CONTROL_INDUCTOR_VALUE_NOMINAL                 0x00000000
+#define MAX8973_CONTROL_INDUCTOR_VALUE_MINUS_30_PER            0x00100000
+#define MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_30_PER             0x00200000
+#define MAX8973_CONTROL_INDUCTOR_VALUE_PLUS_60_PER             0x00300000
+
+/*
+ * struct max8973_regulator_platform_data - max8973 regulator platform data.
+ *
+ * @reg_init_data: The regulator init data.
+ * @control_flags: Control flags which are ORed value of above flags to
+ *             configure device.
+ * @enable_ext_control: Enable the voltage enable/disable through external
+ *             control signal from EN input pin. If it is false then
+ *             voltage output will be enabled/disabled through EN bit of
+ *             device register.
+ * @dvs_gpio: GPIO for dvs. It should be -1 if this is tied with fixed logic.
+ * @dvs_def_state: Default state of dvs. 1 if it is high else 0.
+ */
+struct max8973_regulator_platform_data {
+       struct regulator_init_data *reg_init_data;
+       unsigned long control_flags;
+       bool enable_ext_control;
+       int dvs_gpio;
+       unsigned dvs_def_state:1;
+};
+
+#endif /* __LINUX_REGULATOR_MAX8973_H */
diff --git a/include/linux/regulator/tps51632-regulator.h b/include/linux/regulator/tps51632-regulator.h
new file mode 100644 (file)
index 0000000..d00841e
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * tps51632-regulator.h -- TPS51632 regulator
+ *
+ * Interface for regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down
+ * Driverless Controller with serial VID control and DVFS.
+ *
+ * Copyright (C) 2012 NVIDIA Corporation
+
+ * Author: Laxman Dewangan <ldewangan@nvidia.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.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __LINUX_REGULATOR_TPS51632_H
+#define __LINUX_REGULATOR_TPS51632_H
+
+/*
+ * struct tps51632_regulator_platform_data - tps51632 regulator platform data.
+ *
+ * @reg_init_data: The regulator init data.
+ * @enable_pwm_dvfs: Enable PWM DVFS or not.
+ * @dvfs_step_20mV: Step for DVFS is 20mV or 10mV.
+ * @max_voltage_uV: Maximum possible voltage in PWM-DVFS mode.
+ * @base_voltage_uV: Base voltage when PWM-DVFS enabled.
+ */
+struct tps51632_regulator_platform_data {
+       struct regulator_init_data *reg_init_data;
+       bool enable_pwm_dvfs;
+       bool dvfs_step_20mV;
+       int max_voltage_uV;
+       int base_voltage_uV;
+};
+
+#endif /* __LINUX_REGULATOR_TPS51632_H */
diff --git a/include/linux/regulator/tps65090-regulator.h b/include/linux/regulator/tps65090-regulator.h
deleted file mode 100644 (file)
index 0fa04b6..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Regulator driver interface for TI TPS65090 PMIC family
- *
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
-
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
-
- * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __REGULATOR_TPS65090_H
-#define __REGULATOR_TPS65090_H
-
-#include <linux/regulator/machine.h>
-
-#define tps65090_rails(_name) "tps65090_"#_name
-
-enum {
-       TPS65090_ID_DCDC1,
-       TPS65090_ID_DCDC2,
-       TPS65090_ID_DCDC3,
-       TPS65090_ID_FET1,
-       TPS65090_ID_FET2,
-       TPS65090_ID_FET3,
-       TPS65090_ID_FET4,
-       TPS65090_ID_FET5,
-       TPS65090_ID_FET6,
-       TPS65090_ID_FET7,
-};
-
-/*
- * struct tps65090_regulator_platform_data
- *
- * @regulator: The regulator init data.
- * @slew_rate_uV_per_us: Slew rate microvolt per microsec.
- */
-
-struct tps65090_regulator_platform_data {
-       struct regulator_init_data regulator;
-};
-
-#endif /* __REGULATOR_TPS65090_H */
index 4187da51100631f157d508a1c121609a89204872..a3e7842786679567185ecdbc8835fd5936fb36f4 100644 (file)
@@ -275,9 +275,11 @@ struct rio_id_table {
  * struct rio_net - RIO network info
  * @node: Node in global list of RIO networks
  * @devices: List of devices in this network
+ * @switches: List of switches in this netowrk
  * @mports: List of master ports accessing this network
  * @hport: Default port for accessing this network
  * @id: RIO network ID
+ * @destid_table: destID allocation table
  */
 struct rio_net {
        struct list_head node;  /* node in list of networks */
index c64de9dd7631bb44232eeca7d8080c62521c5b1e..2f694f3846a9ad1a5d052e96d5f68cd9a152c313 100644 (file)
@@ -46,8 +46,9 @@ struct ads7846_platform_data {
        u16     debounce_rep;           /* additional consecutive good readings
                                         * required after the first two */
        int     gpio_pendown;           /* the GPIO used to decide the pendown
-                                        * state if get_pendown_state == NULL
-                                        */
+                                        * state if get_pendown_state == NULL */
+       int     gpio_pendown_debounce;  /* platform specific debounce time for
+                                        * the gpio_pendown */
        int     (*get_pendown_state)(void);
        int     (*filter_init)  (const struct ads7846_platform_data *pdata,
                                 void **filter_data);
index 6f0ba01afe7315d443a0aad152a9df2d5a22abf6..63445ede48bb7fd04b175c111935fb77464568b6 100644 (file)
@@ -1351,7 +1351,7 @@ struct xfrm6_tunnel {
 };
 
 extern void xfrm_init(void);
-extern void xfrm4_init(int rt_hash_size);
+extern void xfrm4_init(void);
 extern int xfrm_state_init(struct net *net);
 extern void xfrm_state_fini(struct net *net);
 extern void xfrm4_state_init(void);
index 88fae8d2015471885972da8407d0077106b527cc..55367b04dc9445e142369e98d2134d459eb5ef83 100644 (file)
@@ -135,6 +135,8 @@ struct scsi_device {
                                     * because we did a bus reset. */
        unsigned use_10_for_rw:1; /* first try 10-byte read / write */
        unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
+       unsigned no_report_opcodes:1;   /* no REPORT SUPPORTED OPERATION CODES */
+       unsigned no_write_same:1;       /* no WRITE SAME command */
        unsigned skip_ms_page_8:1;      /* do not use MODE SENSE page 0x08 */
        unsigned skip_ms_page_3f:1;     /* do not use MODE SENSE page 0x3f */
        unsigned skip_vpd_pages:1;      /* do not read VPD pages */
@@ -362,6 +364,8 @@ extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout,
                                int retries, struct scsi_sense_hdr *sshdr);
 extern int scsi_get_vpd_page(struct scsi_device *, u8 page, unsigned char *buf,
                             int buf_len);
+extern int scsi_report_opcode(struct scsi_device *sdev, unsigned char *buffer,
+                             unsigned int len, unsigned char opcode);
 extern int scsi_device_set_state(struct scsi_device *sdev,
                                 enum scsi_device_state state);
 extern struct scsi_event *sdev_evt_alloc(enum scsi_device_event evt_type,
index a49c4afc70600d22ff904586cd41098a9e360e2d..b29272d621ce21162dc148217e4b6e89f72304b1 100644 (file)
@@ -8,4 +8,13 @@
 #define OOM_SCORE_ADJ_MIN      (-1000)
 #define OOM_SCORE_ADJ_MAX      1000
 
+/*
+ * /proc/<pid>/oom_adj set to -17 protects from the oom killer for legacy
+ * purposes.
+ */
+#define OOM_DISABLE (-17)
+/* inclusive */
+#define OOM_ADJUST_MIN (-16)
+#define OOM_ADJUST_MAX 15
+
 #endif /* _UAPI__INCLUDE_LINUX_OOM_H */
index 3717e7b306e08c0e8c2d3a66219c3cae13176d99..20ef219bbe9b76b3d54e6b501366f15cd97c464a 100644 (file)
@@ -716,7 +716,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb,
                                struct futex_pi_state **ps,
                                struct task_struct *task, int set_waiters)
 {
-       int lock_taken, ret, ownerdied = 0;
+       int lock_taken, ret, force_take = 0;
        u32 uval, newval, curval, vpid = task_pid_vnr(task);
 
 retry:
@@ -755,17 +755,15 @@ retry:
        newval = curval | FUTEX_WAITERS;
 
        /*
-        * There are two cases, where a futex might have no owner (the
-        * owner TID is 0): OWNER_DIED. We take over the futex in this
-        * case. We also do an unconditional take over, when the owner
-        * of the futex died.
-        *
-        * This is safe as we are protected by the hash bucket lock !
+        * Should we force take the futex? See below.
         */
-       if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) {
-               /* Keep the OWNER_DIED bit */
+       if (unlikely(force_take)) {
+               /*
+                * Keep the OWNER_DIED and the WAITERS bit and set the
+                * new TID value.
+                */
                newval = (curval & ~FUTEX_TID_MASK) | vpid;
-               ownerdied = 0;
+               force_take = 0;
                lock_taken = 1;
        }
 
@@ -775,7 +773,7 @@ retry:
                goto retry;
 
        /*
-        * We took the lock due to owner died take over.
+        * We took the lock due to forced take over.
         */
        if (unlikely(lock_taken))
                return 1;
@@ -790,20 +788,25 @@ retry:
                switch (ret) {
                case -ESRCH:
                        /*
-                        * No owner found for this futex. Check if the
-                        * OWNER_DIED bit is set to figure out whether
-                        * this is a robust futex or not.
+                        * We failed to find an owner for this
+                        * futex. So we have no pi_state to block
+                        * on. This can happen in two cases:
+                        *
+                        * 1) The owner died
+                        * 2) A stale FUTEX_WAITERS bit
+                        *
+                        * Re-read the futex value.
                         */
                        if (get_futex_value_locked(&curval, uaddr))
                                return -EFAULT;
 
                        /*
-                        * We simply start over in case of a robust
-                        * futex. The code above will take the futex
-                        * and return happy.
+                        * If the owner died or we have a stale
+                        * WAITERS bit the owner TID in the user space
+                        * futex is 0.
                         */
-                       if (curval & FUTEX_OWNER_DIED) {
-                               ownerdied = 1;
+                       if (!(curval & FUTEX_TID_MASK)) {
+                               force_take = 1;
                                goto retry;
                        }
                default:
index 678ce4f1e124b4be4c255f297cef1e29477e7ce0..095ab157a5215a800d01585bbb50b0d6b6a88a17 100644 (file)
@@ -641,7 +641,14 @@ do { \
        **************  MIPS  *****************
        ***************************************/
 #if defined(__mips__) && W_TYPE_SIZE == 32
-#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4
+#define umul_ppmm(w1, w0, u, v)                        \
+do {                                           \
+       UDItype __ll = (UDItype)(u) * (v);      \
+       w1 = __ll >> 32;                        \
+       w0 = __ll;                              \
+} while (0)
+#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
 #define umul_ppmm(w1, w0, u, v) \
        __asm__ ("multu %2,%3" \
        : "=l" ((USItype)(w0)), \
@@ -666,7 +673,15 @@ do { \
        **************  MIPS/64  **************
        ***************************************/
 #if (defined(__mips) && __mips >= 3) && W_TYPE_SIZE == 64
-#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7
+#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4
+#define umul_ppmm(w1, w0, u, v) \
+do {                                                                   \
+       typedef unsigned int __ll_UTItype __attribute__((mode(TI)));    \
+       __ll_UTItype __ll = (__ll_UTItype)(u) * (v);                    \
+       w1 = __ll >> 64;                                                \
+       w0 = __ll;                                                      \
+} while (0)
+#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7
 #define umul_ppmm(w1, w0, u, v) \
        __asm__ ("dmultu %2,%3" \
        : "=l" ((UDItype)(w0)), \
index 434be4ae7a0495817267e5e100c68f47c2006415..f468185b3b28a517aaceb79b80e7f799df0dfc6f 100644 (file)
@@ -198,8 +198,6 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
                        int order = ilog2(BITS_PER_LONG);
 
                        __free_pages_bootmem(pfn_to_page(start), order);
-                       fixup_zone_present_pages(page_to_nid(pfn_to_page(start)),
-                                       start, start + BITS_PER_LONG);
                        count += BITS_PER_LONG;
                        start += BITS_PER_LONG;
                } else {
@@ -210,9 +208,6 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
                                if (vec & 1) {
                                        page = pfn_to_page(start + off);
                                        __free_pages_bootmem(page, 0);
-                                       fixup_zone_present_pages(
-                                               page_to_nid(page),
-                                               start + off, start + off + 1);
                                        count++;
                                }
                                vec >>= 1;
@@ -226,11 +221,8 @@ static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata)
        pages = bdata->node_low_pfn - bdata->node_min_pfn;
        pages = bootmem_bootmap_pages(pages);
        count += pages;
-       while (pages--) {
-               fixup_zone_present_pages(page_to_nid(page),
-                               page_to_pfn(page), page_to_pfn(page) + 1);
+       while (pages--)
                __free_pages_bootmem(page++, 0);
-       }
 
        bdebug("nid=%td released=%lx\n", bdata - bootmem_node_data, count);
 
index d517cd16a6eb91e8df18f3cbd79cd67621b27d3f..2da13a5c50e2b48e8fe8dea34d4bd4835c127da9 100644 (file)
@@ -98,7 +98,7 @@ struct page *kmap_to_page(void *vaddr)
 {
        unsigned long addr = (unsigned long)vaddr;
 
-       if (addr >= PKMAP_ADDR(0) && addr <= PKMAP_ADDR(LAST_PKMAP)) {
+       if (addr >= PKMAP_ADDR(0) && addr < PKMAP_ADDR(LAST_PKMAP)) {
                int i = (addr - PKMAP_ADDR(0)) >> PAGE_SHIFT;
                return pte_page(pkmap_page_table[i]);
        }
index 7acf43bf04a270cf2bf90f342c66142d1c5cf675..dd39ba000b31f98730c6fd6d22bdf695ced3bedf 100644 (file)
@@ -1055,12 +1055,24 @@ struct lruvec *mem_cgroup_zone_lruvec(struct zone *zone,
                                      struct mem_cgroup *memcg)
 {
        struct mem_cgroup_per_zone *mz;
+       struct lruvec *lruvec;
 
-       if (mem_cgroup_disabled())
-               return &zone->lruvec;
+       if (mem_cgroup_disabled()) {
+               lruvec = &zone->lruvec;
+               goto out;
+       }
 
        mz = mem_cgroup_zoneinfo(memcg, zone_to_nid(zone), zone_idx(zone));
-       return &mz->lruvec;
+       lruvec = &mz->lruvec;
+out:
+       /*
+        * Since a node can be onlined after the mem_cgroup was created,
+        * we have to be prepared to initialize lruvec->zone here;
+        * and if offlined then reonlined, we need to reinitialize it.
+        */
+       if (unlikely(lruvec->zone != zone))
+               lruvec->zone = zone;
+       return lruvec;
 }
 
 /*
@@ -1087,9 +1099,12 @@ struct lruvec *mem_cgroup_page_lruvec(struct page *page, struct zone *zone)
        struct mem_cgroup_per_zone *mz;
        struct mem_cgroup *memcg;
        struct page_cgroup *pc;
+       struct lruvec *lruvec;
 
-       if (mem_cgroup_disabled())
-               return &zone->lruvec;
+       if (mem_cgroup_disabled()) {
+               lruvec = &zone->lruvec;
+               goto out;
+       }
 
        pc = lookup_page_cgroup(page);
        memcg = pc->mem_cgroup;
@@ -1107,7 +1122,16 @@ struct lruvec *mem_cgroup_page_lruvec(struct page *page, struct zone *zone)
                pc->mem_cgroup = memcg = root_mem_cgroup;
 
        mz = page_cgroup_zoneinfo(memcg, page);
-       return &mz->lruvec;
+       lruvec = &mz->lruvec;
+out:
+       /*
+        * Since a node can be onlined after the mem_cgroup was created,
+        * we have to be prepared to initialize lruvec->zone here;
+        * and if offlined then reonlined, we need to reinitialize it.
+        */
+       if (unlikely(lruvec->zone != zone))
+               lruvec->zone = zone;
+       return lruvec;
 }
 
 /**
@@ -1452,17 +1476,26 @@ static int mem_cgroup_count_children(struct mem_cgroup *memcg)
 static u64 mem_cgroup_get_limit(struct mem_cgroup *memcg)
 {
        u64 limit;
-       u64 memsw;
 
        limit = res_counter_read_u64(&memcg->res, RES_LIMIT);
-       limit += total_swap_pages << PAGE_SHIFT;
 
-       memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT);
        /*
-        * If memsw is finite and limits the amount of swap space available
-        * to this memcg, return that limit.
+        * Do not consider swap space if we cannot swap due to swappiness
         */
-       return min(limit, memsw);
+       if (mem_cgroup_swappiness(memcg)) {
+               u64 memsw;
+
+               limit += total_swap_pages << PAGE_SHIFT;
+               memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT);
+
+               /*
+                * If memsw is finite and limits the amount of swap space
+                * available to this memcg, return that limit.
+                */
+               limit = min(limit, memsw);
+       }
+
+       return limit;
 }
 
 void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask,
@@ -3688,17 +3721,17 @@ unsigned long mem_cgroup_soft_limit_reclaim(struct zone *zone, int order,
 static bool mem_cgroup_force_empty_list(struct mem_cgroup *memcg,
                                int node, int zid, enum lru_list lru)
 {
-       struct mem_cgroup_per_zone *mz;
+       struct lruvec *lruvec;
        unsigned long flags, loop;
        struct list_head *list;
        struct page *busy;
        struct zone *zone;
 
        zone = &NODE_DATA(node)->node_zones[zid];
-       mz = mem_cgroup_zoneinfo(memcg, node, zid);
-       list = &mz->lruvec.lists[lru];
+       lruvec = mem_cgroup_zone_lruvec(zone, memcg);
+       list = &lruvec->lists[lru];
 
-       loop = mz->lru_size[lru];
+       loop = mem_cgroup_get_lru_size(lruvec, lru);
        /* give some margin against EBUSY etc...*/
        loop += 256;
        busy = NULL;
@@ -4736,7 +4769,7 @@ static int alloc_mem_cgroup_per_zone_info(struct mem_cgroup *memcg, int node)
 
        for (zone = 0; zone < MAX_NR_ZONES; zone++) {
                mz = &pn->zoneinfo[zone];
-               lruvec_init(&mz->lruvec, &NODE_DATA(node)->node_zones[zone]);
+               lruvec_init(&mz->lruvec);
                mz->usage_in_excess = 0;
                mz->on_tree = false;
                mz->memcg = memcg;
index fb135ba4aba90349e58c79d49838860cb7db8105..221fc9ffcab1da33eb15947776975730b5058b67 100644 (file)
@@ -2527,9 +2527,8 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
        int ret = 0;
        int page_mkwrite = 0;
        struct page *dirty_page = NULL;
-       unsigned long mmun_start;       /* For mmu_notifiers */
-       unsigned long mmun_end;         /* For mmu_notifiers */
-       bool mmun_called = false;       /* For mmu_notifiers */
+       unsigned long mmun_start = 0;   /* For mmu_notifiers */
+       unsigned long mmun_end = 0;     /* For mmu_notifiers */
 
        old_page = vm_normal_page(vma, address, orig_pte);
        if (!old_page) {
@@ -2708,8 +2707,7 @@ gotten:
                goto oom_free_new;
 
        mmun_start  = address & PAGE_MASK;
-       mmun_end    = (address & PAGE_MASK) + PAGE_SIZE;
-       mmun_called = true;
+       mmun_end    = mmun_start + PAGE_SIZE;
        mmu_notifier_invalidate_range_start(mm, mmun_start, mmun_end);
 
        /*
@@ -2778,7 +2776,7 @@ gotten:
                page_cache_release(new_page);
 unlock:
        pte_unmap_unlock(page_table, ptl);
-       if (mmun_called)
+       if (mmun_end > mmun_start)
                mmu_notifier_invalidate_range_end(mm, mmun_start, mmun_end);
        if (old_page) {
                /*
index 56b758ae57d2eeb2230bbcaf3f8e8d4538a15a9d..e4eeacae2b91199142776390bdaef73241416b47 100644 (file)
@@ -106,7 +106,6 @@ static void get_page_bootmem(unsigned long info,  struct page *page,
 void __ref put_page_bootmem(struct page *page)
 {
        unsigned long type;
-       struct zone *zone;
 
        type = (unsigned long) page->lru.next;
        BUG_ON(type < MEMORY_HOTPLUG_MIN_BOOTMEM_TYPE ||
@@ -117,12 +116,6 @@ void __ref put_page_bootmem(struct page *page)
                set_page_private(page, 0);
                INIT_LIST_HEAD(&page->lru);
                __free_pages_bootmem(page, 0);
-
-               zone = page_zone(page);
-               zone_span_writelock(zone);
-               zone->present_pages++;
-               zone_span_writeunlock(zone);
-               totalram_pages++;
        }
 
 }
index 2d942353d681a8b4f08155eebdcfb20b088093e7..9a796c41e7d9ecf8d474089df2d1b2235451ce3c 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -334,8 +334,10 @@ void validate_mm(struct mm_struct *mm)
        struct vm_area_struct *vma = mm->mmap;
        while (vma) {
                struct anon_vma_chain *avc;
+               vma_lock_anon_vma(vma);
                list_for_each_entry(avc, &vma->anon_vma_chain, same_vma)
                        anon_vma_interval_tree_verify(avc);
+               vma_unlock_anon_vma(vma);
                vma = vma->vm_next;
                i++;
        }
index 3cef80f6ac79ff2e8b5fef7bcd373679e91df2c1..4596d81b89b16280b4768e83df3290d674aaf005 100644 (file)
@@ -87,7 +87,7 @@ int memmap_valid_within(unsigned long pfn,
 }
 #endif /* CONFIG_ARCH_HAS_HOLES_MEMORYMODEL */
 
-void lruvec_init(struct lruvec *lruvec, struct zone *zone)
+void lruvec_init(struct lruvec *lruvec)
 {
        enum lru_list lru;
 
@@ -95,8 +95,4 @@ void lruvec_init(struct lruvec *lruvec, struct zone *zone)
 
        for_each_lru(lru)
                INIT_LIST_HEAD(&lruvec->lists[lru]);
-
-#ifdef CONFIG_MEMCG
-       lruvec->zone = zone;
-#endif
 }
index 714d5d6504708c83c64365618749a84b1da4cd66..bd82f6b314114dc937bea707a70072b299860a08 100644 (file)
@@ -116,8 +116,6 @@ static unsigned long __init __free_memory_core(phys_addr_t start,
                return 0;
 
        __free_pages_memory(start_pfn, end_pfn);
-       fixup_zone_present_pages(pfn_to_nid(start >> PAGE_SHIFT),
-                       start_pfn, end_pfn);
 
        return end_pfn - start_pfn;
 }
@@ -128,7 +126,6 @@ unsigned long __init free_low_memory_core_early(int nodeid)
        phys_addr_t start, end, size;
        u64 i;
 
-       reset_zone_present_pages();
        for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL)
                count += __free_memory_core(start, end);
 
index 5b74de6702e06587e0d4f36060f810526ff8fbe3..bcb72c6e2b2d8b5ec498c5250d11a58f71e2f06a 100644 (file)
@@ -1405,7 +1405,7 @@ int capture_free_page(struct page *page, int alloc_order, int migratetype)
 
        mt = get_pageblock_migratetype(page);
        if (unlikely(mt != MIGRATE_ISOLATE))
-               __mod_zone_freepage_state(zone, -(1UL << order), mt);
+               __mod_zone_freepage_state(zone, -(1UL << alloc_order), mt);
 
        if (alloc_order != order)
                expand(zone, page, alloc_order, order,
@@ -4505,7 +4505,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat,
                zone->zone_pgdat = pgdat;
 
                zone_pcp_init(zone);
-               lruvec_init(&zone->lruvec, zone);
+               lruvec_init(&zone->lruvec);
                if (!size)
                        continue;
 
@@ -6098,37 +6098,3 @@ void dump_page(struct page *page)
        dump_page_flags(page->flags);
        mem_cgroup_print_bad_page(page);
 }
-
-/* reset zone->present_pages */
-void reset_zone_present_pages(void)
-{
-       struct zone *z;
-       int i, nid;
-
-       for_each_node_state(nid, N_HIGH_MEMORY) {
-               for (i = 0; i < MAX_NR_ZONES; i++) {
-                       z = NODE_DATA(nid)->node_zones + i;
-                       z->present_pages = 0;
-               }
-       }
-}
-
-/* calculate zone's present pages in buddy system */
-void fixup_zone_present_pages(int nid, unsigned long start_pfn,
-                               unsigned long end_pfn)
-{
-       struct zone *z;
-       unsigned long zone_start_pfn, zone_end_pfn;
-       int i;
-
-       for (i = 0; i < MAX_NR_ZONES; i++) {
-               z = NODE_DATA(nid)->node_zones + i;
-               zone_start_pfn = z->zone_start_pfn;
-               zone_end_pfn = zone_start_pfn + z->spanned_pages;
-
-               /* if the two regions intersect */
-               if (!(zone_start_pfn >= end_pfn || zone_end_pfn <= start_pfn))
-                       z->present_pages += min(end_pfn, zone_end_pfn) -
-                                           max(start_pfn, zone_start_pfn);
-       }
-}
index 67afba5117f2ebe80ef54e487d068fdf99e986bb..89341b658bd06b05d908f8becfef7fe0d904b808 100644 (file)
@@ -643,7 +643,7 @@ static void shmem_evict_inode(struct inode *inode)
                kfree(info->symlink);
 
        simple_xattrs_free(&info->xattrs);
-       BUG_ON(inode->i_blocks);
+       WARN_ON(inode->i_blocks);
        shmem_free_inode(inode->i_sb);
        clear_inode(inode);
 }
@@ -1145,8 +1145,20 @@ repeat:
                if (!error) {
                        error = shmem_add_to_page_cache(page, mapping, index,
                                                gfp, swp_to_radix_entry(swap));
-                       /* We already confirmed swap, and make no allocation */
-                       VM_BUG_ON(error);
+                       /*
+                        * We already confirmed swap under page lock, and make
+                        * no memory allocation here, so usually no possibility
+                        * of error; but free_swap_and_cache() only trylocks a
+                        * page, so it is just possible that the entry has been
+                        * truncated or holepunched since swap was confirmed.
+                        * shmem_undo_range() will have done some of the
+                        * unaccounting, now delete_from_swap_cache() will do
+                        * the rest (including mem_cgroup_uncharge_swapcache).
+                        * Reset swap.val? No, leave it so "failed" goes back to
+                        * "repeat": reading a hole and writing should succeed.
+                        */
+                       if (error)
+                               delete_from_swap_cache(page);
                }
                if (error)
                        goto failed;
index 71cd288b200179d4962222337f3947342fcebe57..f91a25547ffe1f2febdfb0a526ee296996da171b 100644 (file)
@@ -1494,9 +1494,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        BUG_ON(!current->mm);
 
        pathname = getname(specialfile);
-       err = PTR_ERR(pathname);
        if (IS_ERR(pathname))
-               goto out;
+               return PTR_ERR(pathname);
 
        victim = file_open_name(pathname, O_RDWR|O_LARGEFILE, 0);
        err = PTR_ERR(victim);
@@ -1608,6 +1607,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
 out_dput:
        filp_close(victim, NULL);
 out:
+       putname(pathname);
        return err;
 }
 
index 8b055e9379bc23105dea4e58d6bebe2600756a4b..48550c66f1f21d4fdff9afd38f6c1fa97f56ef49 100644 (file)
@@ -1760,28 +1760,6 @@ static bool in_reclaim_compaction(struct scan_control *sc)
        return false;
 }
 
-#ifdef CONFIG_COMPACTION
-/*
- * If compaction is deferred for sc->order then scale the number of pages
- * reclaimed based on the number of consecutive allocation failures
- */
-static unsigned long scale_for_compaction(unsigned long pages_for_compaction,
-                       struct lruvec *lruvec, struct scan_control *sc)
-{
-       struct zone *zone = lruvec_zone(lruvec);
-
-       if (zone->compact_order_failed <= sc->order)
-               pages_for_compaction <<= zone->compact_defer_shift;
-       return pages_for_compaction;
-}
-#else
-static unsigned long scale_for_compaction(unsigned long pages_for_compaction,
-                       struct lruvec *lruvec, struct scan_control *sc)
-{
-       return pages_for_compaction;
-}
-#endif
-
 /*
  * Reclaim/compaction is used for high-order allocation requests. It reclaims
  * order-0 pages before compacting the zone. should_continue_reclaim() returns
@@ -1829,9 +1807,6 @@ static inline bool should_continue_reclaim(struct lruvec *lruvec,
         * inactive lists are large enough, continue reclaiming
         */
        pages_for_compaction = (2UL << sc->order);
-
-       pages_for_compaction = scale_for_compaction(pages_for_compaction,
-                                                   lruvec, sc);
        inactive_lru_pages = get_lru_size(lruvec, LRU_INACTIVE_FILE);
        if (nr_swap_pages > 0)
                inactive_lru_pages += get_lru_size(lruvec, LRU_INACTIVE_ANON);
index b9a28d2dd3e8d907526ebd51dfedba9e993fd526..ce0684a1fc836f6713ce7cf1e1164e39b4cf0fd2 100644 (file)
@@ -325,6 +325,12 @@ void batadv_interface_rx(struct net_device *soft_iface,
 
        soft_iface->last_rx = jiffies;
 
+       /* Let the bridge loop avoidance check the packet. If will
+        * not handle it, we can safely push it up.
+        */
+       if (batadv_bla_rx(bat_priv, skb, vid, is_bcast))
+               goto out;
+
        if (orig_node)
                batadv_tt_add_temporary_global_entry(bat_priv, orig_node,
                                                     ethhdr->h_source);
@@ -332,12 +338,6 @@ void batadv_interface_rx(struct net_device *soft_iface,
        if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest))
                goto dropped;
 
-       /* Let the bridge loop avoidance check the packet. If will
-        * not handle it, we can safely push it up.
-        */
-       if (batadv_bla_rx(bat_priv, skb, vid, is_bcast))
-               goto out;
-
        netif_rx(skb);
        goto out;
 
index 112edd371b2f81c79f431c6e99402165405c1b10..baae71585804313ff406aad0ab7f04b0b7daa189 100644 (file)
@@ -769,6 +769,12 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv,
                 */
                tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP;
 
+               /* the change can carry possible "attribute" flags like the
+                * TT_CLIENT_WIFI, therefore they have to be copied in the
+                * client entry
+                */
+               tt_global_entry->common.flags |= flags;
+
                /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
                 * one originator left in the list and we previously received a
                 * delete + roaming change for this originator.
@@ -1496,7 +1502,7 @@ batadv_tt_response_fill_table(uint16_t tt_len, uint8_t ttvn,
 
                        memcpy(tt_change->addr, tt_common_entry->addr,
                               ETH_ALEN);
-                       tt_change->flags = BATADV_NO_FLAGS;
+                       tt_change->flags = tt_common_entry->flags;
 
                        tt_count++;
                        tt_change++;
@@ -2450,6 +2456,13 @@ bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv,
 {
        bool ret = false;
 
+       /* if the originator is a backbone node (meaning it belongs to the same
+        * LAN of this node) the temporary client must not be added because to
+        * reach such destination the node must use the LAN instead of the mesh
+        */
+       if (batadv_bla_is_backbone_gw_orig(bat_priv, orig_node->orig))
+               goto out;
+
        if (!batadv_tt_global_add(bat_priv, orig_node, addr,
                                  BATADV_TT_CLIENT_TEMP,
                                  atomic_read(&orig_node->last_ttvn)))
index 8a0ce706aebd624ae7fd1c50b9670780dc4f6761..a0a2f97b9c6207a600a256415ada30d12fa88f9d 100644 (file)
@@ -1754,11 +1754,11 @@ int hci_register_dev(struct hci_dev *hdev)
        if (hdev->dev_type != HCI_AMP)
                set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
 
-       schedule_work(&hdev->power_on);
-
        hci_notify(hdev, HCI_DEV_REG);
        hci_dev_hold(hdev);
 
+       schedule_work(&hdev->power_on);
+
        return id;
 
 err_wqueue:
index aa2ea0a8142cc0d6c7378ced06be1257b2f846d7..91de4239da6621d6e5b7a2989beb5bd5b883ff8c 100644 (file)
@@ -326,7 +326,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
        struct hci_dev *d;
        size_t rp_len;
        u16 count;
-       int i, err;
+       int err;
 
        BT_DBG("sock %p", sk);
 
@@ -347,9 +347,7 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
                return -ENOMEM;
        }
 
-       rp->num_controllers = cpu_to_le16(count);
-
-       i = 0;
+       count = 0;
        list_for_each_entry(d, &hci_dev_list, list) {
                if (test_bit(HCI_SETUP, &d->dev_flags))
                        continue;
@@ -357,10 +355,13 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
                if (!mgmt_valid_hdev(d))
                        continue;
 
-               rp->index[i++] = cpu_to_le16(d->id);
+               rp->index[count++] = cpu_to_le16(d->id);
                BT_DBG("Added hci%u", d->id);
        }
 
+       rp->num_controllers = cpu_to_le16(count);
+       rp_len = sizeof(*rp) + (2 * count);
+
        read_unlock(&hci_dev_list_lock);
 
        err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
@@ -1366,6 +1367,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
                        continue;
 
                list_del(&match->list);
+               kfree(match);
                found++;
        }
 
index 2ac8d50861e08165bca0747d840e99672bb105de..a5923378bdf03ab73a259cd3c74f88b890972030 100644 (file)
@@ -267,7 +267,7 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
 
        clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags);
        mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type,
-                        hcon->dst_type, reason);
+                        hcon->dst_type, HCI_ERROR_AUTH_FAILURE);
 
        cancel_delayed_work_sync(&conn->security_timer);
 
index bda6d004f9f0940df66a00170e8a0d6b52dd540a..c0946cb2b3547f4fdea0fa56b8f7e17c71a75012 100644 (file)
@@ -2818,8 +2818,10 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb,
                if (unlikely(tcpu != next_cpu) &&
                    (tcpu == RPS_NO_CPU || !cpu_online(tcpu) ||
                     ((int)(per_cpu(softnet_data, tcpu).input_queue_head -
-                     rflow->last_qtail)) >= 0))
+                     rflow->last_qtail)) >= 0)) {
+                       tcpu = next_cpu;
                        rflow = set_rps_cpu(dev, skb, rflow, next_cpu);
+               }
 
                if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) {
                        *rflowp = rflow;
index 87cc17db2d566e5846601d6eb03ba38ce64b2ddb..b079c7bbc157a3c047db12e7a39595da380071e8 100644 (file)
@@ -319,7 +319,8 @@ int dev_addr_del(struct net_device *dev, const unsigned char *addr,
         */
        ha = list_first_entry(&dev->dev_addrs.list,
                              struct netdev_hw_addr, list);
-       if (ha->addr == dev->dev_addr && ha->refcount == 1)
+       if (!memcmp(ha->addr, addr, dev->addr_len) &&
+           ha->type == addr_type && ha->refcount == 1)
                return -ENOENT;
 
        err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len,
index bcf02f608cbfa76ad06da490f2dbf423e728fc17..017a8bacfb2773483c97c8fa3b162e03f09f454a 100644 (file)
@@ -429,6 +429,17 @@ static struct attribute_group netstat_group = {
        .name  = "statistics",
        .attrs  = netstat_attrs,
 };
+
+#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211)
+static struct attribute *wireless_attrs[] = {
+       NULL
+};
+
+static struct attribute_group wireless_group = {
+       .name = "wireless",
+       .attrs = wireless_attrs,
+};
+#endif
 #endif /* CONFIG_SYSFS */
 
 #ifdef CONFIG_RPS
@@ -1409,6 +1420,15 @@ int netdev_register_kobject(struct net_device *net)
                groups++;
 
        *groups++ = &netstat_group;
+
+#if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211)
+       if (net->ieee80211_ptr)
+               *groups++ = &wireless_group;
+#if IS_ENABLED(CONFIG_WIRELESS_EXT)
+       else if (net->wireless_handlers)
+               *groups++ = &wireless_group;
+#endif
+#endif
 #endif /* CONFIG_SYSFS */
 
        error = device_add(dev);
index 5eea4a811042adaf3df8e65308c2aeeb23c845e9..14bbfcf717acb9d02df641231cdf30a611a43810 100644 (file)
@@ -457,19 +457,28 @@ static int do_ip_setsockopt(struct sock *sk, int level,
        struct inet_sock *inet = inet_sk(sk);
        int val = 0, err;
 
-       if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) |
-                            (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) |
-                            (1<<IP_RETOPTS) | (1<<IP_TOS) |
-                            (1<<IP_TTL) | (1<<IP_HDRINCL) |
-                            (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) |
-                            (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
-                            (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT) |
-                            (1<<IP_MINTTL) | (1<<IP_NODEFRAG))) ||
-           optname == IP_UNICAST_IF ||
-           optname == IP_MULTICAST_TTL ||
-           optname == IP_MULTICAST_ALL ||
-           optname == IP_MULTICAST_LOOP ||
-           optname == IP_RECVORIGDSTADDR) {
+       switch (optname) {
+       case IP_PKTINFO:
+       case IP_RECVTTL:
+       case IP_RECVOPTS:
+       case IP_RECVTOS:
+       case IP_RETOPTS:
+       case IP_TOS:
+       case IP_TTL:
+       case IP_HDRINCL:
+       case IP_MTU_DISCOVER:
+       case IP_RECVERR:
+       case IP_ROUTER_ALERT:
+       case IP_FREEBIND:
+       case IP_PASSSEC:
+       case IP_TRANSPARENT:
+       case IP_MINTTL:
+       case IP_NODEFRAG:
+       case IP_UNICAST_IF:
+       case IP_MULTICAST_TTL:
+       case IP_MULTICAST_ALL:
+       case IP_MULTICAST_LOOP:
+       case IP_RECVORIGDSTADDR:
                if (optlen >= sizeof(int)) {
                        if (get_user(val, (int __user *) optval))
                                return -EFAULT;
index 1831092f999fb32880f2d5e721c242236b000228..858fddf6482a645c46bf441c67d9ed323dc7d78f 100644 (file)
@@ -338,12 +338,17 @@ static int vti_rcv(struct sk_buff *skb)
        if (tunnel != NULL) {
                struct pcpu_tstats *tstats;
 
+               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
+                       return -1;
+
                tstats = this_cpu_ptr(tunnel->dev->tstats);
                u64_stats_update_begin(&tstats->syncp);
                tstats->rx_packets++;
                tstats->rx_bytes += skb->len;
                u64_stats_update_end(&tstats->syncp);
 
+               skb->mark = 0;
+               secpath_reset(skb);
                skb->dev = tunnel->dev;
                return 1;
        }
index a8c651216fa62a44d9226eed3294e3e5f3484a3d..df251424d816b460ae268f21d337c57e64452fc6 100644 (file)
@@ -1785,6 +1785,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
        if (dev_out->flags & IFF_LOOPBACK)
                flags |= RTCF_LOCAL;
 
+       do_cache = true;
        if (type == RTN_BROADCAST) {
                flags |= RTCF_BROADCAST | RTCF_LOCAL;
                fi = NULL;
@@ -1793,6 +1794,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
                if (!ip_check_mc_rcu(in_dev, fl4->daddr, fl4->saddr,
                                     fl4->flowi4_proto))
                        flags &= ~RTCF_LOCAL;
+               else
+                       do_cache = false;
                /* If multicast route do not exist use
                 * default one, but do not gateway in this case.
                 * Yes, it is hack.
@@ -1802,8 +1805,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
        }
 
        fnhe = NULL;
-       do_cache = fi != NULL;
-       if (fi) {
+       do_cache &= fi != NULL;
+       if (do_cache) {
                struct rtable __rcu **prth;
                struct fib_nh *nh = &FIB_RES_NH(*res);
 
@@ -2597,7 +2600,7 @@ int __init ip_rt_init(void)
                pr_err("Unable to create route proc files\n");
 #ifdef CONFIG_XFRM
        xfrm_init();
-       xfrm4_init(ip_rt_max_size);
+       xfrm4_init();
 #endif
        rtnl_register(PF_INET, RTM_GETROUTE, inet_rtm_getroute, NULL, NULL);
 
index 197c0008503c8dc0dc01adc3c1c63ea60f3d374d..083092e3aed68db2dd5e9c3fb9cd43759a529abe 100644 (file)
@@ -1212,7 +1212,7 @@ new_segment:
 wait_for_sndbuf:
                        set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
 wait_for_memory:
-                       if (copied && likely(!tp->repair))
+                       if (copied)
                                tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
 
                        if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)
@@ -1223,7 +1223,7 @@ wait_for_memory:
        }
 
 out:
-       if (copied && likely(!tp->repair))
+       if (copied)
                tcp_push(sk, flags, mss_now, tp->nonagle);
        release_sock(sk);
        return copied + copied_syn;
index 2c2b13a999eae522c264a97a3d43baaa45c53c7b..609ff98aeb47ce99500614ff4a8a9cfe3a290d28 100644 (file)
@@ -5313,11 +5313,6 @@ static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
                goto discard;
        }
 
-       /* ts_recent update must be made after we are sure that the packet
-        * is in window.
-        */
-       tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
-
        /* step 3: check security and precedence [ignored] */
 
        /* step 4: Check for a SYN
@@ -5552,6 +5547,11 @@ step5:
        if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
                goto discard;
 
+       /* ts_recent update must be made after we are sure that the packet
+        * is in window.
+        */
+       tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
        tcp_rcv_rtt_measure_ts(sk, skb);
 
        /* Process urgent data. */
@@ -6130,6 +6130,11 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
        } else
                goto discard;
 
+       /* ts_recent update must be made after we are sure that the packet
+        * is in window.
+        */
+       tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
        /* step 6: check the URG bit */
        tcp_urg(sk, skb, th);
 
index 53bc5847bfa882a34c3d5a34257ec82a3fe92873..f696d7c2e9faac9b2fbfd2e61472d47a7c2fa823 100644 (file)
@@ -1,7 +1,6 @@
 #include <linux/rcupdate.h>
 #include <linux/spinlock.h>
 #include <linux/jiffies.h>
-#include <linux/bootmem.h>
 #include <linux/module.h>
 #include <linux/cache.h>
 #include <linux/slab.h>
@@ -9,6 +8,7 @@
 #include <linux/tcp.h>
 #include <linux/hash.h>
 #include <linux/tcp_metrics.h>
+#include <linux/vmalloc.h>
 
 #include <net/inet_connection_sock.h>
 #include <net/net_namespace.h>
@@ -1034,7 +1034,10 @@ static int __net_init tcp_net_metrics_init(struct net *net)
        net->ipv4.tcp_metrics_hash_log = order_base_2(slots);
        size = sizeof(struct tcpm_hash_bucket) << net->ipv4.tcp_metrics_hash_log;
 
-       net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL);
+       net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
+       if (!net->ipv4.tcp_metrics_hash)
+               net->ipv4.tcp_metrics_hash = vzalloc(size);
+
        if (!net->ipv4.tcp_metrics_hash)
                return -ENOMEM;
 
@@ -1055,7 +1058,10 @@ static void __net_exit tcp_net_metrics_exit(struct net *net)
                        tm = next;
                }
        }
-       kfree(net->ipv4.tcp_metrics_hash);
+       if (is_vmalloc_addr(net->ipv4.tcp_metrics_hash))
+               vfree(net->ipv4.tcp_metrics_hash);
+       else
+               kfree(net->ipv4.tcp_metrics_hash);
 }
 
 static __net_initdata struct pernet_operations tcp_net_metrics_ops = {
index cfe6ffe1c1778b6517297ad3ac9b87d17ce14582..2798706cb06385aa87fdb05ba1ed2c6a0a14e6e5 100644 (file)
@@ -1986,6 +1986,9 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
                tso_segs = tcp_init_tso_segs(sk, skb, mss_now);
                BUG_ON(!tso_segs);
 
+               if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE)
+                       goto repair; /* Skip network transmission */
+
                cwnd_quota = tcp_cwnd_test(tp, skb);
                if (!cwnd_quota)
                        break;
@@ -2026,6 +2029,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
                if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp)))
                        break;
 
+repair:
                /* Advance the send_head.  This one is sent out.
                 * This call will increment packets_out.
                 */
index 05c5ab8d983c462f75ab6143ca653669d36c1005..3be0ac2c1920e668be3f53f44a3df731a44204fc 100644 (file)
@@ -279,19 +279,8 @@ static void __exit xfrm4_policy_fini(void)
        xfrm_policy_unregister_afinfo(&xfrm4_policy_afinfo);
 }
 
-void __init xfrm4_init(int rt_max_size)
+void __init xfrm4_init(void)
 {
-       /*
-        * Select a default value for the gc_thresh based on the main route
-        * table hash size.  It seems to me the worst case scenario is when
-        * we have ipsec operating in transport mode, in which we create a
-        * dst_entry per socket.  The xfrm gc algorithm starts trying to remove
-        * entries at gc_thresh, and prevents new allocations as 2*gc_thresh
-        * so lets set an initial xfrm gc_thresh value at the rt_max_size/2.
-        * That will let us store an ipsec connection per route table entry,
-        * and start cleaning when were 1/2 full
-        */
-       xfrm4_dst_ops.gc_thresh = rt_max_size/2;
        dst_entries_init(&xfrm4_dst_ops);
 
        xfrm4_state_init();
index c4f934176cabd92ebfb4bba774335427b9f8932a..30647857a375bce469c50071636b5aef6c5a33d7 100644 (file)
@@ -252,6 +252,7 @@ struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu)
                return NULL;
        dst->ops->update_pmtu(dst, sk, NULL, mtu);
 
-       return inet6_csk_route_socket(sk, &fl6);
+       dst = inet6_csk_route_socket(sk, &fl6);
+       return IS_ERR(dst) ? NULL : dst;
 }
 EXPORT_SYMBOL_GPL(inet6_csk_update_pmtu);
index ba6d13d1f1e162254fa4e4421e82e4a204a9785c..e02faed6d17efa1684c2c9b0990506008bdb8aff 100644 (file)
@@ -827,6 +827,7 @@ pref_skip_coa:
                if (val < 0 || val > 255)
                        goto e_inval;
                np->min_hopcount = val;
+               retv = 0;
                break;
        case IPV6_DONTFRAG:
                np->dontfrag = valbool;
index 05f3a313db8852b36c677cad188fd7154d6564ef..7371f676cf412e54481751d36bf757f42dfa5134 100644 (file)
@@ -2594,6 +2594,9 @@ static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
                else
                        local->probe_req_reg--;
 
+               if (!local->open_count)
+                       break;
+
                ieee80211_queue_work(&local->hw, &local->reconfig_filter);
                break;
        default:
index bf87c70ac6c5fe1e2b920c6db827e1e9da6abe36..c21e33d1abd0d945ba041182dff52ad3f9ed4dc6 100644 (file)
@@ -1151,10 +1151,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
 
        mutex_lock(&sdata->u.ibss.mtx);
 
-       sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
-       memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
-       sdata->u.ibss.ssid_len = 0;
-
        active_ibss = ieee80211_sta_active_ibss(sdata);
 
        if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) {
@@ -1175,6 +1171,10 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
                }
        }
 
+       ifibss->state = IEEE80211_IBSS_MLME_SEARCH;
+       memset(ifibss->bssid, 0, ETH_ALEN);
+       ifibss->ssid_len = 0;
+
        sta_info_flush(sdata->local, sdata);
 
        spin_lock_bh(&ifibss->incomplete_lock);
index 8c804550465b37857d6dc50b082881ec5bd4ac35..156e5835e37f4b140fb9261c2c1ed44f73cf8408 100644 (file)
@@ -1314,6 +1314,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
                                         struct net_device *dev);
 netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                                       struct net_device *dev);
+void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
+                             struct sk_buff_head *skbs);
 
 /* HT */
 void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
index c80c4490351ce54fb75c41cdb9be1a313b0ffef5..f57f597972f8833ccc5a74a433bfd2ddafe407dd 100644 (file)
@@ -871,8 +871,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                                local->hw.wiphy->cipher_suites,
                                sizeof(u32) * local->hw.wiphy->n_cipher_suites,
                                GFP_KERNEL);
-                       if (!suites)
-                               return -ENOMEM;
+                       if (!suites) {
+                               result = -ENOMEM;
+                               goto fail_wiphy_register;
+                       }
                        for (r = 0; r < local->hw.wiphy->n_cipher_suites; r++) {
                                u32 suite = local->hw.wiphy->cipher_suites[r];
                                if (suite == WLAN_CIPHER_SUITE_WEP40 ||
index c4cdbde24fd3a70db1141c9460f617710daf98e2..43e60b5a7546eba4fd6e5e18eb313b7526d4f5b1 100644 (file)
@@ -917,7 +917,7 @@ int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
                                       struct cfg80211_sched_scan_request *req)
 {
        struct ieee80211_local *local = sdata->local;
-       struct ieee80211_sched_scan_ies sched_scan_ies;
+       struct ieee80211_sched_scan_ies sched_scan_ies = {};
        int ret, i;
 
        mutex_lock(&local->mtx);
index 0a4e4c04db89c5ba43a7f0e8d487385734a841b9..d2eb64e1235383e9b0e6aade66710f74ec1b4f3f 100644 (file)
@@ -117,8 +117,8 @@ static void free_sta_work(struct work_struct *wk)
 
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
                local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]);
-               __skb_queue_purge(&sta->ps_tx_buf[ac]);
-               __skb_queue_purge(&sta->tx_filtered[ac]);
+               ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]);
+               ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]);
        }
 
 #ifdef CONFIG_MAC80211_MESH
@@ -141,7 +141,7 @@ static void free_sta_work(struct work_struct *wk)
                tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]);
                if (!tid_tx)
                        continue;
-               __skb_queue_purge(&tid_tx->pending);
+               ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending);
                kfree(tid_tx);
        }
 
@@ -961,6 +961,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
        struct ieee80211_local *local = sdata->local;
        struct sk_buff_head pending;
        int filtered = 0, buffered = 0, ac;
+       unsigned long flags;
 
        clear_sta_flag(sta, WLAN_STA_SP);
 
@@ -976,12 +977,16 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
                int count = skb_queue_len(&pending), tmp;
 
+               spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags);
                skb_queue_splice_tail_init(&sta->tx_filtered[ac], &pending);
+               spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags);
                tmp = skb_queue_len(&pending);
                filtered += tmp - count;
                count = tmp;
 
+               spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags);
                skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending);
+               spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags);
                tmp = skb_queue_len(&pending);
                buffered += tmp - count;
        }
index 3af0cc4130f1986e1cf672a9246830d478e222e9..101eb88a2b78563965d4477a815bf8069d586db8 100644 (file)
@@ -668,3 +668,12 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb)
        dev_kfree_skb_any(skb);
 }
 EXPORT_SYMBOL(ieee80211_free_txskb);
+
+void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
+                             struct sk_buff_head *skbs)
+{
+       struct sk_buff *skb;
+
+       while ((skb = __skb_dequeue(skbs)))
+               ieee80211_free_txskb(hw, skb);
+}
index c9bf83f36657c3ca9929e64d2fd27c47a6486e3a..b858ebe41fdac2f20326cfd58fb37840270fcaa1 100644 (file)
@@ -1358,7 +1358,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
                if (tx->skb)
                        ieee80211_free_txskb(&tx->local->hw, tx->skb);
                else
-                       __skb_queue_purge(&tx->skbs);
+                       ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs);
                return -1;
        } else if (unlikely(res == TX_QUEUED)) {
                I802_DEBUG_INC(tx->local->tx_handlers_queued);
@@ -2120,10 +2120,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
  */
 void ieee80211_clear_tx_pending(struct ieee80211_local *local)
 {
+       struct sk_buff *skb;
        int i;
 
-       for (i = 0; i < local->hw.queues; i++)
-               skb_queue_purge(&local->pending[i]);
+       for (i = 0; i < local->hw.queues; i++) {
+               while ((skb = skb_dequeue(&local->pending[i])) != NULL)
+                       ieee80211_free_txskb(&local->hw, skb);
+       }
 }
 
 /*
index 239391807ca9cff116576d07975c2ce31db393d3..0151ae33c4cd448e4812b0e9255d47898bf595da 100644 (file)
@@ -1491,6 +1491,8 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                list_for_each_entry(sdata, &local->interfaces, list) {
                        if (sdata->vif.type != NL80211_IFTYPE_STATION)
                                continue;
+                       if (!sdata->u.mgd.associated)
+                               continue;
 
                        ieee80211_send_nullfunc(local, sdata, 0);
                }
index ec3dba5dcd62f081c1749fb60f2aa71cd31d11ad..5c0b78528e55b1af2288aa2e1a398202131413d5 100644 (file)
@@ -173,6 +173,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
                return adtfn(set, &nip, timeout, flags);
        }
 
+       ip_to = ip;
        if (tb[IPSET_ATTR_IP_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
@@ -185,8 +186,7 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (!cidr || cidr > 32)
                        return -IPSET_ERR_INVALID_CIDR;
                ip_set_mask_from_to(ip, ip_to, cidr);
-       } else
-               ip_to = ip;
+       }
 
        hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
 
index 0171f7502fa58d035fcda2361a6c4968acf09b7b..6283351f4eebee920c2939613ff05676b16f91ad 100644 (file)
@@ -162,7 +162,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipport4_elem data = { };
-       u32 ip, ip_to = 0, p = 0, port, port_to;
+       u32 ip, ip_to, p = 0, port, port_to;
        u32 timeout = h->timeout;
        bool with_ports = false;
        int ret;
@@ -210,7 +210,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
-       ip = ntohl(data.ip);
+       ip_to = ip = ntohl(data.ip);
        if (tb[IPSET_ATTR_IP_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
@@ -223,8 +223,7 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (!cidr || cidr > 32)
                        return -IPSET_ERR_INVALID_CIDR;
                ip_set_mask_from_to(ip, ip_to, cidr);
-       } else
-               ip_to = ip;
+       }
 
        port_to = port = ntohs(data.port);
        if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
index 6344ef551ec811208b79ddc54c89a1270c2419cd..6a21271c8d5a9f5da822c9789d55b761924d6da5 100644 (file)
@@ -166,7 +166,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportip4_elem data = { };
-       u32 ip, ip_to = 0, p = 0, port, port_to;
+       u32 ip, ip_to, p = 0, port, port_to;
        u32 timeout = h->timeout;
        bool with_ports = false;
        int ret;
@@ -218,7 +218,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
-       ip = ntohl(data.ip);
+       ip_to = ip = ntohl(data.ip);
        if (tb[IPSET_ATTR_IP_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
@@ -231,8 +231,7 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (!cidr || cidr > 32)
                        return -IPSET_ERR_INVALID_CIDR;
                ip_set_mask_from_to(ip, ip_to, cidr);
-       } else
-               ip_to = ip;
+       }
 
        port_to = port = ntohs(data.port);
        if (with_ports && tb[IPSET_ATTR_PORT_TO]) {
index cb71f9a774e7d50d67998aaaadc199a563f43f40..2d5cd4ee30eb4d5872b4aa9be7199a3d8999f6c7 100644 (file)
@@ -215,8 +215,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        const struct ip_set_hash *h = set->data;
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_ipportnet4_elem data = { .cidr = HOST_MASK - 1 };
-       u32 ip, ip_to = 0, p = 0, port, port_to;
-       u32 ip2_from = 0, ip2_to, ip2_last, ip2;
+       u32 ip, ip_to, p = 0, port, port_to;
+       u32 ip2_from, ip2_to, ip2_last, ip2;
        u32 timeout = h->timeout;
        bool with_ports = false;
        u8 cidr;
@@ -286,6 +286,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                return ip_set_eexist(ret, flags) ? 0 : ret;
        }
 
+       ip_to = ip;
        if (tb[IPSET_ATTR_IP_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
@@ -306,6 +307,8 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (port > port_to)
                        swap(port, port_to);
        }
+
+       ip2_to = ip2_from;
        if (tb[IPSET_ATTR_IP2_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
                if (ret)
index 8847b4d8be06b9ad536c2bb32d9bbd3d34a7c289..701c88a20fea4c2a3ca6c9b4b2189521e13f96fe 100644 (file)
@@ -41,7 +41,8 @@ MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tu
 static LIST_HEAD(cttimeout_list);
 
 static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = {
-       [CTA_TIMEOUT_NAME]      = { .type = NLA_NUL_STRING },
+       [CTA_TIMEOUT_NAME]      = { .type = NLA_NUL_STRING,
+                                   .len  = CTNL_TIMEOUT_NAME_MAX - 1},
        [CTA_TIMEOUT_L3PROTO]   = { .type = NLA_U16 },
        [CTA_TIMEOUT_L4PROTO]   = { .type = NLA_U8 },
        [CTA_TIMEOUT_DATA]      = { .type = NLA_NESTED },
index cc10d073c3381179671ef709b58baf4600e51a2b..9e8f4b2801f6099ebd5afcff20d2b5ef19e16589 100644 (file)
@@ -1210,7 +1210,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)
        local->remote_miu = LLCP_DEFAULT_MIU;
        local->remote_lto = LLCP_DEFAULT_LTO;
 
-       list_add(&llcp_devices, &local->list);
+       list_add(&local->list, &llcp_devices);
 
        return 0;
 }
index c3bea269faf4e6228143f70c6422046842922177..9966e7b16451230319f63d601284281970226799 100644 (file)
@@ -102,7 +102,7 @@ static const struct file_operations sctp_snmp_seq_fops = {
        .open    = sctp_snmp_seq_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = single_release,
+       .release = single_release_net,
 };
 
 /* Set up the proc fs entry for 'snmp' object. */
@@ -251,7 +251,7 @@ static const struct file_operations sctp_eps_seq_fops = {
        .open    = sctp_eps_seq_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_net,
 };
 
 /* Set up the proc fs entry for 'eps' object. */
@@ -372,7 +372,7 @@ static const struct file_operations sctp_assocs_seq_fops = {
        .open    = sctp_assocs_seq_open,
        .read    = seq_read,
        .llseek  = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_net,
 };
 
 /* Set up the proc fs entry for 'assocs' object. */
@@ -517,7 +517,7 @@ static const struct file_operations sctp_remaddr_seq_fops = {
        .open = sctp_remaddr_seq_open,
        .read = seq_read,
        .llseek = seq_lseek,
-       .release = seq_release,
+       .release = seq_release_net,
 };
 
 int __net_init sctp_remaddr_proc_init(struct net *net)
index bcc7d7ee5a516b8263c93a2556ab079d6d369280..b75756b05af76374cf62b432249be933881bc594 100644 (file)
@@ -141,9 +141,8 @@ static const struct ieee80211_regdomain world_regdom = {
        .reg_rules = {
                /* IEEE 802.11b/g, channels 1..11 */
                REG_RULE(2412-10, 2462+10, 40, 6, 20, 0),
-               /* IEEE 802.11b/g, channels 12..13. No HT40
-                * channel fits here. */
-               REG_RULE(2467-10, 2472+10, 20, 6, 20,
+               /* IEEE 802.11b/g, channels 12..13. */
+               REG_RULE(2467-10, 2472+10, 40, 6, 20,
                        NL80211_RRF_PASSIVE_SCAN |
                        NL80211_RRF_NO_IBSS),
                /* IEEE 802.11 channel 14 - Only JP enables
index bd2e098955532a26a3935e44ad58283598cbf673..cdd48600e02a9bd842f2e43ab6b7f263949451ec 100644 (file)
@@ -12,7 +12,7 @@ extern "C" {
 
 #include <assert.h>
 #include <stdio.h>
-#include <sys/queue.h>
+#include "list.h"
 #ifndef __cplusplus
 #include <stdbool.h>
 #endif
@@ -175,12 +175,11 @@ struct menu {
 #define MENU_ROOT              0x0002
 
 struct jump_key {
-       CIRCLEQ_ENTRY(jump_key) entries;
+       struct list_head entries;
        size_t offset;
        struct menu *target;
        int index;
 };
-CIRCLEQ_HEAD(jk_head, jump_key);
 
 #define JUMP_NB                        9
 
diff --git a/scripts/kconfig/list.h b/scripts/kconfig/list.h
new file mode 100644 (file)
index 0000000..0ae730b
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef LIST_H
+#define LIST_H
+
+/*
+ * Copied from include/linux/...
+ */
+
+#undef offsetof
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+
+/**
+ * container_of - cast a member of a structure out to the containing structure
+ * @ptr:        the pointer to the member.
+ * @type:       the type of the container struct this is embedded in.
+ * @member:     the name of the member within the struct.
+ *
+ */
+#define container_of(ptr, type, member) ({                      \
+       const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
+       (type *)( (char *)__mptr - offsetof(type,member) );})
+
+
+struct list_head {
+       struct list_head *next, *prev;
+};
+
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+       struct list_head name = LIST_HEAD_INIT(name)
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr:       the &struct list_head pointer.
+ * @type:      the type of the struct this is embedded in.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+       container_of(ptr, type, member)
+
+/**
+ * list_for_each_entry -       iterate over list of given type
+ * @pos:       the type * to use as a loop cursor.
+ * @head:      the head for your list.
+ * @member:    the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member)                         \
+       for (pos = list_entry((head)->next, typeof(*pos), member);      \
+            &pos->member != (head);    \
+            pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+       return head->next == head;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *_new,
+                             struct list_head *prev,
+                             struct list_head *next)
+{
+       next->prev = _new;
+       _new->next = next;
+       _new->prev = prev;
+       prev->next = _new;
+}
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *_new, struct list_head *head)
+{
+       __list_add(_new, head->prev, head);
+}
+
+#endif
index 1d1c08537f1e59b2cab76bd88437489fcbea393b..ef1a7381f956d5e7d0ebb8d3ba6af2361a0c3c74 100644 (file)
@@ -21,9 +21,9 @@ P(menu_get_root_menu,struct menu *,(struct menu *menu));
 P(menu_get_parent_menu,struct menu *,(struct menu *menu));
 P(menu_has_help,bool,(struct menu *menu));
 P(menu_get_help,const char *,(struct menu *menu));
-P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct jk_head
+P(get_symbol_str, void, (struct gstr *r, struct symbol *sym, struct list_head
                         *head));
-P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct jk_head
+P(get_relations_str, struct gstr, (struct symbol **sym_arr, struct list_head
                                   *head));
 P(menu_get_ext_help,void,(struct menu *menu, struct gstr *help));
 
index 48f67448af7b67cf6c8df7394702a65767891992..53975cf876083ecba455a7033222b2ccc3690686 100644 (file)
@@ -312,7 +312,7 @@ static void set_config_filename(const char *config_filename)
 
 
 struct search_data {
-       struct jk_head *head;
+       struct list_head *head;
        struct menu **targets;
        int *keys;
 };
@@ -323,7 +323,7 @@ static void update_text(char *buf, size_t start, size_t end, void *_data)
        struct jump_key *pos;
        int k = 0;
 
-       CIRCLEQ_FOREACH(pos, data->head, entries) {
+       list_for_each_entry(pos, data->head, entries) {
                if (pos->offset >= start && pos->offset < end) {
                        char header[4];
 
@@ -375,7 +375,7 @@ again:
 
        sym_arr = sym_re_search(dialog_input);
        do {
-               struct jk_head head = CIRCLEQ_HEAD_INITIALIZER(head);
+               LIST_HEAD(head);
                struct menu *targets[JUMP_NB];
                int keys[JUMP_NB + 1], i;
                struct search_data data = {
index a3cade659f89cb5f67828b797ae49b9311bf1d98..e98a05c8e50882d3b2833a2f4d05761dcffd22d3 100644 (file)
@@ -508,7 +508,7 @@ const char *menu_get_help(struct menu *menu)
 }
 
 static void get_prompt_str(struct gstr *r, struct property *prop,
-                          struct jk_head *head)
+                          struct list_head *head)
 {
        int i, j;
        struct menu *submenu[8], *menu, *location = NULL;
@@ -544,12 +544,13 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
                } else
                        jump->target = location;
 
-               if (CIRCLEQ_EMPTY(head))
+               if (list_empty(head))
                        jump->index = 0;
                else
-                       jump->index = CIRCLEQ_LAST(head)->index + 1;
+                       jump->index = list_entry(head->prev, struct jump_key,
+                                                entries)->index + 1;
 
-               CIRCLEQ_INSERT_TAIL(head, jump, entries);
+               list_add_tail(&jump->entries, head);
        }
 
        if (i > 0) {
@@ -573,7 +574,8 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
 /*
  * head is optional and may be NULL
  */
-void get_symbol_str(struct gstr *r, struct symbol *sym, struct jk_head *head)
+void get_symbol_str(struct gstr *r, struct symbol *sym,
+                   struct list_head *head)
 {
        bool hit;
        struct property *prop;
@@ -612,7 +614,7 @@ void get_symbol_str(struct gstr *r, struct symbol *sym, struct jk_head *head)
        str_append(r, "\n\n");
 }
 
-struct gstr get_relations_str(struct symbol **sym_arr, struct jk_head *head)
+struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head)
 {
        struct symbol *sym;
        struct gstr res = str_new();
index 87ca59d36e7ef64754892be3d842ac614bf2a9d5..974a20b661b79c6385f5fbc0cd40cd57e2a7ef94 100755 (executable)
@@ -156,12 +156,12 @@ sub asn1_extract($$@)
 
        if ($l == 0x1) {
            $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1));
-       } elsif ($l = 0x2) {
+       } elsif ($l == 0x2) {
            $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0], 2));
-       } elsif ($l = 0x3) {
+       } elsif ($l == 0x3) {
            $len = unpack("C", substr(${$cursor->[2]}, $cursor->[0], 1)) << 16;
            $len = unpack("n", substr(${$cursor->[2]}, $cursor->[0] + 1, 2));
-       } elsif ($l = 0x4) {
+       } elsif ($l == 0x4) {
            $len = unpack("N", substr(${$cursor->[2]}, $cursor->[0], 4));
        } else {
            die $x509, ": ", $cursor->[0], ": ASN.1 element too long (", $l, ")\n";
index 842c254396dbe8ab2a54fd566b37d29ce6fd4d8b..b08d20c66c2e17e0fa8333984df8eb4a82595e0b 100644 (file)
@@ -164,8 +164,8 @@ static void dev_exception_clean(struct dev_cgroup *dev_cgroup)
        struct dev_exception_item *ex, *tmp;
 
        list_for_each_entry_safe(ex, tmp, &dev_cgroup->exceptions, list) {
-               list_del(&ex->list);
-               kfree(ex);
+               list_del_rcu(&ex->list);
+               kfree_rcu(ex, rcu);
        }
 }
 
@@ -298,7 +298,7 @@ static int may_access(struct dev_cgroup *dev_cgroup,
        struct dev_exception_item *ex;
        bool match = false;
 
-       list_for_each_entry(ex, &dev_cgroup->exceptions, list) {
+       list_for_each_entry_rcu(ex, &dev_cgroup->exceptions, list) {
                if ((refex->type & DEV_BLOCK) && !(ex->type & DEV_BLOCK))
                        continue;
                if ((refex->type & DEV_CHAR) && !(ex->type & DEV_CHAR))
@@ -352,6 +352,8 @@ static int parent_has_perm(struct dev_cgroup *childcg,
  */
 static inline int may_allow_all(struct dev_cgroup *parent)
 {
+       if (!parent)
+               return 1;
        return parent->behavior == DEVCG_DEFAULT_ALLOW;
 }
 
@@ -376,11 +378,14 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
        int count, rc;
        struct dev_exception_item ex;
        struct cgroup *p = devcgroup->css.cgroup;
-       struct dev_cgroup *parent = cgroup_to_devcgroup(p->parent);
+       struct dev_cgroup *parent = NULL;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
+       if (p->parent)
+               parent = cgroup_to_devcgroup(p->parent);
+
        memset(&ex, 0, sizeof(ex));
        b = buffer;
 
@@ -391,11 +396,14 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
                        if (!may_allow_all(parent))
                                return -EPERM;
                        dev_exception_clean(devcgroup);
+                       devcgroup->behavior = DEVCG_DEFAULT_ALLOW;
+                       if (!parent)
+                               break;
+
                        rc = dev_exceptions_copy(&devcgroup->exceptions,
                                                 &parent->exceptions);
                        if (rc)
                                return rc;
-                       devcgroup->behavior = DEVCG_DEFAULT_ALLOW;
                        break;
                case DEVCG_DENY:
                        dev_exception_clean(devcgroup);
index 28f911cdd7c79dc292171fea10385adad51a27eb..c5454c0477c346e4d814f5ff209feba86e5b86ad 100644 (file)
@@ -174,7 +174,8 @@ static void sel_netnode_insert(struct sel_netnode *node)
        if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) {
                struct sel_netnode *tail;
                tail = list_entry(
-                       rcu_dereference(sel_netnode_hash[idx].list.prev),
+                       rcu_dereference_protected(sel_netnode_hash[idx].list.prev,
+                                                 lockdep_is_held(&sel_netnode_lock)),
                        struct sel_netnode, list);
                list_del_rcu(&tail->list);
                kfree_rcu(tail, rcu);
index 50169bcfd90370a92d64eadb3deee907618acc0b..7266020c16cb3a489a22418fd3b1f32e3dbd9fdb 100644 (file)
@@ -2581,9 +2581,14 @@ static u8 snd_es1968_tea575x_get_pins(struct snd_tea575x *tea)
        struct es1968 *chip = tea->private_data;
        unsigned long io = chip->io_port + GPIO_DATA;
        u16 val = inw(io);
-
-       return  (val & STR_DATA) ? TEA575X_DATA : 0 |
-               (val & STR_MOST) ? TEA575X_MOST : 0;
+       u8 ret;
+
+       ret = 0;
+       if (val & STR_DATA)
+               ret |= TEA575X_DATA;
+       if (val & STR_MOST)
+               ret |= TEA575X_MOST;
+       return ret;
 }
 
 static void snd_es1968_tea575x_set_direction(struct snd_tea575x *tea, bool output)
index cc2e91d1553822699251c15baf950e406243df8d..c5806f89be1ed8b23e0ad5e0ace6344815bb13f2 100644 (file)
@@ -767,9 +767,14 @@ static u8 snd_fm801_tea575x_get_pins(struct snd_tea575x *tea)
        struct fm801 *chip = tea->private_data;
        unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL));
        struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip);
-
-       return  (reg & FM801_GPIO_GP(gpio.data)) ? TEA575X_DATA : 0 |
-               (reg & FM801_GPIO_GP(gpio.most)) ? TEA575X_MOST : 0;
+       u8 ret;
+
+       ret = 0;
+       if (reg & FM801_GPIO_GP(gpio.data))
+               ret |= TEA575X_DATA;
+       if (reg & FM801_GPIO_GP(gpio.most))
+               ret |= TEA575X_MOST;
+       return ret;
 }
 
 static void snd_fm801_tea575x_set_direction(struct snd_tea575x *tea, bool output)
index 70d4848b5cd0ad25ce272877f9c759ed010dfc58..d010de12335e16525df3219cbe33647262316f7e 100644 (file)
@@ -95,6 +95,7 @@ int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
 EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
 
 #ifdef CONFIG_PM
+#define codec_in_pm(codec)     ((codec)->in_pm)
 static void hda_power_work(struct work_struct *work);
 static void hda_keep_power_on(struct hda_codec *codec);
 #define hda_codec_is_power_on(codec)   ((codec)->power_on)
@@ -104,6 +105,7 @@ static inline void hda_call_pm_notify(struct hda_bus *bus, bool power_up)
                bus->ops.pm_notify(bus, power_up);
 }
 #else
+#define codec_in_pm(codec)     0
 static inline void hda_keep_power_on(struct hda_codec *codec) {}
 #define hda_codec_is_power_on(codec)   1
 #define hda_call_pm_notify(bus, state) {}
@@ -228,7 +230,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
        }
        mutex_unlock(&bus->cmd_mutex);
        snd_hda_power_down(codec);
-       if (res && *res == -1 && bus->rirb_error) {
+       if (!codec_in_pm(codec) && res && *res == -1 && bus->rirb_error) {
                if (bus->response_reset) {
                        snd_printd("hda_codec: resetting BUS due to "
                                   "fatal communication error\n");
@@ -238,7 +240,7 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
                goto again;
        }
        /* clear reset-flag when the communication gets recovered */
-       if (!err)
+       if (!err || codec_in_pm(codec))
                bus->response_reset = 0;
        return err;
 }
@@ -3616,6 +3618,8 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
 {
        unsigned int state;
 
+       codec->in_pm = 1;
+
        if (codec->patch_ops.suspend)
                codec->patch_ops.suspend(codec);
        hda_cleanup_all_streams(codec);
@@ -3630,6 +3634,7 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
        codec->power_transition = 0;
        codec->power_jiffies = jiffies;
        spin_unlock(&codec->power_lock);
+       codec->in_pm = 0;
        return state;
 }
 
@@ -3638,6 +3643,8 @@ static unsigned int hda_call_codec_suspend(struct hda_codec *codec, bool in_wq)
  */
 static void hda_call_codec_resume(struct hda_codec *codec)
 {
+       codec->in_pm = 1;
+
        /* set as if powered on for avoiding re-entering the resume
         * in the resume / power-save sequence
         */
@@ -3656,6 +3663,8 @@ static void hda_call_codec_resume(struct hda_codec *codec)
                snd_hda_codec_resume_cache(codec);
        }
        snd_hda_jack_report_sync(codec);
+
+       codec->in_pm = 0;
        snd_hda_power_down(codec); /* flag down before returning */
 }
 #endif /* CONFIG_PM */
index 507fe8a917b69b09993193ef460f4fbc3f3af31a..4f4e545c0f4b2ded6029d21851b3443973ea7d23 100644 (file)
@@ -869,6 +869,7 @@ struct hda_codec {
        unsigned int power_on :1;       /* current (global) power-state */
        unsigned int d3_stop_clk:1;     /* support D3 operation without BCLK */
        unsigned int pm_down_notified:1; /* PM notified to controller */
+       unsigned int in_pm:1;           /* suspend/resume being performed */
        int power_transition;   /* power-state in transition */
        int power_count;        /* current (global) power refcount */
        struct delayed_work power_work; /* delayed task for powerdown */
index cd2dbaf1be786c61a3a1a446d7df5836d9622f35..f9d870e554d98d2fabe8791e904d7a393c8925e6 100644 (file)
@@ -556,6 +556,12 @@ enum {
 #define AZX_DCAPS_ALIGN_BUFSIZE        (1 << 22)       /* buffer size alignment */
 #define AZX_DCAPS_4K_BDLE_BOUNDARY (1 << 23)   /* BDLE in 4k boundary */
 #define AZX_DCAPS_COUNT_LPIB_DELAY  (1 << 25)  /* Take LPIB as delay */
+#define AZX_DCAPS_PM_RUNTIME   (1 << 26)       /* runtime PM support */
+
+/* quirks for Intel PCH */
+#define AZX_DCAPS_INTEL_PCH \
+       (AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \
+        AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME)
 
 /* quirks for ATI SB / AMD Hudson */
 #define AZX_DCAPS_PRESET_ATI_SB \
@@ -2433,6 +2439,9 @@ static void azx_power_notify(struct hda_bus *bus, bool power_up)
 {
        struct azx *chip = bus->private_data;
 
+       if (!(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
+               return;
+
        if (power_up)
                pm_runtime_get_sync(&chip->pci->dev);
        else
@@ -2548,7 +2557,8 @@ static int azx_runtime_suspend(struct device *dev)
        struct snd_card *card = dev_get_drvdata(dev);
        struct azx *chip = card->private_data;
 
-       if (!power_save_controller)
+       if (!power_save_controller ||
+           !(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
                return -EAGAIN;
 
        azx_stop_chip(chip);
@@ -3429,39 +3439,30 @@ static void __devexit azx_remove(struct pci_dev *pci)
 static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
        /* CPT */
        { PCI_DEVICE(0x8086, 0x1c20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* PBG */
        { PCI_DEVICE(0x8086, 0x1d20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE},
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Panther Point */
        { PCI_DEVICE(0x8086, 0x1e20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Lynx Point */
        { PCI_DEVICE(0x8086, 0x8c20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Lynx Point-LP */
        { PCI_DEVICE(0x8086, 0x9c20),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Lynx Point-LP */
        { PCI_DEVICE(0x8086, 0x9c21),
-         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
        /* Haswell */
        { PCI_DEVICE(0x8086, 0x0c0c),
-         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
        { PCI_DEVICE(0x8086, 0x0d0c),
-         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
        /* 5 Series/3400 */
        { PCI_DEVICE(0x8086, 0x3b56),
-         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-         AZX_DCAPS_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY },
+         .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
        /* SCH */
        { PCI_DEVICE(0x8086, 0x811b),
          .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
index d5f3a26d608db72f1e4ef3f596392eb5a4f25a67..3bcb671723583ed852ec97aa844d2736ffd4b330 100644 (file)
@@ -466,6 +466,7 @@ static int parse_output(struct hda_codec *codec)
                memcpy(cfg->speaker_pins, cfg->line_out_pins,
                       sizeof(cfg->speaker_pins));
                cfg->line_outs = 0;
+               memset(cfg->line_out_pins, 0, sizeof(cfg->line_out_pins));
        }
 
        return 0;
index c0ce3b1f04b4aafdcb61af4daa7bf85d942a787d..ad68d223f8af9e7dc43d24af303aab1eec64ca3d 100644 (file)
@@ -5407,6 +5407,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO),
+       SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
        SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF),
@@ -7064,6 +7065,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 },
        { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 },
        { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
+       { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 },
        { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
          .patch = patch_alc861 },
        { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
index c03b65af30598f8f03dfba2d7353913a33a0bfe9..054967d8bac2f6d089214e390b1bd6ce416f64b2 100644 (file)
@@ -268,7 +268,7 @@ EXPORT_SYMBOL_GPL(arizona_out_ev);
 static unsigned int arizona_sysclk_48k_rates[] = {
        6144000,
        12288000,
-       22579200,
+       24576000,
        49152000,
        73728000,
        98304000,
@@ -278,7 +278,7 @@ static unsigned int arizona_sysclk_48k_rates[] = {
 static unsigned int arizona_sysclk_44k1_rates[] = {
        5644800,
        11289600,
-       24576000,
+       22579200,
        45158400,
        67737600,
        90316800,
index f994af34f552f4b08c4e01880c3410a4890afb7c..e3f0a7f3131e14b7895aadf2daf8bf81f6058d8b 100644 (file)
@@ -485,7 +485,7 @@ static int cs4271_probe(struct snd_soc_codec *codec)
                gpio_nreset = cs4271plat->gpio_nreset;
 
        if (gpio_nreset >= 0)
-               if (gpio_request(gpio_nreset, "CS4271 Reset"))
+               if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset"))
                        gpio_nreset = -EINVAL;
        if (gpio_nreset >= 0) {
                /* Reset codec */
@@ -535,15 +535,10 @@ static int cs4271_probe(struct snd_soc_codec *codec)
 static int cs4271_remove(struct snd_soc_codec *codec)
 {
        struct cs4271_private *cs4271 = snd_soc_codec_get_drvdata(codec);
-       int gpio_nreset;
 
-       gpio_nreset = cs4271->gpio_nreset;
-
-       if (gpio_is_valid(gpio_nreset)) {
+       if (gpio_is_valid(cs4271->gpio_nreset))
                /* Set codec to the reset state */
-               gpio_set_value(gpio_nreset, 0);
-               gpio_free(gpio_nreset);
-       }
+               gpio_set_value(cs4271->gpio_nreset, 0);
 
        return 0;
 };
index 4d8db3685e961bfb44a05074e3f7bae3acb5952a..97a81051e88d125c9937057e3b51324a7bb0f9ae 100644 (file)
@@ -773,7 +773,6 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
 {
        struct snd_soc_codec *codec = codec_dai->codec;
        struct cs42l52_private *cs42l52 = snd_soc_codec_get_drvdata(codec);
-       int ret = 0;
        u8 iface = 0;
 
        switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -822,7 +821,7 @@ static int cs42l52_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        case SND_SOC_DAIFMT_NB_IF:
                break;
        default:
-               ret = -EINVAL;
+               return -EINVAL;
        }
        cs42l52->config.format = iface;
        snd_soc_write(codec, CS42L52_IFACE_CTL1, cs42l52->config.format);
index 1722b586bdba65bde94d9d3cb5cc1ca51cd44aee..7394e73fa43c0e526e7ab4e83480fb89bbf9891d 100644 (file)
@@ -42,6 +42,556 @@ static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
 static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
 static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0);
 
+static const struct reg_default wm5102_sysclk_reva_patch[] = {
+       { 0x3000, 0x2225 },
+       { 0x3001, 0x3a03 },
+       { 0x3002, 0x0225 },
+       { 0x3003, 0x0801 },
+       { 0x3004, 0x6249 },
+       { 0x3005, 0x0c04 },
+       { 0x3006, 0x0225 },
+       { 0x3007, 0x5901 },
+       { 0x3008, 0xe249 },
+       { 0x3009, 0x030d },
+       { 0x300a, 0x0249 },
+       { 0x300b, 0x2c01 },
+       { 0x300c, 0xe249 },
+       { 0x300d, 0x4342 },
+       { 0x300e, 0xe249 },
+       { 0x300f, 0x73c0 },
+       { 0x3010, 0x4249 },
+       { 0x3011, 0x0c00 },
+       { 0x3012, 0x0225 },
+       { 0x3013, 0x1f01 },
+       { 0x3014, 0x0225 },
+       { 0x3015, 0x1e01 },
+       { 0x3016, 0x0225 },
+       { 0x3017, 0xfa00 },
+       { 0x3018, 0x0000 },
+       { 0x3019, 0xf000 },
+       { 0x301a, 0x0000 },
+       { 0x301b, 0xf000 },
+       { 0x301c, 0x0000 },
+       { 0x301d, 0xf000 },
+       { 0x301e, 0x0000 },
+       { 0x301f, 0xf000 },
+       { 0x3020, 0x0000 },
+       { 0x3021, 0xf000 },
+       { 0x3022, 0x0000 },
+       { 0x3023, 0xf000 },
+       { 0x3024, 0x0000 },
+       { 0x3025, 0xf000 },
+       { 0x3026, 0x0000 },
+       { 0x3027, 0xf000 },
+       { 0x3028, 0x0000 },
+       { 0x3029, 0xf000 },
+       { 0x302a, 0x0000 },
+       { 0x302b, 0xf000 },
+       { 0x302c, 0x0000 },
+       { 0x302d, 0xf000 },
+       { 0x302e, 0x0000 },
+       { 0x302f, 0xf000 },
+       { 0x3030, 0x0225 },
+       { 0x3031, 0x1a01 },
+       { 0x3032, 0x0225 },
+       { 0x3033, 0x1e00 },
+       { 0x3034, 0x0225 },
+       { 0x3035, 0x1f00 },
+       { 0x3036, 0x6225 },
+       { 0x3037, 0xf800 },
+       { 0x3038, 0x0000 },
+       { 0x3039, 0xf000 },
+       { 0x303a, 0x0000 },
+       { 0x303b, 0xf000 },
+       { 0x303c, 0x0000 },
+       { 0x303d, 0xf000 },
+       { 0x303e, 0x0000 },
+       { 0x303f, 0xf000 },
+       { 0x3040, 0x2226 },
+       { 0x3041, 0x3a03 },
+       { 0x3042, 0x0226 },
+       { 0x3043, 0x0801 },
+       { 0x3044, 0x6249 },
+       { 0x3045, 0x0c06 },
+       { 0x3046, 0x0226 },
+       { 0x3047, 0x5901 },
+       { 0x3048, 0xe249 },
+       { 0x3049, 0x030d },
+       { 0x304a, 0x0249 },
+       { 0x304b, 0x2c01 },
+       { 0x304c, 0xe249 },
+       { 0x304d, 0x4342 },
+       { 0x304e, 0xe249 },
+       { 0x304f, 0x73c0 },
+       { 0x3050, 0x4249 },
+       { 0x3051, 0x0c00 },
+       { 0x3052, 0x0226 },
+       { 0x3053, 0x1f01 },
+       { 0x3054, 0x0226 },
+       { 0x3055, 0x1e01 },
+       { 0x3056, 0x0226 },
+       { 0x3057, 0xfa00 },
+       { 0x3058, 0x0000 },
+       { 0x3059, 0xf000 },
+       { 0x305a, 0x0000 },
+       { 0x305b, 0xf000 },
+       { 0x305c, 0x0000 },
+       { 0x305d, 0xf000 },
+       { 0x305e, 0x0000 },
+       { 0x305f, 0xf000 },
+       { 0x3060, 0x0000 },
+       { 0x3061, 0xf000 },
+       { 0x3062, 0x0000 },
+       { 0x3063, 0xf000 },
+       { 0x3064, 0x0000 },
+       { 0x3065, 0xf000 },
+       { 0x3066, 0x0000 },
+       { 0x3067, 0xf000 },
+       { 0x3068, 0x0000 },
+       { 0x3069, 0xf000 },
+       { 0x306a, 0x0000 },
+       { 0x306b, 0xf000 },
+       { 0x306c, 0x0000 },
+       { 0x306d, 0xf000 },
+       { 0x306e, 0x0000 },
+       { 0x306f, 0xf000 },
+       { 0x3070, 0x0226 },
+       { 0x3071, 0x1a01 },
+       { 0x3072, 0x0226 },
+       { 0x3073, 0x1e00 },
+       { 0x3074, 0x0226 },
+       { 0x3075, 0x1f00 },
+       { 0x3076, 0x6226 },
+       { 0x3077, 0xf800 },
+       { 0x3078, 0x0000 },
+       { 0x3079, 0xf000 },
+       { 0x307a, 0x0000 },
+       { 0x307b, 0xf000 },
+       { 0x307c, 0x0000 },
+       { 0x307d, 0xf000 },
+       { 0x307e, 0x0000 },
+       { 0x307f, 0xf000 },
+       { 0x3080, 0x2227 },
+       { 0x3081, 0x3a03 },
+       { 0x3082, 0x0227 },
+       { 0x3083, 0x0801 },
+       { 0x3084, 0x6255 },
+       { 0x3085, 0x0c04 },
+       { 0x3086, 0x0227 },
+       { 0x3087, 0x5901 },
+       { 0x3088, 0xe255 },
+       { 0x3089, 0x030d },
+       { 0x308a, 0x0255 },
+       { 0x308b, 0x2c01 },
+       { 0x308c, 0xe255 },
+       { 0x308d, 0x4342 },
+       { 0x308e, 0xe255 },
+       { 0x308f, 0x73c0 },
+       { 0x3090, 0x4255 },
+       { 0x3091, 0x0c00 },
+       { 0x3092, 0x0227 },
+       { 0x3093, 0x1f01 },
+       { 0x3094, 0x0227 },
+       { 0x3095, 0x1e01 },
+       { 0x3096, 0x0227 },
+       { 0x3097, 0xfa00 },
+       { 0x3098, 0x0000 },
+       { 0x3099, 0xf000 },
+       { 0x309a, 0x0000 },
+       { 0x309b, 0xf000 },
+       { 0x309c, 0x0000 },
+       { 0x309d, 0xf000 },
+       { 0x309e, 0x0000 },
+       { 0x309f, 0xf000 },
+       { 0x30a0, 0x0000 },
+       { 0x30a1, 0xf000 },
+       { 0x30a2, 0x0000 },
+       { 0x30a3, 0xf000 },
+       { 0x30a4, 0x0000 },
+       { 0x30a5, 0xf000 },
+       { 0x30a6, 0x0000 },
+       { 0x30a7, 0xf000 },
+       { 0x30a8, 0x0000 },
+       { 0x30a9, 0xf000 },
+       { 0x30aa, 0x0000 },
+       { 0x30ab, 0xf000 },
+       { 0x30ac, 0x0000 },
+       { 0x30ad, 0xf000 },
+       { 0x30ae, 0x0000 },
+       { 0x30af, 0xf000 },
+       { 0x30b0, 0x0227 },
+       { 0x30b1, 0x1a01 },
+       { 0x30b2, 0x0227 },
+       { 0x30b3, 0x1e00 },
+       { 0x30b4, 0x0227 },
+       { 0x30b5, 0x1f00 },
+       { 0x30b6, 0x6227 },
+       { 0x30b7, 0xf800 },
+       { 0x30b8, 0x0000 },
+       { 0x30b9, 0xf000 },
+       { 0x30ba, 0x0000 },
+       { 0x30bb, 0xf000 },
+       { 0x30bc, 0x0000 },
+       { 0x30bd, 0xf000 },
+       { 0x30be, 0x0000 },
+       { 0x30bf, 0xf000 },
+       { 0x30c0, 0x2228 },
+       { 0x30c1, 0x3a03 },
+       { 0x30c2, 0x0228 },
+       { 0x30c3, 0x0801 },
+       { 0x30c4, 0x6255 },
+       { 0x30c5, 0x0c06 },
+       { 0x30c6, 0x0228 },
+       { 0x30c7, 0x5901 },
+       { 0x30c8, 0xe255 },
+       { 0x30c9, 0x030d },
+       { 0x30ca, 0x0255 },
+       { 0x30cb, 0x2c01 },
+       { 0x30cc, 0xe255 },
+       { 0x30cd, 0x4342 },
+       { 0x30ce, 0xe255 },
+       { 0x30cf, 0x73c0 },
+       { 0x30d0, 0x4255 },
+       { 0x30d1, 0x0c00 },
+       { 0x30d2, 0x0228 },
+       { 0x30d3, 0x1f01 },
+       { 0x30d4, 0x0228 },
+       { 0x30d5, 0x1e01 },
+       { 0x30d6, 0x0228 },
+       { 0x30d7, 0xfa00 },
+       { 0x30d8, 0x0000 },
+       { 0x30d9, 0xf000 },
+       { 0x30da, 0x0000 },
+       { 0x30db, 0xf000 },
+       { 0x30dc, 0x0000 },
+       { 0x30dd, 0xf000 },
+       { 0x30de, 0x0000 },
+       { 0x30df, 0xf000 },
+       { 0x30e0, 0x0000 },
+       { 0x30e1, 0xf000 },
+       { 0x30e2, 0x0000 },
+       { 0x30e3, 0xf000 },
+       { 0x30e4, 0x0000 },
+       { 0x30e5, 0xf000 },
+       { 0x30e6, 0x0000 },
+       { 0x30e7, 0xf000 },
+       { 0x30e8, 0x0000 },
+       { 0x30e9, 0xf000 },
+       { 0x30ea, 0x0000 },
+       { 0x30eb, 0xf000 },
+       { 0x30ec, 0x0000 },
+       { 0x30ed, 0xf000 },
+       { 0x30ee, 0x0000 },
+       { 0x30ef, 0xf000 },
+       { 0x30f0, 0x0228 },
+       { 0x30f1, 0x1a01 },
+       { 0x30f2, 0x0228 },
+       { 0x30f3, 0x1e00 },
+       { 0x30f4, 0x0228 },
+       { 0x30f5, 0x1f00 },
+       { 0x30f6, 0x6228 },
+       { 0x30f7, 0xf800 },
+       { 0x30f8, 0x0000 },
+       { 0x30f9, 0xf000 },
+       { 0x30fa, 0x0000 },
+       { 0x30fb, 0xf000 },
+       { 0x30fc, 0x0000 },
+       { 0x30fd, 0xf000 },
+       { 0x30fe, 0x0000 },
+       { 0x30ff, 0xf000 },
+       { 0x3100, 0x222b },
+       { 0x3101, 0x3a03 },
+       { 0x3102, 0x222b },
+       { 0x3103, 0x5803 },
+       { 0x3104, 0xe26f },
+       { 0x3105, 0x030d },
+       { 0x3106, 0x626f },
+       { 0x3107, 0x2c01 },
+       { 0x3108, 0xe26f },
+       { 0x3109, 0x4342 },
+       { 0x310a, 0xe26f },
+       { 0x310b, 0x73c0 },
+       { 0x310c, 0x026f },
+       { 0x310d, 0x0c00 },
+       { 0x310e, 0x022b },
+       { 0x310f, 0x1f01 },
+       { 0x3110, 0x022b },
+       { 0x3111, 0x1e01 },
+       { 0x3112, 0x022b },
+       { 0x3113, 0xfa00 },
+       { 0x3114, 0x0000 },
+       { 0x3115, 0xf000 },
+       { 0x3116, 0x0000 },
+       { 0x3117, 0xf000 },
+       { 0x3118, 0x0000 },
+       { 0x3119, 0xf000 },
+       { 0x311a, 0x0000 },
+       { 0x311b, 0xf000 },
+       { 0x311c, 0x0000 },
+       { 0x311d, 0xf000 },
+       { 0x311e, 0x0000 },
+       { 0x311f, 0xf000 },
+       { 0x3120, 0x022b },
+       { 0x3121, 0x0a01 },
+       { 0x3122, 0x022b },
+       { 0x3123, 0x1e00 },
+       { 0x3124, 0x022b },
+       { 0x3125, 0x1f00 },
+       { 0x3126, 0x622b },
+       { 0x3127, 0xf800 },
+       { 0x3128, 0x0000 },
+       { 0x3129, 0xf000 },
+       { 0x312a, 0x0000 },
+       { 0x312b, 0xf000 },
+       { 0x312c, 0x0000 },
+       { 0x312d, 0xf000 },
+       { 0x312e, 0x0000 },
+       { 0x312f, 0xf000 },
+       { 0x3130, 0x0000 },
+       { 0x3131, 0xf000 },
+       { 0x3132, 0x0000 },
+       { 0x3133, 0xf000 },
+       { 0x3134, 0x0000 },
+       { 0x3135, 0xf000 },
+       { 0x3136, 0x0000 },
+       { 0x3137, 0xf000 },
+       { 0x3138, 0x0000 },
+       { 0x3139, 0xf000 },
+       { 0x313a, 0x0000 },
+       { 0x313b, 0xf000 },
+       { 0x313c, 0x0000 },
+       { 0x313d, 0xf000 },
+       { 0x313e, 0x0000 },
+       { 0x313f, 0xf000 },
+       { 0x3140, 0x0000 },
+       { 0x3141, 0xf000 },
+       { 0x3142, 0x0000 },
+       { 0x3143, 0xf000 },
+       { 0x3144, 0x0000 },
+       { 0x3145, 0xf000 },
+       { 0x3146, 0x0000 },
+       { 0x3147, 0xf000 },
+       { 0x3148, 0x0000 },
+       { 0x3149, 0xf000 },
+       { 0x314a, 0x0000 },
+       { 0x314b, 0xf000 },
+       { 0x314c, 0x0000 },
+       { 0x314d, 0xf000 },
+       { 0x314e, 0x0000 },
+       { 0x314f, 0xf000 },
+       { 0x3150, 0x0000 },
+       { 0x3151, 0xf000 },
+       { 0x3152, 0x0000 },
+       { 0x3153, 0xf000 },
+       { 0x3154, 0x0000 },
+       { 0x3155, 0xf000 },
+       { 0x3156, 0x0000 },
+       { 0x3157, 0xf000 },
+       { 0x3158, 0x0000 },
+       { 0x3159, 0xf000 },
+       { 0x315a, 0x0000 },
+       { 0x315b, 0xf000 },
+       { 0x315c, 0x0000 },
+       { 0x315d, 0xf000 },
+       { 0x315e, 0x0000 },
+       { 0x315f, 0xf000 },
+       { 0x3160, 0x0000 },
+       { 0x3161, 0xf000 },
+       { 0x3162, 0x0000 },
+       { 0x3163, 0xf000 },
+       { 0x3164, 0x0000 },
+       { 0x3165, 0xf000 },
+       { 0x3166, 0x0000 },
+       { 0x3167, 0xf000 },
+       { 0x3168, 0x0000 },
+       { 0x3169, 0xf000 },
+       { 0x316a, 0x0000 },
+       { 0x316b, 0xf000 },
+       { 0x316c, 0x0000 },
+       { 0x316d, 0xf000 },
+       { 0x316e, 0x0000 },
+       { 0x316f, 0xf000 },
+       { 0x3170, 0x0000 },
+       { 0x3171, 0xf000 },
+       { 0x3172, 0x0000 },
+       { 0x3173, 0xf000 },
+       { 0x3174, 0x0000 },
+       { 0x3175, 0xf000 },
+       { 0x3176, 0x0000 },
+       { 0x3177, 0xf000 },
+       { 0x3178, 0x0000 },
+       { 0x3179, 0xf000 },
+       { 0x317a, 0x0000 },
+       { 0x317b, 0xf000 },
+       { 0x317c, 0x0000 },
+       { 0x317d, 0xf000 },
+       { 0x317e, 0x0000 },
+       { 0x317f, 0xf000 },
+       { 0x3180, 0x2001 },
+       { 0x3181, 0xf101 },
+       { 0x3182, 0x0000 },
+       { 0x3183, 0xf000 },
+       { 0x3184, 0x0000 },
+       { 0x3185, 0xf000 },
+       { 0x3186, 0x0000 },
+       { 0x3187, 0xf000 },
+       { 0x3188, 0x0000 },
+       { 0x3189, 0xf000 },
+       { 0x318a, 0x0000 },
+       { 0x318b, 0xf000 },
+       { 0x318c, 0x0000 },
+       { 0x318d, 0xf000 },
+       { 0x318e, 0x0000 },
+       { 0x318f, 0xf000 },
+       { 0x3190, 0x0000 },
+       { 0x3191, 0xf000 },
+       { 0x3192, 0x0000 },
+       { 0x3193, 0xf000 },
+       { 0x3194, 0x0000 },
+       { 0x3195, 0xf000 },
+       { 0x3196, 0x0000 },
+       { 0x3197, 0xf000 },
+       { 0x3198, 0x0000 },
+       { 0x3199, 0xf000 },
+       { 0x319a, 0x0000 },
+       { 0x319b, 0xf000 },
+       { 0x319c, 0x0000 },
+       { 0x319d, 0xf000 },
+       { 0x319e, 0x0000 },
+       { 0x319f, 0xf000 },
+       { 0x31a0, 0x0000 },
+       { 0x31a1, 0xf000 },
+       { 0x31a2, 0x0000 },
+       { 0x31a3, 0xf000 },
+       { 0x31a4, 0x0000 },
+       { 0x31a5, 0xf000 },
+       { 0x31a6, 0x0000 },
+       { 0x31a7, 0xf000 },
+       { 0x31a8, 0x0000 },
+       { 0x31a9, 0xf000 },
+       { 0x31aa, 0x0000 },
+       { 0x31ab, 0xf000 },
+       { 0x31ac, 0x0000 },
+       { 0x31ad, 0xf000 },
+       { 0x31ae, 0x0000 },
+       { 0x31af, 0xf000 },
+       { 0x31b0, 0x0000 },
+       { 0x31b1, 0xf000 },
+       { 0x31b2, 0x0000 },
+       { 0x31b3, 0xf000 },
+       { 0x31b4, 0x0000 },
+       { 0x31b5, 0xf000 },
+       { 0x31b6, 0x0000 },
+       { 0x31b7, 0xf000 },
+       { 0x31b8, 0x0000 },
+       { 0x31b9, 0xf000 },
+       { 0x31ba, 0x0000 },
+       { 0x31bb, 0xf000 },
+       { 0x31bc, 0x0000 },
+       { 0x31bd, 0xf000 },
+       { 0x31be, 0x0000 },
+       { 0x31bf, 0xf000 },
+       { 0x31c0, 0x0000 },
+       { 0x31c1, 0xf000 },
+       { 0x31c2, 0x0000 },
+       { 0x31c3, 0xf000 },
+       { 0x31c4, 0x0000 },
+       { 0x31c5, 0xf000 },
+       { 0x31c6, 0x0000 },
+       { 0x31c7, 0xf000 },
+       { 0x31c8, 0x0000 },
+       { 0x31c9, 0xf000 },
+       { 0x31ca, 0x0000 },
+       { 0x31cb, 0xf000 },
+       { 0x31cc, 0x0000 },
+       { 0x31cd, 0xf000 },
+       { 0x31ce, 0x0000 },
+       { 0x31cf, 0xf000 },
+       { 0x31d0, 0x0000 },
+       { 0x31d1, 0xf000 },
+       { 0x31d2, 0x0000 },
+       { 0x31d3, 0xf000 },
+       { 0x31d4, 0x0000 },
+       { 0x31d5, 0xf000 },
+       { 0x31d6, 0x0000 },
+       { 0x31d7, 0xf000 },
+       { 0x31d8, 0x0000 },
+       { 0x31d9, 0xf000 },
+       { 0x31da, 0x0000 },
+       { 0x31db, 0xf000 },
+       { 0x31dc, 0x0000 },
+       { 0x31dd, 0xf000 },
+       { 0x31de, 0x0000 },
+       { 0x31df, 0xf000 },
+       { 0x31e0, 0x0000 },
+       { 0x31e1, 0xf000 },
+       { 0x31e2, 0x0000 },
+       { 0x31e3, 0xf000 },
+       { 0x31e4, 0x0000 },
+       { 0x31e5, 0xf000 },
+       { 0x31e6, 0x0000 },
+       { 0x31e7, 0xf000 },
+       { 0x31e8, 0x0000 },
+       { 0x31e9, 0xf000 },
+       { 0x31ea, 0x0000 },
+       { 0x31eb, 0xf000 },
+       { 0x31ec, 0x0000 },
+       { 0x31ed, 0xf000 },
+       { 0x31ee, 0x0000 },
+       { 0x31ef, 0xf000 },
+       { 0x31f0, 0x0000 },
+       { 0x31f1, 0xf000 },
+       { 0x31f2, 0x0000 },
+       { 0x31f3, 0xf000 },
+       { 0x31f4, 0x0000 },
+       { 0x31f5, 0xf000 },
+       { 0x31f6, 0x0000 },
+       { 0x31f7, 0xf000 },
+       { 0x31f8, 0x0000 },
+       { 0x31f9, 0xf000 },
+       { 0x31fa, 0x0000 },
+       { 0x31fb, 0xf000 },
+       { 0x31fc, 0x0000 },
+       { 0x31fd, 0xf000 },
+       { 0x31fe, 0x0000 },
+       { 0x31ff, 0xf000 },
+       { 0x024d, 0xff50 },
+       { 0x0252, 0xff50 },
+       { 0x0259, 0x0112 },
+       { 0x025e, 0x0112 },
+};
+
+static int wm5102_sysclk_ev(struct snd_soc_dapm_widget *w,
+                           struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = w->codec;
+       struct arizona *arizona = dev_get_drvdata(codec->dev);
+       struct regmap *regmap = codec->control_data;
+       const struct reg_default *patch = NULL;
+       int i, patch_size;
+
+       switch (arizona->rev) {
+       case 0:
+               patch = wm5102_sysclk_reva_patch;
+               patch_size = ARRAY_SIZE(wm5102_sysclk_reva_patch);
+               break;
+       }
+
+       switch (event) {
+       case SND_SOC_DAPM_POST_PMU:
+               if (patch)
+                       for (i = 0; i < patch_size; i++)
+                               regmap_write(regmap, patch[i].reg,
+                                            patch[i].def);
+               break;
+
+       default:
+               break;
+       }
+
+       return 0;
+}
+
 static const struct snd_kcontrol_new wm5102_snd_controls[] = {
 SOC_SINGLE("IN1 High Performance Switch", ARIZONA_IN1L_CONTROL,
           ARIZONA_IN1_OSR_SHIFT, 1, 0),
@@ -297,7 +847,7 @@ static const struct snd_kcontrol_new wm5102_aec_loopback_mux =
 
 static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = {
 SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT,
-                   0, NULL, 0),
+                   0, wm5102_sysclk_ev, SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1,
                    ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0),
 SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK,
index 5421fd9fbcb5d37954e77f88962c31e9d953e2dc..4c0a8e496131c1cc2bf9933605dee7664928520d 100644 (file)
@@ -782,7 +782,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream,
                wm8978->mclk_idx = -1;
                f_sel = wm8978->f_mclk;
        } else {
-               if (!wm8978->f_pllout) {
+               if (!wm8978->f_opclk) {
                        /* We only enter here, if OPCLK is not used */
                        int ret = wm8978_configure_pll(codec);
                        if (ret < 0)
index b9f16598324c9b4b85373b6f55d785011c4d8b68..2ba08148655f32ee2fa7301c44d65b54e7ea02fb 100644 (file)
@@ -71,7 +71,6 @@ static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
                printk(KERN_WARNING "%s: got err interrupt 0x%lx\n",
                                __func__, cause);
                writel(cause, priv->io + KIRKWOOD_ERR_CAUSE);
-               return IRQ_HANDLED;
        }
 
        /* we've enabled only bytes interrupts ... */
@@ -178,7 +177,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
        }
 
        dram = mv_mbus_dram_info();
-       addr = virt_to_phys(substream->dma_buffer.area);
+       addr = substream->dma_buffer.addr;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                prdata->play_stream = substream;
                kirkwood_dma_conf_mbus_windows(priv->io,
index 542538d10ab7df46b02fc2b6bb3630c8bed45322..1d5db484d2df331b15e8e385cd32e2acd79e4d79 100644 (file)
@@ -95,7 +95,7 @@ static inline void kirkwood_set_dco(void __iomem *io, unsigned long rate)
        do {
                cpu_relax();
                value = readl(io + KIRKWOOD_DCO_SPCR_STATUS);
-               value &= KIRKWOOD_DCO_SPCR_STATUS;
+               value &= KIRKWOOD_DCO_SPCR_STATUS_DCO_LOCK;
        } while (value == 0);
 }
 
@@ -180,67 +180,72 @@ static int kirkwood_i2s_play_trigger(struct snd_pcm_substream *substream,
                                int cmd, struct snd_soc_dai *dai)
 {
        struct kirkwood_dma_data *priv = snd_soc_dai_get_drvdata(dai);
-       unsigned long value;
-
-       /*
-        * specs says KIRKWOOD_PLAYCTL must be read 2 times before
-        * changing it. So read 1 time here and 1 later.
-        */
-       value = readl(priv->io + KIRKWOOD_PLAYCTL);
+       uint32_t ctl, value;
+
+       ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
+       if (ctl & KIRKWOOD_PLAYCTL_PAUSE) {
+               unsigned timeout = 5000;
+               /*
+                * The Armada510 spec says that if we enter pause mode, the
+                * busy bit must be read back as clear _twice_.  Make sure
+                * we respect that otherwise we get DMA underruns.
+                */
+               do {
+                       value = ctl;
+                       ctl = readl(priv->io + KIRKWOOD_PLAYCTL);
+                       if (!((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY))
+                               break;
+                       udelay(1);
+               } while (timeout--);
+
+               if ((ctl | value) & KIRKWOOD_PLAYCTL_PLAY_BUSY)
+                       dev_notice(dai->dev, "timed out waiting for busy to deassert: %08x\n",
+                                  ctl);
+       }
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               /* stop audio, enable interrupts */
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value |= KIRKWOOD_PLAYCTL_PAUSE;
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
-
                value = readl(priv->io + KIRKWOOD_INT_MASK);
                value |= KIRKWOOD_INT_CAUSE_PLAY_BYTES;
                writel(value, priv->io + KIRKWOOD_INT_MASK);
 
                /* configure audio & enable i2s playback */
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
-               value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
+               ctl &= ~KIRKWOOD_PLAYCTL_BURST_MASK;
+               ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE
                                | KIRKWOOD_PLAYCTL_SPDIF_EN);
 
                if (priv->burst == 32)
-                       value |= KIRKWOOD_PLAYCTL_BURST_32;
+                       ctl |= KIRKWOOD_PLAYCTL_BURST_32;
                else
-                       value |= KIRKWOOD_PLAYCTL_BURST_128;
-               value |= KIRKWOOD_PLAYCTL_I2S_EN;
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+                       ctl |= KIRKWOOD_PLAYCTL_BURST_128;
+               ctl |= KIRKWOOD_PLAYCTL_I2S_EN;
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
                /* stop audio, disable interrupts */
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+               ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
 
                value = readl(priv->io + KIRKWOOD_INT_MASK);
                value &= ~KIRKWOOD_INT_CAUSE_PLAY_BYTES;
                writel(value, priv->io + KIRKWOOD_INT_MASK);
 
                /* disable all playbacks */
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN);
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+               ctl &= ~(KIRKWOOD_PLAYCTL_I2S_EN | KIRKWOOD_PLAYCTL_SPDIF_EN);
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
        case SNDRV_PCM_TRIGGER_SUSPEND:
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+               ctl |= KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE;
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
-               value = readl(priv->io + KIRKWOOD_PLAYCTL);
-               value &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
-               writel(value, priv->io + KIRKWOOD_PLAYCTL);
+               ctl &= ~(KIRKWOOD_PLAYCTL_PAUSE | KIRKWOOD_PLAYCTL_I2S_MUTE);
+               writel(ctl, priv->io + KIRKWOOD_PLAYCTL);
                break;
 
        default:
@@ -260,11 +265,6 @@ static int kirkwood_i2s_rec_trigger(struct snd_pcm_substream *substream,
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               /* stop audio, enable interrupts */
-               value = readl(priv->io + KIRKWOOD_RECCTL);
-               value |= KIRKWOOD_RECCTL_PAUSE;
-               writel(value, priv->io + KIRKWOOD_RECCTL);
-
                value = readl(priv->io + KIRKWOOD_INT_MASK);
                value |= KIRKWOOD_INT_CAUSE_REC_BYTES;
                writel(value, priv->io + KIRKWOOD_INT_MASK);
index aa037b292f3dc05a9b6300c3cc4890988c0c2faf..c294fbb523fce2dac76a70d9e5537a47fee40042 100644 (file)
@@ -523,16 +523,24 @@ static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
 
                if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                        /*
-                        * write a data to saif data register to trigger
-                        * the transfer
+                        * write data to saif data register to trigger
+                        * the transfer.
+                        * For 24-bit format the 32-bit FIFO register stores
+                        * only one channel, so we need to write twice.
+                        * This is also safe for the other non 24-bit formats.
                         */
                        __raw_writel(0, saif->base + SAIF_DATA);
+                       __raw_writel(0, saif->base + SAIF_DATA);
                } else {
                        /*
-                        * read a data from saif data register to trigger
-                        * the receive
+                        * read data from saif data register to trigger
+                        * the receive.
+                        * For 24-bit format the 32-bit FIFO register stores
+                        * only one channel, so we need to read twice.
+                        * This is also safe for the other non 24-bit formats.
                         */
                        __raw_readl(saif->base + SAIF_DATA);
+                       __raw_readl(saif->base + SAIF_DATA);
                }
 
                master_saif->ongoing = 1;
@@ -812,3 +820,4 @@ module_platform_driver(mxs_saif_driver);
 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 MODULE_DESCRIPTION("MXS ASoC SAIF driver");
 MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mxs-saif");
index e7b83179aca2b1469af4ec1e03f35e62df1227b2..3c7c3a59ed3987b9017e89c07cf130a2a54c4a39 100644 (file)
@@ -207,6 +207,8 @@ config SND_SOC_BELLS
        select SND_SOC_WM5102
        select SND_SOC_WM5110
        select SND_SOC_WM9081
+       select SND_SOC_WM0010
+       select SND_SOC_WM1250_EV1
 
 config SND_SOC_LOWLAND
        tristate "Audio support for Wolfson Lowland"
index b0d46d63d55ea784f2f6970cd77bd2915a1c32fa..a2ca1567b9e4ff93a481d99065820d887ff8a72c 100644 (file)
@@ -212,7 +212,7 @@ static struct snd_soc_dai_link bells_dai_wm5102[] = {
        {
                .name = "Sub",
                .stream_name = "Sub",
-               .cpu_dai_name = "wm5110-aif3",
+               .cpu_dai_name = "wm5102-aif3",
                .codec_dai_name = "wm9081-hifi",
                .codec_name = "wm9081.1-006c",
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
index d1198627fc40397b772adad1104579c35842507f..10d21be383f6d511221094a1fa3a9a3b9657a464 100644 (file)
@@ -2786,8 +2786,9 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol,
        val = (ucontrol->value.integer.value[0] + min) & mask;
        val = val << shift;
 
-       if (snd_soc_update_bits_locked(codec, reg, val_mask, val))
-                       return err;
+       err = snd_soc_update_bits_locked(codec, reg, val_mask, val);
+       if (err < 0)
+               return err;
 
        if (snd_soc_volsw_is_stereo(mc)) {
                val_mask = mask << rshift;
index d0a4be38dc0f0473bdafe38d6b18ca30b11de61b..6e35bcae02df4b6a0e79709482a018f099615e21 100644 (file)
@@ -3745,7 +3745,7 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card)
 {
        struct snd_soc_codec *codec;
 
-       list_for_each_entry(codec, &card->codec_dev_list, list) {
+       list_for_each_entry(codec, &card->codec_dev_list, card_list) {
                soc_dapm_shutdown_codec(&codec->dapm);
                if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
                        snd_soc_dapm_set_bias_level(&codec->dapm,
index 282f0fc9fed1ef768bffc7f457b38de5dd39a429..dbf7999d18b4e7b300c0063f73aadf5dfa3f0f95 100644 (file)
@@ -559,9 +559,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
                return;
 
        card = chip->card;
-       mutex_lock(&register_mutex);
        down_write(&chip->shutdown_rwsem);
        chip->shutdown = 1;
+       up_write(&chip->shutdown_rwsem);
+
+       mutex_lock(&register_mutex);
        chip->num_interfaces--;
        if (chip->num_interfaces <= 0) {
                snd_card_disconnect(card);
@@ -582,11 +584,9 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
                        snd_usb_mixer_disconnect(p);
                }
                usb_chip[chip->index] = NULL;
-               up_write(&chip->shutdown_rwsem);
                mutex_unlock(&register_mutex);
                snd_card_free_when_closed(card);
        } else {
-               up_write(&chip->shutdown_rwsem);
                mutex_unlock(&register_mutex);
        }
 }
index c83f6143c0eb34d8f77f969e1928427458b4268a..eeefbce3873c11dc35a6e174c4ace79daeeaa8c1 100644 (file)
@@ -148,6 +148,7 @@ struct snd_usb_midi_out_endpoint {
                struct snd_usb_midi_out_endpoint* ep;
                struct snd_rawmidi_substream *substream;
                int active;
+               bool autopm_reference;
                uint8_t cable;          /* cable number << 4 */
                uint8_t state;
 #define STATE_UNKNOWN  0
@@ -1076,7 +1077,8 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
                return -ENXIO;
        }
        err = usb_autopm_get_interface(umidi->iface);
-       if (err < 0)
+       port->autopm_reference = err >= 0;
+       if (err < 0 && err != -EACCES)
                return -EIO;
        substream->runtime->private_data = port;
        port->state = STATE_UNKNOWN;
@@ -1087,9 +1089,11 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
 static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
 {
        struct snd_usb_midi* umidi = substream->rmidi->private_data;
+       struct usbmidi_out_port *port = substream->runtime->private_data;
 
        substream_open(substream, 0);
-       usb_autopm_put_interface(umidi->iface);
+       if (port->autopm_reference)
+               usb_autopm_put_interface(umidi->iface);
        return 0;
 }
 
index 5c12a3fe8c3e8dfae0af6388b9ee3ea8c6c16047..ef6fa24fc473b08a89dd33ef8158f004185f54cb 100644 (file)
@@ -459,7 +459,7 @@ static int configure_endpoint(struct snd_usb_substream *subs)
                return ret;
 
        if (subs->sync_endpoint)
-               ret = snd_usb_endpoint_set_params(subs->data_endpoint,
+               ret = snd_usb_endpoint_set_params(subs->sync_endpoint,
                                                  subs->pcm_format,
                                                  subs->channels,
                                                  subs->period_bytes,
index 2655ae9a3ad8d9e6f7676006336a5e3b8fec99d1..ea095abbe97e7cc7bec26c575a1d177dc1e2c61d 100644 (file)
@@ -206,8 +206,10 @@ int get_msr(int cpu, off_t offset, unsigned long long *msr)
        retval = pread(fd, msr, sizeof *msr, offset);
        close(fd);
 
-       if (retval != sizeof *msr)
+       if (retval != sizeof *msr) {
+               fprintf(stderr, "%s offset 0x%zx read failed\n", pathname, offset);
                return -1;
+       }
 
        return 0;
 }
@@ -1101,7 +1103,9 @@ void turbostat_loop()
 
 restart:
        retval = for_all_cpus(get_counters, EVEN_COUNTERS);
-       if (retval) {
+       if (retval < -1) {
+               exit(retval);
+       } else if (retval == -1) {
                re_initialize();
                goto restart;
        }
@@ -1114,7 +1118,9 @@ restart:
                }
                sleep(interval_sec);
                retval = for_all_cpus(get_counters, ODD_COUNTERS);
-               if (retval) {
+               if (retval < -1) {
+                       exit(retval);
+               } else if (retval == -1) {
                        re_initialize();
                        goto restart;
                }
@@ -1126,7 +1132,9 @@ restart:
                flush_stdout();
                sleep(interval_sec);
                retval = for_all_cpus(get_counters, EVEN_COUNTERS);
-               if (retval) {
+               if (retval < -1) {
+                       exit(retval);
+               } else if (retval == -1) {
                        re_initialize();
                        goto restart;
                }
@@ -1545,8 +1553,11 @@ void turbostat_init()
 int fork_it(char **argv)
 {
        pid_t child_pid;
+       int status;
 
-       for_all_cpus(get_counters, EVEN_COUNTERS);
+       status = for_all_cpus(get_counters, EVEN_COUNTERS);
+       if (status)
+               exit(status);
        /* clear affinity side-effect of get_counters() */
        sched_setaffinity(0, cpu_present_setsize, cpu_present_set);
        gettimeofday(&tv_even, (struct timezone *)NULL);
@@ -1556,7 +1567,6 @@ int fork_it(char **argv)
                /* child */
                execvp(argv[0], argv);
        } else {
-               int status;
 
                /* parent */
                if (child_pid == -1) {
@@ -1568,7 +1578,7 @@ int fork_it(char **argv)
                signal(SIGQUIT, SIG_IGN);
                if (waitpid(child_pid, &status, 0) == -1) {
                        perror("wait");
-                       exit(1);
+                       exit(status);
                }
        }
        /*
@@ -1585,7 +1595,7 @@ int fork_it(char **argv)
 
        fprintf(stderr, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0);
 
-       return 0;
+       return status;
 }
 
 void cmdline(int argc, char **argv)
@@ -1594,7 +1604,7 @@ void cmdline(int argc, char **argv)
 
        progname = argv[0];
 
-       while ((opt = getopt(argc, argv, "+pPSvisc:sC:m:M:")) != -1) {
+       while ((opt = getopt(argc, argv, "+pPSvi:sc:sC:m:M:")) != -1) {
                switch (opt) {
                case 'p':
                        show_core_only++;