Merge commit 'v3.0-rc5' into android-3.0
authorColin Cross <ccross@android.com>
Wed, 29 Jun 2011 20:54:42 +0000 (13:54 -0700)
committerColin Cross <ccross@android.com>
Wed, 29 Jun 2011 20:54:42 +0000 (13:54 -0700)
510 files changed:
Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 [new file with mode: 0644]
Documentation/accounting/cgroupstats.txt
Documentation/cgroups/blkio-controller.txt
Documentation/cgroups/cgroups.txt
Documentation/cgroups/cpuacct.txt
Documentation/cgroups/cpusets.txt
Documentation/cgroups/devices.txt
Documentation/cgroups/freezer-subsystem.txt
Documentation/cgroups/memory.txt
Documentation/feature-removal-schedule.txt
Documentation/filesystems/proc.txt
Documentation/kmemleak.txt
Documentation/md.txt
Documentation/power/devices.txt
Documentation/power/runtime_pm.txt
Documentation/printk-formats.txt
Documentation/scheduler/sched-design-CFS.txt
Documentation/scheduler/sched-rt-group.txt
Documentation/vm/hwpoison.txt
MAINTAINERS
Makefile
arch/alpha/include/asm/mmzone.h
arch/alpha/kernel/osf_sys.c
arch/arm/boot/compressed/head.S
arch/arm/configs/davinci_all_defconfig
arch/arm/configs/netx_defconfig
arch/arm/configs/viper_defconfig
arch/arm/configs/xcep_defconfig
arch/arm/configs/zeus_defconfig
arch/arm/include/asm/assembler.h
arch/arm/include/asm/entry-macro-multi.S
arch/arm/kernel/devtree.c
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/module.c
arch/arm/kernel/smp.c
arch/arm/kernel/traps.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/devices.c
arch/arm/mach-davinci/gpio.c
arch/arm/mach-footbridge/dc21285-timer.c
arch/arm/mach-footbridge/include/mach/debug-macro.S
arch/arm/mach-h720x/Kconfig
arch/arm/mach-msm/timer.c
arch/arm/mach-mxs/ocotp.c
arch/arm/mach-omap1/Makefile
arch/arm/mach-omap1/pm_bus.c
arch/arm/mach-omap2/board-omap3pandora.c
arch/arm/mach-omap2/pm-debug.c
arch/arm/mach-pxa/spitz_pm.c
arch/arm/mach-shmobile/board-ag5evm.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/intc-sh73a0.c
arch/arm/mach-shmobile/setup-sh7367.c
arch/arm/mach-u300/clock.h
arch/arm/mach-u300/include/mach/u300-regs.h
arch/arm/mach-u300/timer.c
arch/arm/mach-vexpress/v2m.c
arch/arm/mm/context.c
arch/arm/mm/init.c
arch/arm/mm/proc-arm7tdmi.S
arch/arm/mm/proc-arm9tdmi.S
arch/arm/mm/proc-v7.S
arch/arm/plat-iop/cp6.c
arch/arm/plat-mxc/devices/platform-imx-dma.c
arch/arm/plat-omap/omap_device.c
arch/avr32/configs/atngw100_defconfig
arch/avr32/configs/atngw100_evklcd100_defconfig
arch/avr32/configs/atngw100_evklcd101_defconfig
arch/avr32/configs/atngw100_mrmt_defconfig
arch/avr32/configs/atngw100mkii_defconfig
arch/avr32/configs/atngw100mkii_evklcd100_defconfig
arch/avr32/configs/atngw100mkii_evklcd101_defconfig
arch/avr32/configs/atstk1002_defconfig
arch/avr32/configs/atstk1003_defconfig
arch/avr32/configs/atstk1004_defconfig
arch/avr32/configs/atstk1006_defconfig
arch/avr32/configs/favr-32_defconfig
arch/avr32/configs/hammerhead_defconfig
arch/avr32/configs/merisc_defconfig
arch/avr32/configs/mimc200_defconfig
arch/avr32/include/asm/processor.h
arch/avr32/mach-at32ap/at32ap700x.c
arch/avr32/mach-at32ap/include/mach/cpu.h
arch/avr32/mach-at32ap/intc.c
arch/blackfin/configs/CM-BF548_defconfig
arch/m32r/include/asm/mmzone.h
arch/m68k/Kconfig.nommu
arch/m68k/kernel/m68k_ksyms.c
arch/m68k/kernel/vmlinux.lds_no.S
arch/m68k/lib/memcpy.c
arch/m68k/lib/memset.c
arch/m68k/lib/muldi3.c
arch/mips/configs/mtx1_defconfig
arch/mn10300/include/asm/uaccess.h
arch/parisc/include/asm/mmzone.h
arch/powerpc/configs/52xx/pcm030_defconfig
arch/powerpc/configs/ps3_defconfig
arch/powerpc/include/asm/mmzone.h
arch/s390/Kconfig
arch/s390/kernel/smp.c
arch/s390/oprofile/init.c
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/boot/compressed/Makefile
arch/sh/configs/titan_defconfig
arch/sh/include/asm/cmpxchg-grb.h
arch/sh/include/asm/mmzone.h
arch/sh/include/asm/processor_64.h
arch/sh/include/cpu-sh4/cpu/sh7724.h
arch/sh/kernel/cpu/sh4a/setup-sh7724.c
arch/sh/kernel/process_32.c
arch/sh/mm/cache-debugfs.c
arch/sparc/include/asm/mmzone.h
arch/tile/include/asm/mmzone.h
arch/um/include/asm/percpu.h [new file with mode: 0644]
arch/x86/include/asm/memblock.h
arch/x86/include/asm/mmzone_32.h
arch/x86/include/asm/mmzone_64.h
arch/x86/include/asm/pvclock.h
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/process.c
arch/x86/kvm/mmu.c
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/vmx.c
arch/x86/mm/memblock.c
arch/x86/pci/acpi.c
arch/x86/platform/efi/efi.c
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/x86/xen/setup.c
arch/x86/xen/smp.c
block/blk-throttle.c
block/cfq-iosched.c
block/genhd.c
drivers/ata/libata-core.c
drivers/ata/libata-scsi.c
drivers/ata/pata_marvell.c
drivers/ata/sata_dwc_460ex.c
drivers/base/power/clock_ops.c
drivers/base/power/main.c
drivers/bluetooth/btmrvl_debugfs.c
drivers/char/hpet.c
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/powernow-k8.c
drivers/dma/shdma.c
drivers/gpio/gpio-omap.c
drivers/gpu/drm/drm_bufs.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_ioc32.c
drivers/gpu/drm/drm_pci.c
drivers/gpu/drm/drm_vm.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_suspend.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_overlay.c
drivers/gpu/drm/mga/mga_drv.h
drivers/gpu/drm/nouveau/nouveau_acpi.c
drivers/gpu/drm/nouveau/nouveau_fence.c
drivers/gpu/drm/nouveau/nouveau_perf.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/radeon/atombios.h
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/r100_track.h
drivers/gpu/drm/radeon/r600.c
drivers/gpu/drm/radeon/radeon.h
drivers/gpu/drm/radeon/radeon_asic.c
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_clocks.c
drivers/gpu/drm/radeon/radeon_combios.c
drivers/gpu/drm/radeon/radeon_connectors.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_encoders.c
drivers/gpu/drm/radeon/radeon_fence.c
drivers/gpu/drm/radeon/radeon_mode.h
drivers/gpu/drm/radeon/rv770.c
drivers/gpu/drm/savage/savage_bci.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/hid/Kconfig
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-magicmouse.c
drivers/hid/hid-multitouch.c
drivers/hid/usbhid/hid-quirks.c
drivers/hid/usbhid/hiddev.c
drivers/hwmon/asus_atk0110.c
drivers/hwmon/coretemp.c
drivers/hwmon/ibmaem.c
drivers/hwmon/ibmpex.c
drivers/hwmon/s3c-hwmon.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/cq.c
drivers/infiniband/hw/cxgb4/mem.c
drivers/infiniband/hw/cxgb4/qp.c
drivers/infiniband/hw/qib/qib_iba7322.c
drivers/infiniband/hw/qib/qib_intr.c
drivers/input/evdev.c
drivers/input/input.c
drivers/input/keyboard/omap-keypad.c
drivers/input/keyboard/sh_keysc.c
drivers/input/mousedev.c
drivers/isdn/gigaset/interface.c
drivers/leds/Kconfig
drivers/leds/leds-lp5521.c
drivers/leds/leds-lp5523.c
drivers/md/bitmap.c
drivers/md/bitmap.h
drivers/md/md.c
drivers/md/md.h
drivers/md/raid1.c
drivers/md/raid1.h
drivers/md/raid5.c
drivers/misc/apds990x.c
drivers/misc/cb710/sgbuf2.c
drivers/misc/cs5535-mfgpt.c
drivers/misc/ioc4.c
drivers/misc/lkdtm.c
drivers/misc/sgi-xp/xpnet.c
drivers/misc/spear13xx_pcie_gadget.c
drivers/mmc/card/block.c
drivers/mmc/card/queue.c
drivers/mmc/card/queue.h
drivers/mmc/core/core.c
drivers/mmc/core/sdio.c
drivers/mmc/core/sdio_bus.c
drivers/mmc/host/mmci.c
drivers/mmc/host/of_mmc_spi.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/sh_mobile_sdhi.c
drivers/mmc/host/tmio_mmc_pio.c
drivers/mmc/host/vub300.c
drivers/net/3c503.c
drivers/net/bfin_mac.c
drivers/net/bonding/bond_main.c
drivers/net/fs_enet/mac-fcc.c
drivers/net/hp100.c
drivers/net/hplance.c
drivers/net/netxen/netxen_nic_main.c
drivers/net/phy/Kconfig
drivers/net/phy/dp83640.c
drivers/net/ppp_async.c
drivers/net/pxa168_eth.c
drivers/net/r8169.c
drivers/net/tun.c
drivers/net/usb/Kconfig
drivers/net/usb/Makefile
drivers/net/usb/kalmia.c [new file with mode: 0644]
drivers/net/wan/farsync.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwl8k.c
drivers/pci/pci-driver.c
drivers/pci/pci.c
drivers/pci/probe.c
drivers/pci/quirks.c
drivers/pcmcia/pxa2xx_vpac270.c
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-vt8500.c
drivers/sh/clk/core.c
drivers/spi/spi_bfin5xx.c
drivers/staging/iio/accel/adis16201.h
drivers/staging/iio/accel/adis16203.h
drivers/target/loopback/tcm_loop.c
drivers/target/target_core_configfs.c
drivers/target/target_core_device.c
drivers/target/target_core_pr.c
drivers/target/target_core_tmr.c
drivers/target/target_core_transport.c
drivers/target/tcm_fc/tcm_fc.h
drivers/target/tcm_fc/tfc_cmd.c
drivers/target/tcm_fc/tfc_io.c
drivers/target/tcm_fc/tfc_sess.c
drivers/tty/serial/8250_pci.c
drivers/tty/serial/mrst_max3110.c
drivers/tty/serial/pch_uart.c
drivers/usb/core/driver.c
drivers/video/aty/atyfb_base.c
drivers/video/backlight/Kconfig
drivers/video/backlight/Makefile
drivers/video/backlight/adp8870_bl.c [new file with mode: 0644]
drivers/video/efifb.c
drivers/video/s3c-fb.c
drivers/video/sh_mobile_hdmi.c
drivers/w1/masters/Kconfig
drivers/xen/events.c
fs/afs/dir.c
fs/afs/fsclient.c
fs/afs/inode.c
fs/afs/super.c
fs/afs/write.c
fs/bad_inode.c
fs/block_dev.c
fs/btrfs/ctree.h
fs/btrfs/delayed-inode.c
fs/btrfs/delayed-inode.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/relocation.c
fs/btrfs/sysfs.c
fs/btrfs/transaction.c
fs/btrfs/tree-log.c
fs/buffer.c
fs/cifs/Kconfig
fs/cifs/cache.c
fs/cifs/cifs_fs_sb.h
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/cifsproto.h
fs/cifs/connect.c
fs/cifs/fscache.c
fs/cifs/smbencrypt.c
fs/coda/pioctl.c
fs/exec.c
fs/ext4/ext4_extents.h
fs/ext4/extents.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/move_extent.c
fs/ext4/super.c
fs/inode.c
fs/isofs/inode.c
fs/jbd2/checkpoint.c
fs/jbd2/commit.c
fs/jbd2/journal.c
fs/jbd2/transaction.c
fs/jfs/file.c
fs/jfs/jfs_imap.c
fs/jfs/jfs_incore.h
fs/jfs/resize.c
fs/lockd/clntproc.c
fs/logfs/dir.c
fs/namei.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
fs/nfs/objlayout/objio_osd.c
fs/nfs/objlayout/objlayout.c
fs/nfs/pagelist.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/pnfs_dev.c
fs/nfsd/Kconfig
fs/nfsd/nfsctl.c
fs/nfsd/vfs.c
fs/nilfs2/inode.c
fs/omfs/file.c
fs/proc/base.c
fs/proc/namespaces.c
fs/proc/proc_sysctl.c
fs/proc/root.c
fs/reiserfs/xattr.c
fs/romfs/mmap-nommu.c
fs/sysfs/mount.c
fs/sysfs/sysfs.h
fs/timerfd.c
fs/ubifs/super.c
fs/xfs/linux-2.6/xfs_file.c
fs/xfs/linux-2.6/xfs_iops.c
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/xfs_attr.c
fs/xfs/xfs_iget.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_log.c
fs/xfs/xfs_vnodeops.c
include/asm-generic/gpio.h
include/asm-generic/pgtable.h
include/drm/drm_crtc.h
include/linux/blk_types.h
include/linux/blktrace_api.h
include/linux/clocksource.h
include/linux/compat.h
include/linux/device.h
include/linux/device_cgroup.h
include/linux/fs.h
include/linux/gpio.h
include/linux/hrtimer.h
include/linux/i2c/adp8870.h [new file with mode: 0644]
include/linux/input/sh_keysc.h
include/linux/interrupt.h
include/linux/jbd2.h
include/linux/kernel.h
include/linux/kmod.h
include/linux/kmsg_dump.h
include/linux/kobject_ns.h
include/linux/memcontrol.h
include/linux/mmzone.h
include/linux/nfs_page.h
include/linux/nfs_xdr.h
include/linux/pci_ids.h
include/linux/pm.h
include/linux/shmem_fs.h
include/linux/smp.h
include/linux/sunrpc/gss_krb5_enctypes.h [new file with mode: 0644]
include/linux/sunrpc/sched.h
include/linux/swap.h
include/linux/sysfs.h
include/linux/topology.h
include/linux/uts.h
include/net/net_namespace.h
include/net/netfilter/nf_conntrack.h
include/net/sock.h
include/sound/soc.h
include/trace/events/ext4.h
include/trace/events/irq.h
include/trace/events/vmscan.h
init/Kconfig
init/calibrate.c
init/main.c
kernel/exit.c
kernel/gcov/Kconfig
kernel/kmod.c
kernel/power/user.c
kernel/rcutree.c
kernel/rcutree.h
kernel/rcutree_plugin.h
kernel/rcutree_trace.c
kernel/sched_rt.c
kernel/signal.c
kernel/smp.c
kernel/softirq.c
kernel/taskstats.c
kernel/time/alarmtimer.c
kernel/time/clocksource.c
kernel/trace/trace_printk.c
lib/bitmap.c
lib/kobject.c
mm/compaction.c
mm/huge_memory.c
mm/hugetlb.c
mm/ksm.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory.c
mm/memory_hotplug.c
mm/migrate.c
mm/mmap.c
mm/page_cgroup.c
mm/rmap.c
mm/shmem.c
mm/swapfile.c
mm/thrash.c
mm/truncate.c
mm/vmscan.c
net/8021q/vlan.c
net/bluetooth/hci_event.c
net/bluetooth/l2cap_sock.c
net/bluetooth/rfcomm/sock.c
net/bluetooth/sco.c
net/bridge/br_device.c
net/bridge/br_multicast.c
net/caif/cfmuxl.c
net/core/net-sysfs.c
net/core/net_namespace.c
net/ieee802154/nl-phy.c
net/ipv4/af_inet.c
net/ipv4/inet_diag.c
net/ipv4/netfilter/ip_queue.c
net/ipv4/netfilter/ip_tables.c
net/ipv4/netfilter/ipt_ecn.c
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
net/ipv4/ping.c
net/ipv4/route.c
net/ipv4/tcp_ipv4.c
net/ipv6/netfilter/ip6_queue.c
net/ipv6/tcp_ipv6.c
net/netfilter/ipvs/ip_vs_conn.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/nfnetlink_log.c
net/netfilter/nfnetlink_queue.c
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/auth_gss/gss_krb5_mech.c
net/sunrpc/clnt.c
net/sunrpc/sched.c
scripts/checkpatch.pl
security/device_cgroup.c
security/keys/request_key.c
security/selinux/selinuxfs.c
security/selinux/ss/policydb.c
security/tomoyo/mount.c
sound/firewire/isight.c
sound/pci/asihpi/asihpi.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/hda/hda_beep.h
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_via.c
sound/pci/lola/lola.c
sound/pci/rme9652/hdspm.c
sound/soc/codecs/wm8991.c
sound/soc/imx/Kconfig
sound/soc/imx/imx-pcm-dma-mx2.c
sound/soc/imx/imx-ssi.c
sound/soc/pxa/pxa2xx-pcm.c
sound/soc/soc-cache.c
sound/usb/6fire/firmware.c
sound/usb/6fire/pcm.c
tools/perf/Makefile
tools/perf/util/PERF-VERSION-GEN
tools/perf/util/trace-event-parse.c

diff --git a/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870 b/Documentation/ABI/testing/sysfs-class-backlight-driver-adp8870
new file mode 100644 (file)
index 0000000..aa11dbd
--- /dev/null
@@ -0,0 +1,56 @@
+What:          /sys/class/backlight/<backlight>/<ambient light zone>_max
+What:          /sys/class/backlight/<backlight>/l1_daylight_max
+What:          /sys/class/backlight/<backlight>/l2_bright_max
+What:          /sys/class/backlight/<backlight>/l3_office_max
+What:          /sys/class/backlight/<backlight>/l4_indoor_max
+What:          /sys/class/backlight/<backlight>/l5_dark_max
+Date:          Mai 2011
+KernelVersion: 2.6.40
+Contact:       device-drivers-devel@blackfin.uclinux.org
+Description:
+               Control the maximum brightness for <ambient light zone>
+               on this <backlight>. Values are between 0 and 127. This file
+               will also show the brightness level stored for this
+               <ambient light zone>.
+
+What:          /sys/class/backlight/<backlight>/<ambient light zone>_dim
+What:          /sys/class/backlight/<backlight>/l2_bright_dim
+What:          /sys/class/backlight/<backlight>/l3_office_dim
+What:          /sys/class/backlight/<backlight>/l4_indoor_dim
+What:          /sys/class/backlight/<backlight>/l5_dark_dim
+Date:          Mai 2011
+KernelVersion: 2.6.40
+Contact:       device-drivers-devel@blackfin.uclinux.org
+Description:
+               Control the dim brightness for <ambient light zone>
+               on this <backlight>. Values are between 0 and 127, typically
+               set to 0. Full off when the backlight is disabled.
+               This file will also show the dim brightness level stored for
+               this <ambient light zone>.
+
+What:          /sys/class/backlight/<backlight>/ambient_light_level
+Date:          Mai 2011
+KernelVersion: 2.6.40
+Contact:       device-drivers-devel@blackfin.uclinux.org
+Description:
+               Get conversion value of the light sensor.
+               This value is updated every 80 ms (when the light sensor
+               is enabled). Returns integer between 0 (dark) and
+               8000 (max ambient brightness)
+
+What:          /sys/class/backlight/<backlight>/ambient_light_zone
+Date:          Mai 2011
+KernelVersion: 2.6.40
+Contact:       device-drivers-devel@blackfin.uclinux.org
+Description:
+               Get/Set current ambient light zone. Reading returns
+               integer between 1..5 (1 = daylight, 2 = bright, ..., 5 = dark).
+               Writing a value between 1..5 forces the backlight controller
+               to enter the corresponding ambient light zone.
+               Writing 0 returns to normal/automatic ambient light level
+               operation. The ambient light sensing feature on these devices
+               is an extension to the API documented in
+               Documentation/ABI/stable/sysfs-class-backlight.
+               It can be enabled by writing the value stored in
+               /sys/class/backlight/<backlight>/max_brightness to
+               /sys/class/backlight/<backlight>/brightness.
\ No newline at end of file
index eda40fd39cad9df7927e7409765007af38020219..d16a9849e60e127c2cd234cd02dcc9d6f16d35ec 100644 (file)
@@ -21,7 +21,7 @@ information will not be available.
 To extract cgroup statistics a utility very similar to getdelays.c
 has been developed, the sample output of the utility is shown below
 
-~/balbir/cgroupstats # ./getdelays  -C "/cgroup/a"
+~/balbir/cgroupstats # ./getdelays  -C "/sys/fs/cgroup/a"
 sleeping 1, blocked 0, running 1, stopped 0, uninterruptible 0
-~/balbir/cgroupstats # ./getdelays  -C "/cgroup"
+~/balbir/cgroupstats # ./getdelays  -C "/sys/fs/cgroup"
 sleeping 155, blocked 0, running 1, stopped 0, uninterruptible 2
index 465351d4cf853e8a308c9c84abef789b3dcfa42c..cd45c8ea7463f71eccee9d82ce6a82b47bcee467 100644 (file)
@@ -28,16 +28,19 @@ cgroups. Here is what you can do.
 - Enable group scheduling in CFQ
        CONFIG_CFQ_GROUP_IOSCHED=y
 
-- Compile and boot into kernel and mount IO controller (blkio).
+- Compile and boot into kernel and mount IO controller (blkio); see
+  cgroups.txt, Why are cgroups needed?.
 
-       mount -t cgroup -o blkio none /cgroup
+       mount -t tmpfs cgroup_root /sys/fs/cgroup
+       mkdir /sys/fs/cgroup/blkio
+       mount -t cgroup -o blkio none /sys/fs/cgroup/blkio
 
 - Create two cgroups
-       mkdir -p /cgroup/test1/ /cgroup/test2
+       mkdir -p /sys/fs/cgroup/blkio/test1/ /sys/fs/cgroup/blkio/test2
 
 - Set weights of group test1 and test2
-       echo 1000 > /cgroup/test1/blkio.weight
-       echo 500 > /cgroup/test2/blkio.weight
+       echo 1000 > /sys/fs/cgroup/blkio/test1/blkio.weight
+       echo 500 > /sys/fs/cgroup/blkio/test2/blkio.weight
 
 - Create two same size files (say 512MB each) on same disk (file1, file2) and
   launch two dd threads in different cgroup to read those files.
@@ -46,12 +49,12 @@ cgroups. Here is what you can do.
        echo 3 > /proc/sys/vm/drop_caches
 
        dd if=/mnt/sdb/zerofile1 of=/dev/null &
-       echo $! > /cgroup/test1/tasks
-       cat /cgroup/test1/tasks
+       echo $! > /sys/fs/cgroup/blkio/test1/tasks
+       cat /sys/fs/cgroup/blkio/test1/tasks
 
        dd if=/mnt/sdb/zerofile2 of=/dev/null &
-       echo $! > /cgroup/test2/tasks
-       cat /cgroup/test2/tasks
+       echo $! > /sys/fs/cgroup/blkio/test2/tasks
+       cat /sys/fs/cgroup/blkio/test2/tasks
 
 - At macro level, first dd should finish first. To get more precise data, keep
   on looking at (with the help of script), at blkio.disk_time and
@@ -68,13 +71,13 @@ Throttling/Upper Limit policy
 - Enable throttling in block layer
        CONFIG_BLK_DEV_THROTTLING=y
 
-- Mount blkio controller
-        mount -t cgroup -o blkio none /cgroup/blkio
+- Mount blkio controller (see cgroups.txt, Why are cgroups needed?)
+        mount -t cgroup -o blkio none /sys/fs/cgroup/blkio
 
 - Specify a bandwidth rate on particular device for root group. The format
   for policy is "<major>:<minor>  <byes_per_second>".
 
-        echo "8:16  1048576" > /cgroup/blkio/blkio.read_bps_device
+        echo "8:16  1048576" > /sys/fs/cgroup/blkio/blkio.read_bps_device
 
   Above will put a limit of 1MB/second on reads happening for root group
   on device having major/minor number 8:16.
@@ -108,7 +111,7 @@ Hierarchical Cgroups
   CFQ and throttling will practically treat all groups at same level.
 
                                pivot
-                            /  |   \  \
+                            /  /   \  \
                        root  test1 test2  test3
 
   Down the line we can implement hierarchical accounting/control support
@@ -149,7 +152,7 @@ Proportional weight policy files
 
          Following is the format.
 
-         #echo dev_maj:dev_minor weight > /path/to/cgroup/blkio.weight_device
+         # echo dev_maj:dev_minor weight > blkio.weight_device
          Configure weight=300 on /dev/sdb (8:16) in this cgroup
          # echo 8:16 300 > blkio.weight_device
          # cat blkio.weight_device
index 0ed99f08f1f39256bd71067059627ddc9a0203ac..cd67e90003c0e547952de41086f01d59ecb9a493 100644 (file)
@@ -138,11 +138,11 @@ With the ability to classify tasks differently for different resources
 the admin can easily set up a script which receives exec notifications
 and depending on who is launching the browser he can
 
-       # echo browser_pid > /mnt/<restype>/<userclass>/tasks
+    # echo browser_pid > /sys/fs/cgroup/<restype>/<userclass>/tasks
 
 With only a single hierarchy, he now would potentially have to create
 a separate cgroup for every browser launched and associate it with
-approp network and other resource class.  This may lead to
+appropriate network and other resource class.  This may lead to
 proliferation of such cgroups.
 
 Also lets say that the administrator would like to give enhanced network
@@ -153,9 +153,9 @@ apps enhanced CPU power,
 With ability to write pids directly to resource classes, it's just a
 matter of :
 
-       # echo pid > /mnt/network/<new_class>/tasks
+       # echo pid > /sys/fs/cgroup/network/<new_class>/tasks
        (after some time)
-       # echo pid > /mnt/network/<orig_class>/tasks
+       # echo pid > /sys/fs/cgroup/network/<orig_class>/tasks
 
 Without this ability, he would have to split the cgroup into
 multiple separate ones and then associate the new cgroups with the
@@ -310,21 +310,24 @@ subsystem, this is the case for the cpuset.
 To start a new job that is to be contained within a cgroup, using
 the "cpuset" cgroup subsystem, the steps are something like:
 
- 1) mkdir /dev/cgroup
- 2) mount -t cgroup -ocpuset cpuset /dev/cgroup
- 3) Create the new cgroup by doing mkdir's and write's (or echo's) in
-    the /dev/cgroup virtual file system.
- 4) Start a task that will be the "founding father" of the new job.
- 5) Attach that task to the new cgroup by writing its pid to the
-    /dev/cgroup tasks file for that cgroup.
- 6) fork, exec or clone the job tasks from this founding father task.
+ 1) mount -t tmpfs cgroup_root /sys/fs/cgroup
+ 2) mkdir /sys/fs/cgroup/cpuset
+ 3) mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
+ 4) Create the new cgroup by doing mkdir's and write's (or echo's) in
+    the /sys/fs/cgroup virtual file system.
+ 5) Start a task that will be the "founding father" of the new job.
+ 6) Attach that task to the new cgroup by writing its pid to the
+    /sys/fs/cgroup/cpuset/tasks file for that cgroup.
+ 7) fork, exec or clone the job tasks from this founding father task.
 
 For example, the following sequence of commands will setup a cgroup
 named "Charlie", containing just CPUs 2 and 3, and Memory Node 1,
 and then start a subshell 'sh' in that cgroup:
 
-  mount -t cgroup cpuset -ocpuset /dev/cgroup
-  cd /dev/cgroup
+  mount -t tmpfs cgroup_root /sys/fs/cgroup
+  mkdir /sys/fs/cgroup/cpuset
+  mount -t cgroup cpuset -ocpuset /sys/fs/cgroup/cpuset
+  cd /sys/fs/cgroup/cpuset
   mkdir Charlie
   cd Charlie
   /bin/echo 2-3 > cpuset.cpus
@@ -345,7 +348,7 @@ Creating, modifying, using the cgroups can be done through the cgroup
 virtual filesystem.
 
 To mount a cgroup hierarchy with all available subsystems, type:
-# mount -t cgroup xxx /dev/cgroup
+# mount -t cgroup xxx /sys/fs/cgroup
 
 The "xxx" is not interpreted by the cgroup code, but will appear in
 /proc/mounts so may be any useful identifying string that you like.
@@ -354,23 +357,32 @@ Note: Some subsystems do not work without some user input first.  For instance,
 if cpusets are enabled the user will have to populate the cpus and mems files
 for each new cgroup created before that group can be used.
 
+As explained in section `1.2 Why are cgroups needed?' you should create
+different hierarchies of cgroups for each single resource or group of
+resources you want to control. Therefore, you should mount a tmpfs on
+/sys/fs/cgroup and create directories for each cgroup resource or resource
+group.
+
+# mount -t tmpfs cgroup_root /sys/fs/cgroup
+# mkdir /sys/fs/cgroup/rg1
+
 To mount a cgroup hierarchy with just the cpuset and memory
 subsystems, type:
-# mount -t cgroup -o cpuset,memory hier1 /dev/cgroup
+# mount -t cgroup -o cpuset,memory hier1 /sys/fs/cgroup/rg1
 
 To change the set of subsystems bound to a mounted hierarchy, just
 remount with different options:
-# mount -o remount,cpuset,blkio hier1 /dev/cgroup
+# mount -o remount,cpuset,blkio hier1 /sys/fs/cgroup/rg1
 
 Now memory is removed from the hierarchy and blkio is added.
 
 Note this will add blkio to the hierarchy but won't remove memory or
 cpuset, because the new options are appended to the old ones:
-# mount -o remount,blkio /dev/cgroup
+# mount -o remount,blkio /sys/fs/cgroup/rg1
 
 To Specify a hierarchy's release_agent:
 # mount -t cgroup -o cpuset,release_agent="/sbin/cpuset_release_agent" \
-  xxx /dev/cgroup
+  xxx /sys/fs/cgroup/rg1
 
 Note that specifying 'release_agent' more than once will return failure.
 
@@ -379,17 +391,17 @@ when the hierarchy consists of a single (root) cgroup. Supporting
 the ability to arbitrarily bind/unbind subsystems from an existing
 cgroup hierarchy is intended to be implemented in the future.
 
-Then under /dev/cgroup you can find a tree that corresponds to the
-tree of the cgroups in the system. For instance, /dev/cgroup
+Then under /sys/fs/cgroup/rg1 you can find a tree that corresponds to the
+tree of the cgroups in the system. For instance, /sys/fs/cgroup/rg1
 is the cgroup that holds the whole system.
 
 If you want to change the value of release_agent:
-# echo "/sbin/new_release_agent" > /dev/cgroup/release_agent
+# echo "/sbin/new_release_agent" > /sys/fs/cgroup/rg1/release_agent
 
 It can also be changed via remount.
 
-If you want to create a new cgroup under /dev/cgroup:
-# cd /dev/cgroup
+If you want to create a new cgroup under /sys/fs/cgroup/rg1:
+# cd /sys/fs/cgroup/rg1
 # mkdir my_cgroup
 
 Now you want to do something with this cgroup.
index 84e471b612eb98007d1f17c01a6297acc055681e..34197079f1887a6339e4211a9aac81b3b45b9688 100644 (file)
@@ -10,26 +10,25 @@ directly present in its group.
 
 Accounting groups can be created by first mounting the cgroup filesystem.
 
-# mkdir /cgroups
-# mount -t cgroup -ocpuacct none /cgroups
-
-With the above step, the initial or the parent accounting group
-becomes visible at /cgroups. At bootup, this group includes all the
-tasks in the system. /cgroups/tasks lists the tasks in this cgroup.
-/cgroups/cpuacct.usage gives the CPU time (in nanoseconds) obtained by
-this group which is essentially the CPU time obtained by all the tasks
+# mount -t cgroup -ocpuacct none /sys/fs/cgroup
+
+With the above step, the initial or the parent accounting group becomes
+visible at /sys/fs/cgroup. At bootup, this group includes all the tasks in
+the system. /sys/fs/cgroup/tasks lists the tasks in this cgroup.
+/sys/fs/cgroup/cpuacct.usage gives the CPU time (in nanoseconds) obtained
+by this group which is essentially the CPU time obtained by all the tasks
 in the system.
 
-New accounting groups can be created under the parent group /cgroups.
+New accounting groups can be created under the parent group /sys/fs/cgroup.
 
-# cd /cgroups
+# cd /sys/fs/cgroup
 # mkdir g1
 # echo $$ > g1
 
 The above steps create a new group g1 and move the current shell
 process (bash) into it. CPU time consumed by this bash and its children
 can be obtained from g1/cpuacct.usage and the same is accumulated in
-/cgroups/cpuacct.usage also.
+/sys/fs/cgroup/cpuacct.usage also.
 
 cpuacct.stat file lists a few statistics which further divide the
 CPU time obtained by the cgroup into user and system times. Currently
index 98a30829af7a1bb1ce74015ef3fa7170a112af27..5b0d78e55cccc98b34989493e3bd40bda3f6fc41 100644 (file)
@@ -661,21 +661,21 @@ than stress the kernel.
 
 To start a new job that is to be contained within a cpuset, the steps are:
 
- 1) mkdir /dev/cpuset
- 2) mount -t cgroup -ocpuset cpuset /dev/cpuset
+ 1) mkdir /sys/fs/cgroup/cpuset
+ 2) mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
  3) Create the new cpuset by doing mkdir's and write's (or echo's) in
-    the /dev/cpuset virtual file system.
+    the /sys/fs/cgroup/cpuset virtual file system.
  4) Start a task that will be the "founding father" of the new job.
  5) Attach that task to the new cpuset by writing its pid to the
-    /dev/cpuset tasks file for that cpuset.
+    /sys/fs/cgroup/cpuset tasks file for that cpuset.
  6) fork, exec or clone the job tasks from this founding father task.
 
 For example, the following sequence of commands will setup a cpuset
 named "Charlie", containing just CPUs 2 and 3, and Memory Node 1,
 and then start a subshell 'sh' in that cpuset:
 
-  mount -t cgroup -ocpuset cpuset /dev/cpuset
-  cd /dev/cpuset
+  mount -t cgroup -ocpuset cpuset /sys/fs/cgroup/cpuset
+  cd /sys/fs/cgroup/cpuset
   mkdir Charlie
   cd Charlie
   /bin/echo 2-3 > cpuset.cpus
@@ -710,14 +710,14 @@ Creating, modifying, using the cpusets can be done through the cpuset
 virtual filesystem.
 
 To mount it, type:
-# mount -t cgroup -o cpuset cpuset /dev/cpuset
+# mount -t cgroup -o cpuset cpuset /sys/fs/cgroup/cpuset
 
-Then under /dev/cpuset you can find a tree that corresponds to the
-tree of the cpusets in the system. For instance, /dev/cpuset
+Then under /sys/fs/cgroup/cpuset you can find a tree that corresponds to the
+tree of the cpusets in the system. For instance, /sys/fs/cgroup/cpuset
 is the cpuset that holds the whole system.
 
-If you want to create a new cpuset under /dev/cpuset:
-# cd /dev/cpuset
+If you want to create a new cpuset under /sys/fs/cgroup/cpuset:
+# cd /sys/fs/cgroup/cpuset
 # mkdir my_cpuset
 
 Now you want to do something with this cpuset.
@@ -765,12 +765,12 @@ wrapper around the cgroup filesystem.
 
 The command
 
-mount -t cpuset X /dev/cpuset
+mount -t cpuset X /sys/fs/cgroup/cpuset
 
 is equivalent to
 
-mount -t cgroup -ocpuset,noprefix X /dev/cpuset
-echo "/sbin/cpuset_release_agent" > /dev/cpuset/release_agent
+mount -t cgroup -ocpuset,noprefix X /sys/fs/cgroup/cpuset
+echo "/sbin/cpuset_release_agent" > /sys/fs/cgroup/cpuset/release_agent
 
 2.2 Adding/removing cpus
 ------------------------
index 57ca4c89fe5c089aa6d8b9050fa5b2597e4f62b3..16624a7f82224d2f79d2a7aa2999ebe66c063baa 100644 (file)
@@ -22,16 +22,16 @@ removed from the child(ren).
 An entry is added using devices.allow, and removed using
 devices.deny.  For instance
 
-       echo 'c 1:3 mr' > /cgroups/1/devices.allow
+       echo 'c 1:3 mr' > /sys/fs/cgroup/1/devices.allow
 
 allows cgroup 1 to read and mknod the device usually known as
 /dev/null.  Doing
 
-       echo a > /cgroups/1/devices.deny
+       echo a > /sys/fs/cgroup/1/devices.deny
 
 will remove the default 'a *:* rwm' entry. Doing
 
-       echo a > /cgroups/1/devices.allow
+       echo a > /sys/fs/cgroup/1/devices.allow
 
 will add the 'a *:* rwm' entry to the whitelist.
 
index 41f37fea1276839b80cd4c220af27963f52c6a1d..c21d77742a0799424b09466857681ddcc7100f8b 100644 (file)
@@ -59,28 +59,28 @@ is non-freezable.
 
 * Examples of usage :
 
-   # mkdir /containers
-   # mount -t cgroup -ofreezer freezer  /containers
-   # mkdir /containers/0
-   # echo $some_pid > /containers/0/tasks
+   # mkdir /sys/fs/cgroup/freezer
+   # mount -t cgroup -ofreezer freezer /sys/fs/cgroup/freezer
+   # mkdir /sys/fs/cgroup/freezer/0
+   # echo $some_pid > /sys/fs/cgroup/freezer/0/tasks
 
 to get status of the freezer subsystem :
 
-   # cat /containers/0/freezer.state
+   # cat /sys/fs/cgroup/freezer/0/freezer.state
    THAWED
 
 to freeze all tasks in the container :
 
-   # echo FROZEN > /containers/0/freezer.state
-   # cat /containers/0/freezer.state
+   # echo FROZEN > /sys/fs/cgroup/freezer/0/freezer.state
+   # cat /sys/fs/cgroup/freezer/0/freezer.state
    FREEZING
-   # cat /containers/0/freezer.state
+   # cat /sys/fs/cgroup/freezer/0/freezer.state
    FROZEN
 
 to unfreeze all tasks in the container :
 
-   # echo THAWED > /containers/0/freezer.state
-   # cat /containers/0/freezer.state
+   # echo THAWED > /sys/fs/cgroup/freezer/0/freezer.state
+   # cat /sys/fs/cgroup/freezer/0/freezer.state
    THAWED
 
 This is the basic mechanism which should do the right thing for user space task
index 7c163477fcd8f001fb217cc66e4c67812af907a7..06eb6d957c83097b85fd15e87e94b8ed7edfe1cf 100644 (file)
@@ -1,8 +1,8 @@
 Memory Resource Controller
 
-NOTE: The Memory Resource Controller has been generically been referred
-      to as the memory controller in this document. Do not confuse memory
-      controller used here with the memory controller that is used in hardware.
+NOTE: The Memory Resource Controller has generically been referred to as the
+      memory controller in this document. Do not confuse memory controller
+      used here with the memory controller that is used in hardware.
 
 (For editors)
 In this document:
@@ -70,6 +70,7 @@ Brief summary of control files.
                                 (See sysctl's vm.swappiness)
  memory.move_charge_at_immigrate # set/show controls of moving charges
  memory.oom_control             # set/show oom controls.
+ memory.numa_stat               # show the number of memory usage per numa node
 
 1. History
 
@@ -181,7 +182,7 @@ behind this approach is that a cgroup that aggressively uses a shared
 page will eventually get charged for it (once it is uncharged from
 the cgroup that brought it in -- this will happen on memory pressure).
 
-Exception: If CONFIG_CGROUP_CGROUP_MEM_RES_CTLR_SWAP is not used..
+Exception: If CONFIG_CGROUP_CGROUP_MEM_RES_CTLR_SWAP is not used.
 When you do swapoff and make swapped-out pages of shmem(tmpfs) to
 be backed into memory in force, charges for pages are accounted against the
 caller of swapoff rather than the users of shmem.
@@ -213,7 +214,7 @@ affecting global LRU, memory+swap limit is better than just limiting swap from
 OS point of view.
 
 * What happens when a cgroup hits memory.memsw.limit_in_bytes
-When a cgroup his memory.memsw.limit_in_bytes, it's useless to do swap-out
+When a cgroup hits memory.memsw.limit_in_bytes, it's useless to do swap-out
 in this cgroup. Then, swap-out will not be done by cgroup routine and file
 caches are dropped. But as mentioned above, global LRU can do swapout memory
 from it for sanity of the system's memory management state. You can't forbid
@@ -263,16 +264,17 @@ b. Enable CONFIG_RESOURCE_COUNTERS
 c. Enable CONFIG_CGROUP_MEM_RES_CTLR
 d. Enable CONFIG_CGROUP_MEM_RES_CTLR_SWAP (to use swap extension)
 
-1. Prepare the cgroups
-# mkdir -p /cgroups
-# mount -t cgroup none /cgroups -o memory
+1. Prepare the cgroups (see cgroups.txt, Why are cgroups needed?)
+# mount -t tmpfs none /sys/fs/cgroup
+# mkdir /sys/fs/cgroup/memory
+# mount -t cgroup none /sys/fs/cgroup/memory -o memory
 
 2. Make the new group and move bash into it
-# mkdir /cgroups/0
-# echo $$ > /cgroups/0/tasks
+# mkdir /sys/fs/cgroup/memory/0
+# echo $$ > /sys/fs/cgroup/memory/0/tasks
 
 Since now we're in the 0 cgroup, we can alter the memory limit:
-# echo 4M > /cgroups/0/memory.limit_in_bytes
+# echo 4M > /sys/fs/cgroup/memory/0/memory.limit_in_bytes
 
 NOTE: We can use a suffix (k, K, m, M, g or G) to indicate values in kilo,
 mega or gigabytes. (Here, Kilo, Mega, Giga are Kibibytes, Mebibytes, Gibibytes.)
@@ -280,11 +282,11 @@ mega or gigabytes. (Here, Kilo, Mega, Giga are Kibibytes, Mebibytes, Gibibytes.)
 NOTE: We can write "-1" to reset the *.limit_in_bytes(unlimited).
 NOTE: We cannot set limits on the root cgroup any more.
 
-# cat /cgroups/0/memory.limit_in_bytes
+# cat /sys/fs/cgroup/memory/0/memory.limit_in_bytes
 4194304
 
 We can check the usage:
-# cat /cgroups/0/memory.usage_in_bytes
+# cat /sys/fs/cgroup/memory/0/memory.usage_in_bytes
 1216512
 
 A successful write to this file does not guarantee a successful set of
@@ -464,6 +466,24 @@ value for efficient access. (Of course, when necessary, it's synchronized.)
 If you want to know more exact memory usage, you should use RSS+CACHE(+SWAP)
 value in memory.stat(see 5.2).
 
+5.6 numa_stat
+
+This is similar to numa_maps but operates on a per-memcg basis.  This is
+useful for providing visibility into the numa locality information within
+an memcg since the pages are allowed to be allocated from any physical
+node.  One of the usecases is evaluating application performance by
+combining this information with the application's cpu allocation.
+
+We export "total", "file", "anon" and "unevictable" pages per-node for
+each memcg.  The ouput format of memory.numa_stat is:
+
+total=<total pages> N0=<node 0 pages> N1=<node 1 pages> ...
+file=<total file pages> N0=<node 0 pages> N1=<node 1 pages> ...
+anon=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
+unevictable=<total anon pages> N0=<node 0 pages> N1=<node 1 pages> ...
+
+And we have total = file + anon + unevictable.
+
 6. Hierarchy support
 
 The memory controller supports a deep hierarchy and hierarchical accounting.
@@ -471,13 +491,13 @@ The hierarchy is created by creating the appropriate cgroups in the
 cgroup filesystem. Consider for example, the following cgroup filesystem
 hierarchy
 
-               root
+              root
             /  |   \
-             |    \
-         a     b       c
-                       | \
-                       |  \
-                       d   e
+            /  |    \
+          a    b     c
+                     | \
+                     |  \
+                     d   e
 
 In the diagram above, with hierarchical accounting enabled, all memory
 usage of e, is accounted to its ancestors up until the root (i.e, c and root),
index 1a9446b59153d8e4dd9f2bc787714a8179eb5bb4..72e238465b0b6ca452ee4905dc097007b9ff3dc0 100644 (file)
@@ -481,23 +481,6 @@ Who:       FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
 
 ----------------------------
 
-What:   namespace cgroup (ns_cgroup)
-When:   2.6.38
-Why:    The ns_cgroup leads to some problems:
-       * cgroup creation is out-of-control
-       * cgroup name can conflict when pids are looping
-       * it is not possible to have a single process handling
-       a lot of namespaces without falling in a exponential creation time
-       * we may want to create a namespace without creating a cgroup
-
-       The ns_cgroup is replaced by a compatibility flag 'clone_children',
-       where a newly created cgroup will copy the parent cgroup values.
-       The userspace has to manually create a cgroup and add a task to
-       the 'tasks' file.
-Who:    Daniel Lezcano <daniel.lezcano@free.fr>
-
-----------------------------
-
 What:  iwlwifi disable_hw_scan module parameters
 When:  2.6.40
 Why:   Hareware scan is the prefer method for iwlwifi devices for
index f48178024067fd48fc3454806bdaa366c64dd966..db3b1aba32a3f9c0d80ce0cde2d8b6f1943f4dea 100644 (file)
@@ -843,6 +843,7 @@ Provides counts of softirq handlers serviced since boot time, for each cpu.
  TASKLET:          0          0          0        290
    SCHED:      27035      26983      26971      26746
  HRTIMER:          0          0          0          0
+     RCU:       1678       1769       2178       2250
 
 
 1.3 IDE devices in /proc/ide
index 090e6ee04536285398a81257e1f9a1f9d34e398d..51063e681ca4f8cc0b628d2a46503ad1762aeaf5 100644 (file)
@@ -11,7 +11,9 @@ with the difference that the orphan objects are not freed but only
 reported via /sys/kernel/debug/kmemleak. A similar method is used by the
 Valgrind tool (memcheck --leak-check) to detect the memory leaks in
 user-space applications.
-Kmemleak is supported on x86, arm, powerpc, sparc, sh, microblaze and tile.
+
+Please check DEBUG_KMEMLEAK dependencies in lib/Kconfig.debug for supported
+architectures.
 
 Usage
 -----
index 2366b1c8cf19492f52480669449ecd2b0a0d0f34..f0eee83ff78a61801e7d0cf293a2090180f208e8 100644 (file)
@@ -555,7 +555,7 @@ also have
    sync_min
    sync_max
      The two values, given as numbers of sectors, indicate a range
-     withing the array where 'check'/'repair' will operate. Must be
+     within the array where 'check'/'repair' will operate. Must be
      a multiple of chunk_size. When it reaches "sync_max" it will
      pause, rather than complete.
      You can use 'select' or 'poll' on "sync_completed" to wait for
index 88880839ece4e84f8101b4cfd50e3e22b8024515..64565aac6e4009b1bca8f963cf03f900e319d538 100644 (file)
@@ -520,59 +520,20 @@ Support for power domains is provided through the pwr_domain field of struct
 device.  This field is a pointer to an object of type struct dev_power_domain,
 defined in include/linux/pm.h, providing a set of power management callbacks
 analogous to the subsystem-level and device driver callbacks that are executed
-for the given device during all power transitions, in addition to the respective
-subsystem-level callbacks.  Specifically, the power domain "suspend" callbacks
-(i.e. ->runtime_suspend(), ->suspend(), ->freeze(), ->poweroff(), etc.) are
-executed after the analogous subsystem-level callbacks, while the power domain
-"resume" callbacks (i.e. ->runtime_resume(), ->resume(), ->thaw(), ->restore,
-etc.) are executed before the analogous subsystem-level callbacks.  Error codes
-returned by the "suspend" and "resume" power domain callbacks are ignored.
-
-Power domain ->runtime_idle() callback is executed before the subsystem-level
-->runtime_idle() callback and the result returned by it is not ignored.  Namely,
-if it returns error code, the subsystem-level ->runtime_idle() callback will not
-be called and the helper function rpm_idle() executing it will return error
-code.  This mechanism is intended to help platforms where saving device state
-is a time consuming operation and should only be carried out if all devices
-in the power domain are idle, before turning off the shared power resource(s).
-Namely, the power domain ->runtime_idle() callback may return error code until
-the pm_runtime_idle() helper (or its asychronous version) has been called for
-all devices in the power domain (it is recommended that the returned error code
-be -EBUSY in those cases), preventing the subsystem-level ->runtime_idle()
-callback from being run prematurely.
-
-The support for device power domains is only relevant to platforms needing to
-use the same subsystem-level (e.g. platform bus type) and device driver power
-management callbacks in many different power domain configurations and wanting
-to avoid incorporating the support for power domains into the subsystem-level
-callbacks.  The other platforms need not implement it or take it into account
-in any way.
-
-
-System Devices
---------------
-System devices (sysdevs) follow a slightly different API, which can be found in
-
-       include/linux/sysdev.h
-       drivers/base/sys.c
-
-System devices will be suspended with interrupts disabled, and after all other
-devices have been suspended.  On resume, they will be resumed before any other
-devices, and also with interrupts disabled.  These things occur in special
-"sysdev_driver" phases, which affect only system devices.
-
-Thus, after the suspend_noirq (or freeze_noirq or poweroff_noirq) phase, when
-the non-boot CPUs are all offline and IRQs are disabled on the remaining online
-CPU, then a sysdev_driver.suspend phase is carried out, and the system enters a
-sleep state (or a system image is created).  During resume (or after the image
-has been created or loaded) a sysdev_driver.resume phase is carried out, IRQs
-are enabled on the only online CPU, the non-boot CPUs are enabled, and the
-resume_noirq (or thaw_noirq or restore_noirq) phase begins.
-
-Code to actually enter and exit the system-wide low power state sometimes
-involves hardware details that are only known to the boot firmware, and
-may leave a CPU running software (from SRAM or flash memory) that monitors
-the system and manages its wakeup sequence.
+for the given device during all power transitions, instead of the respective
+subsystem-level callbacks.  Specifically, if a device's pm_domain pointer is
+not NULL, the ->suspend() callback from the object pointed to by it will be
+executed instead of its subsystem's (e.g. bus type's) ->suspend() callback and
+anlogously for all of the remaining callbacks.  In other words, power management
+domain callbacks, if defined for the given device, always take precedence over
+the callbacks provided by the device's subsystem (e.g. bus type).
+
+The support for device power management domains is only relevant to platforms
+needing to use the same device driver power management callbacks in many
+different power domain configurations and wanting to avoid incorporating the
+support for power domains into subsystem-level callbacks, for example by
+modifying the platform bus type.  Other platforms need not implement it or take
+it into account in any way.
 
 
 Device Low Power (suspend) States
index 654097b130b46175c4c5165ded5f535718266cc7..22accb3eb40e293c777d6898cb63cb2ce9f5bd91 100644 (file)
@@ -566,11 +566,6 @@ to do this is:
        pm_runtime_set_active(dev);
        pm_runtime_enable(dev);
 
-The PM core always increments the run-time usage counter before calling the
-->prepare() callback and decrements it after calling the ->complete() callback.
-Hence disabling run-time PM temporarily like this will not cause any run-time
-suspend callbacks to be lost.
-
 7. Generic subsystem callbacks
 
 Subsystems may wish to conserve code space by using the set of generic power
index 1b5a5ddbc3ef9a5211f3e7eeb487e524ac6ac0ac..5df176ed59b826e8cbeaca7c96d6ed6d06759fa8 100644 (file)
@@ -9,7 +9,121 @@ If variable is of Type,               use printk format specifier:
                size_t                  %zu or %zx
                ssize_t                 %zd or %zx
 
-Raw pointer value SHOULD be printed with %p.
+Raw pointer value SHOULD be printed with %p. The kernel supports
+the following extended format specifiers for pointer types:
+
+Symbols/Function Pointers:
+
+       %pF     versatile_init+0x0/0x110
+       %pf     versatile_init
+       %pS     versatile_init+0x0/0x110
+       %ps     versatile_init
+       %pB     prev_fn_of_versatile_init+0x88/0x88
+
+       For printing symbols and function pointers. The 'S' and 's' specifiers
+       result in the symbol name with ('S') or without ('s') offsets. Where
+       this is used on a kernel without KALLSYMS - the symbol address is
+       printed instead.
+
+       The 'B' specifier results in the symbol name with offsets and should be
+       used when printing stack backtraces. The specifier takes into
+       consideration the effect of compiler optimisations which may occur
+       when tail-call's are used and marked with the noreturn GCC attribute.
+
+       On ia64, ppc64 and parisc64 architectures function pointers are
+       actually function descriptors which must first be resolved. The 'F' and
+       'f' specifiers perform this resolution and then provide the same
+       functionality as the 'S' and 's' specifiers.
+
+Kernel Pointers:
+
+       %pK     0x01234567 or 0x0123456789abcdef
+
+       For printing kernel pointers which should be hidden from unprivileged
+       users. The behaviour of %pK depends on the kptr_restrict sysctl - see
+       Documentation/sysctl/kernel.txt for more details.
+
+Struct Resources:
+
+       %pr     [mem 0x60000000-0x6fffffff flags 0x2200] or
+               [mem 0x0000000060000000-0x000000006fffffff flags 0x2200]
+       %pR     [mem 0x60000000-0x6fffffff pref] or
+               [mem 0x0000000060000000-0x000000006fffffff pref]
+
+       For printing struct resources. The 'R' and 'r' specifiers result in a
+       printed resource with ('R') or without ('r') a decoded flags member.
+
+MAC/FDDI addresses:
+
+       %pM     00:01:02:03:04:05
+       %pMF    00-01-02-03-04-05
+       %pm     000102030405
+
+       For printing 6-byte MAC/FDDI addresses in hex notation. The 'M' and 'm'
+       specifiers result in a printed address with ('M') or without ('m') byte
+       separators. The default byte separator is the colon (':').
+
+       Where FDDI addresses are concerned the 'F' specifier can be used after
+       the 'M' specifier to use dash ('-') separators instead of the default
+       separator.
+
+IPv4 addresses:
+
+       %pI4    1.2.3.4
+       %pi4    001.002.003.004
+       %p[Ii][hnbl]
+
+       For printing IPv4 dot-separated decimal addresses. The 'I4' and 'i4'
+       specifiers result in a printed address with ('i4') or without ('I4')
+       leading zeros.
+
+       The additional 'h', 'n', 'b', and 'l' specifiers are used to specify
+       host, network, big or little endian order addresses respectively. Where
+       no specifier is provided the default network/big endian order is used.
+
+IPv6 addresses:
+
+       %pI6    0001:0002:0003:0004:0005:0006:0007:0008
+       %pi6    00010002000300040005000600070008
+       %pI6c   1:2:3:4:5:6:7:8
+
+       For printing IPv6 network-order 16-bit hex addresses. The 'I6' and 'i6'
+       specifiers result in a printed address with ('I6') or without ('i6')
+       colon-separators. Leading zeros are always used.
+
+       The additional 'c' specifier can be used with the 'I' specifier to
+       print a compressed IPv6 address as described by
+       http://tools.ietf.org/html/rfc5952
+
+UUID/GUID addresses:
+
+       %pUb    00010203-0405-0607-0809-0a0b0c0d0e0f
+       %pUB    00010203-0405-0607-0809-0A0B0C0D0E0F
+       %pUl    03020100-0504-0706-0809-0a0b0c0e0e0f
+       %pUL    03020100-0504-0706-0809-0A0B0C0E0E0F
+
+       For printing 16-byte UUID/GUIDs addresses. The additional 'l', 'L',
+       'b' and 'B' specifiers are used to specify a little endian order in
+       lower ('l') or upper case ('L') hex characters - and big endian order
+       in lower ('b') or upper case ('B') hex characters.
+
+       Where no additional specifiers are used the default little endian
+       order with lower case hex characters will be printed.
+
+struct va_format:
+
+       %pV
+
+       For printing struct va_format structures. These contain a format string
+       and va_list as follows:
+
+       struct va_format {
+               const char *fmt;
+               va_list *va;
+       };
+
+       Do not use this feature without some mechanism to verify the
+       correctness of the format string and va_list arguments.
 
 u64 SHOULD be printed with %llu/%llx, (unsigned long long):
 
@@ -32,4 +146,5 @@ Reminder: sizeof() result is of type size_t.
 Thank you for your cooperation and attention.
 
 
-By Randy Dunlap <rdunlap@xenotime.net>
+By Randy Dunlap <rdunlap@xenotime.net> and
+Andrew Murray <amurray@mpc-data.co.uk>
index 99961993257a9f9cf358ca9641577e4b5b1699ff..91ecff07cede7dfbb4710273bd9824030a805258 100644 (file)
@@ -223,9 +223,10 @@ When CONFIG_FAIR_GROUP_SCHED is defined, a "cpu.shares" file is created for each
 group created using the pseudo filesystem.  See example steps below to create
 task groups and modify their CPU share using the "cgroups" pseudo filesystem.
 
-       # mkdir /dev/cpuctl
-       # mount -t cgroup -ocpu none /dev/cpuctl
-       # cd /dev/cpuctl
+       # mount -t tmpfs cgroup_root /sys/fs/cgroup
+       # mkdir /sys/fs/cgroup/cpu
+       # mount -t cgroup -ocpu none /sys/fs/cgroup/cpu
+       # cd /sys/fs/cgroup/cpu
 
        # mkdir multimedia      # create "multimedia" group of tasks
        # mkdir browser         # create "browser" group of tasks
index 605b0d40329d843f6c3b838cd4afa5e38438d31e..71b54d54998731ebcfe2c451c15066620b384aaa 100644 (file)
@@ -129,9 +129,8 @@ priority!
 Enabling CONFIG_RT_GROUP_SCHED lets you explicitly allocate real
 CPU bandwidth to task groups.
 
-This uses the /cgroup virtual file system and
-"/cgroup/<cgroup>/cpu.rt_runtime_us" to control the CPU time reserved for each
-control group.
+This uses the cgroup virtual file system and "<cgroup>/cpu.rt_runtime_us"
+to control the CPU time reserved for each control group.
 
 For more information on working with control groups, you should read
 Documentation/cgroups/cgroups.txt as well.
@@ -150,7 +149,7 @@ For now, this can be simplified to just the following (but see Future plans):
 ===============
 
 There is work in progress to make the scheduling period for each group
-("/cgroup/<cgroup>/cpu.rt_period_us") configurable as well.
+("<cgroup>/cpu.rt_period_us") configurable as well.
 
 The constraint on the period is that a subgroup must have a smaller or
 equal period to its parent. But realistically its not very useful _yet_
index 12f9ba20ccb7aebd72aab882f9b6d6d7d9b4a135..550068466605b99e8beecca7a1b4a03788f2829a 100644 (file)
@@ -129,12 +129,12 @@ Limit injection to pages owned by memgroup. Specified by inode number
 of the memcg.
 
 Example:
-        mkdir /cgroup/hwpoison
+        mkdir /sys/fs/cgroup/mem/hwpoison
 
         usemem -m 100 -s 1000 &
-        echo `jobs -p` > /cgroup/hwpoison/tasks
+        echo `jobs -p` > /sys/fs/cgroup/mem/hwpoison/tasks
 
-        memcg_ino=$(ls -id /cgroup/hwpoison | cut -f1 -d' ')
+        memcg_ino=$(ls -id /sys/fs/cgroup/mem/hwpoison | cut -f1 -d' ')
         echo $memcg_ino > /debug/hwpoison/corrupt-filter-memcg
 
         page-types -p `pidof init`   --hwpoison  # shall do nothing
index e50fc6eb99e0ef8279abe24bf4a67027f0692033..f0358cd91de3543a5418f536b1ec17a22a97cb2b 100644 (file)
@@ -1889,7 +1889,6 @@ L:        cpufreq@vger.kernel.org
 W:     http://www.codemonkey.org.uk/projects/cpufreq/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davej/cpufreq.git
 S:     Maintained
-F:     arch/x86/kernel/cpu/cpufreq/
 F:     drivers/cpufreq/
 F:     include/linux/cpufreq.h
 
@@ -2292,8 +2291,7 @@ F:        drivers/scsi/eata_pio.*
 
 EBTABLES
 M:     Bart De Schuymer <bart.de.schuymer@pandora.be>
-L:     ebtables-user@lists.sourceforge.net
-L:     ebtables-devel@lists.sourceforge.net
+L:     netfilter-devel@vger.kernel.org
 W:     http://ebtables.sourceforge.net/
 S:     Maintained
 F:     include/linux/netfilter_bridge/ebt_*.h
@@ -3820,6 +3818,12 @@ S:       Maintained
 F:     drivers/leds/
 F:     include/linux/leds.h
 
+LEGACY EEPROM DRIVER
+M:     Jean Delvare <khali@linux-fr.org>
+S:     Maintained
+F:     Documentation/misc-devices/eeprom
+F:     drivers/misc/eeprom/eeprom.c
+
 LEGO USB Tower driver
 M:     Juergen Stuber <starblue@users.sourceforge.net>
 L:     legousb-devel@lists.sourceforge.net
@@ -4145,7 +4149,7 @@ F:        include/linux/mm.h
 F:     mm/
 
 MEMORY RESOURCE CONTROLLER
-M:     Balbir Singh <balbir@linux.vnet.ibm.com>
+M:     Balbir Singh <bsingharora@gmail.com>
 M:     Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
 M:     KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
 L:     linux-mm@kvack.org
@@ -4890,7 +4894,7 @@ F:        mm/percpu*.c
 F:     arch/*/include/asm/percpu.h
 
 PER-TASK DELAY ACCOUNTING
-M:     Balbir Singh <balbir@linux.vnet.ibm.com>
+M:     Balbir Singh <bsingharora@gmail.com>
 S:     Maintained
 F:     include/linux/delayacct.h
 F:     kernel/delayacct.c
@@ -6098,7 +6102,7 @@ F:        include/target/
 F:     Documentation/target/
 
 TASKSTATS STATISTICS INTERFACE
-M:     Balbir Singh <balbir@linux.vnet.ibm.com>
+M:     Balbir Singh <bsingharora@gmail.com>
 S:     Maintained
 F:     Documentation/accounting/taskstats*
 F:     include/linux/taskstats*
@@ -6458,7 +6462,7 @@ M:        Jiri Kosina <jkosina@suse.cz>
 L:     linux-usb@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid.git
 S:     Maintained
-F:     Documentation/usb/hiddev.txt
+F:     Documentation/hid/hiddev.txt
 F:     drivers/hid/usbhid/
 
 USB ISP116X DRIVER
@@ -6717,6 +6721,14 @@ S:       Maintained
 F:     Documentation/filesystems/vfat.txt
 F:     fs/fat/
 
+VIDEOBUF2 FRAMEWORK
+M:     Pawel Osciak <pawel@osciak.com>
+M:     Marek Szyprowski <m.szyprowski@samsung.com>
+L:     linux-media@vger.kernel.org
+S:     Maintained
+F:     drivers/media/video/videobuf2-*
+F:     include/media/videobuf2-*
+
 VIRTIO CONSOLE DRIVER
 M:     Amit Shah <amit.shah@redhat.com>
 L:     virtualization@lists.linux-foundation.org
@@ -6994,6 +7006,13 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.
 S:     Maintained
 F:     drivers/platform/x86
 
+X86 MCE INFRASTRUCTURE
+M:     Tony Luck <tony.luck@intel.com>
+M:     Borislav Petkov <bp@amd64.org>
+L:     linux-edac@vger.kernel.org
+S:     Maintained
+F:     arch/x86/kernel/cpu/mcheck/*
+
 XEN HYPERVISOR INTERFACE
 M:     Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
 M:     Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
index badb9239e2bb4ab64a8d016bfebe80319aa08d08..dc670467fb8c697703bea67a58528cc5adc04efe 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 0
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
+EXTRAVERSION = -rc5
 NAME = Sneaky Weasel
 
 # *DOCUMENTATION*
@@ -1526,7 +1526,8 @@ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN   $(wildcard $(rm-files))
 
 # Run depmod only if we have System.map and depmod is executable
 quiet_cmd_depmod = DEPMOD  $(KERNELRELEASE)
-      cmd_depmod = $(srctree)/scripts/depmod.sh $(DEPMOD) $(KERNELRELEASE)
+      cmd_depmod = $(CONFIG_SHELL) $(srctree)/scripts/depmod.sh $(DEPMOD) \
+                   $(KERNELRELEASE)
 
 # Create temporary dir for module support files
 # clean it up only when building all modules
index 8af56ce346add9d2bebd26641f30656141464a03..445dc42e033495be2ac6b1ae37fe3a8221c483e8 100644 (file)
@@ -56,7 +56,6 @@ PLAT_NODE_DATA_LOCALNR(unsigned long p, int n)
  * Given a kernel address, find the home node of the underlying memory.
  */
 #define kvaddr_to_nid(kaddr)   pa_to_nid(__pa(kaddr))
-#define node_start_pfn(nid)    (NODE_DATA(nid)->node_start_pfn)
 
 /*
  * Given a kaddr, LOCAL_BASE_ADDR finds the owning node of the memory
index 376f2213079190f65196b0e3f6554f0f55834183..326f0a2d56e52922920aad724dfec0e78487986a 100644 (file)
@@ -409,7 +409,7 @@ SYSCALL_DEFINE2(osf_getdomainname, char __user *, name, int, namelen)
                return -EFAULT;
 
        len = namelen;
-       if (namelen > 32)
+       if (len > 32)
                len = 32;
 
        down_read(&uts_sem);
@@ -594,7 +594,7 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count)
        down_read(&uts_sem);
        res = sysinfo_table[offset];
        len = strlen(res)+1;
-       if (len > count)
+       if ((unsigned long)len > (unsigned long)count)
                len = count;
        if (copy_to_user(buf, res, len))
                err = -EFAULT;
@@ -649,7 +649,7 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer,
                return 1;
 
        case GSI_GET_HWRPB:
-               if (nbytes < sizeof(*hwrpb))
+               if (nbytes > sizeof(*hwrpb))
                        return -EINVAL;
                if (copy_to_user(buffer, hwrpb, nbytes) != 0)
                        return -EFAULT;
@@ -1008,6 +1008,7 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options,
 {
        struct rusage r;
        long ret, err;
+       unsigned int status = 0;
        mm_segment_t old_fs;
 
        if (!ur)
@@ -1016,13 +1017,15 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options,
        old_fs = get_fs();
                
        set_fs (KERNEL_DS);
-       ret = sys_wait4(pid, ustatus, options, (struct rusage __user *) &r);
+       ret = sys_wait4(pid, (unsigned int __user *) &status, options,
+                       (struct rusage __user *) &r);
        set_fs (old_fs);
 
        if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
                return -EFAULT;
 
        err = 0;
+       err |= put_user(status, ustatus);
        err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec);
        err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec);
        err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec);
index d7bfd2ee75e017b341550eb18402f98e1e2dcc7d..e58603b00060032c625bcc4ce11613ca96344732 100644 (file)
@@ -597,6 +597,8 @@ __common_mmu_cache_on:
                sub     pc, lr, r0, lsr #32     @ properly flush pipeline
 #endif
 
+#define PROC_ENTRY_SIZE (4*5)
+
 /*
  * Here follow the relocatable cache support functions for the
  * various processors.  This is a generic hook for locating an
@@ -624,7 +626,7 @@ call_cache_fn:      adr     r12, proc_types
  ARM(          addeq   pc, r12, r3             ) @ call cache function
  THUMB(                addeq   r12, r3                 )
  THUMB(                moveq   pc, r12                 ) @ call cache function
-               add     r12, r12, #4*5
+               add     r12, r12, #PROC_ENTRY_SIZE
                b       1b
 
 /*
@@ -694,9 +696,9 @@ proc_types:
 
                .word   0x41069260              @ ARM926EJ-S (v5TEJ)
                .word   0xff0ffff0
-               b       __arm926ejs_mmu_cache_on
-               b       __armv4_mmu_cache_off
-               b       __armv5tej_mmu_cache_flush
+               W(b)    __arm926ejs_mmu_cache_on
+               W(b)    __armv4_mmu_cache_off
+               W(b)    __armv5tej_mmu_cache_flush
 
                .word   0x00007000              @ ARM7 IDs
                .word   0x0000f000
@@ -797,6 +799,16 @@ proc_types:
 
                .size   proc_types, . - proc_types
 
+               /*
+                * If you get a "non-constant expression in ".if" statement"
+                * error from the assembler on this line, check that you have
+                * not accidentally written a "b" instruction where you should
+                * have written W(b).
+                */
+               .if (. - proc_types) % PROC_ENTRY_SIZE != 0
+               .error "The size of one or more proc_types entries is wrong."
+               .endif
+
 /*
  * Turn off the Cache and MMU.  ARMv3 does not support
  * reading the control register, but ARMv4 does.
index 889922ad229c31e8419c7f211cb5ef481e4d612a..67b5abb6f8576e3fa47d248ecea51facf7f7b5dc 100644 (file)
@@ -157,7 +157,7 @@ CONFIG_LEDS_GPIO=m
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=m
 CONFIG_LEDS_TRIGGER_HEARTBEAT=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_XFS_FS=m
index 316af5479d90b0cec88b479d70f5991155d5497e..9c0ad7993986f340952c2a74352e3d24e75c1a01 100644 (file)
@@ -60,7 +60,7 @@ CONFIG_FB_ARMCLCD=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_INOTIFY=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
index 8b0c717378faa6c9596b9c4b22a4d9dea1b9da65..1d01ddd33122d76fa7db12e989ed0ac09e2293d7 100644 (file)
@@ -142,7 +142,7 @@ CONFIG_USB_GADGETFS=m
 CONFIG_USB_FILE_STORAGE=m
 CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=m
 CONFIG_RTC_DRV_SA1100=m
 CONFIG_EXT2_FS=m
index 5b5504143647fe23fafb93e0a7df67b9b5b7f8c3..721832ffe2d728476ff5395333d23795efcfba8a 100644 (file)
@@ -73,7 +73,7 @@ CONFIG_SENSORS_MAX6650=m
 # CONFIG_VGA_CONSOLE is not set
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_SA1100=m
 CONFIG_DMADEVICES=y
 # CONFIG_DNOTIFY is not set
index 960f65514d88161389798236bb26ecd4c704b0cd..59577ad3f4efdfda65e65753054673a32614e80f 100644 (file)
@@ -158,7 +158,7 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=m
 CONFIG_LEDS_TRIGGER_BACKLIGHT=m
 CONFIG_LEDS_TRIGGER_GPIO=m
 CONFIG_LEDS_TRIGGER_DEFAULT_ON=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_ISL1208=m
 CONFIG_RTC_DRV_PXA=m
 CONFIG_EXT2_FS=y
index bc2d2d75f7068998bb69a92b69c1216ec4dbd8fe..65c3f2474f5e3333142952b4dc7a1f445bcaedb4 100644 (file)
@@ -13,6 +13,9 @@
  *  Do not include any C declarations in this file - it is included by
  *  assembler source.
  */
+#ifndef __ASM_ASSEMBLER_H__
+#define __ASM_ASSEMBLER_H__
+
 #ifndef __ASSEMBLY__
 #error "Only include this from assembly code"
 #endif
        .macro  ldrusr, reg, ptr, inc, cond=al, rept=1, abort=9001f
        usracc  ldr, \reg, \ptr, \inc, \cond, \rept, \abort
        .endm
+#endif /* __ASM_ASSEMBLER_H__ */
index ec0bbf79c71fd30d6c523773a4baf6bafffe5c6f..2da8547de6d6203c605759a9326f1b1a8d259d08 100644 (file)
@@ -1,3 +1,5 @@
+#include <asm/assembler.h>
+
 /*
  * Interrupt handling.  Preserves r7, r8, r9
  */
index a701e4226a6c85f804ce13a627de3d6d82127464..0cdd7b456cb2a072ce3902f2a6d7934967b083d7 100644 (file)
@@ -76,6 +76,9 @@ struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
        unsigned long dt_root;
        const char *model;
 
+       if (!dt_phys)
+               return NULL;
+
        devtree = phys_to_virt(dt_phys);
 
        /* check device tree validity */
index 45516a4840e321b57cbfff272ae25264357dc2a3..2cd00764016d78cb48f56954479f663fe1004936 100644 (file)
@@ -435,6 +435,10 @@ __irq_usr:
        usr_entry
        kuser_cmpxchg_check
 
+#ifdef CONFIG_IRQSOFF_TRACER
+       bl      trace_hardirqs_off
+#endif
+
        get_thread_info tsk
 #ifdef CONFIG_PREEMPT
        ldr     r8, [tsk, #TI_PREEMPT]          @ get preempt count
@@ -453,7 +457,7 @@ __irq_usr:
 #endif
 
        mov     why, #0
-       b       ret_to_user
+       b       ret_to_user_from_irq
  UNWIND(.fnend         )
 ENDPROC(__irq_usr)
 
index 1e7b04a40a3164f7226ce82907012acb231fec45..b2a27b6b0046ee6c1e0f0928c3269ab5f6c63cd2 100644 (file)
@@ -64,6 +64,7 @@ work_resched:
 ENTRY(ret_to_user)
 ret_slow_syscall:
        disable_irq                             @ disable interrupts
+ENTRY(ret_to_user_from_irq)
        ldr     r1, [tsk, #TI_FLAGS]
        tst     r1, #_TIF_WORK_MASK
        bne     work_pending
@@ -75,6 +76,7 @@ no_work_pending:
        arch_ret_to_user r1, lr
 
        restore_user_regs fast = 0, offset = 0
+ENDPROC(ret_to_user_from_irq)
 ENDPROC(ret_to_user)
 
 /*
index fee7c36349eb6c137e7c578946968e20caf35910..016d6a0830a3e202bc42df7c40108a0875916d4b 100644 (file)
@@ -193,8 +193,17 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
                                offset -= 0x02000000;
                        offset += sym->st_value - loc;
 
-                       /* only Thumb addresses allowed (no interworking) */
-                       if (!(offset & 1) ||
+                       /*
+                        * For function symbols, only Thumb addresses are
+                        * allowed (no interworking).
+                        *
+                        * For non-function symbols, the destination
+                        * has no specific ARM/Thumb disposition, so
+                        * the branch is resolved under the assumption
+                        * that interworking is not required.
+                        */
+                       if ((ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&
+                               !(offset & 1)) ||
                            offset <= (s32)0xff000000 ||
                            offset >= (s32)0x01000000) {
                                pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n",
index 344e52b16c8cd4234b523547d07a8b6ff9106bd6..e7f92a4321f370d0c9e9f9dc73460a0be65c014a 100644 (file)
@@ -318,9 +318,13 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
        smp_store_cpu_info(cpu);
 
        /*
-        * OK, now it's safe to let the boot CPU continue
+        * OK, now it's safe to let the boot CPU continue.  Wait for
+        * the CPU migration code to notice that the CPU is online
+        * before we continue.
         */
        set_cpu_online(cpu, true);
+       while (!cpu_active(cpu))
+               cpu_relax();
 
        /*
         * OK, it's off to the idle thread for us
index d1a0892ae262f38e7cf1c96a1515ec518872a8c4..56b2715355b119f738ee04d224e457fbcf1f15ee 100644 (file)
@@ -139,7 +139,7 @@ static void dump_instr(const char *lvl, struct pt_regs *regs)
        fs = get_fs();
        set_fs(KERNEL_DS);
 
-       for (i = -4; i < 1; i++) {
+       for (i = -4; i < 1 + !!thumb; i++) {
                unsigned int val, bad;
 
                if (thumb)
@@ -565,7 +565,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
                if (!pmd_present(*pmd))
                        goto bad_access;
                pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
-               if (!pte_present(*pte) || !pte_dirty(*pte)) {
+               if (!pte_present(*pte) || !pte_write(*pte) || !pte_dirty(*pte)) {
                        pte_unmap_unlock(pte, ptl);
                        goto bad_access;
                }
index 4e66881c7aee748dddf82a304fb261dc89edde97..fc4e98ea7543a397e4ece003b3ff9f9d498fd42f 100644 (file)
@@ -494,7 +494,7 @@ static struct platform_device da850_mcasp_device = {
        .resource       = da850_mcasp_resources,
 };
 
-struct platform_device davinci_pcm_device = {
+static struct platform_device davinci_pcm_device = {
        .name   = "davinci-pcm-audio",
        .id     = -1,
 };
index 8f4f736aa267104455fdf2f1502e467e63bd9aad..806a2f02b9808abf870ac9b9b0e1c77d99e60bb4 100644 (file)
@@ -298,7 +298,7 @@ static void davinci_init_wdt(void)
 
 /*-------------------------------------------------------------------------*/
 
-struct platform_device davinci_pcm_device = {
+static struct platform_device davinci_pcm_device = {
        .name           = "davinci-pcm-audio",
        .id             = -1,
 };
index a0b838894ac99b27daaf413fbfbd8f78ae842066..e7221398e5af9c751d1dc8f85c1d294b2afb0f9b 100644 (file)
@@ -252,9 +252,11 @@ static struct irq_chip gpio_irqchip = {
 static void
 gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
-       struct davinci_gpio_regs __iomem *g = irq2regs(irq);
+       struct davinci_gpio_regs __iomem *g;
        u32 mask = 0xffff;
 
+       g = (__force struct davinci_gpio_regs __iomem *) irq_desc_get_handler_data(desc);
+
        /* we only care about one bank */
        if (irq & 1)
                mask <<= 16;
@@ -422,8 +424,7 @@ static int __init davinci_gpio_irq_setup(void)
 
                /* set up all irqs in this bank */
                irq_set_chained_handler(bank_irq, gpio_irq_handler);
-               irq_set_chip_data(bank_irq, (__force void *)g);
-               irq_set_handler_data(bank_irq, (void *)irq);
+               irq_set_handler_data(bank_irq, (__force void *)g);
 
                for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) {
                        irq_set_chip(irq, &gpio_irqchip);
index 5f1f9867fc70eedff4620119fead758eb7c0e2b2..121ad1d4fa39f9a0d4f70c6cbd23021f4e62617f 100644 (file)
@@ -103,6 +103,7 @@ static void __init footbridge_timer_init(void)
        clockevents_calc_mult_shift(ce, mem_fclk_21285, 5);
        ce->max_delta_ns = clockevent_delta2ns(0xffffff, ce);
        ce->min_delta_ns = clockevent_delta2ns(0x000004, ce);
+       ce->cpumask = cpumask_of(smp_processor_id());
 
        clockevents_register_device(ce);
 }
index 30b971d65815f342069719afca2052769ac99ba9..1be2eeb7a0a042198a73ec78a3b33278c25e533b 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/hardware/debug-8250.S>
 
 #else
+#include <mach/hardware.h>
        /* For EBSA285 debugging */
                .equ    dc21285_high, ARMCSR_BASE & 0xff000000
                .equ    dc21285_low,  ARMCSR_BASE & 0x00ffffff
@@ -36,8 +37,8 @@
                .else
                mov     \rp, #0
                .endif
-               orr     \rv, \rp, #0x42000000
-               orr     \rp, \rp, #dc21285_high
+               orr     \rv, \rp, #dc21285_high
+               orr     \rp, \rp, #0x42000000
                .endm
 
                .macro  senduart,rd,rx
index 9b6982efbd22014e59b56e33b7c46bd3c20ccd56..abf356c02343fd144fc305f1c2c7f45af38b3a60 100644 (file)
@@ -6,12 +6,14 @@ config ARCH_H7201
        bool "gms30c7201"
        depends on ARCH_H720X
        select CPU_H7201
+       select ZONE_DMA
        help
          Say Y here if you are using the Hynix GMS30C7201 Reference Board
 
 config ARCH_H7202
        bool "hms30c7202"
        select CPU_H7202
+       select ZONE_DMA
        depends on ARCH_H720X
        help
          Say Y here if you are using the Hynix HMS30C7202 Reference Board
index 38b95e949d13b0a87d83a3274b0369e98c8321ed..63621f152c989c0a2041208cf7ff1ab58bb9ee52 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/io.h>
 
 #include <asm/mach/time.h>
+#include <asm/hardware/gic.h>
+
 #include <mach/msm_iomap.h>
 #include <mach/cpu.h>
 
@@ -55,10 +57,12 @@ enum timer_location {
 #if defined(CONFIG_ARCH_QSD8X50)
 #define DGT_HZ (19200000 / 4) /* 19.2 MHz / 4 by default */
 #define MSM_DGT_SHIFT (0)
-#elif defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60) || \
-                                     defined(CONFIG_ARCH_MSM8960)
+#elif defined(CONFIG_ARCH_MSM7X30)
 #define DGT_HZ (24576000 / 4) /* 24.576 MHz (LPXO) / 4 by default */
 #define MSM_DGT_SHIFT (0)
+#elif defined(CONFIG_ARCH_MSM8X60) || defined(CONFIG_ARCH_MSM8960)
+#define DGT_HZ (27000000 / 4) /* 27 MHz (PXO) / 4 by default */
+#define MSM_DGT_SHIFT (0)
 #else
 #define DGT_HZ 19200000 /* 19.2 MHz or 600 KHz after shift */
 #define MSM_DGT_SHIFT (5)
@@ -100,7 +104,11 @@ static cycle_t msm_read_timer_count(struct clocksource *cs)
 {
        struct msm_clock *clk = container_of(cs, struct msm_clock, clocksource);
 
-       return readl(clk->global_counter);
+       /*
+        * Shift timer count down by a constant due to unreliable lower bits
+        * on some targets.
+        */
+       return readl(clk->global_counter) >> clk->shift;
 }
 
 static struct msm_clock *clockevent_to_clock(struct clock_event_device *evt)
index 65157a35dbba351d6751bdcb4ee483e37b25ee88..54add60f94c98c5d8d15c119e996395a13b6fc86 100644 (file)
@@ -16,6 +16,8 @@
 #include <linux/err.h>
 #include <linux/mutex.h>
 
+#include <asm/processor.h>     /* for cpu_relax() */
+
 #include <mach/mxs.h>
 
 #define OCOTP_WORD_OFFSET              0x20
index af98117043d214f8e088e8fd1429656410300a14..5b114d1558c83f41fe8acc524b1aa86f2ffa4a54 100644 (file)
@@ -4,14 +4,14 @@
 
 # Common support
 obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o
-obj-y += clock.o clock_data.o opp_data.o reset.o
+obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
 obj-$(CONFIG_OMAP_32K_TIMER)   += timer32k.o
 
 # Power Management
-obj-$(CONFIG_PM) += pm.o sleep.o pm_bus.o
+obj-$(CONFIG_PM) += pm.o sleep.o
 
 # DSP
 obj-$(CONFIG_OMAP_MBOX_FWK)    += mailbox_mach.o
index fe31d933f0edee78106d52d0c82fb95ef70a3a58..334fb8871bc319348f9edb152e5d611fb539aa6f 100644 (file)
@@ -56,9 +56,13 @@ static struct dev_power_domain default_power_domain = {
                USE_PLATFORM_PM_SLEEP_OPS
        },
 };
+#define OMAP1_PWR_DOMAIN (&default_power_domain)
+#else
+#define OMAP1_PWR_DOMAIN NULL
+#endif /* CONFIG_PM_RUNTIME */
 
 static struct pm_clk_notifier_block platform_bus_notifier = {
-       .pwr_domain = &default_power_domain,
+       .pwr_domain = OMAP1_PWR_DOMAIN,
        .con_ids = { "ick", "fck", NULL, },
 };
 
@@ -72,4 +76,4 @@ static int __init omap1_pm_runtime_init(void)
        return 0;
 }
 core_initcall(omap1_pm_runtime_init);
-#endif /* CONFIG_PM_RUNTIME */
+
index 2a0bb4818caef6a99a99e068946f970f8adcee1e..23f71d40883ea1fafbd2fd331d33fd9c581731dd 100644 (file)
@@ -84,7 +84,8 @@ static struct mtd_partition omap3pandora_nand_partitions[] = {
 
 static struct omap_nand_platform_data pandora_nand_data = {
        .cs             = 0,
-       .devsize        = 1,    /* '0' for 8-bit, '1' for 16-bit device */
+       .devsize        = NAND_BUSWIDTH_16,
+       .xfer_type      = NAND_OMAP_PREFETCH_DMA,
        .parts          = omap3pandora_nand_partitions,
        .nr_parts       = ARRAY_SIZE(omap3pandora_nand_partitions),
 };
index a5a83b358ddd89724de71eace26e11d8289c8e65..e01da45c053756f62ac08956620dc16dd09d3407 100644 (file)
@@ -189,7 +189,7 @@ static struct dentry *pm_dbg_dir;
 
 static int pm_dbg_init_done;
 
-static int __init pm_dbg_init(void);
+static int pm_dbg_init(void);
 
 enum {
        DEBUG_FILE_COUNTERS = 0,
@@ -595,7 +595,7 @@ static int option_set(void *data, u64 val)
 
 DEFINE_SIMPLE_ATTRIBUTE(pm_dbg_option_fops, option_get, option_set, "%llu\n");
 
-static int __init pm_dbg_init(void)
+static int pm_dbg_init(void)
 {
        int i;
        struct dentry *d;
index 7fe74067d85fc7e2aeb1469878f28c8cd73b3456..094279aefe9c6fd5d6a86dd88fbbc44b6d55c07b 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/apm-emulation.h>
index c95258c274c11c0c3eea565ef0709531440c3cab..1e2aba23e0d6d56ea6ddcd696937344027493e8b 100644 (file)
@@ -382,10 +382,8 @@ void ag5evm_sdhi1_set_pwr(struct platform_device *pdev, int state)
 }
 
 static struct sh_mobile_sdhi_info sh_sdhi1_platdata = {
-       .dma_slave_tx   = SHDMA_SLAVE_SDHI1_TX,
-       .dma_slave_rx   = SHDMA_SLAVE_SDHI1_RX,
        .tmio_flags     = TMIO_MMC_WRPROTECT_DISABLE,
-       .tmio_caps      = MMC_CAP_NONREMOVABLE,
+       .tmio_caps      = MMC_CAP_NONREMOVABLE | MMC_CAP_SDIO_IRQ,
        .tmio_ocr_mask  = MMC_VDD_32_33 | MMC_VDD_33_34,
        .set_pwr        = ag5evm_sdhi1_set_pwr,
 };
index 776f20560e721579d5adbc6d25176d9915f96bfe..7e1d375843211e52944720a562a5c580dbe20149 100644 (file)
  * ------+--------------------+--------------------+-------
  * IRQ0  | ICR1A.IRQ0SA=0010  | SDHI2 card detect  | Low
  * IRQ6  | ICR1A.IRQ6SA=0011  | Ether(LAN9220)     | High
- * IRQ7  | ICR1A.IRQ7SA=0010  | LCD Tuch Panel     | Low
+ * IRQ7  | ICR1A.IRQ7SA=0010  | LCD Touch Panel    | Low
  * IRQ8  | ICR2A.IRQ8SA=0010  | MMC/SD card detect | Low
  * IRQ9  | ICR2A.IRQ9SA=0010  | KEY(TCA6408)       | Low
  * IRQ21 | ICR4A.IRQ21SA=0011 | Sensor(ADXL345)    | High
  * USB1 can become Host by r8a66597, and become Function by renesas_usbhs.
  * But don't select both drivers in same time.
  * These uses same IRQ number for request_irq(), and aren't supporting
- * IRQF_SHARD / IORESOURCE_IRQ_SHAREABLE.
+ * IRQF_SHARED / IORESOURCE_IRQ_SHAREABLE.
  *
  * Actually these are old/new version of USB driver.
- * This mean its register will be broken if it supports SHARD IRQ,
+ * This mean its register will be broken if it supports shared IRQ,
  */
 
 /*
@@ -562,7 +562,121 @@ out:
                clk_put(hdmi_ick);
 }
 
-/* USB1 (Host) */
+/* USBHS0 is connected to CN22 which takes a USB Mini-B plug
+ *
+ * The sh7372 SoC has IRQ7 set aside for USBHS0 hotplug,
+ * but on this particular board IRQ7 is already used by
+ * the touch screen. This leaves us with software polling.
+ */
+#define USBHS0_POLL_INTERVAL (HZ * 5)
+
+struct usbhs_private {
+       unsigned int usbphyaddr;
+       unsigned int usbcrcaddr;
+       struct renesas_usbhs_platform_info info;
+       struct delayed_work work;
+       struct platform_device *pdev;
+};
+
+#define usbhs_get_priv(pdev)                           \
+       container_of(renesas_usbhs_get_info(pdev),      \
+                    struct usbhs_private, info)
+
+#define usbhs_is_connected(priv)                       \
+       (!((1 << 7) & __raw_readw(priv->usbcrcaddr)))
+
+static int usbhs_get_vbus(struct platform_device *pdev)
+{
+       return usbhs_is_connected(usbhs_get_priv(pdev));
+}
+
+static void usbhs_phy_reset(struct platform_device *pdev)
+{
+       struct usbhs_private *priv = usbhs_get_priv(pdev);
+
+       /* init phy */
+       __raw_writew(0x8a0a, priv->usbcrcaddr);
+}
+
+static int usbhs0_get_id(struct platform_device *pdev)
+{
+       return USBHS_GADGET;
+}
+
+static void usbhs0_work_function(struct work_struct *work)
+{
+       struct usbhs_private *priv = container_of(work, struct usbhs_private,
+                                                 work.work);
+
+       renesas_usbhs_call_notify_hotplug(priv->pdev);
+       schedule_delayed_work(&priv->work, USBHS0_POLL_INTERVAL);
+}
+
+static int usbhs0_hardware_init(struct platform_device *pdev)
+{
+       struct usbhs_private *priv = usbhs_get_priv(pdev);
+
+       priv->pdev = pdev;
+       INIT_DELAYED_WORK(&priv->work, usbhs0_work_function);
+       schedule_delayed_work(&priv->work, USBHS0_POLL_INTERVAL);
+       return 0;
+}
+
+static void usbhs0_hardware_exit(struct platform_device *pdev)
+{
+       struct usbhs_private *priv = usbhs_get_priv(pdev);
+
+       cancel_delayed_work_sync(&priv->work);
+}
+
+static struct usbhs_private usbhs0_private = {
+       .usbcrcaddr     = 0xe605810c,           /* USBCR2 */
+       .info = {
+               .platform_callback = {
+                       .hardware_init  = usbhs0_hardware_init,
+                       .hardware_exit  = usbhs0_hardware_exit,
+                       .phy_reset      = usbhs_phy_reset,
+                       .get_id         = usbhs0_get_id,
+                       .get_vbus       = usbhs_get_vbus,
+               },
+               .driver_param = {
+                       .buswait_bwait  = 4,
+               },
+       },
+};
+
+static struct resource usbhs0_resources[] = {
+       [0] = {
+               .name   = "USBHS0",
+               .start  = 0xe6890000,
+               .end    = 0xe68900e6 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = evt2irq(0x1ca0) /* USB0_USB0I0 */,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device usbhs0_device = {
+       .name   = "renesas_usbhs",
+       .id     = 0,
+       .dev = {
+               .platform_data          = &usbhs0_private.info,
+       },
+       .num_resources  = ARRAY_SIZE(usbhs0_resources),
+       .resource       = usbhs0_resources,
+};
+
+/* USBHS1 is connected to CN31 which takes a USB Mini-AB plug
+ *
+ * Use J30 to select between Host and Function. This setting
+ * can however not be detected by software. Hotplug of USBHS1
+ * is provided via IRQ8.
+ */
+#define IRQ8 evt2irq(0x0300)
+
+/* USBHS1 USB Host support via r8a66597_hcd */
 static void usb1_host_port_power(int port, int power)
 {
        if (!power) /* only power-on is supported for now */
@@ -579,9 +693,9 @@ static struct r8a66597_platdata usb1_host_data = {
 
 static struct resource usb1_host_resources[] = {
        [0] = {
-               .name   = "USBHS",
-               .start  = 0xE68B0000,
-               .end    = 0xE68B00E6 - 1,
+               .name   = "USBHS1",
+               .start  = 0xe68b0000,
+               .end    = 0xe68b00e6 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -602,37 +716,14 @@ static struct platform_device usb1_host_device = {
        .resource       = usb1_host_resources,
 };
 
-/* USB1 (Function) */
+/* USBHS1 USB Function support via renesas_usbhs */
+
 #define USB_PHY_MODE           (1 << 4)
 #define USB_PHY_INT_EN         ((1 << 3) | (1 << 2))
 #define USB_PHY_ON             (1 << 1)
 #define USB_PHY_OFF            (1 << 0)
 #define USB_PHY_INT_CLR                (USB_PHY_ON | USB_PHY_OFF)
 
-struct usbhs_private {
-       unsigned int irq;
-       unsigned int usbphyaddr;
-       unsigned int usbcrcaddr;
-       struct renesas_usbhs_platform_info info;
-};
-
-#define usbhs_get_priv(pdev)                           \
-       container_of(renesas_usbhs_get_info(pdev),      \
-                    struct usbhs_private, info)
-
-#define usbhs_is_connected(priv)                       \
-       (!((1 << 7) & __raw_readw(priv->usbcrcaddr)))
-
-static int usbhs1_get_id(struct platform_device *pdev)
-{
-       return USBHS_GADGET;
-}
-
-static int usbhs1_get_vbus(struct platform_device *pdev)
-{
-       return usbhs_is_connected(usbhs_get_priv(pdev));
-}
-
 static irqreturn_t usbhs1_interrupt(int irq, void *data)
 {
        struct platform_device *pdev = data;
@@ -654,12 +745,10 @@ static int usbhs1_hardware_init(struct platform_device *pdev)
        struct usbhs_private *priv = usbhs_get_priv(pdev);
        int ret;
 
-       irq_set_irq_type(priv->irq, IRQ_TYPE_LEVEL_HIGH);
-
        /* clear interrupt status */
        __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr);
 
-       ret = request_irq(priv->irq, usbhs1_interrupt, 0,
+       ret = request_irq(IRQ8, usbhs1_interrupt, IRQF_TRIGGER_HIGH,
                          dev_name(&pdev->dev), pdev);
        if (ret) {
                dev_err(&pdev->dev, "request_irq err\n");
@@ -679,15 +768,12 @@ static void usbhs1_hardware_exit(struct platform_device *pdev)
        /* clear interrupt status */
        __raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr);
 
-       free_irq(priv->irq, pdev);
+       free_irq(IRQ8, pdev);
 }
 
-static void usbhs1_phy_reset(struct platform_device *pdev)
+static int usbhs1_get_id(struct platform_device *pdev)
 {
-       struct usbhs_private *priv = usbhs_get_priv(pdev);
-
-       /* init phy */
-       __raw_writew(0x8a0a, priv->usbcrcaddr);
+       return USBHS_GADGET;
 }
 
 static u32 usbhs1_pipe_cfg[] = {
@@ -710,16 +796,15 @@ static u32 usbhs1_pipe_cfg[] = {
 };
 
 static struct usbhs_private usbhs1_private = {
-       .irq            = evt2irq(0x0300),      /* IRQ8 */
-       .usbphyaddr     = 0xE60581E2,           /* USBPHY1INTAP */
-       .usbcrcaddr     = 0xE6058130,           /* USBCR4 */
+       .usbphyaddr     = 0xe60581e2,           /* USBPHY1INTAP */
+       .usbcrcaddr     = 0xe6058130,           /* USBCR4 */
        .info = {
                .platform_callback = {
                        .hardware_init  = usbhs1_hardware_init,
                        .hardware_exit  = usbhs1_hardware_exit,
-                       .phy_reset      = usbhs1_phy_reset,
                        .get_id         = usbhs1_get_id,
-                       .get_vbus       = usbhs1_get_vbus,
+                       .phy_reset      = usbhs_phy_reset,
+                       .get_vbus       = usbhs_get_vbus,
                },
                .driver_param = {
                        .buswait_bwait  = 4,
@@ -731,9 +816,9 @@ static struct usbhs_private usbhs1_private = {
 
 static struct resource usbhs1_resources[] = {
        [0] = {
-               .name   = "USBHS",
-               .start  = 0xE68B0000,
-               .end    = 0xE68B00E6 - 1,
+               .name   = "USBHS1",
+               .start  = 0xe68b0000,
+               .end    = 0xe68b00e6 - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -752,7 +837,6 @@ static struct platform_device usbhs1_device = {
        .resource       = usbhs1_resources,
 };
 
-
 /* LED */
 static struct gpio_led mackerel_leds[] = {
        {
@@ -1203,6 +1287,7 @@ static struct platform_device *mackerel_devices[] __initdata = {
        &nor_flash_device,
        &smc911x_device,
        &lcdc_device,
+       &usbhs0_device,
        &usb1_host_device,
        &usbhs1_device,
        &leds_device,
@@ -1301,6 +1386,7 @@ static void __init mackerel_map_io(void)
 
 #define GPIO_PORT9CR   0xE6051009
 #define GPIO_PORT10CR  0xE605100A
+#define GPIO_PORT167CR 0xE60520A7
 #define GPIO_PORT168CR 0xE60520A8
 #define SRCR4          0xe61580bc
 #define USCCR1         0xE6058144
@@ -1354,17 +1440,17 @@ static void __init mackerel_init(void)
        gpio_request(GPIO_PORT151, NULL); /* LCDDON */
        gpio_direction_output(GPIO_PORT151, 1);
 
-       /* USB enable */
-       gpio_request(GPIO_FN_VBUS0_1,    NULL);
-       gpio_request(GPIO_FN_IDIN_1_18,  NULL);
-       gpio_request(GPIO_FN_PWEN_1_115, NULL);
-       gpio_request(GPIO_FN_OVCN_1_114, NULL);
-       gpio_request(GPIO_FN_EXTLP_1,    NULL);
-       gpio_request(GPIO_FN_OVCN2_1,    NULL);
-       gpio_pull_down(GPIO_PORT168CR);
-
-       /* setup USB phy */
-       __raw_writew(0x8a0a, 0xE6058130);       /* USBCR4 */
+       /* USBHS0 */
+       gpio_request(GPIO_FN_VBUS0_0, NULL);
+       gpio_pull_down(GPIO_PORT168CR); /* VBUS0_0 pull down */
+
+       /* USBHS1 */
+       gpio_request(GPIO_FN_VBUS0_1, NULL);
+       gpio_pull_down(GPIO_PORT167CR); /* VBUS0_1 pull down */
+       gpio_request(GPIO_FN_IDIN_1_113, NULL);
+
+       /* USB phy tweak to make the r8a66597_hcd host driver work */
+       __raw_writew(0x8a0a, 0xe6058130);       /* USBCR4 */
 
        /* enable FSI2 port A (ak4643) */
        gpio_request(GPIO_FN_FSIAIBT,   NULL);
index 5d0e1503ece66fb9385f3ffc80abb88e60d2ed27..a911a60e7719a1e0fa040f5798b0e7174b060fa1 100644 (file)
@@ -250,6 +250,11 @@ static irqreturn_t sh73a0_intcs_demux(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
+static int sh73a0_set_wake(struct irq_data *data, unsigned int on)
+{
+       return 0; /* always allow wakeup */
+}
+
 void __init sh73a0_init_irq(void)
 {
        void __iomem *gic_dist_base = __io(0xf0001000);
@@ -257,6 +262,7 @@ void __init sh73a0_init_irq(void)
        void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
 
        gic_init(0, 29, gic_dist_base, gic_cpu_base);
+       gic_arch_extn.irq_set_wake = sh73a0_set_wake;
 
        register_intc_controller(&intcs_desc);
 
index 2c10190dbb554eb7a9063de3f31408dfab1d5e93..e546017f15dea1202df2be20fa6303b69d70f1f4 100644 (file)
@@ -38,7 +38,7 @@ static struct plat_sci_port scif0_platform_data = {
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE,
        .scbrr_algo_id  = SCBRR_ALGO_4,
-       .type           = PORT_SCIF,
+       .type           = PORT_SCIFA,
        .irqs           = { evt2irq(0xc00), evt2irq(0xc00),
                            evt2irq(0xc00), evt2irq(0xc00) },
 };
@@ -57,7 +57,7 @@ static struct plat_sci_port scif1_platform_data = {
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE,
        .scbrr_algo_id  = SCBRR_ALGO_4,
-       .type           = PORT_SCIF,
+       .type           = PORT_SCIFA,
        .irqs           = { evt2irq(0xc20), evt2irq(0xc20),
                            evt2irq(0xc20), evt2irq(0xc20) },
 };
@@ -76,7 +76,7 @@ static struct plat_sci_port scif2_platform_data = {
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE,
        .scbrr_algo_id  = SCBRR_ALGO_4,
-       .type           = PORT_SCIF,
+       .type           = PORT_SCIFA,
        .irqs           = { evt2irq(0xc40), evt2irq(0xc40),
                            evt2irq(0xc40), evt2irq(0xc40) },
 };
@@ -95,7 +95,7 @@ static struct plat_sci_port scif3_platform_data = {
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE,
        .scbrr_algo_id  = SCBRR_ALGO_4,
-       .type           = PORT_SCIF,
+       .type           = PORT_SCIFA,
        .irqs           = { evt2irq(0xc60), evt2irq(0xc60),
                            evt2irq(0xc60), evt2irq(0xc60) },
 };
@@ -114,7 +114,7 @@ static struct plat_sci_port scif4_platform_data = {
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE,
        .scbrr_algo_id  = SCBRR_ALGO_4,
-       .type           = PORT_SCIF,
+       .type           = PORT_SCIFA,
        .irqs           = { evt2irq(0xd20), evt2irq(0xd20),
                            evt2irq(0xd20), evt2irq(0xd20) },
 };
@@ -133,7 +133,7 @@ static struct plat_sci_port scif5_platform_data = {
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE,
        .scbrr_algo_id  = SCBRR_ALGO_4,
-       .type           = PORT_SCIF,
+       .type           = PORT_SCIFA,
        .irqs           = { evt2irq(0xd40), evt2irq(0xd40),
                            evt2irq(0xd40), evt2irq(0xd40) },
 };
@@ -152,7 +152,7 @@ static struct plat_sci_port scif6_platform_data = {
        .flags          = UPF_BOOT_AUTOCONF,
        .scscr          = SCSCR_RE | SCSCR_TE,
        .scbrr_algo_id  = SCBRR_ALGO_4,
-       .type           = PORT_SCIF,
+       .type           = PORT_SCIFB,
        .irqs           = { evt2irq(0xd60), evt2irq(0xd60),
                            evt2irq(0xd60), evt2irq(0xd60) },
 };
index c34f3ea3017c4db1b4da624b12c1f800e24a91b0..4f50ca8f901e2bebd5de51defd425ba9e83f9ff4 100644 (file)
@@ -31,7 +31,7 @@ struct clk {
        bool reset;
        __u16 clk_val;
        __s8 usecount;
-       __u32 res_reg;
+       void __iomem * res_reg;
        __u16 res_mask;
 
        bool hw_ctrld;
index 8b85df4c8d8fcce5530535ffb2d91e15f25b636d..035fdc9dbdb03ebb50e88873a67232707d4fbc50 100644 (file)
  * the defines are used for setting up the I/O memory mapping.
  */
 
+#ifdef __ASSEMBLER__
+#define IOMEM(a) (a)
+#else
+#define IOMEM(a) (void __iomem *) a
+#endif
+
 /* NAND Flash CS0 */
 #define U300_NAND_CS0_PHYS_BASE                0x80000000
 
 #define U300_SEMI_CONFIG_BASE          0x30000000
 #endif
 
-/*
- * All the following peripherals are specified at their PHYSICAL address,
- * so if you need to access them (in the kernel), you MUST use the macros
- * defined in <asm/io.h> to map to the IO_ADDRESS_AHB() IO_ADDRESS_FAST()
- * etc.
- */
-
 /*
  * AHB peripherals
  */
 
 /* Vectored Interrupt Controller 0, servicing 32 interrupts */
 #define U300_INTCON0_BASE              (U300_AHB_PER_PHYS_BASE+0x1000)
-#define U300_INTCON0_VBASE             (U300_AHB_PER_VIRT_BASE+0x1000)
+#define U300_INTCON0_VBASE             IOMEM(U300_AHB_PER_VIRT_BASE+0x1000)
 
 /* Vectored Interrupt Controller 1, servicing 32 interrupts */
 #define U300_INTCON1_BASE              (U300_AHB_PER_PHYS_BASE+0x2000)
-#define U300_INTCON1_VBASE             (U300_AHB_PER_VIRT_BASE+0x2000)
+#define U300_INTCON1_VBASE             IOMEM(U300_AHB_PER_VIRT_BASE+0x2000)
 
 /* Memory Stick Pro (MSPRO) controller */
 #define U300_MSPRO_BASE                        (U300_AHB_PER_PHYS_BASE+0x3000)
 
 /* SYSCON */
 #define U300_SYSCON_BASE               (U300_SLOW_PER_PHYS_BASE+0x1000)
-#define U300_SYSCON_VBASE              (U300_SLOW_PER_VIRT_BASE+0x1000)
+#define U300_SYSCON_VBASE              IOMEM(U300_SLOW_PER_VIRT_BASE+0x1000)
 
 /* Watchdog */
 #define U300_WDOG_BASE                 (U300_SLOW_PER_PHYS_BASE+0x2000)
 
 /* APP side special timer */
 #define U300_TIMER_APP_BASE            (U300_SLOW_PER_PHYS_BASE+0x4000)
-#define U300_TIMER_APP_VBASE           (U300_SLOW_PER_VIRT_BASE+0x4000)
+#define U300_TIMER_APP_VBASE           IOMEM(U300_SLOW_PER_VIRT_BASE+0x4000)
 
 /* Keypad */
 #define U300_KEYPAD_BASE               (U300_SLOW_PER_PHYS_BASE+0x5000)
  * Virtual accessor macros for static devices
  */
 
-
 #endif
index 891cf44591e073ea4de84968d33f598595a8263c..18d7fa0603c230259ff96d3f9dc910b4a53a3b04 100644 (file)
@@ -411,8 +411,7 @@ static void __init u300_timer_init(void)
        /* Use general purpose timer 2 as clock source */
        if (clocksource_mmio_init(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC,
                        "GPT2", rate, 300, 32, clocksource_mmio_readl_up))
-               printk(KERN_ERR "timer: failed to initialize clock "
-                      "source %s\n", clocksource_u300_1mhz.name);
+               pr_err("timer: failed to initialize U300 clock source\n");
 
        clockevents_calc_mult_shift(&clockevent_u300_1mhz,
                                    rate, APPTIMER_MIN_RANGE);
index 285edcd2da2aa9a9d6186a6c17cf053918b0b66e..9e6b93b1a04342e7883aa241ddecb02856818a0e 100644 (file)
@@ -46,12 +46,6 @@ static struct map_desc v2m_io_desc[] __initdata = {
        },
 };
 
-static void __init v2m_init_early(void)
-{
-       ct_desc->init_early();
-       versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000);
-}
-
 static void __init v2m_timer_init(void)
 {
        u32 scctrl;
@@ -365,6 +359,13 @@ static struct clk_lookup v2m_lookups[] = {
        },
 };
 
+static void __init v2m_init_early(void)
+{
+       ct_desc->init_early();
+       clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups));
+       versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000);
+}
+
 static void v2m_power_off(void)
 {
        if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE_MB, 0))
@@ -418,8 +419,6 @@ static void __init v2m_init(void)
 {
        int i;
 
-       clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups));
-
        platform_device_register(&v2m_pcie_i2c_device);
        platform_device_register(&v2m_ddc_i2c_device);
        platform_device_register(&v2m_flash_device);
index 8bfae964b133987e061c430a0426f951b07172fa..b0ee9ba3cfab41a52853eca727466abff88ddf27 100644 (file)
@@ -24,7 +24,9 @@ DEFINE_PER_CPU(struct mm_struct *, current_mm);
 
 /*
  * We fork()ed a process, and we need a new context for the child
- * to run in.
+ * to run in.  We reserve version 0 for initial tasks so we will
+ * always allocate an ASID. The ASID 0 is reserved for the TTBR
+ * register changing sequence.
  */
 void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 {
@@ -34,11 +36,8 @@ void __init_new_context(struct task_struct *tsk, struct mm_struct *mm)
 
 static void flush_context(void)
 {
-       u32 ttb;
-       /* Copy TTBR1 into TTBR0 */
-       asm volatile("mrc       p15, 0, %0, c2, c0, 1\n"
-                    "mcr       p15, 0, %0, c2, c0, 0"
-                    : "=r" (ttb));
+       /* set the reserved ASID before flushing the TLB */
+       asm("mcr        p15, 0, %0, c13, c0, 1\n" : : "r" (0));
        isb();
        local_flush_tlb_all();
        if (icache_is_vivt_asid_tagged()) {
@@ -94,7 +93,7 @@ static void reset_context(void *info)
                return;
 
        smp_rmb();
-       asid = cpu_last_asid + cpu;
+       asid = cpu_last_asid + cpu + 1;
 
        flush_context();
        set_mm_context(mm, asid);
@@ -144,13 +143,13 @@ void __new_context(struct mm_struct *mm)
         * to start a new version and flush the TLB.
         */
        if (unlikely((asid & ~ASID_MASK) == 0)) {
-               asid = cpu_last_asid + smp_processor_id();
+               asid = cpu_last_asid + smp_processor_id() + 1;
                flush_context();
 #ifdef CONFIG_SMP
                smp_wmb();
                smp_call_function(reset_context, NULL, 1);
 #endif
-               cpu_last_asid += NR_CPUS - 1;
+               cpu_last_asid += NR_CPUS;
        }
 
        set_mm_context(mm, asid);
index 2c2cce9cd8c8399e02cf841298649daf72d06330..c19571c40a21ca62902d65cd01dcb8db9ea4f178 100644 (file)
@@ -330,6 +330,12 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
        memblock_reserve(__pa(_stext), _end - _stext);
 #endif
 #ifdef CONFIG_BLK_DEV_INITRD
+       if (phys_initrd_size &&
+           !memblock_is_region_memory(phys_initrd_start, phys_initrd_size)) {
+               pr_err("INITRD: 0x%08lx+0x%08lx is not a memory region - disabling initrd\n",
+                      phys_initrd_start, phys_initrd_size);
+               phys_initrd_start = phys_initrd_size = 0;
+       }
        if (phys_initrd_size &&
            memblock_is_region_reserved(phys_initrd_start, phys_initrd_size)) {
                pr_err("INITRD: 0x%08lx+0x%08lx overlaps in-use memory region - disabling initrd\n",
@@ -635,7 +641,8 @@ void __init mem_init(void)
                        "    modules : 0x%08lx - 0x%08lx   (%4ld MB)\n"
                        "      .init : 0x%p" " - 0x%p" "   (%4d kB)\n"
                        "      .text : 0x%p" " - 0x%p" "   (%4d kB)\n"
-                       "      .data : 0x%p" " - 0x%p" "   (%4d kB)\n",
+                       "      .data : 0x%p" " - 0x%p" "   (%4d kB)\n"
+                       "       .bss : 0x%p" " - 0x%p" "   (%4d kB)\n",
 
                        MLK(UL(CONFIG_VECTORS_BASE), UL(CONFIG_VECTORS_BASE) +
                                (PAGE_SIZE)),
@@ -657,7 +664,8 @@ void __init mem_init(void)
 
                        MLK_ROUNDUP(__init_begin, __init_end),
                        MLK_ROUNDUP(_text, _etext),
-                       MLK_ROUNDUP(_sdata, _edata));
+                       MLK_ROUNDUP(_sdata, _edata),
+                       MLK_ROUNDUP(__bss_start, __bss_stop));
 
 #undef MLK
 #undef MLM
index e4c165ca669680eb6d74ce8e3d5822de50bbe44f..537ffcb0646d5e0c77ef8a336f4b39b07937beab 100644 (file)
@@ -146,7 +146,7 @@ __arm7tdmi_proc_info:
                .long   0
                .long   0
                .long   v4_cache_fns
-               .size   __arm7tdmi_proc_info, . - __arm7dmi_proc_info
+               .size   __arm7tdmi_proc_info, . - __arm7tdmi_proc_info
 
                .type   __triscenda7_proc_info, #object
 __triscenda7_proc_info:
index 7b7ebd4d096d9cb3939bed7a059be8514486d463..546b54da10059752195476dc6bd9fc0b1b243775 100644 (file)
@@ -116,7 +116,7 @@ __arm9tdmi_proc_info:
                .long   0
                .long   0
                .long   v4_cache_fns
-               .size   __arm9tdmi_proc_info, . - __arm9dmi_proc_info
+               .size   __arm9tdmi_proc_info, . - __arm9tdmi_proc_info
 
                .type   __p2001_proc_info, #object
 __p2001_proc_info:
index b3b566ec83d397c1074c1dcbee0d5e33542e7d9c..089c0b5e454fccbdbc63a4d4e9d72d15baa7075a 100644 (file)
@@ -108,16 +108,18 @@ ENTRY(cpu_v7_switch_mm)
 #ifdef CONFIG_ARM_ERRATA_430973
        mcr     p15, 0, r2, c7, c5, 6           @ flush BTAC/BTB
 #endif
-       mrc     p15, 0, r2, c2, c0, 1           @ load TTB 1
-       mcr     p15, 0, r2, c2, c0, 0           @ into TTB 0
+#ifdef CONFIG_ARM_ERRATA_754322
+       dsb
+#endif
+       mcr     p15, 0, r2, c13, c0, 1          @ set reserved context ID
+       isb
+1:     mcr     p15, 0, r0, c2, c0, 0           @ set TTB 0
        isb
 #ifdef CONFIG_ARM_ERRATA_754322
        dsb
 #endif
        mcr     p15, 0, r1, c13, c0, 1          @ set context ID
        isb
-       mcr     p15, 0, r0, c2, c0, 0           @ set TTB 0
-       isb
 #endif
        mov     pc, lr
 ENDPROC(cpu_v7_switch_mm)
@@ -208,19 +210,21 @@ cpu_v7_name:
 
 /* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
 .globl cpu_v7_suspend_size
-.equ   cpu_v7_suspend_size, 4 * 8
+.equ   cpu_v7_suspend_size, 4 * 9
 #ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_v7_do_suspend)
        stmfd   sp!, {r4 - r11, lr}
        mrc     p15, 0, r4, c13, c0, 0  @ FCSE/PID
        mrc     p15, 0, r5, c13, c0, 1  @ Context ID
+       mrc     p15, 0, r6, c13, c0, 3  @ User r/o thread ID
+       stmia   r0!, {r4 - r6}
        mrc     p15, 0, r6, c3, c0, 0   @ Domain ID
        mrc     p15, 0, r7, c2, c0, 0   @ TTB 0
        mrc     p15, 0, r8, c2, c0, 1   @ TTB 1
        mrc     p15, 0, r9, c1, c0, 0   @ Control register
        mrc     p15, 0, r10, c1, c0, 1  @ Auxiliary control register
        mrc     p15, 0, r11, c1, c0, 2  @ Co-processor access control
-       stmia   r0, {r4 - r11}
+       stmia   r0, {r6 - r11}
        ldmfd   sp!, {r4 - r11, pc}
 ENDPROC(cpu_v7_do_suspend)
 
@@ -228,9 +232,11 @@ ENTRY(cpu_v7_do_resume)
        mov     ip, #0
        mcr     p15, 0, ip, c8, c7, 0   @ invalidate TLBs
        mcr     p15, 0, ip, c7, c5, 0   @ invalidate I cache
-       ldmia   r0, {r4 - r11}
+       ldmia   r0!, {r4 - r6}
        mcr     p15, 0, r4, c13, c0, 0  @ FCSE/PID
        mcr     p15, 0, r5, c13, c0, 1  @ Context ID
+       mcr     p15, 0, r6, c13, c0, 3  @ User r/o thread ID
+       ldmia   r0, {r6 - r11}
        mcr     p15, 0, r6, c3, c0, 0   @ Domain ID
        mcr     p15, 0, r7, c2, c0, 0   @ TTB 0
        mcr     p15, 0, r8, c2, c0, 1   @ TTB 1
@@ -416,9 +422,9 @@ ENTRY(v7_processor_functions)
        .word   cpu_v7_dcache_clean_area
        .word   cpu_v7_switch_mm
        .word   cpu_v7_set_pte_ext
-       .word   0
-       .word   0
-       .word   0
+       .word   cpu_v7_suspend_size
+       .word   cpu_v7_do_suspend
+       .word   cpu_v7_do_resume
        .size   v7_processor_functions, . - v7_processor_functions
 
        .section ".rodata"
index 9612a87e2a881df2f49126e02ed0b6ed60982977..bab73e2c79db9653701e32a1babc63f770fff3d7 100644 (file)
@@ -18,6 +18,7 @@
  */
 #include <linux/init.h>
 #include <asm/traps.h>
+#include <asm/ptrace.h>
 
 static int cp6_trap(struct pt_regs *regs, unsigned int instr)
 {
index 3538b85ede910a4bc32c8e85b604789809cef21d..b130f60ca6b73e9b7b8435dcc52633bb1761078c 100644 (file)
@@ -139,7 +139,7 @@ static struct sdma_script_start_addrs addr_imx35_to2 = {
 #endif
 
 #ifdef CONFIG_SOC_IMX51
-static struct sdma_script_start_addrs addr_imx51_to1 = {
+static struct sdma_script_start_addrs addr_imx51 = {
        .ap_2_ap_addr = 642,
        .uart_2_mcu_addr = 817,
        .mcu_2_app_addr = 747,
@@ -196,7 +196,9 @@ static int __init imxXX_add_imx_dma(void)
 
 #if defined(CONFIG_SOC_IMX51)
        if (cpu_is_mx51()) {
-               imx51_imx_sdma_data.pdata.script_addrs = &addr_imx51_to1;
+               int to_version = mx51_revision() >> 4;
+               imx51_imx_sdma_data.pdata.to_version = to_version;
+               imx51_imx_sdma_data.pdata.script_addrs = &addr_imx51;
                ret = imx_add_imx_sdma(&imx51_imx_sdma_data);
        } else
 #endif
index a37b8eb65b76a6c2b13a019545852b3c9b48a7cc..49fc0df0c21f58be364d6da00e14d73eb8c32344 100644 (file)
@@ -84,6 +84,7 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/pm_runtime.h>
 
 #include <plat/omap_device.h>
 #include <plat/omap_hwmod.h>
@@ -539,20 +540,34 @@ int omap_early_device_register(struct omap_device *od)
 static int _od_runtime_suspend(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
+       int ret;
+
+       ret = pm_generic_runtime_suspend(dev);
+
+       if (!ret)
+               omap_device_idle(pdev);
+
+       return ret;
+}
 
-       return omap_device_idle(pdev);
+static int _od_runtime_idle(struct device *dev)
+{
+       return pm_generic_runtime_idle(dev);
 }
 
 static int _od_runtime_resume(struct device *dev)
 {
        struct platform_device *pdev = to_platform_device(dev);
 
-       return omap_device_enable(pdev);
+       omap_device_enable(pdev);
+
+       return pm_generic_runtime_resume(dev);
 }
 
 static struct dev_power_domain omap_device_power_domain = {
        .ops = {
                .runtime_suspend = _od_runtime_suspend,
+               .runtime_idle = _od_runtime_idle,
                .runtime_resume = _od_runtime_resume,
                USE_PLATFORM_PM_SLEEP_OPS
        }
index 6f9ca56de1f6b19ee52cca2b98e8a07411700109..a06bfccc2840e5204c5519203a6c343837ebac3c 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
index 7eece0af34c92ee46992b0a4d315110a2d254620..d8f1fe80d210daea5b764c50b0977a09d58c6a9f 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
index 387eb9d6e423321297fa1959741a9ff93812777c..d4c5b19ec950a2eddc4b6399e8d0286626aeb0c9 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
index 19f6ceeeff7b4710d5ccf916b231e0b469f9478f..77ca4f905d2cf9da872e12cb1efb4536a728a8f4 100644 (file)
@@ -7,6 +7,7 @@ CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_SLUB_DEBUG is not set
@@ -109,7 +110,7 @@ CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_S35390A=m
 CONFIG_RTC_DRV_AT32AP700X=m
 CONFIG_DMADEVICES=y
index f0fe237133a93f1a2d0984ab10e57d403f83cd71..6e0dca4d3131ff920a7580408ab48b45cd92b916 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
index e4a7c1dc8380f4aefbd17b055ef66b4a42acd4cb..7f2a344a5fa8334594929bcae48ec4fee4b5242c 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
index 6f37f70c2c37a83d4126162b4910705a1693dd10..085eeba88f67e5b94efefe4284c57b69ca1c60c7 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
index 4fb01f5ab42f1db7f20e653564946ca1443dc03f..d1a887e6405595010c7181c6a928c5fc35a3cb7b 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
index 9faaf9b900f242358032ea65279d61575ffe6ec7..956f2819ad45495a96c9244a53781028b48c4d91 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
index 3d2a5d85f970f46985096290085a1fe19e1006e1..40c69f38c61a2ab2b9a409dc1304cf495d0606b5 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
index 1ed8f22d4fe2cd8ff5f8b9f3bfc04805fd19b3d6..511eb8af356dab0a3681ee274aade2a988c89096 100644 (file)
@@ -5,6 +5,7 @@ CONFIG_POSIX_MQUEUE=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
index aeadc955db323b9da70dbb0b8b675243bcdcfee6..19973b06170c94a5518619a4fb07869c08c1727d 100644 (file)
@@ -6,6 +6,7 @@ CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_RELAY=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
index 1692beeb7ed3beeb321a1de732448dc0f886b12e..6f45681196d135a1290c2a5d7ae8be2b7b180d99 100644 (file)
@@ -7,6 +7,7 @@ CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
index 8b670a6530bf163304e48fe383e66bfc03123e15..3befab966827bacb4339247637e27d39333a7b1b 100644 (file)
@@ -7,6 +7,7 @@ CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 CONFIG_MODULES=y
index 5a51f2e7ffb9f9390294145d0332b936187ee536..1bee51f2215475e5f4bdbbaf00b49e84daf6719a 100644 (file)
@@ -7,6 +7,7 @@ CONFIG_BSD_PROCESS_ACCT_V3=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_BASE_FULL is not set
 # CONFIG_COMPAT_BRK is not set
index 49a88f5a9d2feda1c7b033cfd19c71453c6dd6bf..108502bc67706786d3125dff42be43f6a1d9b7d2 100644 (file)
@@ -131,7 +131,6 @@ struct thread_struct {
  */
 #define start_thread(regs, new_pc, new_sp)      \
        do {                                     \
-               set_fs(USER_DS);                 \
                memset(regs, 0, sizeof(*regs));  \
                regs->sr = MODE_USER;            \
                regs->pc = new_pc & ~1;          \
index aa677e2a3823d89272ed42a367400be93598c2fa..7fbf0dcb9afe5f88e9e307f3530cdbd875cf20f1 100644 (file)
@@ -1043,8 +1043,9 @@ void __init at32_map_usart(unsigned int hw_id, unsigned int line, int flags)
                data->regs = (void __iomem *)pdev->resource[0].start;
        }
 
+       pdev->id = line;
        pdata = pdev->dev.platform_data;
-       pdata->num = portnr;
+       pdata->num = line;
        at32_usarts[line] = pdev;
 }
 
index 9c96a130f3a858b02b33a3d66f1347623a2ba1ea..8181293115e427b1087c95a3b56f041437fa1ced 100644 (file)
 #define cpu_is_at91sam9263()   (0)
 #define cpu_is_at91sam9rl()    (0)
 #define cpu_is_at91cap9()      (0)
+#define cpu_is_at91cap9_revB() (0)
+#define cpu_is_at91cap9_revC() (0)
 #define cpu_is_at91sam9g10()   (0)
+#define cpu_is_at91sam9g20()   (0)
 #define cpu_is_at91sam9g45()   (0)
 #define cpu_is_at91sam9g45es() (0)
+#define cpu_is_at91sam9m10()   (0)
+#define cpu_is_at91sam9g46()   (0)
+#define cpu_is_at91sam9m11()   (0)
+#define cpu_is_at91sam9x5()    (0)
+#define cpu_is_at91sam9g15()   (0)
+#define cpu_is_at91sam9g35()   (0)
+#define cpu_is_at91sam9x35()   (0)
+#define cpu_is_at91sam9g25()   (0)
+#define cpu_is_at91sam9x25()   (0)
 
 #endif /* __ASM_ARCH_CPU_H */
index 3e3646186c9ffa686aa01ff86821fe1cc7639ebe..c9ac2f8e8f648af54f08407c7f31fb85a4807d06 100644 (file)
@@ -167,14 +167,12 @@ static int intc_suspend(void)
        return 0;
 }
 
-static int intc_resume(void)
+static void intc_resume(void)
 {
        int i;
 
        for (i = 0; i < 64; i++)
                intc_writel(&intc0, INTPR0 + 4 * i, intc0.saved_ipr[i]);
-
-       return 0;
 }
 #else
 #define intc_suspend   NULL
index 31d954216c054ec37748ffb942d6d3f463d8ba8b..9f1d08401fcaacdf6d53f661da44e2cee641b66e 100644 (file)
@@ -112,7 +112,7 @@ CONFIG_USB_G_SERIAL=m
 CONFIG_USB_G_PRINTER=m
 CONFIG_MMC=m
 CONFIG_SDH_BFIN=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_BFIN=m
 CONFIG_EXT2_FS=m
 # CONFIG_DNOTIFY is not set
index 9f3b5accda88a0b9d9c275b6c1cd9b69ce9e50f7..115ced33febdbe59de005c23f07abbf01371423a 100644 (file)
@@ -14,12 +14,6 @@ extern struct pglist_data *node_data[];
 #define NODE_DATA(nid)         (node_data[nid])
 
 #define node_localnr(pfn, nid) ((pfn) - NODE_DATA(nid)->node_start_pfn)
-#define node_start_pfn(nid)    (NODE_DATA(nid)->node_start_pfn)
-#define node_end_pfn(nid)                                              \
-({                                                                     \
-       pg_data_t *__pgdat = NODE_DATA(nid);                            \
-       __pgdat->node_start_pfn + __pgdat->node_spanned_pages - 1;      \
-})
 
 #define pmd_page(pmd)          (pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT))
 /*
@@ -44,7 +38,7 @@ static __inline__ int pfn_to_nid(unsigned long pfn)
        int node;
 
        for (node = 0 ; node < MAX_NUMNODES ; node++)
-               if (pfn >= node_start_pfn(node) && pfn <= node_end_pfn(node))
+               if (pfn >= node_start_pfn(node) && pfn < node_end_pfn(node))
                        break;
 
        return node;
index fc98f9b9d4d2ce417f29b547cad1884e9f7964df..b004dc1b1710bc3f8bfceddf7695266249b5bbdb 100644 (file)
@@ -14,6 +14,33 @@ config GENERIC_CLOCKEVENTS
        bool
        default n
 
+config M68000
+       bool
+       help
+         The Freescale (was Motorola) 68000 CPU is the first generation of
+         the well known M68K family of processors. The CPU core as well as
+         being available as a stand alone CPU was also used in many
+         System-On-Chip devices (eg 68328, 68302, etc). It does not contain
+         a paging MMU.
+
+config MCPU32
+       bool
+       help
+         The Freescale (was then Motorola) CPU32 is a CPU core that is
+         based on the 68020 processor. For the most part it is used in
+         System-On-Chip parts, and does not contain a paging MMU.
+
+config COLDFIRE
+       bool
+       select GENERIC_GPIO
+       select ARCH_REQUIRE_GPIOLIB
+       help
+         The Freescale ColdFire family of processors is a modern derivitive
+         of the 68000 processor family. They are mainly targeted at embedded
+         applications, and are all System-On-Chip (SOC) devices, as opposed
+         to stand alone CPUs. They implement a subset of the original 68000
+         processor instruction set.
+
 config COLDFIRE_SW_A7
        bool
        default n
@@ -36,26 +63,31 @@ choice
 
 config M68328
        bool "MC68328"
+       select M68000
        help
          Motorola 68328 processor support.
 
 config M68EZ328
        bool "MC68EZ328"
+       select M68000
        help
          Motorola 68EX328 processor support.
 
 config M68VZ328
        bool "MC68VZ328"
+       select M68000
        help
          Motorola 68VZ328 processor support.
 
 config M68360
        bool "MC68360"
+       select MCPU32
        help
          Motorola 68360 processor support.
 
 config M5206
        bool "MCF5206"
+       select COLDFIRE
        select COLDFIRE_SW_A7
        select HAVE_MBAR
        help
@@ -63,6 +95,7 @@ config M5206
 
 config M5206e
        bool "MCF5206e"
+       select COLDFIRE
        select COLDFIRE_SW_A7
        select HAVE_MBAR
        help
@@ -70,6 +103,7 @@ config M5206e
 
 config M520x
        bool "MCF520x"
+       select COLDFIRE
        select GENERIC_CLOCKEVENTS
        select HAVE_CACHE_SPLIT
        help
@@ -77,6 +111,7 @@ config M520x
 
 config M523x
        bool "MCF523x"
+       select COLDFIRE
        select GENERIC_CLOCKEVENTS
        select HAVE_CACHE_SPLIT
        select HAVE_IPSBAR
@@ -85,6 +120,7 @@ config M523x
 
 config M5249
        bool "MCF5249"
+       select COLDFIRE
        select COLDFIRE_SW_A7
        select HAVE_MBAR
        help
@@ -92,6 +128,7 @@ config M5249
 
 config M5271
        bool "MCF5271"
+       select COLDFIRE
        select HAVE_CACHE_SPLIT
        select HAVE_IPSBAR
        help
@@ -99,6 +136,7 @@ config M5271
 
 config M5272
        bool "MCF5272"
+       select COLDFIRE
        select COLDFIRE_SW_A7
        select HAVE_MBAR
        help
@@ -106,6 +144,7 @@ config M5272
 
 config M5275
        bool "MCF5275"
+       select COLDFIRE
        select HAVE_CACHE_SPLIT
        select HAVE_IPSBAR
        help
@@ -113,6 +152,7 @@ config M5275
 
 config M528x
        bool "MCF528x"
+       select COLDFIRE
        select GENERIC_CLOCKEVENTS
        select HAVE_CACHE_SPLIT
        select HAVE_IPSBAR
@@ -121,6 +161,7 @@ config M528x
 
 config M5307
        bool "MCF5307"
+       select COLDFIRE
        select COLDFIRE_SW_A7
        select HAVE_CACHE_CB
        select HAVE_MBAR
@@ -129,12 +170,14 @@ config M5307
 
 config M532x
        bool "MCF532x"
+       select COLDFIRE
        select HAVE_CACHE_CB
        help
          Freescale (Motorola) ColdFire 532x processor support.
 
 config M5407
        bool "MCF5407"
+       select COLDFIRE
        select COLDFIRE_SW_A7
        select HAVE_CACHE_CB
        select HAVE_MBAR
@@ -143,6 +186,7 @@ config M5407
 
 config M547x
        bool "MCF547x"
+       select COLDFIRE
        select HAVE_CACHE_CB
        select HAVE_MBAR
        help
@@ -150,6 +194,7 @@ config M547x
 
 config M548x
        bool "MCF548x"
+       select COLDFIRE
        select HAVE_CACHE_CB
        select HAVE_MBAR
        help
@@ -168,13 +213,6 @@ config M54xx
        depends on (M548x || M547x)
        default y
 
-config COLDFIRE
-       bool
-       depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407 || M54xx)
-       select GENERIC_GPIO
-       select ARCH_REQUIRE_GPIOLIB
-       default y
-
 config CLOCK_SET
        bool "Enable setting the CPU clock frequency"
        default n
index 33f82769547c003e85a5a3084fc09441f38c6e90..1b7a14d1a00070af31fe62299f6dbe3b8e03d4be 100644 (file)
@@ -14,8 +14,7 @@ EXPORT_SYMBOL(__ashrdi3);
 EXPORT_SYMBOL(__lshrdi3);
 EXPORT_SYMBOL(__muldi3);
 
-#if !defined(__mc68020__) && !defined(__mc68030__) && \
-    !defined(__mc68040__) && !defined(__mc68060__) && !defined(__mcpu32__)
+#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE)
 /*
  * Simpler 68k and ColdFire parts also need a few other gcc functions.
  */
index f4d715cdca0e7d5dca002943d88a8aeafa255ea3..7dc4087a9545aaa9df48b92a18ab80bbead41469 100644 (file)
@@ -84,52 +84,52 @@ SECTIONS {
                /* Kernel symbol table: Normal symbols */
                . = ALIGN(4);
                __start___ksymtab = .;
-               *(__ksymtab)
+               *(SORT(___ksymtab+*))
                __stop___ksymtab = .;
 
                /* Kernel symbol table: GPL-only symbols */
                __start___ksymtab_gpl = .;
-               *(__ksymtab_gpl)
+               *(SORT(___ksymtab_gpl+*))
                __stop___ksymtab_gpl = .;
 
                /* Kernel symbol table: Normal unused symbols */
                __start___ksymtab_unused = .;
-               *(__ksymtab_unused)
+               *(SORT(___ksymtab_unused+*))
                __stop___ksymtab_unused = .;
 
                /* Kernel symbol table: GPL-only unused symbols */
                __start___ksymtab_unused_gpl = .;
-               *(__ksymtab_unused_gpl)
+               *(SORT(___ksymtab_unused_gpl+*))
                __stop___ksymtab_unused_gpl = .;
 
                /* Kernel symbol table: GPL-future symbols */
                __start___ksymtab_gpl_future = .;
-               *(__ksymtab_gpl_future)
+               *(SORT(___ksymtab_gpl_future+*))
                __stop___ksymtab_gpl_future = .;
 
                /* Kernel symbol table: Normal symbols */
                __start___kcrctab = .;
-               *(__kcrctab)
+               *(SORT(___kcrctab+*))
                __stop___kcrctab = .;
 
                /* Kernel symbol table: GPL-only symbols */
                __start___kcrctab_gpl = .;
-               *(__kcrctab_gpl)
+               *(SORT(___kcrctab_gpl+*))
                __stop___kcrctab_gpl = .;
 
                /* Kernel symbol table: Normal unused symbols */
                __start___kcrctab_unused = .;
-               *(__kcrctab_unused)
+               *(SORT(___kcrctab_unused+*))
                __stop___kcrctab_unused = .;
 
                /* Kernel symbol table: GPL-only unused symbols */
                __start___kcrctab_unused_gpl = .;
-               *(__kcrctab_unused_gpl)
+               *(SORT(___kcrctab_unused_gpl+*))
                __stop___kcrctab_unused_gpl = .;
 
                /* Kernel symbol table: GPL-future symbols */
                __start___kcrctab_gpl_future = .;
-               *(__kcrctab_gpl_future)
+               *(SORT(___kcrctab_gpl_future+*))
                __stop___kcrctab_gpl_future = .;
 
                /* Kernel symbol table: strings */
index 62182c81e91c55bf106df98d14a00e4dc950ccd9..064889316974756878ff3a5f969068ab71b5cc2a 100644 (file)
@@ -34,8 +34,10 @@ void *memcpy(void *to, const void *from, size_t n)
        if (temp) {
                long *lto = to;
                const long *lfrom = from;
-#if defined(__mc68020__) || defined(__mc68030__) || \
-    defined(__mc68040__) || defined(__mc68060__) || defined(__mcpu32__)
+#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE)
+               for (; temp; temp--)
+                       *lto++ = *lfrom++;
+#else
                asm volatile (
                        "       movel %2,%3\n"
                        "       andw  #7,%3\n"
@@ -56,9 +58,6 @@ void *memcpy(void *to, const void *from, size_t n)
                        "       jpl   4b"
                        : "=a" (lfrom), "=a" (lto), "=d" (temp), "=&d" (temp1)
                        : "0" (lfrom), "1" (lto), "2" (temp));
-#else
-               for (; temp; temp--)
-                       *lto++ = *lfrom++;
 #endif
                to = lto;
                from = lfrom;
index f649e6a2e644686966e3b7c4ed01b245292c04c6..8a7639f0a2fe5c05d1ecc70065e15da88961db99 100644 (file)
@@ -32,8 +32,10 @@ void *memset(void *s, int c, size_t count)
        temp = count >> 2;
        if (temp) {
                long *ls = s;
-#if defined(__mc68020__) || defined(__mc68030__) || \
-    defined(__mc68040__) || defined(__mc68060__) || defined(__mcpu32__)
+#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE)
+               for (; temp; temp--)
+                       *ls++ = c;
+#else
                size_t temp1;
                asm volatile (
                        "       movel %1,%2\n"
@@ -55,9 +57,6 @@ void *memset(void *s, int c, size_t count)
                        "       jpl   1b"
                        : "=a" (ls), "=d" (temp), "=&d" (temp1)
                        : "d" (c), "0" (ls), "1" (temp));
-#else
-               for (; temp; temp--)
-                       *ls++ = c;
 #endif
                s = ls;
        }
index 079bafca073effea75f2af80847d1f174bf674f5..79e928a525d078169e0617270e1fcea9da08b5f2 100644 (file)
@@ -19,17 +19,7 @@ along with GNU CC; see the file COPYING.  If not, write to
 the Free Software Foundation, 59 Temple Place - Suite 330,
 Boston, MA 02111-1307, USA.  */
 
-#if defined(__mc68020__) || defined(__mc68030__) || \
-    defined(__mc68040__) || defined(__mc68060__) || defined(__mcpu32__)
-
-#define umul_ppmm(w1, w0, u, v) \
-  __asm__ ("mulu%.l %3,%1:%0"                                          \
-           : "=d" ((USItype)(w0)),                                     \
-             "=d" ((USItype)(w1))                                      \
-           : "%0" ((USItype)(u)),                                      \
-             "dmi" ((USItype)(v)))
-
-#else
+#if defined(CONFIG_M68000) || defined(CONFIG_COLDFIRE)
 
 #define SI_TYPE_SIZE 32
 #define __BITS4 (SI_TYPE_SIZE / 4)
@@ -61,6 +51,15 @@ Boston, MA 02111-1307, USA.  */
     (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0);         \
   } while (0)
 
+#else
+
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("mulu%.l %3,%1:%0"                                          \
+           : "=d" ((USItype)(w0)),                                     \
+             "=d" ((USItype)(w1))                                      \
+           : "%0" ((USItype)(u)),                                      \
+             "dmi" ((USItype)(v)))
+
 #endif
 
 #define __umulsidi3(u, v) \
index 37862b2ce3633a3f87f3aeb0ce3f8e119688a143..807c97eed8a8ed48a5957c144e907894c8d8c397 100644 (file)
@@ -678,7 +678,7 @@ CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
 CONFIG_RTC_DRV_TEST=m
 CONFIG_RTC_DRV_DS1307=m
index 3d6e60dad9d98a2b99a44029658638c48f300d50..780560b330d9ef9109a76b0210185f3bc178ca8e 100644 (file)
@@ -15,6 +15,7 @@
  * User space memory access functions
  */
 #include <linux/thread_info.h>
+#include <linux/kernel.h>
 #include <asm/page.h>
 #include <asm/errno.h>
 
index 9608d2cf214ac7d33d76661b6bff10cc9dad00c1..e67eb9c3d1bfb47769d2de11e3532a22250b308d 100644 (file)
@@ -14,13 +14,6 @@ extern struct node_map_data node_data[];
 
 #define NODE_DATA(nid)          (&node_data[nid].pg_data)
 
-#define node_start_pfn(nid)    (NODE_DATA(nid)->node_start_pfn)
-#define node_end_pfn(nid)                                              \
-({                                                                     \
-       pg_data_t *__pgdat = NODE_DATA(nid);                            \
-       __pgdat->node_start_pfn + __pgdat->node_spanned_pages;          \
-})
-
 /* We have these possible memory map layouts:
  * Astro: 0-3.75, 67.75-68, 4-64
  * zx1: 0-1, 257-260, 4-256
index 7f7e4a8786029897df66ca0e49c64b2c6aa5065d..22e719575c60b33cb64cee5fcb840c2507f942c8 100644 (file)
@@ -85,7 +85,7 @@ CONFIG_USB_OHCI_HCD=m
 CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 # CONFIG_USB_OHCI_HCD_PCI is not set
 CONFIG_USB_STORAGE=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PCF8563=m
 CONFIG_EXT2_FS=m
 CONFIG_EXT3_FS=m
index 6472322bf13b6820af3c364c1a994baebe914fbe..185c292b0f1c8cab6968420212c9690bc895e6b3 100644 (file)
@@ -141,7 +141,7 @@ CONFIG_USB_EHCI_TT_NEWSCHED=y
 # CONFIG_USB_EHCI_HCD_PPC_OF is not set
 CONFIG_USB_OHCI_HCD=m
 CONFIG_USB_STORAGE=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PS3=m
 CONFIG_EXT2_FS=m
 CONFIG_EXT3_FS=m
index fd3fd58bad845df6f2fbb1753257de994cd7cc1d..7b589178be46b293519bf2244c0e4dd6251fe9a1 100644 (file)
@@ -38,13 +38,6 @@ u64 memory_hotplug_max(void);
 #define memory_hotplug_max() memblock_end_of_DRAM()
 #endif
 
-/*
- * Following are macros that each numa implmentation must define.
- */
-
-#define node_start_pfn(nid)    (NODE_DATA(nid)->node_start_pfn)
-#define node_end_pfn(nid)      (NODE_DATA(nid)->node_end_pfn)
-
 #else
 #define memory_hotplug_max() memblock_end_of_DRAM()
 #endif /* CONFIG_NEED_MULTIPLE_NODES */
index 90d77bd078f51acc243b21ee0c63432d01369ee9..c03fef7a9c2220c45ca1584ad8f65191bb5c9e76 100644 (file)
@@ -579,6 +579,7 @@ config S390_GUEST
        def_bool y
        prompt "s390 guest support for KVM (EXPERIMENTAL)"
        depends on 64BIT && EXPERIMENTAL
+       select VIRTUALIZATION
        select VIRTIO
        select VIRTIO_RING
        select VIRTIO_CONSOLE
index 52420d2785b3607e1c682568358ea8f31a398d17..1d55c95f617c76d3f86784d34750395fb7573391 100644 (file)
@@ -262,7 +262,7 @@ void smp_ctl_set_bit(int cr, int bit)
 
        memset(&parms.orvals, 0, sizeof(parms.orvals));
        memset(&parms.andvals, 0xff, sizeof(parms.andvals));
-       parms.orvals[cr] = 1 << bit;
+       parms.orvals[cr] = 1UL << bit;
        on_each_cpu(smp_ctl_bit_callback, &parms, 1);
 }
 EXPORT_SYMBOL(smp_ctl_set_bit);
@@ -276,7 +276,7 @@ void smp_ctl_clear_bit(int cr, int bit)
 
        memset(&parms.orvals, 0, sizeof(parms.orvals));
        memset(&parms.andvals, 0xff, sizeof(parms.andvals));
-       parms.andvals[cr] = ~(1L << bit);
+       parms.andvals[cr] = ~(1UL << bit);
        on_each_cpu(smp_ctl_bit_callback, &parms, 1);
 }
 EXPORT_SYMBOL(smp_ctl_clear_bit);
index 5995e9bc72d9c291d57df38ab66c0a1929f43dd6..0e358c2cffeb5e6bf1955ba6ca2c3de7092e03b3 100644 (file)
@@ -25,7 +25,7 @@ extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth);
 
 #include "hwsampler.h"
 
-#define DEFAULT_INTERVAL       4096
+#define DEFAULT_INTERVAL       4127518
 
 #define DEFAULT_SDBT_BLOCKS    1
 #define DEFAULT_SDB_BLOCKS     511
@@ -151,6 +151,12 @@ static int oprofile_hwsampler_init(struct oprofile_operations *ops)
        if (oprofile_max_interval == 0)
                return -ENODEV;
 
+       /* The initial value should be sane */
+       if (oprofile_hw_interval < oprofile_min_interval)
+               oprofile_hw_interval = oprofile_min_interval;
+       if (oprofile_hw_interval > oprofile_max_interval)
+               oprofile_hw_interval = oprofile_max_interval;
+
        if (oprofile_timer_init(ops))
                return -ENODEV;
 
index 3a32741cc0ac34ad7adde46b27ec3beb2d47adb2..513cb1a2e6c830bc2d25cf27cf485ff8b37c37f8 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/usb/r8a66597.h>
+#include <linux/usb/renesas_usbhs.h>
 #include <linux/i2c.h>
 #include <linux/i2c/tsc2007.h>
 #include <linux/spi/spi.h>
@@ -232,6 +233,52 @@ static struct platform_device usb1_common_device = {
        .resource       = usb1_common_resources,
 };
 
+/*
+ * USBHS
+ */
+static int usbhs_get_id(struct platform_device *pdev)
+{
+       return gpio_get_value(GPIO_PTB3);
+}
+
+static struct renesas_usbhs_platform_info usbhs_info = {
+       .platform_callback = {
+               .get_id         = usbhs_get_id,
+       },
+       .driver_param = {
+               .buswait_bwait          = 4,
+               .detection_delay        = 5,
+       },
+};
+
+static struct resource usbhs_resources[] = {
+       [0] = {
+               .start  = 0xa4d90000,
+               .end    = 0xa4d90124 - 1,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 66,
+               .end    = 66,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device usbhs_device = {
+       .name   = "renesas_usbhs",
+       .id     = 1,
+       .dev = {
+               .dma_mask               = NULL,         /*  not use dma */
+               .coherent_dma_mask      = 0xffffffff,
+               .platform_data          = &usbhs_info,
+       },
+       .num_resources  = ARRAY_SIZE(usbhs_resources),
+       .resource       = usbhs_resources,
+       .archdata = {
+               .hwblk_id = HWBLK_USB1,
+       },
+};
+
 /* LCDC */
 const static struct fb_videomode ecovec_lcd_modes[] = {
        {
@@ -897,6 +944,7 @@ static struct platform_device *ecovec_devices[] __initdata = {
        &sh_eth_device,
        &usb0_host_device,
        &usb1_common_device,
+       &usbhs_device,
        &lcdc_device,
        &ceu0_device,
        &ceu1_device,
index 780e083e4d17fe6e2f55edf7793d24d57cb1559b..23bc849d9c64a2274924cbab5f29462c22402103 100644 (file)
@@ -27,8 +27,6 @@ IMAGE_OFFSET  := $(shell /bin/bash -c 'printf "0x%08x" \
                        $(CONFIG_BOOT_LINK_OFFSET)]')
 endif
 
-LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
-
 ifeq ($(CONFIG_MCOUNT),y)
 ORIG_CFLAGS := $(KBUILD_CFLAGS)
 KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
@@ -37,7 +35,25 @@ endif
 LDFLAGS_vmlinux := --oformat $(ld-bfd) -Ttext $(IMAGE_OFFSET) -e startup \
                   -T $(obj)/../../kernel/vmlinux.lds
 
-$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE
+#
+# Pull in the necessary libgcc bits from the in-kernel implementation.
+#
+lib1funcs-$(CONFIG_SUPERH32)   := ashiftrt.S ashldi3.c ashrsi3.S ashlsi3.S \
+                                  lshrsi3.S
+lib1funcs-obj                  := \
+       $(addsuffix .o, $(basename $(addprefix $(obj)/, $(lib1funcs-y))))
+
+lib1funcs-dir          := $(srctree)/arch/$(SRCARCH)/lib
+ifeq ($(BITS),64)
+       lib1funcs-dir   := $(addsuffix $(BITS), $(lib1funcs-dir))
+endif
+
+KBUILD_CFLAGS += -I$(lib1funcs-dir)
+
+$(addprefix $(obj)/,$(lib1funcs-y)): $(obj)/%: $(lib1funcs-dir)/% FORCE
+       $(call cmd,shipped)
+
+$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(lib1funcs-obj) FORCE
        $(call if_changed,ld)
        @:
 
index 0f558914e7604cc56a6822eeb2a2dec09c510abc..e2cbd92d520b347ca8e695cb2a8392dc72ac2794 100644 (file)
@@ -227,7 +227,7 @@ CONFIG_USB_SERIAL=m
 CONFIG_USB_SERIAL_GENERIC=y
 CONFIG_USB_SERIAL_ARK3116=m
 CONFIG_USB_SERIAL_PL2303=m
-CONFIG_RTC_CLASS=m
+CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_SH=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
index 4676bf57693a0ec3daf573d885731cfe7ed21963..f848dec9e483de8ed72cf3240c733d52f0da38e5 100644 (file)
@@ -15,8 +15,9 @@ static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val)
                "   mov.l   %2,   @%1     \n\t" /* store new value */
                "1: mov     r1,   r15     \n\t" /* LOGOUT */
                : "=&r" (retval),
-                 "+r"  (m)
-               : "r"   (val)
+                 "+r"  (m),
+                 "+r"  (val)           /* inhibit r15 overloading */
+               :
                : "memory", "r0", "r1");
 
        return retval;
@@ -36,8 +37,9 @@ static inline unsigned long xchg_u8(volatile u8 *m, unsigned long val)
                "   mov.b   %2,   @%1     \n\t" /* store new value */
                "1: mov     r1,   r15     \n\t" /* LOGOUT */
                : "=&r" (retval),
-                 "+r"  (m)
-               : "r"   (val)
+                 "+r"  (m),
+                 "+r"  (val)           /* inhibit r15 overloading */
+               :
                : "memory" , "r0", "r1");
 
        return retval;
@@ -54,13 +56,14 @@ static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old,
                "   nop                   \n\t"
                "   mov    r15,   r1      \n\t" /* r1 = saved sp */
                "   mov    #-8,   r15     \n\t" /* LOGIN */
-               "   mov.l  @%1,   %0      \n\t" /* load  old value */
-               "   cmp/eq  %0,   %2      \n\t"
+               "   mov.l  @%3,   %0      \n\t" /* load  old value */
+               "   cmp/eq  %0,   %1      \n\t"
                "   bf            1f      \n\t" /* if not equal */
-               "   mov.l   %3,   @%1     \n\t" /* store new value */
+               "   mov.l   %2,   @%3     \n\t" /* store new value */
                "1: mov     r1,   r15     \n\t" /* LOGOUT */
-               : "=&r" (retval)
-               :  "r"  (m), "r"  (old), "r"  (new)
+               : "=&r" (retval),
+                 "+r"  (old), "+r"  (new) /* old or new can be r15 */
+               :  "r"  (m)
                : "memory" , "r0", "r1", "t");
 
        return retval;
index 8887baff5effef0db2657c24f4a52eaf7cf89b0b..15a8496960e6a9987105939832b13c94f33aebaa 100644 (file)
@@ -9,10 +9,6 @@
 extern struct pglist_data *node_data[];
 #define NODE_DATA(nid)         (node_data[nid])
 
-#define node_start_pfn(nid)    (NODE_DATA(nid)->node_start_pfn)
-#define node_end_pfn(nid)      (NODE_DATA(nid)->node_start_pfn + \
-                                NODE_DATA(nid)->node_spanned_pages)
-
 static inline int pfn_to_nid(unsigned long pfn)
 {
        int nid;
index 2a541ddb5a1b2f907a00b6e4764a6f2ecc3bfafa..e25c4c7d6b63171221e247cea5f6ee45136efaf7 100644 (file)
@@ -150,7 +150,6 @@ struct thread_struct {
 #define SR_USER (SR_MMU | SR_FD)
 
 #define start_thread(_regs, new_pc, new_sp)                    \
-       set_fs(USER_DS);                                        \
        _regs->sr = SR_USER;    /* User mode. */                \
        _regs->pc = new_pc - 4; /* Compensate syscall exit */   \
        _regs->pc |= 1;         /* Set SHmedia ! */             \
index 3daef8ecbc635eaf47fe7eb6e63dd092d9125c11..cbc47e6bcab5474b4c675af5600da0c66da1883e 100644 (file)
@@ -298,6 +298,14 @@ enum {
        SHDMA_SLAVE_SCIF4_RX,
        SHDMA_SLAVE_SCIF5_TX,
        SHDMA_SLAVE_SCIF5_RX,
+       SHDMA_SLAVE_USB0D0_TX,
+       SHDMA_SLAVE_USB0D0_RX,
+       SHDMA_SLAVE_USB0D1_TX,
+       SHDMA_SLAVE_USB0D1_RX,
+       SHDMA_SLAVE_USB1D0_TX,
+       SHDMA_SLAVE_USB1D0_RX,
+       SHDMA_SLAVE_USB1D1_TX,
+       SHDMA_SLAVE_USB1D1_RX,
        SHDMA_SLAVE_SDHI0_TX,
        SHDMA_SLAVE_SDHI0_RX,
        SHDMA_SLAVE_SDHI1_TX,
index 0333fe9e3881913e82c5458b45e4f6aef5d867dd..134a397b1918e0898c6f839503fe0d9a4411c08c 100644 (file)
@@ -92,6 +92,46 @@ static const struct sh_dmae_slave_config sh7724_dmae_slaves[] = {
                .addr           = 0xa4e50024,
                .chcr           = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_8BIT),
                .mid_rid        = 0x36,
+       }, {
+               .slave_id       = SHDMA_SLAVE_USB0D0_TX,
+               .addr           = 0xA4D80100,
+               .chcr           = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+               .mid_rid        = 0x73,
+       }, {
+               .slave_id       = SHDMA_SLAVE_USB0D0_RX,
+               .addr           = 0xA4D80100,
+               .chcr           = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+               .mid_rid        = 0x73,
+       }, {
+               .slave_id       = SHDMA_SLAVE_USB0D1_TX,
+               .addr           = 0xA4D80120,
+               .chcr           = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+               .mid_rid        = 0x77,
+       }, {
+               .slave_id       = SHDMA_SLAVE_USB0D1_RX,
+               .addr           = 0xA4D80120,
+               .chcr           = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+               .mid_rid        = 0x77,
+       }, {
+               .slave_id       = SHDMA_SLAVE_USB1D0_TX,
+               .addr           = 0xA4D90100,
+               .chcr           = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+               .mid_rid        = 0xab,
+       }, {
+               .slave_id       = SHDMA_SLAVE_USB1D0_RX,
+               .addr           = 0xA4D90100,
+               .chcr           = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+               .mid_rid        = 0xab,
+       }, {
+               .slave_id       = SHDMA_SLAVE_USB1D1_TX,
+               .addr           = 0xA4D90120,
+               .chcr           = DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+               .mid_rid        = 0xaf,
+       }, {
+               .slave_id       = SHDMA_SLAVE_USB1D1_RX,
+               .addr           = 0xA4D90120,
+               .chcr           = DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL(XMIT_SZ_32BIT),
+               .mid_rid        = 0xaf,
        }, {
                .slave_id       = SHDMA_SLAVE_SDHI0_TX,
                .addr           = 0x04ce0030,
index b473f0c06fbc11bf545f66b84bd0a566fb344286..aaf6d59c201227b52c431e6be891868d756a5fda 100644 (file)
@@ -102,8 +102,6 @@ EXPORT_SYMBOL(kernel_thread);
 void start_thread(struct pt_regs *regs, unsigned long new_pc,
                  unsigned long new_sp)
 {
-       set_fs(USER_DS);
-
        regs->pr = 0;
        regs->sr = SR_FD;
        regs->pc = new_pc;
index 52411462c4096f973243e5c05acc9ebfc357819a..115725198038da862a19ef634a0ec38adf23b76f 100644 (file)
@@ -26,9 +26,9 @@ static int cache_seq_show(struct seq_file *file, void *iter)
 {
        unsigned int cache_type = (unsigned int)file->private;
        struct cache_info *cache;
-       unsigned int waysize, way, cache_size;
-       unsigned long ccr, base;
-       static unsigned long addrstart = 0;
+       unsigned int waysize, way;
+       unsigned long ccr;
+       unsigned long addrstart = 0;
 
        /*
         * Go uncached immediately so we don't skew the results any
@@ -45,28 +45,13 @@ static int cache_seq_show(struct seq_file *file, void *iter)
        }
 
        if (cache_type == CACHE_TYPE_DCACHE) {
-               base = CACHE_OC_ADDRESS_ARRAY;
+               addrstart = CACHE_OC_ADDRESS_ARRAY;
                cache = &current_cpu_data.dcache;
        } else {
-               base = CACHE_IC_ADDRESS_ARRAY;
+               addrstart = CACHE_IC_ADDRESS_ARRAY;
                cache = &current_cpu_data.icache;
        }
 
-       /*
-        * Due to the amount of data written out (depending on the cache size),
-        * we may be iterated over multiple times. In this case, keep track of
-        * the entry position in addrstart, and rewind it when we've hit the
-        * end of the cache.
-        *
-        * Likewise, the same code is used for multiple caches, so care must
-        * be taken for bouncing addrstart back and forth so the appropriate
-        * cache is hit.
-        */
-       cache_size = cache->ways * cache->sets * cache->linesz;
-       if (((addrstart & 0xff000000) != base) ||
-            (addrstart & 0x00ffffff) > cache_size)
-               addrstart = base;
-
        waysize = cache->sets;
 
        /*
index e8c648741ed4d12a52949f095257d3aec6176850..99d9b9f577bfb15826faa7e5b488f3e76d7f81d7 100644 (file)
@@ -8,8 +8,6 @@
 extern struct pglist_data *node_data[];
 
 #define NODE_DATA(nid)         (node_data[nid])
-#define node_start_pfn(nid)    (NODE_DATA(nid)->node_start_pfn)
-#define node_end_pfn(nid)      (NODE_DATA(nid)->node_end_pfn)
 
 extern int numa_cpu_lookup_table[];
 extern cpumask_t numa_cpumask_lookup_table[];
index c6344c4f32ac17ddf27dcbcd5563a302708052c2..9d3dbce8f953167aca40e12eb56dc376ee0acc73 100644 (file)
@@ -40,17 +40,6 @@ static inline int pfn_to_nid(unsigned long pfn)
        return highbits_to_node[__pfn_to_highbits(pfn)];
 }
 
-/*
- * Following are macros that each numa implmentation must define.
- */
-
-#define node_start_pfn(nid)    (NODE_DATA(nid)->node_start_pfn)
-#define node_end_pfn(nid)                                              \
-({                                                                     \
-       pg_data_t *__pgdat = NODE_DATA(nid);                            \
-       __pgdat->node_start_pfn + __pgdat->node_spanned_pages;          \
-})
-
 #define kern_addr_valid(kaddr) virt_addr_valid((void *)kaddr)
 
 static inline int pfn_valid(int pfn)
diff --git a/arch/um/include/asm/percpu.h b/arch/um/include/asm/percpu.h
new file mode 100644 (file)
index 0000000..efe7508
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __UM_PERCPU_H
+#define __UM_PERCPU_H
+
+#include <asm-generic/percpu.h>
+
+#endif /* __UM_PERCPU_H */
index 19ae14ba69780c38defd3fbcfe7fdcb05859f9c0..0cd3800f33b9dcf68e39a1288ebf7ccd442f3a97 100644 (file)
@@ -4,7 +4,6 @@
 #define ARCH_DISCARD_MEMBLOCK
 
 u64 memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align);
-void memblock_x86_to_bootmem(u64 start, u64 end);
 
 void memblock_x86_reserve_range(u64 start, u64 end, char *name);
 void memblock_x86_free_range(u64 start, u64 end);
@@ -19,5 +18,6 @@ u64 memblock_x86_hole_size(u64 start, u64 end);
 u64 memblock_x86_find_in_range_node(int nid, u64 start, u64 end, u64 size, u64 align);
 u64 memblock_x86_free_memory_in_range(u64 addr, u64 limit);
 u64 memblock_x86_memory_in_range(u64 addr, u64 limit);
+bool memblock_x86_check_reserved_size(u64 *addrp, u64 *sizep, u64 align);
 
 #endif
index 5e83a416eca8941410c0b93a99beff853831f433..224e8c5eb3070351fe06a6838a611b6a5a1799bb 100644 (file)
@@ -48,17 +48,6 @@ static inline int pfn_to_nid(unsigned long pfn)
 #endif
 }
 
-/*
- * Following are macros that each numa implmentation must define.
- */
-
-#define node_start_pfn(nid)    (NODE_DATA(nid)->node_start_pfn)
-#define node_end_pfn(nid)                                              \
-({                                                                     \
-       pg_data_t *__pgdat = NODE_DATA(nid);                            \
-       __pgdat->node_start_pfn + __pgdat->node_spanned_pages;          \
-})
-
 static inline int pfn_valid(int pfn)
 {
        int nid = pfn_to_nid(pfn);
index b3f88d7867c79235372b5ad6f5cfc6edd254a083..129d9aa3ceb3646665370b37bdae1e7665b906a4 100644 (file)
@@ -13,8 +13,5 @@ extern struct pglist_data *node_data[];
 
 #define NODE_DATA(nid)         (node_data[nid])
 
-#define node_start_pfn(nid)    (NODE_DATA(nid)->node_start_pfn)
-#define node_end_pfn(nid)       (NODE_DATA(nid)->node_start_pfn +      \
-                                NODE_DATA(nid)->node_spanned_pages)
 #endif
 #endif /* _ASM_X86_MMZONE_64_H */
index 31d84acc15125646018914b51a758821ec796590..a518c0a4504465e6ac46068ba6d34a68d66a6fd3 100644 (file)
@@ -22,6 +22,8 @@ static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift)
        u64 product;
 #ifdef __i386__
        u32 tmp1, tmp2;
+#else
+       ulong tmp;
 #endif
 
        if (shift < 0)
@@ -42,8 +44,11 @@ static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift)
                : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) );
 #elif defined(__x86_64__)
        __asm__ (
-               "mul %%rdx ; shrd $32,%%rdx,%%rax"
-               : "=a" (product) : "0" (delta), "d" ((u64)mul_frac) );
+               "mul %[mul_frac] ; shrd $32, %[hi], %[lo]"
+               : [lo]"=a"(product),
+                 [hi]"=d"(tmp)
+               : "0"(delta),
+                 [mul_frac]"rm"((u64)mul_frac));
 #else
 #error implement me!
 #endif
index b511a011b7d08f31405371445c00271abfdeed54..adc66c3a1fef2417be8741d334d5f8460c23ff10 100644 (file)
@@ -632,14 +632,14 @@ late_initcall(uv_init_heartbeat);
 
 /* Direct Legacy VGA I/O traffic to designated IOH */
 int uv_set_vga_state(struct pci_dev *pdev, bool decode,
-                     unsigned int command_bits, bool change_bridge)
+                     unsigned int command_bits, u32 flags)
 {
        int domain, bus, rc;
 
-       PR_DEVEL("devfn %x decode %d cmd %x chg_brdg %d\n",
-                       pdev->devfn, decode, command_bits, change_bridge);
+       PR_DEVEL("devfn %x decode %d cmd %x flags %d\n",
+                       pdev->devfn, decode, command_bits, flags);
 
-       if (!change_bridge)
+       if (!(flags & PCI_VGA_STATE_CHANGE_BRIDGE))
                return 0;
 
        if ((command_bits & PCI_COMMAND_IO) == 0)
index 2e4928d45a2dd476d89904778df6ac2dbf5e681c..e1ba8cb24e4edb6629a9107312c071739c32de75 100644 (file)
@@ -337,7 +337,7 @@ EXPORT_SYMBOL(boot_option_idle_override);
  * Powermanagement idle function, if any..
  */
 void (*pm_idle)(void);
-#if defined(CONFIG_APM_MODULE) && defined(CONFIG_APM_CPU_IDLE)
+#ifdef CONFIG_APM_MODULE
 EXPORT_SYMBOL(pm_idle);
 #endif
 
@@ -399,7 +399,7 @@ void default_idle(void)
                cpu_relax();
        }
 }
-#if defined(CONFIG_APM_MODULE) && defined(CONFIG_APM_CPU_IDLE)
+#ifdef CONFIG_APM_MODULE
 EXPORT_SYMBOL(default_idle);
 #endif
 
index bd14bb4c8594c4cb7b8375e6567e6a0aa56c61cc..aee38623b768edae62394fc09c64742f54b5b955 100644 (file)
@@ -565,7 +565,7 @@ gfn_to_memslot_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t gfn,
 
 static bool mapping_level_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t large_gfn)
 {
-       return gfn_to_memslot_dirty_bitmap(vcpu, large_gfn, true);
+       return !gfn_to_memslot_dirty_bitmap(vcpu, large_gfn, true);
 }
 
 static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn)
index 6c4dc010c4cbfdc2dd49f1e82696022373e817fd..9d03ad4dd5ec95366b1e5b22ccf76c8a737a7155 100644 (file)
@@ -121,7 +121,7 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
                                    gva_t addr, u32 access)
 {
        pt_element_t pte;
-       pt_element_t __user *ptep_user;
+       pt_element_t __user *uninitialized_var(ptep_user);
        gfn_t table_gfn;
        unsigned index, pt_access, uninitialized_var(pte_access);
        gpa_t pte_gpa;
index 4c3fa0f6746970cef9bb5d26e5808d8bbdabcb1f..d48ec60ea421a8211271195db0193bc42a9a7532 100644 (file)
@@ -2047,7 +2047,8 @@ static void ept_update_paging_mode_cr0(unsigned long *hw_cr0,
                                        unsigned long cr0,
                                        struct kvm_vcpu *vcpu)
 {
-       vmx_decache_cr3(vcpu);
+       if (!test_bit(VCPU_EXREG_CR3, (ulong *)&vcpu->arch.regs_avail))
+               vmx_decache_cr3(vcpu);
        if (!(cr0 & X86_CR0_PG)) {
                /* From paging/starting to nonpaging */
                vmcs_write32(CPU_BASED_VM_EXEC_CONTROL,
index aa1169392b83eb44350ec5da13cd23bfc3477986..992da5ec5a64d69ddc3381d9e8508e4d6061d4ef 100644 (file)
@@ -8,7 +8,7 @@
 #include <linux/range.h>
 
 /* Check for already reserved areas */
-static bool __init check_with_memblock_reserved_size(u64 *addrp, u64 *sizep, u64 align)
+bool __init memblock_x86_check_reserved_size(u64 *addrp, u64 *sizep, u64 align)
 {
        struct memblock_region *r;
        u64 addr = *addrp, last;
@@ -59,7 +59,7 @@ u64 __init memblock_x86_find_in_range_size(u64 start, u64 *sizep, u64 align)
                if (addr >= ei_last)
                        continue;
                *sizep = ei_last - addr;
-               while (check_with_memblock_reserved_size(&addr, sizep, align))
+               while (memblock_x86_check_reserved_size(&addr, sizep, align))
                        ;
 
                if (*sizep)
index 0972315c3860c40c719f1b03081b892c3e8f20bf..68c3c1395202eec5ad68bfc584d14ee9f4c1975e 100644 (file)
@@ -188,7 +188,7 @@ static bool resource_contains(struct resource *res, resource_size_t point)
        return false;
 }
 
-static void coalesce_windows(struct pci_root_info *info, int type)
+static void coalesce_windows(struct pci_root_info *info, unsigned long type)
 {
        int i, j;
        struct resource *res1, *res2;
index 0d3a4fa34560018c55a2619251bcb0db6546c4d1..474356b98ede32e647d4343c32a7e7893fe4beff 100644 (file)
@@ -310,14 +310,31 @@ void __init efi_reserve_boot_services(void)
 
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
                efi_memory_desc_t *md = p;
-               unsigned long long start = md->phys_addr;
-               unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
+               u64 start = md->phys_addr;
+               u64 size = md->num_pages << EFI_PAGE_SHIFT;
 
                if (md->type != EFI_BOOT_SERVICES_CODE &&
                    md->type != EFI_BOOT_SERVICES_DATA)
                        continue;
-
-               memblock_x86_reserve_range(start, start + size, "EFI Boot");
+               /* Only reserve where possible:
+                * - Not within any already allocated areas
+                * - Not over any memory area (really needed, if above?)
+                * - Not within any part of the kernel
+                * - Not the bios reserved area
+               */
+               if ((start+size >= virt_to_phys(_text)
+                               && start <= virt_to_phys(_end)) ||
+                       !e820_all_mapped(start, start+size, E820_RAM) ||
+                       memblock_x86_check_reserved_size(&start, &size,
+                                                       1<<EFI_PAGE_SHIFT)) {
+                       /* Could not reserve, skip it */
+                       md->num_pages = 0;
+                       memblock_dbg(PFX "Could not reserve boot range "
+                                       "[0x%010llx-0x%010llx]\n",
+                                               start, start+size-1);
+               } else
+                       memblock_x86_reserve_range(start, start+size,
+                                                       "EFI Boot");
        }
 }
 
@@ -334,6 +351,10 @@ static void __init efi_free_boot_services(void)
                    md->type != EFI_BOOT_SERVICES_DATA)
                        continue;
 
+               /* Could not reserve boot area */
+               if (!size)
+                       continue;
+
                free_bootmem_late(start, size);
        }
 }
index dd7b88f2ec7a6f30bf4ec628fc7f59112cf4d65e..5525163a03985a517e7a043c3daa92fe04d4bb6e 100644 (file)
@@ -1033,6 +1033,13 @@ static void xen_machine_halt(void)
        xen_reboot(SHUTDOWN_poweroff);
 }
 
+static void xen_machine_power_off(void)
+{
+       if (pm_power_off)
+               pm_power_off();
+       xen_reboot(SHUTDOWN_poweroff);
+}
+
 static void xen_crash_shutdown(struct pt_regs *regs)
 {
        xen_reboot(SHUTDOWN_crash);
@@ -1058,7 +1065,7 @@ int xen_panic_handler_init(void)
 static const struct machine_ops xen_machine_ops __initconst = {
        .restart = xen_restart,
        .halt = xen_machine_halt,
-       .power_off = xen_machine_halt,
+       .power_off = xen_machine_power_off,
        .shutdown = xen_machine_halt,
        .crash_shutdown = xen_crash_shutdown,
        .emergency_restart = xen_emergency_restart,
index dc708dcc62f1e5106fefebd390bc24bb1cf97cf1..673e968df3cfd6c67a1b8a9dc3885fcaad15249f 100644 (file)
@@ -59,6 +59,7 @@
 #include <asm/page.h>
 #include <asm/init.h>
 #include <asm/pat.h>
+#include <asm/smp.h>
 
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
@@ -1231,7 +1232,7 @@ static void xen_flush_tlb_others(const struct cpumask *cpus,
 {
        struct {
                struct mmuext_op op;
-               DECLARE_BITMAP(mask, NR_CPUS);
+               DECLARE_BITMAP(mask, num_processors);
        } *args;
        struct multicall_space mcs;
 
@@ -1599,6 +1600,11 @@ static void __init xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)
                for (pteidx = 0; pteidx < PTRS_PER_PTE; pteidx++, pfn++) {
                        pte_t pte;
 
+#ifdef CONFIG_X86_32
+                       if (pfn > max_pfn_mapped)
+                               max_pfn_mapped = pfn;
+#endif
+
                        if (!pte_none(pte_page[pteidx]))
                                continue;
 
@@ -1766,7 +1772,9 @@ pgd_t * __init xen_setup_kernel_pagetable(pgd_t *pgd,
        initial_kernel_pmd =
                extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
 
-       max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list));
+       max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) +
+                                 xen_start_info->nr_pt_frames * PAGE_SIZE +
+                                 512*1024);
 
        kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd);
        memcpy(initial_kernel_pmd, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
index be1a464f6d66eac7f6d24ae74894b321dc1cd4b5..60aeeb56948f753f87559f3e4ff8c1f8704d21a4 100644 (file)
@@ -227,11 +227,7 @@ char * __init xen_memory_setup(void)
 
        memcpy(map_raw, map, sizeof(map));
        e820.nr_map = 0;
-#ifdef CONFIG_X86_32
        xen_extra_mem_start = mem_end;
-#else
-       xen_extra_mem_start = max((1ULL << 32), mem_end);
-#endif
        for (i = 0; i < memmap.nr_entries; i++) {
                unsigned long long end;
 
@@ -266,6 +262,12 @@ char * __init xen_memory_setup(void)
                if (map[i].size > 0)
                        e820_add_region(map[i].addr, map[i].size, map[i].type);
        }
+       /* Align the balloon area so that max_low_pfn does not get set
+        * to be at the _end_ of the PCI gap at the far end (fee01000).
+        * Note that xen_extra_mem_start gets set in the loop above to be
+        * past the last E820 region. */
+       if (xen_initial_domain() && (xen_extra_mem_start < (1ULL<<32)))
+               xen_extra_mem_start = (1ULL<<32);
 
        /*
         * In domU, the ISA region is normal, usable memory, but we
index 41038c01de403e48c71052ab615dcf7f647f2653..b4533a86d7e410668e24033cae32d8382bf4111d 100644 (file)
@@ -205,11 +205,18 @@ static void __init xen_smp_prepare_boot_cpu(void)
 static void __init xen_smp_prepare_cpus(unsigned int max_cpus)
 {
        unsigned cpu;
+       unsigned int i;
 
        xen_init_lock_cpu(0);
 
        smp_store_cpu_info(0);
        cpu_data(0).x86_max_cores = 1;
+
+       for_each_possible_cpu(i) {
+               zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL);
+               zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL);
+               zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL);
+       }
        set_cpu_sibling_map(0);
 
        if (xen_smp_intr_init(0))
index a62be8d0dc1b34cfdf832947856669a8ee449a84..3689f833afdc57c12916e2fc985ef8c18ccc2904 100644 (file)
@@ -927,7 +927,7 @@ static int throtl_dispatch(struct request_queue *q)
 
        bio_list_init(&bio_list_on_stack);
 
-       throtl_log(td, "dispatch nr_queued=%lu read=%u write=%u",
+       throtl_log(td, "dispatch nr_queued=%d read=%u write=%u",
                        total_nr_queued(td), td->nr_queued[READ],
                        td->nr_queued[WRITE]);
 
@@ -1204,7 +1204,7 @@ int blk_throtl_bio(struct request_queue *q, struct bio **biop)
        }
 
 queue_bio:
-       throtl_log_tg(td, tg, "[%c] bio. bdisp=%u sz=%u bps=%llu"
+       throtl_log_tg(td, tg, "[%c] bio. bdisp=%llu sz=%u bps=%llu"
                        " iodisp=%u iops=%u queued=%d/%d",
                        rw == READ ? 'R' : 'W',
                        tg->bytes_disp[rw], bio->bi_size, tg->bps[rw],
index 3c7b537bf9081f9f43b90c7cdcd9a95073f1c02b..f3799432676d53cc3648c9ab6801fe4fd084b911 100644 (file)
@@ -988,9 +988,10 @@ static void cfq_group_served(struct cfq_data *cfqd, struct cfq_group *cfqg,
 
        cfq_log_cfqg(cfqd, cfqg, "served: vt=%llu min_vt=%llu", cfqg->vdisktime,
                                        st->min_vdisktime);
-       cfq_log_cfqq(cfqq->cfqd, cfqq, "sl_used=%u disp=%u charge=%u iops=%u"
-                       " sect=%u", used_sl, cfqq->slice_dispatch, charge,
-                       iops_mode(cfqd), cfqq->nr_sectors);
+       cfq_log_cfqq(cfqq->cfqd, cfqq,
+                    "sl_used=%u disp=%u charge=%u iops=%u sect=%lu",
+                    used_sl, cfqq->slice_dispatch, charge,
+                    iops_mode(cfqd), cfqq->nr_sectors);
        cfq_blkiocg_update_timeslice_used(&cfqg->blkg, used_sl,
                                          unaccounted_sl);
        cfq_blkiocg_set_start_empty_time(&cfqg->blkg);
@@ -2023,8 +2024,8 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
         */
        if (sample_valid(cic->ttime_samples) &&
            (cfqq->slice_end - jiffies < cic->ttime_mean)) {
-               cfq_log_cfqq(cfqd, cfqq, "Not idling. think_time:%d",
-                               cic->ttime_mean);
+               cfq_log_cfqq(cfqd, cfqq, "Not idling. think_time:%lu",
+                            cic->ttime_mean);
                return;
        }
 
@@ -2772,8 +2773,11 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd,
        smp_wmb();
        cic->key = cfqd_dead_key(cfqd);
 
-       if (ioc->ioc_data == cic)
+       if (rcu_dereference(ioc->ioc_data) == cic) {
+               spin_lock(&ioc->lock);
                rcu_assign_pointer(ioc->ioc_data, NULL);
+               spin_unlock(&ioc->lock);
+       }
 
        if (cic->cfqq[BLK_RW_ASYNC]) {
                cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_ASYNC]);
index 50b61c39f66ebad6d3cd005d3d02fea38f8474b8..cbf7b880e9d4701cf4745fad3fc1ec4b4d5e44b6 100644 (file)
@@ -1388,6 +1388,7 @@ struct disk_events {
        struct gendisk          *disk;          /* the associated disk */
        spinlock_t              lock;
 
+       struct mutex            block_mutex;    /* protects blocking */
        int                     block;          /* event blocking depth */
        unsigned int            pending;        /* events already sent out */
        unsigned int            clearing;       /* events being cleared */
@@ -1431,22 +1432,44 @@ static unsigned long disk_events_poll_jiffies(struct gendisk *disk)
        return msecs_to_jiffies(intv_msecs);
 }
 
-static void __disk_block_events(struct gendisk *disk, bool sync)
+/**
+ * disk_block_events - block and flush disk event checking
+ * @disk: disk to block events for
+ *
+ * On return from this function, it is guaranteed that event checking
+ * isn't in progress and won't happen until unblocked by
+ * disk_unblock_events().  Events blocking is counted and the actual
+ * unblocking happens after the matching number of unblocks are done.
+ *
+ * Note that this intentionally does not block event checking from
+ * disk_clear_events().
+ *
+ * CONTEXT:
+ * Might sleep.
+ */
+void disk_block_events(struct gendisk *disk)
 {
        struct disk_events *ev = disk->ev;
        unsigned long flags;
        bool cancel;
 
+       if (!ev)
+               return;
+
+       /*
+        * Outer mutex ensures that the first blocker completes canceling
+        * the event work before further blockers are allowed to finish.
+        */
+       mutex_lock(&ev->block_mutex);
+
        spin_lock_irqsave(&ev->lock, flags);
        cancel = !ev->block++;
        spin_unlock_irqrestore(&ev->lock, flags);
 
-       if (cancel) {
-               if (sync)
-                       cancel_delayed_work_sync(&disk->ev->dwork);
-               else
-                       cancel_delayed_work(&disk->ev->dwork);
-       }
+       if (cancel)
+               cancel_delayed_work_sync(&disk->ev->dwork);
+
+       mutex_unlock(&ev->block_mutex);
 }
 
 static void __disk_unblock_events(struct gendisk *disk, bool check_now)
@@ -1477,27 +1500,6 @@ out_unlock:
        spin_unlock_irqrestore(&ev->lock, flags);
 }
 
-/**
- * disk_block_events - block and flush disk event checking
- * @disk: disk to block events for
- *
- * On return from this function, it is guaranteed that event checking
- * isn't in progress and won't happen until unblocked by
- * disk_unblock_events().  Events blocking is counted and the actual
- * unblocking happens after the matching number of unblocks are done.
- *
- * Note that this intentionally does not block event checking from
- * disk_clear_events().
- *
- * CONTEXT:
- * Might sleep.
- */
-void disk_block_events(struct gendisk *disk)
-{
-       if (disk->ev)
-               __disk_block_events(disk, true);
-}
-
 /**
  * disk_unblock_events - unblock disk event checking
  * @disk: disk to unblock events for
@@ -1525,10 +1527,18 @@ void disk_unblock_events(struct gendisk *disk)
  */
 void disk_check_events(struct gendisk *disk)
 {
-       if (disk->ev) {
-               __disk_block_events(disk, false);
-               __disk_unblock_events(disk, true);
+       struct disk_events *ev = disk->ev;
+       unsigned long flags;
+
+       if (!ev)
+               return;
+
+       spin_lock_irqsave(&ev->lock, flags);
+       if (!ev->block) {
+               cancel_delayed_work(&ev->dwork);
+               queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
        }
+       spin_unlock_irqrestore(&ev->lock, flags);
 }
 EXPORT_SYMBOL_GPL(disk_check_events);
 
@@ -1563,7 +1573,7 @@ unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask)
        spin_unlock_irq(&ev->lock);
 
        /* uncondtionally schedule event check and wait for it to finish */
-       __disk_block_events(disk, true);
+       disk_block_events(disk);
        queue_delayed_work(system_nrt_wq, &ev->dwork, 0);
        flush_delayed_work(&ev->dwork);
        __disk_unblock_events(disk, false);
@@ -1681,7 +1691,7 @@ static ssize_t disk_events_poll_msecs_store(struct device *dev,
        if (intv < 0 && intv != -1)
                return -EINVAL;
 
-       __disk_block_events(disk, true);
+       disk_block_events(disk);
        disk->ev->poll_msecs = intv;
        __disk_unblock_events(disk, true);
 
@@ -1767,6 +1777,7 @@ static void disk_add_events(struct gendisk *disk)
        INIT_LIST_HEAD(&ev->node);
        ev->disk = disk;
        spin_lock_init(&ev->lock);
+       mutex_init(&ev->block_mutex);
        ev->block = 1;
        ev->poll_msecs = -1;
        INIT_DELAYED_WORK(&ev->dwork, disk_events_workfn);
@@ -1787,7 +1798,7 @@ static void disk_del_events(struct gendisk *disk)
        if (!disk->ev)
                return;
 
-       __disk_block_events(disk, true);
+       disk_block_events(disk);
 
        mutex_lock(&disk_events_mutex);
        list_del_init(&disk->ev->node);
index 736bee5dafebcffc3e13bcf9f8a4b48d13680903..000d03ae6653d7ad294d7477ab84d254d7e2f012 100644 (file)
@@ -4143,9 +4143,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
         * Devices which choke on SETXFER.  Applies only if both the
         * device and controller are SATA.
         */
-       { "PIONEER DVD-RW  DVRTD08",    "1.00", ATA_HORKAGE_NOSETXFER },
-       { "PIONEER DVD-RW  DVR-212D",   "1.28", ATA_HORKAGE_NOSETXFER },
-       { "PIONEER DVD-RW  DVR-216D",   "1.08", ATA_HORKAGE_NOSETXFER },
+       { "PIONEER DVD-RW  DVRTD08",    NULL,   ATA_HORKAGE_NOSETXFER },
+       { "PIONEER DVD-RW  DVR-212D",   NULL,   ATA_HORKAGE_NOSETXFER },
+       { "PIONEER DVD-RW  DVR-216D",   NULL,   ATA_HORKAGE_NOSETXFER },
 
        /* End Marker */
        { }
index d51f9795c064bbc20b1b4c2a48bc277f09980060..927f968e99d9f8b4dd896c8c8eb5f521fb1cff72 100644 (file)
@@ -3797,6 +3797,12 @@ EXPORT_SYMBOL_GPL(ata_sas_port_alloc);
  */
 int ata_sas_port_start(struct ata_port *ap)
 {
+       /*
+        * the port is marked as frozen at allocation time, but if we don't
+        * have new eh, we won't thaw it
+        */
+       if (!ap->ops->error_handler)
+               ap->pflags &= ~ATA_PFLAG_FROZEN;
        return 0;
 }
 EXPORT_SYMBOL_GPL(ata_sas_port_start);
index 75a6a0c0094fb1b8220a50ddd2cc94765003c18b..5d7f58a7e34dba624e5319cbdf15aab24a1f3ea6 100644 (file)
@@ -161,6 +161,9 @@ static const struct pci_device_id marvell_pci_tbl[] = {
        { PCI_DEVICE(0x11AB, 0x6121), },
        { PCI_DEVICE(0x11AB, 0x6123), },
        { PCI_DEVICE(0x11AB, 0x6145), },
+       { PCI_DEVICE(0x1B4B, 0x91A0), },
+       { PCI_DEVICE(0x1B4B, 0x91A4), },
+
        { }     /* terminate list */
 };
 
index 1c4b3aa4c7c40da65c8c6f86f936be6891839e6c..dc88a39e7db8b04c9a2ec3e85ed888ee90194e69 100644 (file)
@@ -389,7 +389,7 @@ static void sata_dwc_tf_dump(struct ata_taskfile *tf)
 /*
  * Function: get_burst_length_encode
  * arguments: datalength: length in bytes of data
- * returns value to be programmed in register corrresponding to data length
+ * returns value to be programmed in register corresponding to data length
  * This value is effectively the log(base 2) of the length
  */
 static  int get_burst_length_encode(int datalength)
index eaa8a854af03f6d4adc902fece195e7aabb69fd6..ad367c4139b14ead6102ed2e31d03f52c63d1fcf 100644 (file)
@@ -387,7 +387,7 @@ static int pm_runtime_clk_notify(struct notifier_block *nb,
        clknb = container_of(nb, struct pm_clk_notifier_block, nb);
 
        switch (action) {
-       case BUS_NOTIFY_ADD_DEVICE:
+       case BUS_NOTIFY_BIND_DRIVER:
                if (clknb->con_ids[0]) {
                        for (con_id = clknb->con_ids; *con_id; con_id++)
                                enable_clock(dev, *con_id);
@@ -395,7 +395,7 @@ static int pm_runtime_clk_notify(struct notifier_block *nb,
                        enable_clock(dev, NULL);
                }
                break;
-       case BUS_NOTIFY_DEL_DEVICE:
+       case BUS_NOTIFY_UNBOUND_DRIVER:
                if (clknb->con_ids[0]) {
                        for (con_id = clknb->con_ids; *con_id; con_id++)
                                disable_clock(dev, *con_id);
index 06e43912a973cc057d6887342e2c69107f66fe99..4282d442d35231c83c74dab5cbc5ee3bf4a696ef 100644 (file)
@@ -64,7 +64,8 @@ static int async_error;
  */
 void device_pm_init(struct device *dev)
 {
-       dev->power.in_suspend = false;
+       dev->power.is_prepared = false;
+       dev->power.is_suspended = false;
        init_completion(&dev->power.completion);
        complete_all(&dev->power.completion);
        dev->power.wakeup = NULL;
@@ -98,7 +99,7 @@ void device_pm_add(struct device *dev)
        pr_debug("PM: Adding info for %s:%s\n",
                 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
        mutex_lock(&dpm_list_mtx);
-       if (dev->parent && dev->parent->power.in_suspend)
+       if (dev->parent && dev->parent->power.is_prepared)
                dev_warn(dev, "parent %s should not be sleeping\n",
                        dev_name(dev->parent));
        list_add_tail(&dev->power.entry, &dpm_list);
@@ -518,7 +519,14 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
        dpm_wait(dev->parent, async);
        device_lock(dev);
 
-       dev->power.in_suspend = false;
+       /*
+        * This is a fib.  But we'll allow new children to be added below
+        * a resumed device, even if the device hasn't been completed yet.
+        */
+       dev->power.is_prepared = false;
+
+       if (!dev->power.is_suspended)
+               goto Unlock;
 
        if (dev->pwr_domain) {
                pm_dev_dbg(dev, state, "power domain ");
@@ -555,6 +563,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
        }
 
  End:
+       dev->power.is_suspended = false;
+
+ Unlock:
        device_unlock(dev);
        complete_all(&dev->power.completion);
 
@@ -701,7 +712,7 @@ void dpm_complete(pm_message_t state)
                struct device *dev = to_device(dpm_prepared_list.prev);
 
                get_device(dev);
-               dev->power.in_suspend = false;
+               dev->power.is_prepared = false;
                list_move(&dev->power.entry, &list);
                mutex_unlock(&dpm_list_mtx);
 
@@ -877,11 +888,11 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
        device_lock(dev);
 
        if (async_error)
-               goto End;
+               goto Unlock;
 
        if (pm_wakeup_pending()) {
                async_error = -EBUSY;
-               goto End;
+               goto Unlock;
        }
 
        if (dev->pwr_domain) {
@@ -919,6 +930,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
        }
 
  End:
+       dev->power.is_suspended = !error;
+
+ Unlock:
        device_unlock(dev);
 
        del_timer_sync(&timer);
@@ -1088,7 +1102,7 @@ int dpm_prepare(pm_message_t state)
                        put_device(dev);
                        break;
                }
-               dev->power.in_suspend = true;
+               dev->power.is_prepared = true;
                if (!list_empty(&dev->power.entry))
                        list_move_tail(&dev->power.entry, &dpm_prepared_list);
                put_device(dev);
index fd6305bf953e4084c9b7557a26acb002deb101fe..8ecf4c6c28740243979920dd98ea7bdc638e5172 100644 (file)
@@ -64,6 +64,8 @@ static ssize_t btmrvl_hscfgcmd_write(struct file *file,
                return -EFAULT;
 
        ret = strict_strtol(buf, 10, &result);
+       if (ret)
+               return ret;
 
        priv->btmrvl_dev.hscfgcmd = result;
 
@@ -108,6 +110,8 @@ static ssize_t btmrvl_psmode_write(struct file *file, const char __user *ubuf,
                return -EFAULT;
 
        ret = strict_strtol(buf, 10, &result);
+       if (ret)
+               return ret;
 
        priv->btmrvl_dev.psmode = result;
 
@@ -147,6 +151,8 @@ static ssize_t btmrvl_pscmd_write(struct file *file, const char __user *ubuf,
                return -EFAULT;
 
        ret = strict_strtol(buf, 10, &result);
+       if (ret)
+               return ret;
 
        priv->btmrvl_dev.pscmd = result;
 
@@ -191,6 +197,8 @@ static ssize_t btmrvl_gpiogap_write(struct file *file, const char __user *ubuf,
                return -EFAULT;
 
        ret = strict_strtol(buf, 16, &result);
+       if (ret)
+               return ret;
 
        priv->btmrvl_dev.gpio_gap = result;
 
@@ -230,6 +238,8 @@ static ssize_t btmrvl_hscmd_write(struct file *file, const char __user *ubuf,
                return -EFAULT;
 
        ret = strict_strtol(buf, 10, &result);
+       if (ret)
+               return ret;
 
        priv->btmrvl_dev.hscmd = result;
        if (priv->btmrvl_dev.hscmd) {
@@ -272,6 +282,8 @@ static ssize_t btmrvl_hsmode_write(struct file *file, const char __user *ubuf,
                return -EFAULT;
 
        ret = strict_strtol(buf, 10, &result);
+       if (ret)
+               return ret;
 
        priv->btmrvl_dev.hsmode = result;
 
index 051474c65b783c5e9f3315de2fb3732516810027..34d6a1cab8def622d95c46b138b02a7d8a0eeeec 100644 (file)
@@ -163,11 +163,32 @@ static irqreturn_t hpet_interrupt(int irq, void *data)
         * This has the effect of treating non-periodic like periodic.
         */
        if ((devp->hd_flags & (HPET_IE | HPET_PERIODIC)) == HPET_IE) {
-               unsigned long m, t;
+               unsigned long m, t, mc, base, k;
+               struct hpet __iomem *hpet = devp->hd_hpet;
+               struct hpets *hpetp = devp->hd_hpets;
 
                t = devp->hd_ireqfreq;
                m = read_counter(&devp->hd_timer->hpet_compare);
-               write_counter(t + m, &devp->hd_timer->hpet_compare);
+               mc = read_counter(&hpet->hpet_mc);
+               /* The time for the next interrupt would logically be t + m,
+                * however, if we are very unlucky and the interrupt is delayed
+                * for longer than t then we will completely miss the next
+                * interrupt if we set t + m and an application will hang.
+                * Therefore we need to make a more complex computation assuming
+                * that there exists a k for which the following is true:
+                * k * t + base < mc + delta
+                * (k + 1) * t + base > mc + delta
+                * where t is the interval in hpet ticks for the given freq,
+                * base is the theoretical start value 0 < base < t,
+                * mc is the main counter value at the time of the interrupt,
+                * delta is the time it takes to write the a value to the
+                * comparator.
+                * k may then be computed as (mc - base + delta) / t .
+                */
+               base = mc % t;
+               k = (mc - base + hpetp->hp_delta) / t;
+               write_counter(t * (k + 1) + base,
+                             &devp->hd_timer->hpet_compare);
        }
 
        if (devp->hd_flags & HPET_SHARED_IRQ)
index 16f6f4bc013e81a18fc72ff32213de8852037172..c315ec9d568650b25a10963646f14ca39cfacb1c 100644 (file)
@@ -298,11 +298,13 @@ static int cpufreq_stat_notifier_trans(struct notifier_block *nb,
        old_index = stat->last_index;
        new_index = freq_table_get_index(stat, freq->new);
 
-       cpufreq_stats_update(freq->cpu);
-       if (old_index == new_index)
+       /* We can't do stat->time_in_state[-1]= .. */
+       if (old_index == -1 || new_index == -1)
                return 0;
 
-       if (old_index == -1 || new_index == -1)
+       cpufreq_stats_update(freq->cpu);
+
+       if (old_index == new_index)
                return 0;
 
        spin_lock(&cpufreq_stats_lock);
@@ -412,6 +414,7 @@ static void __exit cpufreq_stats_exit(void)
        unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
        for_each_online_cpu(cpu) {
                cpufreq_stats_free_table(cpu);
+               cpufreq_stats_free_sysfs(cpu);
        }
 }
 
index 83479b6fb9a14fc9ef9826c18274560951c45f19..bce576d7478ed41f9b69ac727cc5d143d850bb83 100644 (file)
@@ -1079,6 +1079,9 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data,
        }
 
        res = transition_fid_vid(data, fid, vid);
+       if (res)
+               return res;
+
        freqs.new = find_khz_freq_from_fid(data->currfid);
 
        for_each_cpu(i, data->available_cores) {
@@ -1101,7 +1104,8 @@ static int transition_frequency_pstate(struct powernow_k8_data *data,
        /* get MSR index for hardware pstate transition */
        pstate = index & HW_PSTATE_MASK;
        if (pstate > data->max_hw_pstate)
-               return 0;
+               return -EINVAL;
+
        freqs.old = find_khz_freq_from_pstate(data->powernow_table,
                        data->currpstate);
        freqs.new = find_khz_freq_from_pstate(data->powernow_table, pstate);
index 2a638f9f09a25d5ed37411d7a997172b928491ce..02833004420151fac42fdbb07e6cebd86d29df70 100644 (file)
@@ -1221,6 +1221,11 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
        } else {
                do {
                        for (i = chanirq_res->start; i <= chanirq_res->end; i++) {
+                               if (irq_cnt >= SH_DMAC_MAX_CHANNELS) {
+                                       irq_cap = 1;
+                                       break;
+                               }
+
                                if ((errirq_res->flags & IORESOURCE_BITS) ==
                                    IORESOURCE_IRQ_SHAREABLE)
                                        chan_flag[irq_cnt] = IRQF_SHARED;
@@ -1230,15 +1235,11 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
                                        "Found IRQ %d for channel %d\n",
                                        i, irq_cnt);
                                chan_irq[irq_cnt++] = i;
-
-                               if (irq_cnt >= SH_DMAC_MAX_CHANNELS)
-                                       break;
                        }
 
-                       if (irq_cnt >= SH_DMAC_MAX_CHANNELS) {
-                               irq_cap = 1;
+                       if (irq_cnt >= SH_DMAC_MAX_CHANNELS)
                                break;
-                       }
+
                        chanirq_res = platform_get_resource(pdev,
                                                IORESOURCE_IRQ, ++irqres);
                } while (irq_cnt < pdata->channel_num && chanirq_res);
index 01f74a8459d99e6b12a7d5bebe5820f17769a62d..35bebde23e835c7674aaaa5e6bbf0e998ab0fd32 100644 (file)
@@ -469,8 +469,9 @@ static inline void set_24xx_gpio_triggering(struct gpio_bank *bank, int gpio,
                                        + OMAP24XX_GPIO_CLEARWKUENA);
                }
        }
-       /* This part needs to be executed always for OMAP34xx */
-       if (cpu_is_omap34xx() || (bank->non_wakeup_gpios & gpio_bit)) {
+       /* This part needs to be executed always for OMAP{34xx, 44xx} */
+       if (cpu_is_omap34xx() || cpu_is_omap44xx() ||
+                       (bank->non_wakeup_gpios & gpio_bit)) {
                /*
                 * Log the edge gpio and manually trigger the IRQ
                 * after resume if the input level changes
index 3e257a50bf56f447563318d86bff3f6b2650c517..61e1ef90d4e5190cc9ca515f5f043b55a0465c5f 100644 (file)
@@ -46,10 +46,11 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
        list_for_each_entry(entry, &dev->maplist, head) {
                /*
                 * Because the kernel-userspace ABI is fixed at a 32-bit offset
-                * while PCI resources may live above that, we ignore the map
-                * offset for maps of type _DRM_FRAMEBUFFER or _DRM_REGISTERS.
-                * It is assumed that each driver will have only one resource of
-                * each type.
+                * while PCI resources may live above that, we only compare the
+                * lower 32 bits of the map offset for maps of type
+                * _DRM_FRAMEBUFFER or _DRM_REGISTERS.
+                * It is assumed that if a driver have more than one resource
+                * of each type, the lower 32 bits are different.
                 */
                if (!entry->map ||
                    map->type != entry->map->type ||
@@ -59,9 +60,12 @@ static struct drm_map_list *drm_find_matching_map(struct drm_device *dev,
                case _DRM_SHM:
                        if (map->flags != _DRM_CONTAINS_LOCK)
                                break;
+                       return entry;
                case _DRM_REGISTERS:
                case _DRM_FRAME_BUFFER:
-                       return entry;
+                       if ((entry->map->offset & 0xffffffff) ==
+                           (map->offset & 0xffffffff))
+                               return entry;
                default: /* Make gcc happy */
                        ;
                }
@@ -182,9 +186,6 @@ static int drm_addmap_core(struct drm_device * dev, resource_size_t offset,
                        kfree(map);
                        return -EINVAL;
                }
-#endif
-#ifdef __alpha__
-               map->offset += dev->hose->mem_space->start;
 #endif
                /* Some drivers preinitialize some maps, without the X Server
                 * needing to be aware of it.  Therefore, we just return success
index 872747c5a544a08ffb57c1e0b55578b9d3b3596f..21058e6ad2b80ccbc10be90795402701270d1585 100644 (file)
@@ -1113,7 +1113,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
        if (card_res->count_fbs >= fb_count) {
                copied = 0;
                fb_id = (uint32_t __user *)(unsigned long)card_res->fb_id_ptr;
-               list_for_each_entry(fb, &file_priv->fbs, head) {
+               list_for_each_entry(fb, &file_priv->fbs, filp_head) {
                        if (put_user(fb->base.id, fb_id + copied)) {
                                ret = -EFAULT;
                                goto out;
index 0a9357c66ff8703b76123487c8ef8d05b373c136..09292193dafe0b28466e37061acc7bee25e348f5 100644 (file)
@@ -184,9 +184,9 @@ drm_edid_block_valid(u8 *raw_edid)
 
 bad:
        if (raw_edid) {
-               DRM_ERROR("Raw EDID:\n");
+               printk(KERN_ERR "Raw EDID:\n");
                print_hex_dump_bytes(KERN_ERR, DUMP_PREFIX_NONE, raw_edid, EDID_LENGTH);
-               printk("\n");
+               printk(KERN_ERR "\n");
        }
        return 0;
 }
@@ -258,6 +258,17 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,
        return ret == 2 ? 0 : -1;
 }
 
+static bool drm_edid_is_zero(u8 *in_edid, int length)
+{
+       int i;
+       u32 *raw_edid = (u32 *)in_edid;
+
+       for (i = 0; i < length / 4; i++)
+               if (*(raw_edid + i) != 0)
+                       return false;
+       return true;
+}
+
 static u8 *
 drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
 {
@@ -273,6 +284,10 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
                        goto out;
                if (drm_edid_block_valid(block))
                        break;
+               if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) {
+                       connector->null_edid_counter++;
+                       goto carp;
+               }
        }
        if (i == 4)
                goto carp;
index 74e4ff578017b90d3e0649219d71a87163fb5b19..4012fe4234607c1b586c76c1a88e50f99d93267b 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/module.h>
 #include <linux/mman.h>
 #include <linux/pagemap.h>
+#include <linux/shmem_fs.h>
 #include "drmP.h"
 
 /** @file drm_gem.c
index d61d185cf040499232d508d4daa66e2f85113fdf..4a058c7af6c096f6dd69dd533701a9adb3091b09 100644 (file)
@@ -28,6 +28,7 @@
  * IN THE SOFTWARE.
  */
 #include <linux/compat.h>
+#include <linux/ratelimit.h>
 
 #include "drmP.h"
 #include "drm_core.h"
@@ -253,10 +254,10 @@ static int compat_drm_addmap(struct file *file, unsigned int cmd,
                return -EFAULT;
 
        m32.handle = (unsigned long)handle;
-       if (m32.handle != (unsigned long)handle && printk_ratelimit())
-               printk(KERN_ERR "compat_drm_addmap truncated handle"
-                      " %p for type %d offset %x\n",
-                      handle, m32.type, m32.offset);
+       if (m32.handle != (unsigned long)handle)
+               printk_ratelimited(KERN_ERR "compat_drm_addmap truncated handle"
+                                  " %p for type %d offset %x\n",
+                                  handle, m32.type, m32.offset);
 
        if (copy_to_user(argp, &m32, sizeof(m32)))
                return -EFAULT;
index e1aee4f6a7c69dacdc59ff2a057340ee914bc4b5..b6a19cb07cafc3591f2ff946532851f63a14270d 100644 (file)
@@ -251,7 +251,7 @@ err:
 }
 
 
-int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
+static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
 {
        if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
            (p->busnum & 0xff) != dev->pdev->bus->number ||
@@ -292,6 +292,7 @@ static struct drm_bus drm_pci_bus = {
        .get_name = drm_pci_get_name,
        .set_busid = drm_pci_set_busid,
        .set_unique = drm_pci_set_unique,
+       .irq_by_busid = drm_pci_irq_by_busid,
        .agp_init = drm_pci_agp_init,
 };
 
index 2c3fcbdfd8ff64f8c5a53ff35884f59ce51bd621..5db96d45fc71677fcf0b6432e0f32dfd22b774d4 100644 (file)
@@ -526,7 +526,7 @@ static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
 static resource_size_t drm_core_get_reg_ofs(struct drm_device *dev)
 {
 #ifdef __alpha__
-       return dev->hose->dense_mem_base - dev->hose->mem_space->start;
+       return dev->hose->dense_mem_base;
 #else
        return 0;
 #endif
index 0239e9974bf29cf8053c54fd42cb0239b21e65d6..2b79588541e7fdde18b6ce6e9d24b6a0420e1e7e 100644 (file)
@@ -2182,9 +2182,8 @@ int i915_driver_unload(struct drm_device *dev)
                /* Flush any outstanding unpin_work. */
                flush_workqueue(dev_priv->wq);
 
-               i915_gem_free_all_phys_object(dev);
-
                mutex_lock(&dev->struct_mutex);
+               i915_gem_free_all_phys_object(dev);
                i915_gem_cleanup_ringbuffer(dev);
                mutex_unlock(&dev->struct_mutex);
                if (I915_HAS_FBC(dev) && i915_powersave)
index 12d32579b9514bda3446865fa3ba1588a81fcafb..85f713746a1fbc59908fe8aa17f9284dc27af207 100644 (file)
@@ -31,6 +31,7 @@
 #include "i915_drv.h"
 #include "i915_trace.h"
 #include "intel_drv.h"
+#include <linux/shmem_fs.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/pci.h>
@@ -359,8 +360,7 @@ i915_gem_shmem_pread_fast(struct drm_device *dev,
                if ((page_offset + remain) > PAGE_SIZE)
                        page_length = PAGE_SIZE - page_offset;
 
-               page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT,
-                                          GFP_HIGHUSER | __GFP_RECLAIMABLE);
+               page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);
                if (IS_ERR(page))
                        return PTR_ERR(page);
 
@@ -463,10 +463,11 @@ i915_gem_shmem_pread_slow(struct drm_device *dev,
                if ((data_page_offset + page_length) > PAGE_SIZE)
                        page_length = PAGE_SIZE - data_page_offset;
 
-               page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT,
-                                          GFP_HIGHUSER | __GFP_RECLAIMABLE);
-               if (IS_ERR(page))
-                       return PTR_ERR(page);
+               page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);
+               if (IS_ERR(page)) {
+                       ret = PTR_ERR(page);
+                       goto out;
+               }
 
                if (do_bit17_swizzling) {
                        slow_shmem_bit17_copy(page,
@@ -795,8 +796,7 @@ i915_gem_shmem_pwrite_fast(struct drm_device *dev,
                if ((page_offset + remain) > PAGE_SIZE)
                        page_length = PAGE_SIZE - page_offset;
 
-               page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT,
-                                          GFP_HIGHUSER | __GFP_RECLAIMABLE);
+               page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);
                if (IS_ERR(page))
                        return PTR_ERR(page);
 
@@ -905,8 +905,7 @@ i915_gem_shmem_pwrite_slow(struct drm_device *dev,
                if ((data_page_offset + page_length) > PAGE_SIZE)
                        page_length = PAGE_SIZE - data_page_offset;
 
-               page = read_cache_page_gfp(mapping, offset >> PAGE_SHIFT,
-                                          GFP_HIGHUSER | __GFP_RECLAIMABLE);
+               page = shmem_read_mapping_page(mapping, offset >> PAGE_SHIFT);
                if (IS_ERR(page)) {
                        ret = PTR_ERR(page);
                        goto out;
@@ -1217,11 +1216,11 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
                ret = i915_gem_object_bind_to_gtt(obj, 0, true);
                if (ret)
                        goto unlock;
-       }
 
-       ret = i915_gem_object_set_to_gtt_domain(obj, write);
-       if (ret)
-               goto unlock;
+               ret = i915_gem_object_set_to_gtt_domain(obj, write);
+               if (ret)
+                       goto unlock;
+       }
 
        if (obj->tiling_mode == I915_TILING_NONE)
                ret = i915_gem_object_put_fence(obj);
@@ -1556,12 +1555,10 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,
 
        inode = obj->base.filp->f_path.dentry->d_inode;
        mapping = inode->i_mapping;
+       gfpmask |= mapping_gfp_mask(mapping);
+
        for (i = 0; i < page_count; i++) {
-               page = read_cache_page_gfp(mapping, i,
-                                          GFP_HIGHUSER |
-                                          __GFP_COLD |
-                                          __GFP_RECLAIMABLE |
-                                          gfpmask);
+               page = shmem_read_mapping_page_gfp(mapping, i, gfpmask);
                if (IS_ERR(page))
                        goto err_pages;
 
@@ -1699,13 +1696,10 @@ i915_gem_object_truncate(struct drm_i915_gem_object *obj)
        /* Our goal here is to return as much of the memory as
         * is possible back to the system as we are called from OOM.
         * To do this we must instruct the shmfs to drop all of its
-        * backing pages, *now*. Here we mirror the actions taken
-        * when by shmem_delete_inode() to release the backing store.
+        * backing pages, *now*.
         */
        inode = obj->base.filp->f_path.dentry->d_inode;
-       truncate_inode_pages(inode->i_mapping, 0);
-       if (inode->i_op->truncate_range)
-               inode->i_op->truncate_range(inode, 0, (loff_t)-1);
+       shmem_truncate_range(inode, 0, (loff_t)-1);
 
        obj->madv = __I915_MADV_PURGED;
 }
@@ -2924,8 +2918,6 @@ i915_gem_object_flush_gtt_write_domain(struct drm_i915_gem_object *obj)
         */
        wmb();
 
-       i915_gem_release_mmap(obj);
-
        old_write_domain = obj->base.write_domain;
        obj->base.write_domain = 0;
 
@@ -3565,6 +3557,7 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct drm_i915_gem_object *obj;
+       struct address_space *mapping;
 
        obj = kzalloc(sizeof(*obj), GFP_KERNEL);
        if (obj == NULL)
@@ -3575,6 +3568,9 @@ struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
                return NULL;
        }
 
+       mapping = obj->base.filp->f_path.dentry->d_inode->i_mapping;
+       mapping_set_gfp_mask(mapping, GFP_HIGHUSER | __GFP_RECLAIMABLE);
+
        i915_gem_info_add_obj(dev_priv, size);
 
        obj->base.write_domain = I915_GEM_DOMAIN_CPU;
@@ -3950,8 +3946,7 @@ void i915_gem_detach_phys_object(struct drm_device *dev,
 
        page_count = obj->base.size / PAGE_SIZE;
        for (i = 0; i < page_count; i++) {
-               struct page *page = read_cache_page_gfp(mapping, i,
-                                                       GFP_HIGHUSER | __GFP_RECLAIMABLE);
+               struct page *page = shmem_read_mapping_page(mapping, i);
                if (!IS_ERR(page)) {
                        char *dst = kmap_atomic(page);
                        memcpy(dst, vaddr + i*PAGE_SIZE, PAGE_SIZE);
@@ -4012,8 +4007,7 @@ i915_gem_attach_phys_object(struct drm_device *dev,
                struct page *page;
                char *dst, *src;
 
-               page = read_cache_page_gfp(mapping, i,
-                                          GFP_HIGHUSER | __GFP_RECLAIMABLE);
+               page = shmem_read_mapping_page(mapping, i);
                if (IS_ERR(page))
                        return PTR_ERR(page);
 
index 20a4cc5b818f51632ad50a94bdfa4092c3f1a454..4934cf84c320336aa84320da544cc1e0d091da1c 100644 (file)
@@ -187,10 +187,6 @@ i915_gem_object_set_to_gpu_domain(struct drm_i915_gem_object *obj,
        if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_CPU)
                i915_gem_clflush_object(obj);
 
-       /* blow away mappings if mapped through GTT */
-       if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_GTT)
-               i915_gem_release_mmap(obj);
-
        if (obj->base.pending_write_domain)
                cd->flips |= atomic_read(&obj->pending_flip);
 
index b9fafe3b045bda5817047f2a5cde8a6fc1b58265..ae2b49969b995c0b1c7f7f76f65d2426ea003522 100644 (file)
@@ -1740,6 +1740,17 @@ void ironlake_irq_preinstall(struct drm_device *dev)
                INIT_WORK(&dev_priv->rps_work, gen6_pm_rps_work);
 
        I915_WRITE(HWSTAM, 0xeffe);
+       if (IS_GEN6(dev)) {
+               /* Workaround stalls observed on Sandy Bridge GPUs by
+                * making the blitter command streamer generate a
+                * write to the Hardware Status Page for
+                * MI_USER_INTERRUPT.  This appears to serialize the
+                * previous seqno write out before the interrupt
+                * happens.
+                */
+               I915_WRITE(GEN6_BLITTER_HWSTAM, ~GEN6_BLITTER_USER_INTERRUPT);
+               I915_WRITE(GEN6_BSD_HWSTAM, ~GEN6_BSD_USER_INTERRUPT);
+       }
 
        /* XXX hotplug from PCH */
 
index 2f967af8e62edced1deff2dc906c8ca28203e20a..5d5def756c9e5beee9ae10def1cbe39d5f7cf02f 100644 (file)
 #define   GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE           0
 #define   GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR                   (1 << 3)
 
+#define GEN6_BSD_HWSTAM                        0x12098
 #define GEN6_BSD_IMR                   0x120a8
 #define   GEN6_BSD_USER_INTERRUPT      (1 << 12)
 
index 60a94d2b526482532667dc7b4fba4bf8f5cfbe5c..e8152d23d5b67c31ecf77b39f7250df71cb12bca 100644 (file)
@@ -678,6 +678,7 @@ void i915_save_display(struct drm_device *dev)
        }
 
        /* VGA state */
+       mutex_lock(&dev->struct_mutex);
        dev_priv->saveVGA0 = I915_READ(VGA0);
        dev_priv->saveVGA1 = I915_READ(VGA1);
        dev_priv->saveVGA_PD = I915_READ(VGA_PD);
@@ -687,6 +688,7 @@ void i915_save_display(struct drm_device *dev)
                dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
 
        i915_save_vga(dev);
+       mutex_unlock(&dev->struct_mutex);
 }
 
 void i915_restore_display(struct drm_device *dev)
@@ -780,6 +782,8 @@ void i915_restore_display(struct drm_device *dev)
                I915_WRITE(CPU_VGACNTRL, dev_priv->saveVGACNTRL);
        else
                I915_WRITE(VGACNTRL, dev_priv->saveVGACNTRL);
+
+       mutex_lock(&dev->struct_mutex);
        I915_WRITE(VGA0, dev_priv->saveVGA0);
        I915_WRITE(VGA1, dev_priv->saveVGA1);
        I915_WRITE(VGA_PD, dev_priv->saveVGA_PD);
@@ -787,6 +791,7 @@ void i915_restore_display(struct drm_device *dev)
        udelay(150);
 
        i915_restore_vga(dev);
+       mutex_unlock(&dev->struct_mutex);
 }
 
 int i915_save_state(struct drm_device *dev)
index 81a9059b6a94ea0278bd691342294f4c0893cf21..aa43e7be6053bdfd6dc6fd7274d17ccd544b799f 100644 (file)
@@ -4687,6 +4687,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc,
 
        I915_WRITE(DSPCNTR(plane), dspcntr);
        POSTING_READ(DSPCNTR(plane));
+       intel_enable_plane(dev_priv, plane, pipe);
 
        ret = intel_pipe_set_base(crtc, x, y, old_fb);
 
@@ -5217,8 +5218,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc,
 
        I915_WRITE(DSPCNTR(plane), dspcntr);
        POSTING_READ(DSPCNTR(plane));
-       if (!HAS_PCH_SPLIT(dev))
-               intel_enable_plane(dev_priv, plane, pipe);
 
        ret = intel_pipe_set_base(crtc, x, y, old_fb);
 
index d3b903bce7c5b3a25845c570aaf21f064d416224..d98cee60b602650063225ce9fbbf4f01220de562 100644 (file)
@@ -401,8 +401,7 @@ int intel_setup_gmbus(struct drm_device *dev)
                bus->reg0 = i | GMBUS_RATE_100KHZ;
 
                /* XXX force bit banging until GMBUS is fully debugged */
-               if (IS_GEN2(dev))
-                       bus->force_bit = intel_gpio_create(dev_priv, i);
+               bus->force_bit = intel_gpio_create(dev_priv, i);
        }
 
        intel_i2c_reset(dev_priv->dev);
index a670c006982e5056e418f81aaec1d439a589a7ae..56a8e2aea19c553a3ba9623df8ccec0df2052332 100644 (file)
@@ -1416,6 +1416,8 @@ void intel_setup_overlay(struct drm_device *dev)
                goto out_free;
        overlay->reg_bo = reg_bo;
 
+       mutex_lock(&dev->struct_mutex);
+
        if (OVERLAY_NEEDS_PHYSICAL(dev)) {
                ret = i915_gem_attach_phys_object(dev, reg_bo,
                                                  I915_GEM_PHYS_OVERLAY_REGS,
@@ -1440,6 +1442,8 @@ void intel_setup_overlay(struct drm_device *dev)
                 }
        }
 
+       mutex_unlock(&dev->struct_mutex);
+
        /* init all values */
        overlay->color_key = 0x0101fe;
        overlay->brightness = -19;
@@ -1464,6 +1468,7 @@ out_unpin_bo:
        i915_gem_object_unpin(reg_bo);
 out_free_bo:
        drm_gem_object_unreference(&reg_bo->base);
+       mutex_unlock(&dev->struct_mutex);
 out_free:
        kfree(overlay);
        return;
index 1084fa4d261b7c9d6638d965a5a4c401c9949720..54558a01969ae02d6875c99fafb605f27a717ce0 100644 (file)
@@ -195,29 +195,10 @@ extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
 
 #define mga_flush_write_combine()      DRM_WRITEMEMORYBARRIER()
 
-#if defined(__linux__) && defined(__alpha__)
-#define MGA_BASE(reg)          ((unsigned long)(dev_priv->mmio->handle))
-#define MGA_ADDR(reg)          (MGA_BASE(reg) + reg)
-
-#define MGA_DEREF(reg)         (*(volatile u32 *)MGA_ADDR(reg))
-#define MGA_DEREF8(reg)                (*(volatile u8 *)MGA_ADDR(reg))
-
-#define MGA_READ(reg)          (_MGA_READ((u32 *)MGA_ADDR(reg)))
-#define MGA_READ8(reg)         (_MGA_READ((u8 *)MGA_ADDR(reg)))
-#define MGA_WRITE(reg, val)    do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF(reg) = val; } while (0)
-#define MGA_WRITE8(reg, val)   do { DRM_WRITEMEMORYBARRIER(); MGA_DEREF8(reg) = val; } while (0)
-
-static inline u32 _MGA_READ(u32 *addr)
-{
-       DRM_MEMORYBARRIER();
-       return *(volatile u32 *)addr;
-}
-#else
 #define MGA_READ8(reg)         DRM_READ8(dev_priv->mmio, (reg))
 #define MGA_READ(reg)          DRM_READ32(dev_priv->mmio, (reg))
 #define MGA_WRITE8(reg, val)   DRM_WRITE8(dev_priv->mmio, (reg), (val))
 #define MGA_WRITE(reg, val)    DRM_WRITE32(dev_priv->mmio, (reg), (val))
-#endif
 
 #define DWGREG0                0x1c00
 #define DWGREG0_END    0x1dff
index f0d459bb46e4152a2f40c0fa2e0b54311c79a328..525744d593c1e981cc1039c79391f6aa38813b1d 100644 (file)
@@ -262,7 +262,6 @@ static bool nouveau_dsm_detect(void)
                vga_count++;
 
                retval = nouveau_dsm_pci_probe(pdev);
-               printk("ret val is %d\n", retval);
                if (retval & NOUVEAU_DSM_HAS_MUX)
                        has_dsm |= 1;
                if (retval & NOUVEAU_DSM_HAS_OPT)
index 4b9f4493c9f9d3008d46b64597d7c27d51a21197..7347075ca5b873a2192f57ad0647ee8fb15d8908 100644 (file)
@@ -339,11 +339,12 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
        int ret;
 
        if (dev_priv->chipset < 0x84) {
-               ret = RING_SPACE(chan, 3);
+               ret = RING_SPACE(chan, 4);
                if (ret)
                        return ret;
 
-               BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 2);
+               BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 3);
+               OUT_RING  (chan, NvSema);
                OUT_RING  (chan, sema->mem->start);
                OUT_RING  (chan, 1);
        } else
@@ -351,10 +352,12 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
                struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
                u64 offset = vma->offset + sema->mem->start;
 
-               ret = RING_SPACE(chan, 5);
+               ret = RING_SPACE(chan, 7);
                if (ret)
                        return ret;
 
+               BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
+               OUT_RING  (chan, chan->vram_handle);
                BEGIN_RING(chan, NvSubSw, 0x0010, 4);
                OUT_RING  (chan, upper_32_bits(offset));
                OUT_RING  (chan, lower_32_bits(offset));
@@ -394,11 +397,12 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
        int ret;
 
        if (dev_priv->chipset < 0x84) {
-               ret = RING_SPACE(chan, 4);
+               ret = RING_SPACE(chan, 5);
                if (ret)
                        return ret;
 
-               BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1);
+               BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 2);
+               OUT_RING  (chan, NvSema);
                OUT_RING  (chan, sema->mem->start);
                BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1);
                OUT_RING  (chan, 1);
@@ -407,10 +411,12 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
                struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
                u64 offset = vma->offset + sema->mem->start;
 
-               ret = RING_SPACE(chan, 5);
+               ret = RING_SPACE(chan, 7);
                if (ret)
                        return ret;
 
+               BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
+               OUT_RING  (chan, chan->vram_handle);
                BEGIN_RING(chan, NvSubSw, 0x0010, 4);
                OUT_RING  (chan, upper_32_bits(offset));
                OUT_RING  (chan, lower_32_bits(offset));
@@ -504,22 +510,22 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
        struct nouveau_gpuobj *obj = NULL;
        int ret;
 
-       if (dev_priv->card_type >= NV_C0)
-               goto out_initialised;
+       if (dev_priv->card_type < NV_C0) {
+               /* Create an NV_SW object for various sync purposes */
+               ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW);
+               if (ret)
+                       return ret;
 
-       /* Create an NV_SW object for various sync purposes */
-       ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW);
-       if (ret)
-               return ret;
+               ret = RING_SPACE(chan, 2);
+               if (ret)
+                       return ret;
 
-       /* we leave subchannel empty for nvc0 */
-       ret = RING_SPACE(chan, 2);
-       if (ret)
-               return ret;
-       BEGIN_RING(chan, NvSubSw, 0, 1);
-       OUT_RING(chan, NvSw);
+               BEGIN_RING(chan, NvSubSw, 0, 1);
+               OUT_RING  (chan, NvSw);
+               FIRE_RING (chan);
+       }
 
-       /* Create a DMA object for the shared cross-channel sync area. */
+       /* Setup area of memory shared between all channels for x-chan sync */
        if (USE_SEMA(dev) && dev_priv->chipset < 0x84) {
                struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem;
 
@@ -534,23 +540,8 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
                nouveau_gpuobj_ref(NULL, &obj);
                if (ret)
                        return ret;
-
-               ret = RING_SPACE(chan, 2);
-               if (ret)
-                       return ret;
-               BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
-               OUT_RING(chan, NvSema);
-       } else {
-               ret = RING_SPACE(chan, 2);
-               if (ret)
-                       return ret;
-               BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
-               OUT_RING  (chan, chan->vram_handle); /* whole VM */
        }
 
-       FIRE_RING(chan);
-
-out_initialised:
        INIT_LIST_HEAD(&chan->fence.pending);
        spin_lock_init(&chan->fence.lock);
        atomic_set(&chan->fence.last_sequence_irq, 0);
index 922fb6b664edda718e2e15f929500a2fe3967d21..ef9dec0e6f8b343c293eb7002560686838731180 100644 (file)
@@ -182,6 +182,11 @@ nouveau_perf_init(struct drm_device *dev)
                entries   = perf[2];
        }
 
+       if (entries > NOUVEAU_PM_MAX_LEVEL) {
+               NV_DEBUG(dev, "perf table has too many entries - buggy vbios?\n");
+               entries = NOUVEAU_PM_MAX_LEVEL;
+       }
+
        entry = perf + headerlen;
        for (i = 0; i < entries; i++) {
                struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl];
index 80218887e0a004fc19337f180a93fe4ecb4196d2..144f79a350ae3d69b542a7f364988d194a28cbcb 100644 (file)
@@ -881,8 +881,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
 
 #ifdef __BIG_ENDIAN
        /* Put the card in BE mode if it's not */
-       if (nv_rd32(dev, NV03_PMC_BOOT_1))
-               nv_wr32(dev, NV03_PMC_BOOT_1, 0x00000001);
+       if (nv_rd32(dev, NV03_PMC_BOOT_1) != 0x01000001)
+               nv_wr32(dev, NV03_PMC_BOOT_1, 0x01000001);
 
        DRM_MEMORYBARRIER();
 #endif
index 74a3f687270124cdfb32ddd55ce78f9ae70a6157..08da478ba544e312ab72b4b23b1db23607a433e5 100644 (file)
@@ -409,7 +409,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        struct nouveau_channel *evo = dispc->sync;
        int ret;
 
-       ret = RING_SPACE(evo, 24);
+       ret = RING_SPACE(evo, chan ? 25 : 27);
        if (unlikely(ret))
                return ret;
 
@@ -458,8 +458,19 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        /* queue the flip on the crtc's "display sync" channel */
        BEGIN_RING(evo, 0, 0x0100, 1);
        OUT_RING  (evo, 0xfffe0000);
-       BEGIN_RING(evo, 0, 0x0084, 5);
-       OUT_RING  (evo, chan ? 0x00000100 : 0x00000010);
+       if (chan) {
+               BEGIN_RING(evo, 0, 0x0084, 1);
+               OUT_RING  (evo, 0x00000100);
+       } else {
+               BEGIN_RING(evo, 0, 0x0084, 1);
+               OUT_RING  (evo, 0x00000010);
+               /* allows gamma somehow, PDISP will bitch at you if
+                * you don't wait for vblank before changing this..
+                */
+               BEGIN_RING(evo, 0, 0x00e0, 1);
+               OUT_RING  (evo, 0x40000000);
+       }
+       BEGIN_RING(evo, 0, 0x0088, 4);
        OUT_RING  (evo, dispc->sem.offset);
        OUT_RING  (evo, 0xf00d0000 | dispc->sem.value);
        OUT_RING  (evo, 0x74b1e000);
index 49611e2365d984e539fe2f7d5169303e7e052f60..1b50ad8919d55e9e268095dcd54e824006ffd895 100644 (file)
@@ -1200,6 +1200,7 @@ typedef struct _EXTERNAL_ENCODER_CONTROL_PARAMETERS_V3
 #define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF   0x10
 #define EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING       0x11
 #define EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION      0x12
+#define EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP              0x14
 
 // ucConfig
 #define EXTERNAL_ENCODER_CONFIG_V3_DPLINKRATE_MASK                             0x03
index 84a69e7fa11e898769041160be2cc32fbb5ec146..9541995e4b21df3d4ba5cb9b3ab496a3255b8034 100644 (file)
@@ -671,6 +671,13 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
                                                                DISPPLL_CONFIG_DUAL_LINK;
                                        }
                                }
+                               if (radeon_encoder_is_dp_bridge(encoder)) {
+                                       struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
+                                       struct radeon_encoder *ext_radeon_encoder = to_radeon_encoder(ext_encoder);
+                                       args.v3.sInput.ucExtTransmitterID = ext_radeon_encoder->encoder_id;
+                               } else
+                                       args.v3.sInput.ucExtTransmitterID = 0;
+
                                atom_execute_table(rdev->mode_info.atom_context,
                                                   index, (uint32_t *)&args);
                                adjusted_clock = le32_to_cpu(args.v3.sOutput.ulDispPllFreq) * 10;
index 98ea597bc76d88566644a00eca83113c6d8a787e..12d2fdc52414463d42cdc0ecb2a66f0b7e1e76e2 100644 (file)
@@ -88,7 +88,8 @@ u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
 /* get temperature in millidegrees */
 int evergreen_get_temp(struct radeon_device *rdev)
 {
-       u32 temp, toffset, actual_temp = 0;
+       u32 temp, toffset;
+       int actual_temp = 0;
 
        if (rdev->family == CHIP_JUNIPER) {
                toffset = (RREG32(CG_THERMAL_CTRL) & TOFFSET_MASK) >>
@@ -139,11 +140,17 @@ void evergreen_pm_misc(struct radeon_device *rdev)
        struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
 
        if (voltage->type == VOLTAGE_SW) {
+               /* 0xff01 is a flag rather then an actual voltage */
+               if (voltage->voltage == 0xff01)
+                       return;
                if (voltage->voltage && (voltage->voltage != rdev->pm.current_vddc)) {
                        radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);
                        rdev->pm.current_vddc = voltage->voltage;
                        DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage);
                }
+               /* 0xff01 is a flag rather then an actual voltage */
+               if (voltage->vddci == 0xff01)
+                       return;
                if (voltage->vddci && (voltage->vddci != rdev->pm.current_vddci)) {
                        radeon_atom_set_voltage(rdev, voltage->vddci, SET_VOLTAGE_TYPE_ASIC_VDDCI);
                        rdev->pm.current_vddci = voltage->vddci;
@@ -2006,9 +2013,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
                rdev->config.evergreen.tile_config |= (3 << 0);
                break;
        }
-       /* num banks is 8 on all fusion asics */
+       /* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */
        if (rdev->flags & RADEON_IS_IGP)
-               rdev->config.evergreen.tile_config |= 8 << 4;
+               rdev->config.evergreen.tile_config |= 1 << 4;
        else
                rdev->config.evergreen.tile_config |=
                        ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4;
@@ -2694,28 +2701,25 @@ static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev)
 
 int evergreen_irq_process(struct radeon_device *rdev)
 {
-       u32 wptr = evergreen_get_ih_wptr(rdev);
-       u32 rptr = rdev->ih.rptr;
+       u32 wptr;
+       u32 rptr;
        u32 src_id, src_data;
        u32 ring_index;
        unsigned long flags;
        bool queue_hotplug = false;
 
-       DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
-       if (!rdev->ih.enabled)
+       if (!rdev->ih.enabled || rdev->shutdown)
                return IRQ_NONE;
 
-       spin_lock_irqsave(&rdev->ih.lock, flags);
+       wptr = evergreen_get_ih_wptr(rdev);
+       rptr = rdev->ih.rptr;
+       DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
 
+       spin_lock_irqsave(&rdev->ih.lock, flags);
        if (rptr == wptr) {
                spin_unlock_irqrestore(&rdev->ih.lock, flags);
                return IRQ_NONE;
        }
-       if (rdev->shutdown) {
-               spin_unlock_irqrestore(&rdev->ih.lock, flags);
-               return IRQ_NONE;
-       }
-
 restart_ih:
        /* display interrupts */
        evergreen_irq_ack(rdev);
@@ -2944,7 +2948,7 @@ restart_ih:
                        radeon_fence_process(rdev);
                        break;
                case 233: /* GUI IDLE */
-                       DRM_DEBUG("IH: CP EOP\n");
+                       DRM_DEBUG("IH: GUI idle\n");
                        rdev->pm.gui_idle = true;
                        wake_up(&rdev->irq.idle_queue);
                        break;
index 2fef9de7f363b2fb47478e8720ea1a7ca7fb7331..686f9dc5d4bd94f8f8dec4a23de185aee832542a 100644 (file)
@@ -63,7 +63,7 @@ struct r100_cs_track {
        unsigned                        num_arrays;
        unsigned                        max_indx;
        unsigned                        color_channel_mask;
-       struct r100_cs_track_array      arrays[11];
+       struct r100_cs_track_array      arrays[16];
        struct r100_cs_track_cb         cb[R300_MAX_CB];
        struct r100_cs_track_cb         zb;
        struct r100_cs_track_cb         aa;
@@ -146,6 +146,12 @@ static inline int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
        ib = p->ib->ptr;
        track = (struct r100_cs_track *)p->track;
        c = radeon_get_ib_value(p, idx++) & 0x1F;
+       if (c > 16) {
+           DRM_ERROR("Only 16 vertex buffers are allowed %d\n",
+                     pkt->opcode);
+           r100_cs_dump_packet(p, pkt);
+           return -EINVAL;
+       }
        track->num_arrays = c;
        for (i = 0; i < (c - 1); i+=2, idx+=3) {
                r = r100_cs_packet_next_reloc(p, &reloc);
index d74d4d71437f1aa75c111bdb4d4e8def3ea13cb9..f79d2ccb675553c73204c14bd46183f05fd4567b 100644 (file)
@@ -590,6 +590,9 @@ void r600_pm_misc(struct radeon_device *rdev)
        struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
 
        if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
+               /* 0xff01 is a flag rather then an actual voltage */
+               if (voltage->voltage == 0xff01)
+                       return;
                if (voltage->voltage != rdev->pm.current_vddc) {
                        radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);
                        rdev->pm.current_vddc = voltage->voltage;
@@ -3294,27 +3297,26 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev)
 
 int r600_irq_process(struct radeon_device *rdev)
 {
-       u32 wptr = r600_get_ih_wptr(rdev);
-       u32 rptr = rdev->ih.rptr;
+       u32 wptr;
+       u32 rptr;
        u32 src_id, src_data;
        u32 ring_index;
        unsigned long flags;
        bool queue_hotplug = false;
 
-       DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
-       if (!rdev->ih.enabled)
+       if (!rdev->ih.enabled || rdev->shutdown)
                return IRQ_NONE;
 
+       wptr = r600_get_ih_wptr(rdev);
+       rptr = rdev->ih.rptr;
+       DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
+
        spin_lock_irqsave(&rdev->ih.lock, flags);
 
        if (rptr == wptr) {
                spin_unlock_irqrestore(&rdev->ih.lock, flags);
                return IRQ_NONE;
        }
-       if (rdev->shutdown) {
-               spin_unlock_irqrestore(&rdev->ih.lock, flags);
-               return IRQ_NONE;
-       }
 
 restart_ih:
        /* display interrupts */
@@ -3444,7 +3446,7 @@ restart_ih:
                        radeon_fence_process(rdev);
                        break;
                case 233: /* GUI IDLE */
-                       DRM_DEBUG("IH: CP EOP\n");
+                       DRM_DEBUG("IH: GUI idle\n");
                        rdev->pm.gui_idle = true;
                        wake_up(&rdev->irq.idle_queue);
                        break;
index ba643b5760542e0e6ad3298464be1e7505995739..ef0e0e016914d53aadcddbd897913d07da495bd4 100644 (file)
@@ -165,6 +165,7 @@ struct radeon_clock {
        uint32_t default_sclk;
        uint32_t default_dispclk;
        uint32_t dp_extclk;
+       uint32_t max_pixel_clock;
 };
 
 /*
@@ -178,6 +179,7 @@ void radeon_pm_resume(struct radeon_device *rdev);
 void radeon_combios_get_power_modes(struct radeon_device *rdev);
 void radeon_atombios_get_power_modes(struct radeon_device *rdev);
 void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type);
+int radeon_atom_get_max_vddc(struct radeon_device *rdev, u16 *voltage);
 void rs690_pm_info(struct radeon_device *rdev);
 extern int rv6xx_get_temp(struct radeon_device *rdev);
 extern int rv770_get_temp(struct radeon_device *rdev);
index 9bd162fc9b0c5ecdf079f68e83b618d1d1bf1b3e..b2449629537d3b5922e86e325ac85bb214cacea2 100644 (file)
@@ -938,6 +938,13 @@ static struct radeon_asic cayman_asic = {
 int radeon_asic_init(struct radeon_device *rdev)
 {
        radeon_register_accessor_init(rdev);
+
+       /* set the number of crtcs */
+       if (rdev->flags & RADEON_SINGLE_CRTC)
+               rdev->num_crtc = 1;
+       else
+               rdev->num_crtc = 2;
+
        switch (rdev->family) {
        case CHIP_R100:
        case CHIP_RV100:
@@ -1017,6 +1024,11 @@ int radeon_asic_init(struct radeon_device *rdev)
        case CHIP_JUNIPER:
        case CHIP_CYPRESS:
        case CHIP_HEMLOCK:
+               /* set num crtcs */
+               if (rdev->family == CHIP_CEDAR)
+                       rdev->num_crtc = 4;
+               else
+                       rdev->num_crtc = 6;
                rdev->asic = &evergreen_asic;
                break;
        case CHIP_PALM:
@@ -1027,10 +1039,17 @@ int radeon_asic_init(struct radeon_device *rdev)
        case CHIP_BARTS:
        case CHIP_TURKS:
        case CHIP_CAICOS:
+               /* set num crtcs */
+               if (rdev->family == CHIP_CAICOS)
+                       rdev->num_crtc = 4;
+               else
+                       rdev->num_crtc = 6;
                rdev->asic = &btc_asic;
                break;
        case CHIP_CAYMAN:
                rdev->asic = &cayman_asic;
+               /* set num crtcs */
+               rdev->num_crtc = 6;
                break;
        default:
                /* FIXME: not supported yet */
@@ -1042,18 +1061,6 @@ int radeon_asic_init(struct radeon_device *rdev)
                rdev->asic->set_memory_clock = NULL;
        }
 
-       /* set the number of crtcs */
-       if (rdev->flags & RADEON_SINGLE_CRTC)
-               rdev->num_crtc = 1;
-       else {
-               if (ASIC_IS_DCE41(rdev))
-                       rdev->num_crtc = 2;
-               else if (ASIC_IS_DCE4(rdev))
-                       rdev->num_crtc = 6;
-               else
-                       rdev->num_crtc = 2;
-       }
-
        return 0;
 }
 
index 90dfb2b8cf0318529b28b84b0bfd831764e5d59e..bf2b61584cdb5a70fc06fbc41dd2ca51733532fc 100644 (file)
@@ -1246,6 +1246,10 @@ bool radeon_atom_get_clock_info(struct drm_device *dev)
                }
                *dcpll = *p1pll;
 
+               rdev->clock.max_pixel_clock = le16_to_cpu(firmware_info->info.usMaxPixelClock);
+               if (rdev->clock.max_pixel_clock == 0)
+                       rdev->clock.max_pixel_clock = 40000;
+
                return true;
        }
 
@@ -2316,6 +2320,14 @@ static bool radeon_atombios_parse_pplib_clock_info(struct radeon_device *rdev,
                        le16_to_cpu(clock_info->r600.usVDDC);
        }
 
+       /* patch up vddc if necessary */
+       if (rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage == 0xff01) {
+               u16 vddc;
+
+               if (radeon_atom_get_max_vddc(rdev, &vddc) == 0)
+                       rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage = vddc;
+       }
+
        if (rdev->flags & RADEON_IS_IGP) {
                /* skip invalid modes */
                if (rdev->pm.power_state[state_index].clock_info[mode_index].sclk == 0)
@@ -2603,6 +2615,10 @@ void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 v
        if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
                return;
 
+       /* 0xff01 is a flag rather then an actual voltage */
+       if (voltage_level == 0xff01)
+               return;
+
        switch (crev) {
        case 1:
                args.v1.ucVoltageType = voltage_type;
@@ -2622,7 +2638,35 @@ void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 v
        atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
 }
 
+int radeon_atom_get_max_vddc(struct radeon_device *rdev,
+                            u16 *voltage)
+{
+       union set_voltage args;
+       int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
+       u8 frev, crev;
+
+       if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
+               return -EINVAL;
 
+       switch (crev) {
+       case 1:
+               return -EINVAL;
+       case 2:
+               args.v2.ucVoltageType = SET_VOLTAGE_GET_MAX_VOLTAGE;
+               args.v2.ucVoltageMode = 0;
+               args.v2.usVoltageLevel = 0;
+
+               atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
+
+               *voltage = le16_to_cpu(args.v2.usVoltageLevel);
+               break;
+       default:
+               DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
+               return -EINVAL;
+       }
+
+       return 0;
+}
 
 void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev)
 {
index 5249af8931e60549e01362102f9c8ca941ba0d24..2d48e7a1474b4d915652cc8c6718dc4c8f4a8db4 100644 (file)
@@ -117,7 +117,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
        p1pll->reference_div = RREG32_PLL(RADEON_PPLL_REF_DIV) & 0x3ff;
        if (p1pll->reference_div < 2)
                p1pll->reference_div = 12;
-       p2pll->reference_div = p1pll->reference_div;    
+       p2pll->reference_div = p1pll->reference_div;
 
        /* These aren't in the device-tree */
        if (rdev->family >= CHIP_R420) {
@@ -139,6 +139,8 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
                p2pll->pll_out_min = 12500;
                p2pll->pll_out_max = 35000;
        }
+       /* not sure what the max should be in all cases */
+       rdev->clock.max_pixel_clock = 35000;
 
        spll->reference_freq = mpll->reference_freq = p1pll->reference_freq;
        spll->reference_div = mpll->reference_div =
@@ -151,7 +153,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
        else
                rdev->clock.default_sclk =
                        radeon_legacy_get_engine_clock(rdev);
-                       
+
        val = of_get_property(dp, "ATY,MCLK", NULL);
        if (val && *val)
                rdev->clock.default_mclk = (*val) / 10;
@@ -160,7 +162,7 @@ static bool __devinit radeon_read_clocks_OF(struct drm_device *dev)
                        radeon_legacy_get_memory_clock(rdev);
 
        DRM_INFO("Using device-tree clock info\n");
-       
+
        return true;
 }
 #else
index 5b991f7c6e2add24f1b4290b270cf1d44282915f..e4594676a07c2c4bdb0c1f3575e91e8e98c8265d 100644 (file)
@@ -866,6 +866,11 @@ bool radeon_combios_get_clock_info(struct drm_device *dev)
                rdev->clock.default_sclk = sclk;
                rdev->clock.default_mclk = mclk;
 
+               if (RBIOS32(pll_info + 0x16))
+                       rdev->clock.max_pixel_clock = RBIOS32(pll_info + 0x16);
+               else
+                       rdev->clock.max_pixel_clock = 35000; /* might need something asic specific */
+
                return true;
        }
        return false;
@@ -1548,10 +1553,12 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
                           (rdev->pdev->subsystem_device == 0x4a48)) {
                        /* Mac X800 */
                        rdev->mode_info.connector_table = CT_MAC_X800;
-               } else if ((rdev->pdev->device == 0x4150) &&
+               } else if ((of_machine_is_compatible("PowerMac7,2") ||
+                           of_machine_is_compatible("PowerMac7,3")) &&
+                          (rdev->pdev->device == 0x4150) &&
                           (rdev->pdev->subsystem_vendor == 0x1002) &&
                           (rdev->pdev->subsystem_device == 0x4150)) {
-                       /* Mac G5 9600 */
+                       /* Mac G5 tower 9600 */
                        rdev->mode_info.connector_table = CT_MAC_G5_9600;
                } else
 #endif /* CONFIG_PPC_PMAC */
index ee1dccb3fec9792e721c17aae9b0eb81d832c396..cbfca3a24fdf9caac828d4cca8ce8445963af4c4 100644 (file)
@@ -44,6 +44,8 @@ extern void
 radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
                             struct drm_connector *drm_connector);
 
+bool radeon_connector_encoder_is_dp_bridge(struct drm_connector *connector);
+
 void radeon_connector_hotplug(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
@@ -626,8 +628,14 @@ static int radeon_vga_get_modes(struct drm_connector *connector)
 static int radeon_vga_mode_valid(struct drm_connector *connector,
                                  struct drm_display_mode *mode)
 {
+       struct drm_device *dev = connector->dev;
+       struct radeon_device *rdev = dev->dev_private;
+
        /* XXX check mode bandwidth */
-       /* XXX verify against max DAC output frequency */
+
+       if ((mode->clock / 10) > rdev->clock.max_pixel_clock)
+               return MODE_CLOCK_HIGH;
+
        return MODE_OK;
 }
 
@@ -830,6 +838,13 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
                if (!radeon_connector->edid) {
                        DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
                                        drm_get_connector_name(connector));
+                       /* rs690 seems to have a problem with connectors not existing and always
+                        * return a block of 0's. If we see this just stop polling on this output */
+                       if ((rdev->family == CHIP_RS690 || rdev->family == CHIP_RS740) && radeon_connector->base.null_edid_counter) {
+                               ret = connector_status_disconnected;
+                               DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector));
+                               radeon_connector->ddc_bus = NULL;
+                       }
                } else {
                        radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL);
 
@@ -1015,6 +1030,11 @@ static int radeon_dvi_mode_valid(struct drm_connector *connector,
                } else
                        return MODE_CLOCK_HIGH;
        }
+
+       /* check against the max pixel clock */
+       if ((mode->clock / 10) > rdev->clock.max_pixel_clock)
+               return MODE_CLOCK_HIGH;
+
        return MODE_OK;
 }
 
@@ -1052,10 +1072,11 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
 {
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
+       struct drm_encoder *encoder = radeon_best_single_encoder(connector);
        int ret;
 
-       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
-               struct drm_encoder *encoder;
+       if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
+           (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
                struct drm_display_mode *mode;
 
                if (!radeon_dig_connector->edp_on)
@@ -1067,7 +1088,6 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
                                                     ATOM_TRANSMITTER_ACTION_POWER_OFF);
 
                if (ret > 0) {
-                       encoder = radeon_best_single_encoder(connector);
                        if (encoder) {
                                radeon_fixup_lvds_native_mode(encoder, connector);
                                /* add scaled modes */
@@ -1091,8 +1111,14 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
                        /* add scaled modes */
                        radeon_add_common_modes(encoder, connector);
                }
-       } else
+       } else {
+               /* need to setup ddc on the bridge */
+               if (radeon_connector_encoder_is_dp_bridge(connector)) {
+                       if (encoder)
+                               radeon_atom_ext_encoder_setup_ddc(encoder);
+               }
                ret = radeon_ddc_get_modes(radeon_connector);
+       }
 
        return ret;
 }
@@ -1176,14 +1202,15 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        enum drm_connector_status ret = connector_status_disconnected;
        struct radeon_connector_atom_dig *radeon_dig_connector = radeon_connector->con_priv;
+       struct drm_encoder *encoder = radeon_best_single_encoder(connector);
 
        if (radeon_connector->edid) {
                kfree(radeon_connector->edid);
                radeon_connector->edid = NULL;
        }
 
-       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
-               struct drm_encoder *encoder = radeon_best_single_encoder(connector);
+       if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
+           (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
                if (encoder) {
                        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
                        struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
@@ -1203,6 +1230,11 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                        atombios_set_edp_panel_power(connector,
                                                     ATOM_TRANSMITTER_ACTION_POWER_OFF);
        } else {
+               /* need to setup ddc on the bridge */
+               if (radeon_connector_encoder_is_dp_bridge(connector)) {
+                       if (encoder)
+                               radeon_atom_ext_encoder_setup_ddc(encoder);
+               }
                radeon_dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector);
                if (radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) {
                        ret = connector_status_connected;
@@ -1217,6 +1249,16 @@ radeon_dp_detect(struct drm_connector *connector, bool force)
                                        ret = connector_status_connected;
                        }
                }
+
+               if ((ret == connector_status_disconnected) &&
+                   radeon_connector->dac_load_detect) {
+                       struct drm_encoder *encoder = radeon_best_single_encoder(connector);
+                       struct drm_encoder_helper_funcs *encoder_funcs;
+                       if (encoder) {
+                               encoder_funcs = encoder->helper_private;
+                               ret = encoder_funcs->detect(encoder, connector);
+                       }
+               }
        }
 
        radeon_connector_update_scratch_regs(connector, ret);
@@ -1231,7 +1273,8 @@ static int radeon_dp_mode_valid(struct drm_connector *connector,
 
        /* XXX check mode bandwidth */
 
-       if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
+       if ((connector->connector_type == DRM_MODE_CONNECTOR_eDP) ||
+           (connector->connector_type == DRM_MODE_CONNECTOR_LVDS)) {
                struct drm_encoder *encoder = radeon_best_single_encoder(connector);
 
                if ((mode->hdisplay < 320) || (mode->vdisplay < 240))
@@ -1241,7 +1284,7 @@ static int radeon_dp_mode_valid(struct drm_connector *connector,
                        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
                        struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
 
-               /* AVIVO hardware supports downscaling modes larger than the panel
+                       /* AVIVO hardware supports downscaling modes larger than the panel
                         * to the panel size, but I'm not sure this is desirable.
                         */
                        if ((mode->hdisplay > native_mode->hdisplay) ||
@@ -1390,6 +1433,10 @@ radeon_add_atom_connector(struct drm_device *dev,
                default:
                        connector->interlace_allowed = true;
                        connector->doublescan_allowed = true;
+                       radeon_connector->dac_load_detect = true;
+                       drm_connector_attach_property(&radeon_connector->base,
+                                                     rdev->mode_info.load_detect_property,
+                                                     1);
                        break;
                case DRM_MODE_CONNECTOR_DVII:
                case DRM_MODE_CONNECTOR_DVID:
@@ -1411,6 +1458,12 @@ radeon_add_atom_connector(struct drm_device *dev,
                                connector->doublescan_allowed = true;
                        else
                                connector->doublescan_allowed = false;
+                       if (connector_type == DRM_MODE_CONNECTOR_DVII) {
+                               radeon_connector->dac_load_detect = true;
+                               drm_connector_attach_property(&radeon_connector->base,
+                                                             rdev->mode_info.load_detect_property,
+                                                             1);
+                       }
                        break;
                case DRM_MODE_CONNECTOR_LVDS:
                case DRM_MODE_CONNECTOR_eDP:
index e680501c78ea50e7d7a9d9d8f5d727c7c4e3337a..7cfaa7e2f3b57195671beb6958c8447f9f108683 100644 (file)
@@ -215,6 +215,8 @@ int radeon_wb_init(struct radeon_device *rdev)
                return r;
        }
 
+       /* clear wb memory */
+       memset((char *)rdev->wb.wb, 0, RADEON_GPU_PAGE_SIZE);
        /* disable event_write fences */
        rdev->wb.use_event = false;
        /* disabled via module param */
index 03f124d626c2aba034d0d74d4ac1f2f1d4e9c636..b293487e5aa3dc2193fee36eb0f9c00fe7080a0c 100644 (file)
@@ -367,7 +367,8 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
        }
 
        if (ASIC_IS_DCE3(rdev) &&
-           (radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT))) {
+           ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) ||
+            radeon_encoder_is_dp_bridge(encoder))) {
                struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
                radeon_dp_set_link_config(connector, mode);
        }
@@ -660,21 +661,16 @@ atombios_get_encoder_mode(struct drm_encoder *encoder)
        if (radeon_encoder_is_dp_bridge(encoder))
                return ATOM_ENCODER_MODE_DP;
 
+       /* DVO is always DVO */
+       if (radeon_encoder->encoder_id == ATOM_ENCODER_MODE_DVO)
+               return ATOM_ENCODER_MODE_DVO;
+
        connector = radeon_get_connector_for_encoder(encoder);
-       if (!connector) {
-               switch (radeon_encoder->encoder_id) {
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
-               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
-               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
-                       return ATOM_ENCODER_MODE_DVI;
-               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1:
-               case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2:
-               default:
-                       return ATOM_ENCODER_MODE_CRT;
-               }
-       }
+       /* if we don't have an active device yet, just use one of
+        * the connectors tied to the encoder.
+        */
+       if (!connector)
+               connector = radeon_get_connector_for_encoder_init(encoder);
        radeon_connector = to_radeon_connector(connector);
 
        switch (connector->connector_type) {
@@ -1094,9 +1090,10 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
                        break;
                }
 
-               if (is_dp)
+               if (is_dp) {
                        args.v2.acConfig.fCoherentMode = 1;
-               else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
+                       args.v2.acConfig.fDPConnector = 1;
+               } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
                        if (dig->coherent_mode)
                                args.v2.acConfig.fCoherentMode = 1;
                        if (radeon_encoder->pixel_clock > 165000)
@@ -1435,7 +1432,11 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
        if (is_dig) {
                switch (mode) {
                case DRM_MODE_DPMS_ON:
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
+                       /* some early dce3.2 boards have a bug in their transmitter control table */
+                       if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730))
+                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+                       else
+                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
                        if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
                                struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
 
@@ -1526,26 +1527,29 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
        }
 
        if (ext_encoder) {
-               int action;
-
                switch (mode) {
                case DRM_MODE_DPMS_ON:
                default:
-                       if (ASIC_IS_DCE41(rdev))
-                               action = EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT;
-                       else
-                               action = ATOM_ENABLE;
+                       if (ASIC_IS_DCE41(rdev)) {
+                               atombios_external_encoder_setup(encoder, ext_encoder,
+                                                               EXTERNAL_ENCODER_ACTION_V3_ENABLE_OUTPUT);
+                               atombios_external_encoder_setup(encoder, ext_encoder,
+                                                               EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING_OFF);
+                       } else
+                               atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
                        break;
                case DRM_MODE_DPMS_STANDBY:
                case DRM_MODE_DPMS_SUSPEND:
                case DRM_MODE_DPMS_OFF:
-                       if (ASIC_IS_DCE41(rdev))
-                               action = EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT;
-                       else
-                               action = ATOM_DISABLE;
+                       if (ASIC_IS_DCE41(rdev)) {
+                               atombios_external_encoder_setup(encoder, ext_encoder,
+                                                               EXTERNAL_ENCODER_ACTION_V3_ENCODER_BLANKING);
+                               atombios_external_encoder_setup(encoder, ext_encoder,
+                                                               EXTERNAL_ENCODER_ACTION_V3_DISABLE_OUTPUT);
+                       } else
+                               atombios_external_encoder_setup(encoder, ext_encoder, ATOM_DISABLE);
                        break;
                }
-               atombios_external_encoder_setup(encoder, ext_encoder, action);
        }
 
        radeon_atombios_encoder_dpms_scratch_regs(encoder, (mode == DRM_MODE_DPMS_ON) ? true : false);
@@ -2004,6 +2008,65 @@ radeon_atom_dac_detect(struct drm_encoder *encoder, struct drm_connector *connec
        return connector_status_disconnected;
 }
 
+static enum drm_connector_status
+radeon_atom_dig_detect(struct drm_encoder *encoder, struct drm_connector *connector)
+{
+       struct drm_device *dev = encoder->dev;
+       struct radeon_device *rdev = dev->dev_private;
+       struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct radeon_connector *radeon_connector = to_radeon_connector(connector);
+       struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
+       u32 bios_0_scratch;
+
+       if (!ASIC_IS_DCE4(rdev))
+               return connector_status_unknown;
+
+       if (!ext_encoder)
+               return connector_status_unknown;
+
+       if ((radeon_connector->devices & ATOM_DEVICE_CRT_SUPPORT) == 0)
+               return connector_status_unknown;
+
+       /* load detect on the dp bridge */
+       atombios_external_encoder_setup(encoder, ext_encoder,
+                                       EXTERNAL_ENCODER_ACTION_V3_DACLOAD_DETECTION);
+
+       bios_0_scratch = RREG32(R600_BIOS_0_SCRATCH);
+
+       DRM_DEBUG_KMS("Bios 0 scratch %x %08x\n", bios_0_scratch, radeon_encoder->devices);
+       if (radeon_connector->devices & ATOM_DEVICE_CRT1_SUPPORT) {
+               if (bios_0_scratch & ATOM_S0_CRT1_MASK)
+                       return connector_status_connected;
+       }
+       if (radeon_connector->devices & ATOM_DEVICE_CRT2_SUPPORT) {
+               if (bios_0_scratch & ATOM_S0_CRT2_MASK)
+                       return connector_status_connected;
+       }
+       if (radeon_connector->devices & ATOM_DEVICE_CV_SUPPORT) {
+               if (bios_0_scratch & (ATOM_S0_CV_MASK|ATOM_S0_CV_MASK_A))
+                       return connector_status_connected;
+       }
+       if (radeon_connector->devices & ATOM_DEVICE_TV1_SUPPORT) {
+               if (bios_0_scratch & (ATOM_S0_TV1_COMPOSITE | ATOM_S0_TV1_COMPOSITE_A))
+                       return connector_status_connected; /* CTV */
+               else if (bios_0_scratch & (ATOM_S0_TV1_SVIDEO | ATOM_S0_TV1_SVIDEO_A))
+                       return connector_status_connected; /* STV */
+       }
+       return connector_status_disconnected;
+}
+
+void
+radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder)
+{
+       struct drm_encoder *ext_encoder = radeon_atom_get_external_encoder(encoder);
+
+       if (ext_encoder)
+               /* ddc_setup on the dp bridge */
+               atombios_external_encoder_setup(encoder, ext_encoder,
+                                               EXTERNAL_ENCODER_ACTION_V3_DDC_SETUP);
+
+}
+
 static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
 {
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
@@ -2167,7 +2230,7 @@ static const struct drm_encoder_helper_funcs radeon_atom_dig_helper_funcs = {
        .mode_set = radeon_atom_encoder_mode_set,
        .commit = radeon_atom_encoder_commit,
        .disable = radeon_atom_encoder_disable,
-       /* no detect for TMDS/LVDS yet */
+       .detect = radeon_atom_dig_detect,
 };
 
 static const struct drm_encoder_helper_funcs radeon_atom_dac_helper_funcs = {
index 1f822943657017b3684d6204ae19c76abd95ae6a..021d2b6b556f9e837d2c8a508891c4b6bc19850e 100644 (file)
 #include "radeon.h"
 #include "radeon_trace.h"
 
+static void radeon_fence_write(struct radeon_device *rdev, u32 seq)
+{
+       if (rdev->wb.enabled) {
+               u32 scratch_index;
+               if (rdev->wb.use_event)
+                       scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
+               else
+                       scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
+               rdev->wb.wb[scratch_index/4] = cpu_to_le32(seq);;
+       } else
+               WREG32(rdev->fence_drv.scratch_reg, seq);
+}
+
+static u32 radeon_fence_read(struct radeon_device *rdev)
+{
+       u32 seq;
+
+       if (rdev->wb.enabled) {
+               u32 scratch_index;
+               if (rdev->wb.use_event)
+                       scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
+               else
+                       scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
+               seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]);
+       } else
+               seq = RREG32(rdev->fence_drv.scratch_reg);
+       return seq;
+}
+
 int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)
 {
        unsigned long irq_flags;
@@ -50,12 +79,12 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence *fence)
                return 0;
        }
        fence->seq = atomic_add_return(1, &rdev->fence_drv.seq);
-       if (!rdev->cp.ready) {
+       if (!rdev->cp.ready)
                /* FIXME: cp is not running assume everythings is done right
                 * away
                 */
-               WREG32(rdev->fence_drv.scratch_reg, fence->seq);
-       else
+               radeon_fence_write(rdev, fence->seq);
+       else
                radeon_fence_ring_emit(rdev, fence);
 
        trace_radeon_fence_emit(rdev->ddev, fence->seq);
@@ -73,15 +102,7 @@ static bool radeon_fence_poll_locked(struct radeon_device *rdev)
        bool wake = false;
        unsigned long cjiffies;
 
-       if (rdev->wb.enabled) {
-               u32 scratch_index;
-               if (rdev->wb.use_event)
-                       scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
-               else
-                       scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
-               seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]);
-       } else
-               seq = RREG32(rdev->fence_drv.scratch_reg);
+       seq = radeon_fence_read(rdev);
        if (seq != rdev->fence_drv.last_seq) {
                rdev->fence_drv.last_seq = seq;
                rdev->fence_drv.last_jiffies = jiffies;
@@ -251,7 +272,7 @@ retry:
                        r = radeon_gpu_reset(rdev);
                        if (r)
                                return r;
-                       WREG32(rdev->fence_drv.scratch_reg, fence->seq);
+                       radeon_fence_write(rdev, fence->seq);
                        rdev->gpu_lockup = false;
                }
                timeout = RADEON_FENCE_JIFFIES_TIMEOUT;
@@ -351,7 +372,7 @@ int radeon_fence_driver_init(struct radeon_device *rdev)
                write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
                return r;
        }
-       WREG32(rdev->fence_drv.scratch_reg, 0);
+       radeon_fence_write(rdev, 0);
        atomic_set(&rdev->fence_drv.seq, 0);
        INIT_LIST_HEAD(&rdev->fence_drv.created);
        INIT_LIST_HEAD(&rdev->fence_drv.emited);
@@ -391,7 +412,7 @@ static int radeon_debugfs_fence_info(struct seq_file *m, void *data)
        struct radeon_fence *fence;
 
        seq_printf(m, "Last signaled fence 0x%08X\n",
-                  RREG32(rdev->fence_drv.scratch_reg));
+                  radeon_fence_read(rdev));
        if (!list_empty(&rdev->fence_drv.emited)) {
                   fence = list_entry(rdev->fence_drv.emited.prev,
                                      struct radeon_fence, list);
index 977a341266b6d2d5c52fa5073c7f1a21a8dcdd37..6df4e3cec0c23cdced34b0da862eddd6d08c2c88 100644 (file)
@@ -483,6 +483,8 @@ extern void radeon_atom_encoder_init(struct radeon_device *rdev);
 extern void atombios_dig_transmitter_setup(struct drm_encoder *encoder,
                                           int action, uint8_t lane_num,
                                           uint8_t lane_set);
+extern void radeon_atom_ext_encoder_setup_ddc(struct drm_encoder *encoder);
+extern struct drm_encoder *radeon_atom_get_external_encoder(struct drm_encoder *encoder);
 extern int radeon_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode,
                                u8 write_byte, u8 *read_byte);
 
index ef8a5babe9f7679fce662775faa98afb4f1002a2..6f508ffd1035c0814d7096af09d718e9b040ec9a 100644 (file)
@@ -105,6 +105,9 @@ void rv770_pm_misc(struct radeon_device *rdev)
        struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
 
        if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
+               /* 0xff01 is a flag rather then an actual voltage */
+               if (voltage->voltage == 0xff01)
+                       return;
                if (voltage->voltage != rdev->pm.current_vddc) {
                        radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);
                        rdev->pm.current_vddc = voltage->voltage;
index bf5f83ea14fe19819874311b66618957859286f2..cb1ee4e0050ade2a0da63d4b8cdac714f10c1aff 100644 (file)
@@ -647,9 +647,6 @@ int savage_driver_firstopen(struct drm_device *dev)
        ret = drm_addmap(dev, aperture_base, SAVAGE_APERTURE_SIZE,
                         _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING,
                         &dev_priv->aperture);
-       if (ret)
-               return ret;
-
        return ret;
 }
 
index 90e23e0bfadb054ffbcf8ee65c6cbac98881790a..58c271ebc0f73f6829dae7cffa9d680480ad0dd1 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/sched.h>
 #include <linux/highmem.h>
 #include <linux/pagemap.h>
+#include <linux/shmem_fs.h>
 #include <linux/file.h>
 #include <linux/swap.h>
 #include <linux/slab.h>
@@ -484,7 +485,7 @@ static int ttm_tt_swapin(struct ttm_tt *ttm)
        swap_space = swap_storage->f_path.dentry->d_inode->i_mapping;
 
        for (i = 0; i < ttm->num_pages; ++i) {
-               from_page = read_mapping_page(swap_space, i, NULL);
+               from_page = shmem_read_mapping_page(swap_space, i);
                if (IS_ERR(from_page)) {
                        ret = PTR_ERR(from_page);
                        goto out_err;
@@ -557,7 +558,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
                from_page = ttm->pages[i];
                if (unlikely(from_page == NULL))
                        continue;
-               to_page = read_mapping_page(swap_space, i, NULL);
+               to_page = shmem_read_mapping_page(swap_space, i);
                if (unlikely(IS_ERR(to_page))) {
                        ret = PTR_ERR(to_page);
                        goto out_err;
index 67d2a7585934c31b3607710c675e531acb21e6a6..36ca465c00cefac036a22fad61fc70b2568a1ccc 100644 (file)
@@ -305,6 +305,7 @@ config HID_MULTITOUCH
          - 3M PCT touch screens
          - ActionStar dual touch panels
          - Cando dual touch panels
+         - Chunghwa panels
          - CVTouch panels
          - Cypress TrueTouch panels
          - Elo TouchSystems IntelliTouch Plus panels
index c957c4b4fe703368a4d19e739277b5c9bd41383b..6f3289a5788812ef573561482f581d04ca6524cc 100644 (file)
@@ -1359,6 +1359,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) },
        { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
@@ -1422,6 +1423,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH_DUAL) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) },
index 0b374a6d6db007853f6762ef489e9191a5e1258e..a756ee6c7df59389c3f79b8a7f06a2343a28aed8 100644 (file)
 #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH      0xb19d
 #define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618
 
+#define USB_VENDOR_ID_CHUNGHWAT                0x2247
+#define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH     0x0001
+
 #define USB_VENDOR_ID_CIDC             0x1677
 
 #define USB_VENDOR_ID_CMEDIA           0x0d8c
 
 #define USB_VENDOR_ID_LUMIO            0x202e
 #define USB_DEVICE_ID_CRYSTALTOUCH     0x0006
+#define USB_DEVICE_ID_CRYSTALTOUCH_DUAL        0x0007
 
 #define USB_VENDOR_ID_MCC              0x09db
 #define USB_DEVICE_ID_MCC_PMD1024LS    0x0076
 #define USB_VENDOR_ID_UCLOGIC          0x5543
 #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209    0x0042
 #define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5      0x6001
+#define USB_DEVICE_ID_UCLOGIC_TABLET_TWA60     0x0064
 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U   0x0003
 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U   0x0004
 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U   0x0005
index a5eda4c8127a274ee20343d26a82383135c3048b..0ec91c18a4216a52a4a3c7d85292a22f61a6e828 100644 (file)
@@ -501,17 +501,9 @@ static int magicmouse_probe(struct hid_device *hdev,
        }
        report->size = 6;
 
-       /*
-        * The device reponds with 'invalid report id' when feature
-        * report switching it into multitouch mode is sent to it.
-        *
-        * This results in -EIO from the _raw low-level transport callback,
-        * but there seems to be no other way of switching the mode.
-        * Thus the super-ugly hacky success check below.
-        */
        ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature),
                        HID_FEATURE_REPORT);
-       if (ret != -EIO) {
+       if (ret != sizeof(feature)) {
                hid_err(hdev, "unable to request touch data (%d)\n", ret);
                goto err_stop_hw;
        }
index ecd4d2db9e800ca2397c3ad18945d30b2080a028..62cac4dc3b627c6bb598a77ce0c1cb78eee62be5 100644 (file)
@@ -64,6 +64,7 @@ struct mt_device {
        struct mt_class *mtclass;       /* our mt device class */
        unsigned last_field_index;      /* last field index of the report */
        unsigned last_slot_field;       /* the last field of a slot */
+       int last_mt_collection; /* last known mt-related collection */
        __s8 inputmode;         /* InputMode HID feature, -1 if non-existent */
        __u8 num_received;      /* how many contacts we received */
        __u8 num_expected;      /* expected last contact index */
@@ -225,8 +226,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                                cls->sn_move);
                        /* touchscreen emulation */
                        set_abs(hi->input, ABS_X, field, cls->sn_move);
-                       td->last_slot_field = usage->hid;
-                       td->last_field_index = field->index;
+                       if (td->last_mt_collection == usage->collection_index) {
+                               td->last_slot_field = usage->hid;
+                               td->last_field_index = field->index;
+                       }
                        return 1;
                case HID_GD_Y:
                        if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
@@ -237,8 +240,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                                cls->sn_move);
                        /* touchscreen emulation */
                        set_abs(hi->input, ABS_Y, field, cls->sn_move);
-                       td->last_slot_field = usage->hid;
-                       td->last_field_index = field->index;
+                       if (td->last_mt_collection == usage->collection_index) {
+                               td->last_slot_field = usage->hid;
+                               td->last_field_index = field->index;
+                       }
                        return 1;
                }
                return 0;
@@ -246,31 +251,42 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
        case HID_UP_DIGITIZER:
                switch (usage->hid) {
                case HID_DG_INRANGE:
-                       td->last_slot_field = usage->hid;
-                       td->last_field_index = field->index;
+                       if (td->last_mt_collection == usage->collection_index) {
+                               td->last_slot_field = usage->hid;
+                               td->last_field_index = field->index;
+                       }
                        return 1;
                case HID_DG_CONFIDENCE:
-                       td->last_slot_field = usage->hid;
-                       td->last_field_index = field->index;
+                       if (td->last_mt_collection == usage->collection_index) {
+                               td->last_slot_field = usage->hid;
+                               td->last_field_index = field->index;
+                       }
                        return 1;
                case HID_DG_TIPSWITCH:
                        hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
                        input_set_capability(hi->input, EV_KEY, BTN_TOUCH);
-                       td->last_slot_field = usage->hid;
-                       td->last_field_index = field->index;
+                       if (td->last_mt_collection == usage->collection_index) {
+                               td->last_slot_field = usage->hid;
+                               td->last_field_index = field->index;
+                       }
                        return 1;
                case HID_DG_CONTACTID:
+                       if (!td->maxcontacts)
+                               td->maxcontacts = MT_DEFAULT_MAXCONTACT;
                        input_mt_init_slots(hi->input, td->maxcontacts);
                        td->last_slot_field = usage->hid;
                        td->last_field_index = field->index;
+                       td->last_mt_collection = usage->collection_index;
                        return 1;
                case HID_DG_WIDTH:
                        hid_map_usage(hi, usage, bit, max,
                                        EV_ABS, ABS_MT_TOUCH_MAJOR);
                        set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field,
                                cls->sn_width);
-                       td->last_slot_field = usage->hid;
-                       td->last_field_index = field->index;
+                       if (td->last_mt_collection == usage->collection_index) {
+                               td->last_slot_field = usage->hid;
+                               td->last_field_index = field->index;
+                       }
                        return 1;
                case HID_DG_HEIGHT:
                        hid_map_usage(hi, usage, bit, max,
@@ -279,8 +295,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                                cls->sn_height);
                        input_set_abs_params(hi->input,
                                        ABS_MT_ORIENTATION, 0, 1, 0, 0);
-                       td->last_slot_field = usage->hid;
-                       td->last_field_index = field->index;
+                       if (td->last_mt_collection == usage->collection_index) {
+                               td->last_slot_field = usage->hid;
+                               td->last_field_index = field->index;
+                       }
                        return 1;
                case HID_DG_TIPPRESSURE:
                        if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
@@ -292,16 +310,20 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
                        /* touchscreen emulation */
                        set_abs(hi->input, ABS_PRESSURE, field,
                                cls->sn_pressure);
-                       td->last_slot_field = usage->hid;
-                       td->last_field_index = field->index;
+                       if (td->last_mt_collection == usage->collection_index) {
+                               td->last_slot_field = usage->hid;
+                               td->last_field_index = field->index;
+                       }
                        return 1;
                case HID_DG_CONTACTCOUNT:
-                       td->last_field_index = field->index;
+                       if (td->last_mt_collection == usage->collection_index)
+                               td->last_field_index = field->index;
                        return 1;
                case HID_DG_CONTACTMAX:
                        /* we don't set td->last_slot_field as contactcount and
                         * contact max are global to the report */
-                       td->last_field_index = field->index;
+                       if (td->last_mt_collection == usage->collection_index)
+                               td->last_field_index = field->index;
                        return -1;
                }
                /* let hid-input decide for the others */
@@ -516,6 +538,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
        }
        td->mtclass = mtclass;
        td->inputmode = -1;
+       td->last_mt_collection = -1;
        hid_set_drvdata(hdev, td);
 
        ret = hid_parse(hdev);
@@ -526,9 +549,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id)
        if (ret)
                goto fail;
 
-       if (!td->maxcontacts)
-               td->maxcontacts = MT_DEFAULT_MAXCONTACT;
-
        td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot),
                                GFP_KERNEL);
        if (!td->slots) {
@@ -593,6 +613,11 @@ static const struct hid_device_id mt_devices[] = {
                HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
                        USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) },
 
+       /* Chunghwa Telecom touch panels */
+       {  .driver_data = MT_CLS_DEFAULT,
+               HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT,
+                       USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) },
+
        /* CVTouch panels */
        { .driver_data = MT_CLS_DEFAULT,
                HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH,
@@ -651,6 +676,9 @@ static const struct hid_device_id mt_devices[] = {
        { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
                HID_USB_DEVICE(USB_VENDOR_ID_LUMIO,
                        USB_DEVICE_ID_CRYSTALTOUCH) },
+       { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
+               HID_USB_DEVICE(USB_VENDOR_ID_LUMIO,
+                       USB_DEVICE_ID_CRYSTALTOUCH_DUAL) },
 
        /* MosArt panels */
        { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
@@ -681,10 +709,10 @@ static const struct hid_device_id mt_devices[] = {
                HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
                        USB_DEVICE_ID_MTP)},
        { .driver_data = MT_CLS_CONFIDENCE,
-               HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
+               HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM,
                        USB_DEVICE_ID_MTP_STM)},
        { .driver_data = MT_CLS_CONFIDENCE,
-               HID_USB_DEVICE(USB_VENDOR_ID_STANTUM,
+               HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX,
                        USB_DEVICE_ID_MTP_SITRONIX)},
 
        /* Touch International panels */
index 0e30b140edca173d3fb47b4d2b756ad7c53f9f43..621959d5cc42c6b6798328fe32ce32072fa8669a 100644 (file)
@@ -74,6 +74,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT },
+       { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT },
        { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT },
index ff3c644888b1ba8b0bf14e2426313b66db3688c0..7c1188b53c3ec0ea4aca4364239d9e3596cb7cfa 100644 (file)
@@ -248,12 +248,15 @@ static int hiddev_release(struct inode * inode, struct file * file)
                        usbhid_close(list->hiddev->hid);
                        usbhid_put_power(list->hiddev->hid);
                } else {
+                       mutex_unlock(&list->hiddev->existancelock);
                        kfree(list->hiddev);
+                       kfree(list);
+                       return 0;
                }
        }
 
-       kfree(list);
        mutex_unlock(&list->hiddev->existancelock);
+       kfree(list);
 
        return 0;
 }
@@ -923,10 +926,11 @@ void hiddev_disconnect(struct hid_device *hid)
        usb_deregister_dev(usbhid->intf, &hiddev_class);
 
        if (hiddev->open) {
+               mutex_unlock(&hiddev->existancelock);
                usbhid_close(hiddev->hid);
                wake_up_interruptible(&hiddev->wait);
        } else {
+               mutex_unlock(&hiddev->existancelock);
                kfree(hiddev);
        }
-       mutex_unlock(&hiddev->existancelock);
 }
index b5e892017e0c57497f7726d59812a56144f35ea8..dcb78a7a804754956035f2c57e2e1f8673ac45df 100644 (file)
@@ -268,6 +268,7 @@ static struct device_attribute atk_name_attr =
 static void atk_init_attribute(struct device_attribute *attr, char *name,
                sysfs_show_func show)
 {
+       sysfs_attr_init(&attr->attr);
        attr->attr.name = name;
        attr->attr.mode = 0444;
        attr->show = show;
@@ -1188,19 +1189,15 @@ static int atk_create_files(struct atk_data *data)
        int err;
 
        list_for_each_entry(s, &data->sensor_list, list) {
-               sysfs_attr_init(&s->input_attr.attr);
                err = device_create_file(data->hwmon_dev, &s->input_attr);
                if (err)
                        return err;
-               sysfs_attr_init(&s->label_attr.attr);
                err = device_create_file(data->hwmon_dev, &s->label_attr);
                if (err)
                        return err;
-               sysfs_attr_init(&s->limit1_attr.attr);
                err = device_create_file(data->hwmon_dev, &s->limit1_attr);
                if (err)
                        return err;
-               sysfs_attr_init(&s->limit2_attr.attr);
                err = device_create_file(data->hwmon_dev, &s->limit2_attr);
                if (err)
                        return err;
index 85e937984ff7594a8a610db84c08871898c67f15..0070d5476dd0b5ee96bba29259c821d5419bf117 100644 (file)
@@ -97,9 +97,7 @@ struct platform_data {
 struct pdev_entry {
        struct list_head list;
        struct platform_device *pdev;
-       unsigned int cpu;
        u16 phys_proc_id;
-       u16 cpu_core_id;
 };
 
 static LIST_HEAD(pdev_list);
@@ -653,9 +651,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu)
        }
 
        pdev_entry->pdev = pdev;
-       pdev_entry->cpu = cpu;
        pdev_entry->phys_proc_id = TO_PHYS_ID(cpu);
-       pdev_entry->cpu_core_id = TO_CORE_ID(cpu);
 
        list_add_tail(&pdev_entry->list, &pdev_list);
        mutex_unlock(&pdev_list_mutex);
index 537409d07ee730b55e358fcb1e9e6d515d27e1e8..1a409c5bc9bce687922ce5389150599c6e928f39 100644 (file)
@@ -947,6 +947,7 @@ static int aem_register_sensors(struct aem_data *data,
 
        /* Set up read-only sensors */
        while (ro->label) {
+               sysfs_attr_init(&sensors->dev_attr.attr);
                sensors->dev_attr.attr.name = ro->label;
                sensors->dev_attr.attr.mode = S_IRUGO;
                sensors->dev_attr.show = ro->show;
@@ -963,6 +964,7 @@ static int aem_register_sensors(struct aem_data *data,
 
        /* Set up read-write sensors */
        while (rw->label) {
+               sysfs_attr_init(&sensors->dev_attr.attr);
                sensors->dev_attr.attr.name = rw->label;
                sensors->dev_attr.attr.mode = S_IRUGO | S_IWUSR;
                sensors->dev_attr.show = rw->show;
index 06d4eafcf76b231fdc74e0418341e496387b78d9..41dbf8161ed7b4fb1bc29811c61f006152c9a41c 100644 (file)
@@ -358,6 +358,7 @@ static int create_sensor(struct ibmpex_bmc_data *data, int type,
        else if (type == POWER_SENSOR)
                sprintf(n, power_sensor_name_templates[func], "power", counter);
 
+       sysfs_attr_init(&data->sensors[sensor].attr[func].dev_attr.attr);
        data->sensors[sensor].attr[func].dev_attr.attr.name = n;
        data->sensors[sensor].attr[func].dev_attr.attr.mode = S_IRUGO;
        data->sensors[sensor].attr[func].dev_attr.show = ibmpex_show_sensor;
index 92b42db43bcfd9e5706c41bfb9049a26fd967b93..b39f52e2752a7bca54a1bb25c7083382b01aa52e 100644 (file)
@@ -232,6 +232,7 @@ static int s3c_hwmon_create_attr(struct device *dev,
 
        attr = &attrs->in;
        attr->index = channel;
+       sysfs_attr_init(&attr->dev_attr.attr);
        attr->dev_attr.attr.name  = attrs->in_name;
        attr->dev_attr.attr.mode  = S_IRUGO;
        attr->dev_attr.show = s3c_hwmon_ch_show;
@@ -249,6 +250,7 @@ static int s3c_hwmon_create_attr(struct device *dev,
 
                attr = &attrs->label;
                attr->index = channel;
+               sysfs_attr_init(&attr->dev_attr.attr);
                attr->dev_attr.attr.name  = attrs->label_name;
                attr->dev_attr.attr.mode  = S_IRUGO;
                attr->dev_attr.show = s3c_hwmon_label_show;
index f660cd04ec2f31774ed678b16dbb85d3a8ed6b39..31fb44085c9b4dd7e3cdd4f97f59727f4a82d107 100644 (file)
@@ -1463,9 +1463,9 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
        struct c4iw_qp_attributes attrs;
        int disconnect = 1;
        int release = 0;
-       int abort = 0;
        struct tid_info *t = dev->rdev.lldi.tids;
        unsigned int tid = GET_TID(hdr);
+       int ret;
 
        ep = lookup_tid(t, tid);
        PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
@@ -1501,10 +1501,12 @@ static int peer_close(struct c4iw_dev *dev, struct sk_buff *skb)
                start_ep_timer(ep);
                __state_set(&ep->com, CLOSING);
                attrs.next_state = C4IW_QP_STATE_CLOSING;
-               abort = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
+               ret = c4iw_modify_qp(ep->com.qp->rhp, ep->com.qp,
                                       C4IW_QP_ATTR_NEXT_STATE, &attrs, 1);
-               peer_close_upcall(ep);
-               disconnect = 1;
+               if (ret != -ECONNRESET) {
+                       peer_close_upcall(ep);
+                       disconnect = 1;
+               }
                break;
        case ABORTING:
                disconnect = 0;
@@ -2109,15 +2111,16 @@ int c4iw_ep_disconnect(struct c4iw_ep *ep, int abrupt, gfp_t gfp)
                break;
        }
 
-       mutex_unlock(&ep->com.mutex);
        if (close) {
-               if (abrupt)
-                       ret = abort_connection(ep, NULL, gfp);
-               else
+               if (abrupt) {
+                       close_complete_upcall(ep);
+                       ret = send_abort(ep, NULL, gfp);
+               } else
                        ret = send_halfclose(ep, gfp);
                if (ret)
                        fatal = 1;
        }
+       mutex_unlock(&ep->com.mutex);
        if (fatal)
                release_ep_resources(ep);
        return ret;
@@ -2301,6 +2304,31 @@ static int fw6_msg(struct c4iw_dev *dev, struct sk_buff *skb)
        return 0;
 }
 
+static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb)
+{
+       struct cpl_abort_req_rss *req = cplhdr(skb);
+       struct c4iw_ep *ep;
+       struct tid_info *t = dev->rdev.lldi.tids;
+       unsigned int tid = GET_TID(req);
+
+       ep = lookup_tid(t, tid);
+       if (is_neg_adv_abort(req->status)) {
+               PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep,
+                    ep->hwtid);
+               kfree_skb(skb);
+               return 0;
+       }
+       PDBG("%s ep %p tid %u state %u\n", __func__, ep, ep->hwtid,
+            ep->com.state);
+
+       /*
+        * Wake up any threads in rdma_init() or rdma_fini().
+        */
+       c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET);
+       sched(dev, skb);
+       return 0;
+}
+
 /*
  * Most upcalls from the T4 Core go to sched() to
  * schedule the processing on a work queue.
@@ -2317,7 +2345,7 @@ c4iw_handler_func c4iw_handlers[NUM_CPL_CMDS] = {
        [CPL_PASS_ESTABLISH] = sched,
        [CPL_PEER_CLOSE] = sched,
        [CPL_CLOSE_CON_RPL] = sched,
-       [CPL_ABORT_REQ_RSS] = sched,
+       [CPL_ABORT_REQ_RSS] = peer_abort_intr,
        [CPL_RDMA_TERMINATE] = sched,
        [CPL_FW4_ACK] = sched,
        [CPL_SET_TCB_RPL] = set_tcb_rpl,
index 8d8f8add6fcd93e71fd5b8931616554099bd7b00..1720dc790d13d1367594478a95ad1c9148bb91b1 100644 (file)
@@ -801,6 +801,10 @@ struct ib_cq *c4iw_create_cq(struct ib_device *ibdev, int entries,
        if (ucontext) {
                memsize = roundup(memsize, PAGE_SIZE);
                hwentries = memsize / sizeof *chp->cq.queue;
+               while (hwentries > T4_MAX_IQ_SIZE) {
+                       memsize -= PAGE_SIZE;
+                       hwentries = memsize / sizeof *chp->cq.queue;
+               }
        }
        chp->cq.size = hwentries;
        chp->cq.memsize = memsize;
index 273ffe49525a5d3d1642a292730af15a388ad9da..0347eed4a16778f173415f47c49c45d9f6d99acc 100644 (file)
@@ -625,7 +625,7 @@ pbl_done:
        mhp->attr.perms = c4iw_ib_to_tpt_access(acc);
        mhp->attr.va_fbo = virt;
        mhp->attr.page_size = shift - 12;
-       mhp->attr.len = (u32) length;
+       mhp->attr.len = length;
 
        err = register_mem(rhp, php, mhp, shift);
        if (err)
index 3b773b05a8989a0a7b81bda16f64c0f747577344..a41578e48c7b0bb366795bfd3da1dd961f3d42d1 100644 (file)
@@ -1207,11 +1207,8 @@ int c4iw_modify_qp(struct c4iw_dev *rhp, struct c4iw_qp *qhp,
                                c4iw_get_ep(&qhp->ep->com);
                        }
                        ret = rdma_fini(rhp, qhp, ep);
-                       if (ret) {
-                               if (internal)
-                                       c4iw_get_ep(&qhp->ep->com);
+                       if (ret)
                                goto err;
-                       }
                        break;
                case C4IW_QP_STATE_TERMINATE:
                        set_state(qhp, C4IW_QP_STATE_TERMINATE);
index 9f53e68a096a329f499cbb1c9d63b6800b5add55..8ec5237031a08f3aa493ccf84715a2d5652f0e39 100644 (file)
@@ -469,6 +469,8 @@ static u8 ib_rate_to_delay[IB_RATE_120_GBPS + 1] = {
 #define IB_7322_LT_STATE_RECOVERIDLE     0x0f
 #define IB_7322_LT_STATE_CFGENH          0x10
 #define IB_7322_LT_STATE_CFGTEST         0x11
+#define IB_7322_LT_STATE_CFGWAITRMTTEST  0x12
+#define IB_7322_LT_STATE_CFGWAITENH      0x13
 
 /* link state machine states from IBC */
 #define IB_7322_L_STATE_DOWN             0x0
@@ -498,8 +500,10 @@ static const u8 qib_7322_physportstate[0x20] = {
                IB_PHYSPORTSTATE_LINK_ERR_RECOVER,
        [IB_7322_LT_STATE_CFGENH] = IB_PHYSPORTSTATE_CFG_ENH,
        [IB_7322_LT_STATE_CFGTEST] = IB_PHYSPORTSTATE_CFG_TRAIN,
-       [0x12] = IB_PHYSPORTSTATE_CFG_TRAIN,
-       [0x13] = IB_PHYSPORTSTATE_CFG_WAIT_ENH,
+       [IB_7322_LT_STATE_CFGWAITRMTTEST] =
+               IB_PHYSPORTSTATE_CFG_TRAIN,
+       [IB_7322_LT_STATE_CFGWAITENH] =
+               IB_PHYSPORTSTATE_CFG_WAIT_ENH,
        [0x14] = IB_PHYSPORTSTATE_CFG_TRAIN,
        [0x15] = IB_PHYSPORTSTATE_CFG_TRAIN,
        [0x16] = IB_PHYSPORTSTATE_CFG_TRAIN,
@@ -1692,7 +1696,9 @@ static void handle_serdes_issues(struct qib_pportdata *ppd, u64 ibcst)
                break;
        }
 
-       if (ibclt == IB_7322_LT_STATE_CFGTEST &&
+       if (((ibclt >= IB_7322_LT_STATE_CFGTEST &&
+             ibclt <= IB_7322_LT_STATE_CFGWAITENH) ||
+            ibclt == IB_7322_LT_STATE_LINKUP) &&
            (ibcst & SYM_MASK(IBCStatusA_0, LinkSpeedQDR))) {
                force_h1(ppd);
                ppd->cpspec->qdr_reforce = 1;
@@ -7301,12 +7307,17 @@ static void ibsd_wr_allchans(struct qib_pportdata *ppd, int addr, unsigned data,
 static void serdes_7322_los_enable(struct qib_pportdata *ppd, int enable)
 {
        u64 data = qib_read_kreg_port(ppd, krp_serdesctrl);
-       printk(KERN_INFO QIB_DRV_NAME " IB%u:%u Turning LOS %s\n",
-               ppd->dd->unit, ppd->port, (enable ? "on" : "off"));
-       if (enable)
+       u8 state = SYM_FIELD(data, IBSerdesCtrl_0, RXLOSEN);
+
+       if (enable && !state) {
+               printk(KERN_INFO QIB_DRV_NAME " IB%u:%u Turning LOS on\n",
+                       ppd->dd->unit, ppd->port);
                data |= SYM_MASK(IBSerdesCtrl_0, RXLOSEN);
-       else
+       } else if (!enable && state) {
+               printk(KERN_INFO QIB_DRV_NAME " IB%u:%u Turning LOS off\n",
+                       ppd->dd->unit, ppd->port);
                data &= ~SYM_MASK(IBSerdesCtrl_0, RXLOSEN);
+       }
        qib_write_kreg_port(ppd, krp_serdesctrl, data);
 }
 
index a693c56ec8a6bf97df295c23868e74272c21ef40..6ae57d23004a11310f6f1e77556a961f50584c7c 100644 (file)
@@ -96,8 +96,12 @@ void qib_handle_e_ibstatuschanged(struct qib_pportdata *ppd, u64 ibcs)
         * states, or if it transitions from any of the up (INIT or better)
         * states into any of the down states (except link recovery), then
         * call the chip-specific code to take appropriate actions.
+        *
+        * ppd->lflags could be 0 if this is the first time the interrupt
+        * handlers has been called but the link is already up.
         */
-       if (lstate >= IB_PORT_INIT && (ppd->lflags & QIBL_LINKDOWN) &&
+       if (lstate >= IB_PORT_INIT &&
+           (!ppd->lflags || (ppd->lflags & QIBL_LINKDOWN)) &&
            ltstate == IB_PHYSPORTSTATE_LINKUP) {
                /* transitioned to UP */
                if (dd->f_ib_updown(ppd, 1, ibcs))
index 54c7e1ec66910fcfc9e9e601ab9cdf46787397a7..07b6c8153913611c196b22de86e151e4a7e4e28d 100644 (file)
@@ -118,7 +118,8 @@ static void evdev_event(struct input_handle *handle,
 
        rcu_read_unlock();
 
-       wake_up_interruptible(&evdev->wait);
+       if (type == EV_SYN && code == SYN_REPORT)
+               wake_up_interruptible(&evdev->wait);
 }
 
 static int evdev_fasync(int fd, struct file *file, int on)
index 75e11c7b70fda5fb8d9ecc66a33d3ed460649a01..da38d97a51b1c67782f3265a19bac3cdb5fd2686 100644 (file)
@@ -1756,7 +1756,7 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev)
        } else if (test_bit(ABS_MT_TRACKING_ID, dev->absbit)) {
                mt_slots = dev->absinfo[ABS_MT_TRACKING_ID].maximum -
                           dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1,
-               clamp(mt_slots, 2, 32);
+               mt_slots = clamp(mt_slots, 2, 32);
        } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
                mt_slots = 2;
        } else {
index f23a743817dbb1932445a4704046dd7e4ac58d37..33d0bdc837c099a486e2bffc95dbe0fb6a8ee7c4 100644 (file)
@@ -209,6 +209,7 @@ static void omap_kp_tasklet(unsigned long data)
 #endif
                }
        }
+       input_sync(omap_kp_data->input);
        memcpy(keypad_state, new_state, sizeof(keypad_state));
 
        if (key_down) {
index 834cf98e7efb060fdcc163aa223312d8806d001a..6876700a4469d191446a20a9c81dc2606279b9d2 100644 (file)
@@ -32,7 +32,7 @@ static const struct {
        [SH_KEYSC_MODE_3] = { 2, 4, 7 },
        [SH_KEYSC_MODE_4] = { 3, 6, 6 },
        [SH_KEYSC_MODE_5] = { 4, 6, 7 },
-       [SH_KEYSC_MODE_6] = { 5, 7, 7 },
+       [SH_KEYSC_MODE_6] = { 5, 8, 8 },
 };
 
 struct sh_keysc_priv {
index 257e033986e40f61ad9a6bcb957439bd5d3f744f..0110b5a3a1678a7a0843672b8505e6f42c664fc1 100644 (file)
@@ -187,7 +187,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
                if (size == 0)
                        size = xres ? : 1;
 
-               clamp(value, min, max);
+               value = clamp(value, min, max);
 
                mousedev->packet.x = ((value - min) * xres) / size;
                mousedev->packet.abs_event = 1;
@@ -201,7 +201,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
                if (size == 0)
                        size = yres ? : 1;
 
-               clamp(value, min, max);
+               value = clamp(value, min, max);
 
                mousedev->packet.y = yres - ((value - min) * yres) / size;
                mousedev->packet.abs_event = 1;
index 59de638225fe4b30b71bcddc1cdf4ff8b50a4fa5..e35058bcd7b98e0f1b690f2e359cec96df05140e 100644 (file)
@@ -156,8 +156,10 @@ static int if_open(struct tty_struct *tty, struct file *filp)
        if (!cs || !try_module_get(cs->driver->owner))
                return -ENODEV;
 
-       if (mutex_lock_interruptible(&cs->mutex))
+       if (mutex_lock_interruptible(&cs->mutex)) {
+               module_put(cs->driver->owner);
                return -ERESTARTSYS;
+       }
        tty->driver_data = cs;
 
        ++cs->open_count;
index 23768c15b48779e3a08e47fe6cb1cd5e66fce795..b84e46bdedce88104049f02cda84f3ed8651d3ed 100644 (file)
@@ -1,3 +1,10 @@
+config LEDS_GPIO_REGISTER
+       bool
+       help
+         This option provides the function gpio_led_register_device.
+         As this function is used by arch code it must not be compiled as a
+         module.
+
 menuconfig NEW_LEDS
        bool "LED Support"
        help
@@ -7,22 +14,14 @@ menuconfig NEW_LEDS
          This is not related to standard keyboard LEDs which are controlled
          via the input system.
 
+if NEW_LEDS
+
 config LEDS_CLASS
        bool "LED Class Support"
-       depends on NEW_LEDS
        help
          This option enables the led sysfs class in /sys/class/leds.  You'll
          need this to do anything useful with LEDs.  If unsure, say N.
 
-config LEDS_GPIO_REGISTER
-       bool
-       help
-         This option provides the function gpio_led_register_device.
-         As this function is used by arch code it must not be compiled as a
-         module.
-
-if NEW_LEDS
-
 comment "LED drivers"
 
 config LEDS_88PM860X
@@ -391,6 +390,7 @@ config LEDS_NETXBIG
 
 config LEDS_ASIC3
        bool "LED support for the HTC ASIC3"
+       depends on LEDS_CLASS
        depends on MFD_ASIC3
        default y
        help
index c0cff64a1ae64240e76c06f2cba931a908435d8a..cc1dc4817facfcc52e08d0d9f8169dec64271aee 100644 (file)
@@ -593,7 +593,7 @@ static void lp5521_unregister_sysfs(struct i2c_client *client)
                                &lp5521_led_attribute_group);
 }
 
-static int __init lp5521_init_led(struct lp5521_led *led,
+static int __devinit lp5521_init_led(struct lp5521_led *led,
                                struct i2c_client *client,
                                int chan, struct lp5521_platform_data *pdata)
 {
@@ -637,7 +637,7 @@ static int __init lp5521_init_led(struct lp5521_led *led,
        return 0;
 }
 
-static int lp5521_probe(struct i2c_client *client,
+static int __devinit lp5521_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
        struct lp5521_chip              *chip;
index e19fed25f1376e2632995d71661df0e9d49dc091..5971e309b2342390a1988cd7f58d6e49d5a24301 100644 (file)
@@ -826,7 +826,7 @@ static int __init lp5523_init_engine(struct lp5523_engine *engine, int id)
        return 0;
 }
 
-static int __init lp5523_init_led(struct lp5523_led *led, struct device *dev,
+static int __devinit lp5523_init_led(struct lp5523_led *led, struct device *dev,
                           int chan, struct lp5523_platform_data *pdata)
 {
        char name[32];
@@ -872,7 +872,7 @@ static int __init lp5523_init_led(struct lp5523_led *led, struct device *dev,
 
 static struct i2c_driver lp5523_driver;
 
-static int lp5523_probe(struct i2c_client *client,
+static int __devinit lp5523_probe(struct i2c_client *client,
                        const struct i2c_device_id *id)
 {
        struct lp5523_chip              *chip;
index 70bd738b8b99eff89185b8dee59f5a4f6599e4d3..574b09afedd32ff1f8f30ddefab722fb01edd17d 100644 (file)
@@ -534,6 +534,82 @@ void bitmap_print_sb(struct bitmap *bitmap)
        kunmap_atomic(sb, KM_USER0);
 }
 
+/*
+ * bitmap_new_disk_sb
+ * @bitmap
+ *
+ * This function is somewhat the reverse of bitmap_read_sb.  bitmap_read_sb
+ * reads and verifies the on-disk bitmap superblock and populates bitmap_info.
+ * This function verifies 'bitmap_info' and populates the on-disk bitmap
+ * structure, which is to be written to disk.
+ *
+ * Returns: 0 on success, -Exxx on error
+ */
+static int bitmap_new_disk_sb(struct bitmap *bitmap)
+{
+       bitmap_super_t *sb;
+       unsigned long chunksize, daemon_sleep, write_behind;
+       int err = -EINVAL;
+
+       bitmap->sb_page = alloc_page(GFP_KERNEL);
+       if (IS_ERR(bitmap->sb_page)) {
+               err = PTR_ERR(bitmap->sb_page);
+               bitmap->sb_page = NULL;
+               return err;
+       }
+       bitmap->sb_page->index = 0;
+
+       sb = kmap_atomic(bitmap->sb_page, KM_USER0);
+
+       sb->magic = cpu_to_le32(BITMAP_MAGIC);
+       sb->version = cpu_to_le32(BITMAP_MAJOR_HI);
+
+       chunksize = bitmap->mddev->bitmap_info.chunksize;
+       BUG_ON(!chunksize);
+       if (!is_power_of_2(chunksize)) {
+               kunmap_atomic(sb, KM_USER0);
+               printk(KERN_ERR "bitmap chunksize not a power of 2\n");
+               return -EINVAL;
+       }
+       sb->chunksize = cpu_to_le32(chunksize);
+
+       daemon_sleep = bitmap->mddev->bitmap_info.daemon_sleep;
+       if (!daemon_sleep ||
+           (daemon_sleep < 1) || (daemon_sleep > MAX_SCHEDULE_TIMEOUT)) {
+               printk(KERN_INFO "Choosing daemon_sleep default (5 sec)\n");
+               daemon_sleep = 5 * HZ;
+       }
+       sb->daemon_sleep = cpu_to_le32(daemon_sleep);
+       bitmap->mddev->bitmap_info.daemon_sleep = daemon_sleep;
+
+       /*
+        * FIXME: write_behind for RAID1.  If not specified, what
+        * is a good choice?  We choose COUNTER_MAX / 2 arbitrarily.
+        */
+       write_behind = bitmap->mddev->bitmap_info.max_write_behind;
+       if (write_behind > COUNTER_MAX)
+               write_behind = COUNTER_MAX / 2;
+       sb->write_behind = cpu_to_le32(write_behind);
+       bitmap->mddev->bitmap_info.max_write_behind = write_behind;
+
+       /* keep the array size field of the bitmap superblock up to date */
+       sb->sync_size = cpu_to_le64(bitmap->mddev->resync_max_sectors);
+
+       memcpy(sb->uuid, bitmap->mddev->uuid, 16);
+
+       bitmap->flags |= BITMAP_STALE;
+       sb->state |= cpu_to_le32(BITMAP_STALE);
+       bitmap->events_cleared = bitmap->mddev->events;
+       sb->events_cleared = cpu_to_le64(bitmap->mddev->events);
+
+       bitmap->flags |= BITMAP_HOSTENDIAN;
+       sb->version = cpu_to_le32(BITMAP_MAJOR_HOSTENDIAN);
+
+       kunmap_atomic(sb, KM_USER0);
+
+       return 0;
+}
+
 /* read the superblock from the bitmap file and initialize some bitmap fields */
 static int bitmap_read_sb(struct bitmap *bitmap)
 {
@@ -575,7 +651,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
                reason = "unrecognized superblock version";
        else if (chunksize < 512)
                reason = "bitmap chunksize too small";
-       else if ((1 << ffz(~chunksize)) != chunksize)
+       else if (!is_power_of_2(chunksize))
                reason = "bitmap chunksize not a power of 2";
        else if (daemon_sleep < 1 || daemon_sleep > MAX_SCHEDULE_TIMEOUT)
                reason = "daemon sleep period out of range";
@@ -1076,8 +1152,8 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start)
        }
 
        printk(KERN_INFO "%s: bitmap initialized from disk: "
-               "read %lu/%lu pages, set %lu bits\n",
-               bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt);
+              "read %lu/%lu pages, set %lu of %lu bits\n",
+              bmname(bitmap), bitmap->file_pages, num_pages, bit_cnt, chunks);
 
        return 0;
 
@@ -1332,7 +1408,7 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
                        return 0;
                }
 
-               if (unlikely((*bmc & COUNTER_MAX) == COUNTER_MAX)) {
+               if (unlikely(COUNTER(*bmc) == COUNTER_MAX)) {
                        DEFINE_WAIT(__wait);
                        /* note that it is safe to do the prepare_to_wait
                         * after the test as long as we do it before dropping
@@ -1404,10 +1480,10 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
                        sysfs_notify_dirent_safe(bitmap->sysfs_can_clear);
                }
 
-               if (!success && ! (*bmc & NEEDED_MASK))
+               if (!success && !NEEDED(*bmc))
                        *bmc |= NEEDED_MASK;
 
-               if ((*bmc & COUNTER_MAX) == COUNTER_MAX)
+               if (COUNTER(*bmc) == COUNTER_MAX)
                        wake_up(&bitmap->overflow_wait);
 
                (*bmc)--;
@@ -1728,9 +1804,16 @@ int bitmap_create(mddev_t *mddev)
                vfs_fsync(file, 1);
        }
        /* read superblock from bitmap file (this sets mddev->bitmap_info.chunksize) */
-       if (!mddev->bitmap_info.external)
-               err = bitmap_read_sb(bitmap);
-       else {
+       if (!mddev->bitmap_info.external) {
+               /*
+                * If 'MD_ARRAY_FIRST_USE' is set, then device-mapper is
+                * instructing us to create a new on-disk bitmap instance.
+                */
+               if (test_and_clear_bit(MD_ARRAY_FIRST_USE, &mddev->flags))
+                       err = bitmap_new_disk_sb(bitmap);
+               else
+                       err = bitmap_read_sb(bitmap);
+       } else {
                err = 0;
                if (mddev->bitmap_info.chunksize == 0 ||
                    mddev->bitmap_info.daemon_sleep == 0)
@@ -1754,9 +1837,6 @@ int bitmap_create(mddev_t *mddev)
        bitmap->chunks = chunks;
        bitmap->pages = pages;
        bitmap->missing_pages = pages;
-       bitmap->counter_bits = COUNTER_BITS;
-
-       bitmap->syncchunk = ~0UL;
 
 #ifdef INJECT_FATAL_FAULT_1
        bitmap->bp = NULL;
index d0aeaf46d932017505e4b3728cfa1ca3c9e6fe3c..b2a127e891acedc9843ff4b61e1e8c62b2456a48 100644 (file)
@@ -85,7 +85,6 @@
 typedef __u16 bitmap_counter_t;
 #define COUNTER_BITS 16
 #define COUNTER_BIT_SHIFT 4
-#define COUNTER_BYTE_RATIO (COUNTER_BITS / 8)
 #define COUNTER_BYTE_SHIFT (COUNTER_BIT_SHIFT - 3)
 
 #define NEEDED_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 1)))
@@ -196,19 +195,10 @@ struct bitmap {
 
        mddev_t *mddev; /* the md device that the bitmap is for */
 
-       int counter_bits; /* how many bits per block counter */
-
        /* bitmap chunksize -- how much data does each bit represent? */
        unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */
        unsigned long chunks; /* total number of data chunks for the array */
 
-       /* We hold a count on the chunk currently being synced, and drop
-        * it when the last block is started.  If the resync is aborted
-        * midway, we need to be able to drop that count, so we remember
-        * the counted chunk..
-        */
-       unsigned long syncchunk;
-
        __u64   events_cleared;
        int need_sync;
 
index aa640a85bb2169aa14fb8d9875beb0ac9091192c..4332fc2f25d4a2260b575f66229514bad10a2fa4 100644 (file)
@@ -351,6 +351,9 @@ void mddev_resume(mddev_t *mddev)
        mddev->suspended = 0;
        wake_up(&mddev->sb_wait);
        mddev->pers->quiesce(mddev, 0);
+
+       md_wakeup_thread(mddev->thread);
+       md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */
 }
 EXPORT_SYMBOL_GPL(mddev_resume);
 
@@ -1750,6 +1753,18 @@ static struct super_type super_types[] = {
        },
 };
 
+static void sync_super(mddev_t *mddev, mdk_rdev_t *rdev)
+{
+       if (mddev->sync_super) {
+               mddev->sync_super(mddev, rdev);
+               return;
+       }
+
+       BUG_ON(mddev->major_version >= ARRAY_SIZE(super_types));
+
+       super_types[mddev->major_version].sync_super(mddev, rdev);
+}
+
 static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2)
 {
        mdk_rdev_t *rdev, *rdev2;
@@ -1781,8 +1796,8 @@ int md_integrity_register(mddev_t *mddev)
 
        if (list_empty(&mddev->disks))
                return 0; /* nothing to do */
-       if (blk_get_integrity(mddev->gendisk))
-               return 0; /* already registered */
+       if (!mddev->gendisk || blk_get_integrity(mddev->gendisk))
+               return 0; /* shouldn't register, or already is */
        list_for_each_entry(rdev, &mddev->disks, same_set) {
                /* skip spares and non-functional disks */
                if (test_bit(Faulty, &rdev->flags))
@@ -2168,8 +2183,7 @@ static void sync_sbs(mddev_t * mddev, int nospares)
                        /* Don't update this superblock */
                        rdev->sb_loaded = 2;
                } else {
-                       super_types[mddev->major_version].
-                               sync_super(mddev, rdev);
+                       sync_super(mddev, rdev);
                        rdev->sb_loaded = 1;
                }
        }
@@ -2462,7 +2476,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
                if (rdev->raid_disk == -1)
                        return -EEXIST;
                /* personality does all needed checks */
-               if (rdev->mddev->pers->hot_add_disk == NULL)
+               if (rdev->mddev->pers->hot_remove_disk == NULL)
                        return -EINVAL;
                err = rdev->mddev->pers->
                        hot_remove_disk(rdev->mddev, rdev->raid_disk);
@@ -4619,9 +4633,6 @@ int md_run(mddev_t *mddev)
        if (mddev->flags)
                md_update_sb(mddev, 0);
 
-       md_wakeup_thread(mddev->thread);
-       md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */
-
        md_new_event(mddev);
        sysfs_notify_dirent_safe(mddev->sysfs_state);
        sysfs_notify_dirent_safe(mddev->sysfs_action);
@@ -4642,6 +4653,10 @@ static int do_md_run(mddev_t *mddev)
                bitmap_destroy(mddev);
                goto out;
        }
+
+       md_wakeup_thread(mddev->thread);
+       md_wakeup_thread(mddev->sync_thread); /* possibly kick off a reshape */
+
        set_capacity(mddev->gendisk, mddev->array_sectors);
        revalidate_disk(mddev->gendisk);
        mddev->changed = 1;
@@ -5259,6 +5274,8 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
                if (mddev->degraded)
                        set_bit(MD_RECOVERY_RECOVER, &mddev->recovery);
                set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+               if (!err)
+                       md_new_event(mddev);
                md_wakeup_thread(mddev->thread);
                return err;
        }
@@ -6866,8 +6883,8 @@ void md_do_sync(mddev_t *mddev)
         * Tune reconstruction:
         */
        window = 32*(PAGE_SIZE/512);
-       printk(KERN_INFO "md: using %dk window, over a total of %llu blocks.\n",
-               window/2,(unsigned long long) max_sectors/2);
+       printk(KERN_INFO "md: using %dk window, over a total of %lluk.\n",
+               window/2, (unsigned long long)max_sectors/2);
 
        atomic_set(&mddev->recovery_active, 0);
        last_check = 0;
@@ -7045,7 +7062,6 @@ void md_do_sync(mddev_t *mddev)
 }
 EXPORT_SYMBOL_GPL(md_do_sync);
 
-
 static int remove_and_add_spares(mddev_t *mddev)
 {
        mdk_rdev_t *rdev;
@@ -7157,6 +7173,9 @@ static void reap_sync_thread(mddev_t *mddev)
  */
 void md_check_recovery(mddev_t *mddev)
 {
+       if (mddev->suspended)
+               return;
+
        if (mddev->bitmap)
                bitmap_daemon_work(mddev);
 
index 0b1fd3f1d85b5decfaaba4ab8b70595fffbaba1f..1c26c7a08ae6c053524cbee6c751c84935c5cfe3 100644 (file)
@@ -124,6 +124,7 @@ struct mddev_s
 #define MD_CHANGE_DEVS 0       /* Some device status has changed */
 #define MD_CHANGE_CLEAN 1      /* transition to or from 'clean' */
 #define MD_CHANGE_PENDING 2    /* switch from 'clean' to 'active' in progress */
+#define MD_ARRAY_FIRST_USE 3    /* First use of array, needs initialization */
 
        int                             suspended;
        atomic_t                        active_io;
@@ -330,6 +331,7 @@ struct mddev_s
        atomic_t flush_pending;
        struct work_struct flush_work;
        struct work_struct event_work;  /* used by dm to report failure event */
+       void (*sync_super)(mddev_t *mddev, mdk_rdev_t *rdev);
 };
 
 
index 5d096096f9584972a9da2197ed1bef9303edf95f..f7431b6d8447df5979c0b80a5ded841f61a16cc1 100644 (file)
@@ -497,21 +497,19 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
        return best_disk;
 }
 
-static int raid1_congested(void *data, int bits)
+int md_raid1_congested(mddev_t *mddev, int bits)
 {
-       mddev_t *mddev = data;
        conf_t *conf = mddev->private;
        int i, ret = 0;
 
-       if (mddev_congested(mddev, bits))
-               return 1;
-
        rcu_read_lock();
        for (i = 0; i < mddev->raid_disks; i++) {
                mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
                if (rdev && !test_bit(Faulty, &rdev->flags)) {
                        struct request_queue *q = bdev_get_queue(rdev->bdev);
 
+                       BUG_ON(!q);
+
                        /* Note the '|| 1' - when read_balance prefers
                         * non-congested targets, it can be removed
                         */
@@ -524,7 +522,15 @@ static int raid1_congested(void *data, int bits)
        rcu_read_unlock();
        return ret;
 }
+EXPORT_SYMBOL_GPL(md_raid1_congested);
 
+static int raid1_congested(void *data, int bits)
+{
+       mddev_t *mddev = data;
+
+       return mddev_congested(mddev, bits) ||
+               md_raid1_congested(mddev, bits);
+}
 
 static void flush_pending_writes(conf_t *conf)
 {
@@ -1972,6 +1978,8 @@ static int run(mddev_t *mddev)
                return PTR_ERR(conf);
 
        list_for_each_entry(rdev, &mddev->disks, same_set) {
+               if (!mddev->gendisk)
+                       continue;
                disk_stack_limits(mddev->gendisk, rdev->bdev,
                                  rdev->data_offset << 9);
                /* as we don't honour merge_bvec_fn, we must never risk
@@ -2013,8 +2021,10 @@ static int run(mddev_t *mddev)
 
        md_set_array_sectors(mddev, raid1_size(mddev, 0, 0));
 
-       mddev->queue->backing_dev_info.congested_fn = raid1_congested;
-       mddev->queue->backing_dev_info.congested_data = mddev;
+       if (mddev->queue) {
+               mddev->queue->backing_dev_info.congested_fn = raid1_congested;
+               mddev->queue->backing_dev_info.congested_data = mddev;
+       }
        return md_integrity_register(mddev);
 }
 
index 5fc4ca1af8639b5a61a6a17901866fe0987effcc..e743a64fac4f10f2dbc27f2c194658fdd35f3fa7 100644 (file)
@@ -126,4 +126,6 @@ struct r1bio_s {
  */
 #define        R1BIO_Returned 6
 
+extern int md_raid1_congested(mddev_t *mddev, int bits);
+
 #endif
index 346e69bfdab3f8b0b744f6b239c93ea0f3f099e2..b72edf35ec544d0da66346107cededa933ed20dc 100644 (file)
@@ -129,7 +129,7 @@ static inline int raid5_dec_bi_hw_segments(struct bio *bio)
 
 static inline void raid5_set_bi_hw_segments(struct bio *bio, unsigned int cnt)
 {
-       bio->bi_phys_segments = raid5_bi_phys_segments(bio) || (cnt << 16);
+       bio->bi_phys_segments = raid5_bi_phys_segments(bio) | (cnt << 16);
 }
 
 /* Find first data disk in a raid6 stripe */
@@ -514,7 +514,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                bi = &sh->dev[i].req;
 
                bi->bi_rw = rw;
-               if (rw == WRITE)
+               if (rw & WRITE)
                        bi->bi_end_io = raid5_end_write_request;
                else
                        bi->bi_end_io = raid5_end_read_request;
@@ -548,13 +548,13 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                        bi->bi_io_vec[0].bv_offset = 0;
                        bi->bi_size = STRIPE_SIZE;
                        bi->bi_next = NULL;
-                       if (rw == WRITE &&
+                       if ((rw & WRITE) &&
                            test_bit(R5_ReWrite, &sh->dev[i].flags))
                                atomic_add(STRIPE_SECTORS,
                                        &rdev->corrected_errors);
                        generic_make_request(bi);
                } else {
-                       if (rw == WRITE)
+                       if (rw & WRITE)
                                set_bit(STRIPE_DEGRADED, &sh->state);
                        pr_debug("skip op %ld on disc %d for sector %llu\n",
                                bi->bi_rw, i, (unsigned long long)sh->sector);
@@ -585,7 +585,7 @@ async_copy_data(int frombio, struct bio *bio, struct page *page,
        init_async_submit(&submit, flags, tx, NULL, NULL, NULL);
 
        bio_for_each_segment(bvl, bio, i) {
-               int len = bio_iovec_idx(bio, i)->bv_len;
+               int len = bvl->bv_len;
                int clen;
                int b_offset = 0;
 
@@ -601,8 +601,8 @@ async_copy_data(int frombio, struct bio *bio, struct page *page,
                        clen = len;
 
                if (clen > 0) {
-                       b_offset += bio_iovec_idx(bio, i)->bv_offset;
-                       bio_page = bio_iovec_idx(bio, i)->bv_page;
+                       b_offset += bvl->bv_offset;
+                       bio_page = bvl->bv_page;
                        if (frombio)
                                tx = async_memcpy(page, bio_page, page_offset,
                                                  b_offset, clen, &submit);
@@ -4858,7 +4858,7 @@ static raid5_conf_t *setup_conf(mddev_t *mddev)
                        printk(KERN_INFO "md/raid:%s: device %s operational as raid"
                               " disk %d\n",
                               mdname(mddev), bdevname(rdev->bdev, b), raid_disk);
-               } else
+               } else if (rdev->saved_raid_disk != raid_disk)
                        /* Cannot rely on bitmap to complete recovery */
                        conf->fullsync = 1;
        }
index 200311fea369e6a952f38b8c205a0fb5c0c01f00..e2a52e5cf449c7f65f97e3e492a8304e321a80df 100644 (file)
@@ -609,6 +609,7 @@ static int apds990x_detect(struct apds990x_chip *chip)
        return ret;
 }
 
+#if defined(CONFIG_PM) || defined(CONFIG_PM_RUNTIME)
 static int apds990x_chip_on(struct apds990x_chip *chip)
 {
        int err  = regulator_bulk_enable(ARRAY_SIZE(chip->regs),
@@ -624,6 +625,7 @@ static int apds990x_chip_on(struct apds990x_chip *chip)
        apds990x_mode_on(chip);
        return 0;
 }
+#endif
 
 static int apds990x_chip_off(struct apds990x_chip *chip)
 {
index d019746551f3481f00c06e209b30a833586e92fa..2a40d0efdff5d33115ac61a0fc97287638ae18ca 100644 (file)
@@ -47,7 +47,7 @@ static uint32_t sg_dwiter_read_buffer(struct sg_mapping_iter *miter)
 
 static inline bool needs_unaligned_copy(const void *ptr)
 {
-#ifdef HAVE_EFFICIENT_UNALIGNED_ACCESS
+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
        return false;
 #else
        return ((ptr - NULL) & 3) != 0;
index e01e08c8c88b6cb72e3e585fec9ccfacfe79eb2e..bc685bfc4c33aaacf89a5dc7205943bd69f14f8d 100644 (file)
@@ -174,7 +174,7 @@ struct cs5535_mfgpt_timer *cs5535_mfgpt_alloc_timer(int timer_nr, int domain)
                timer_nr = t < max ? (int) t : -1;
        } else {
                /* check if the requested timer's available */
-               if (test_bit(timer_nr, mfgpt->avail))
+               if (!test_bit(timer_nr, mfgpt->avail))
                        timer_nr = -1;
        }
 
index 668d41e594a9bed240ac4863364f0b26e9f4bb9b..df03dd3bd0e2b331db3459f3a632ffd2f85f6155 100644 (file)
@@ -270,7 +270,7 @@ ioc4_variant(struct ioc4_driver_data *idd)
        return IOC4_VARIANT_PCI_RT;
 }
 
-static void __devinit
+static void
 ioc4_load_modules(struct work_struct *work)
 {
        request_module("sgiioc4");
index 81d7fa4ec0db0a284891a31ab280720a19bd32d9..150cd7061b808019d4a775ab29fc287558d7508e 100644 (file)
@@ -120,6 +120,7 @@ static int recur_count = REC_NUM_DEFAULT;
 static enum cname cpoint = CN_INVALID;
 static enum ctype cptype = CT_NONE;
 static int count = DEFAULT_COUNT;
+static DEFINE_SPINLOCK(count_lock);
 
 module_param(recur_count, int, 0644);
 MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\
@@ -230,11 +231,14 @@ static const char *cp_name_to_str(enum cname name)
 static int lkdtm_parse_commandline(void)
 {
        int i;
+       unsigned long flags;
 
        if (cpoint_count < 1 || recur_count < 1)
                return -EINVAL;
 
+       spin_lock_irqsave(&count_lock, flags);
        count = cpoint_count;
+       spin_unlock_irqrestore(&count_lock, flags);
 
        /* No special parameters */
        if (!cpoint_type && !cpoint_name)
@@ -349,6 +353,9 @@ static void lkdtm_do_action(enum ctype which)
 
 static void lkdtm_handler(void)
 {
+       unsigned long flags;
+
+       spin_lock_irqsave(&count_lock, flags);
        count--;
        printk(KERN_INFO "lkdtm: Crash point %s of type %s hit, trigger in %d rounds\n",
                        cp_name_to_str(cpoint), cp_type_to_str(cptype), count);
@@ -357,6 +364,7 @@ static void lkdtm_handler(void)
                lkdtm_do_action(cptype);
                count = cpoint_count;
        }
+       spin_unlock_irqrestore(&count_lock, flags);
 }
 
 static int lkdtm_register_cpoint(enum cname which)
index ee5109a3cd984f287c824fd71d3221ead361bccd..42f067347bc70fd8f24466ed4384408191812611 100644 (file)
@@ -495,14 +495,14 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
                }
        }
 
+       dev->stats.tx_packets++;
+       dev->stats.tx_bytes += skb->len;
+
        if (atomic_dec_return(&queued_msg->use_count) == 0) {
                dev_kfree_skb(skb);
                kfree(queued_msg);
        }
 
-       dev->stats.tx_packets++;
-       dev->stats.tx_bytes += skb->len;
-
        return NETDEV_TX_OK;
 }
 
index 7aded90f9daa1683b7a40fa24befed62b26376da..cfbddbef11de3b67c54be85797dd124843ca8596 100644 (file)
@@ -845,7 +845,7 @@ err_iounmap:
 err_iounmap_app:
        iounmap(config->va_app_base);
 err_kzalloc:
-       kfree(config);
+       kfree(target);
 err_rel_res:
        release_mem_region(res1->start, resource_size(res1));
 err_rel_res0:
index ac13768e83c377bc6fd7661defa8712e6470c2ad..c779503e75784c6815a1fe3fe1981b5e19fbd432 100644 (file)
@@ -1032,7 +1032,7 @@ static struct mmc_blk_data *mmc_blk_alloc_req(struct mmc_card *card,
        INIT_LIST_HEAD(&md->part);
        md->usage = 1;
 
-       ret = mmc_init_queue(&md->queue, card, &md->lock);
+       ret = mmc_init_queue(&md->queue, card, &md->lock, subname);
        if (ret)
                goto err_putdisk;
 
@@ -1309,6 +1309,9 @@ static void mmc_blk_remove(struct mmc_card *card)
        struct mmc_blk_data *md = mmc_get_drvdata(card);
 
        mmc_blk_remove_parts(card, md);
+       mmc_claim_host(card->host);
+       mmc_blk_part_switch(card, md);
+       mmc_release_host(card->host);
        mmc_blk_remove_req(md);
        mmc_set_drvdata(card, NULL);
 #ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
index c07322c2658cd171049bf59d4325f2e04ae2a90c..6413afa318d2c65532bd11dc6f36a539c6291107 100644 (file)
@@ -106,10 +106,12 @@ static void mmc_request(struct request_queue *q)
  * @mq: mmc queue
  * @card: mmc card to attach this queue
  * @lock: queue lock
+ * @subname: partition subname
  *
  * Initialise a MMC card request queue.
  */
-int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock)
+int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card,
+                  spinlock_t *lock, const char *subname)
 {
        struct mmc_host *host = card->host;
        u64 limit = BLK_BOUNCE_HIGH;
@@ -133,12 +135,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
                mq->queue->limits.max_discard_sectors = UINT_MAX;
                if (card->erased_byte == 0)
                        mq->queue->limits.discard_zeroes_data = 1;
-               if (!mmc_can_trim(card) && is_power_of_2(card->erase_size)) {
-                       mq->queue->limits.discard_granularity =
-                                                       card->erase_size << 9;
-                       mq->queue->limits.discard_alignment =
-                                                       card->erase_size << 9;
-               }
+               mq->queue->limits.discard_granularity = card->pref_erase << 9;
                if (mmc_can_secure_erase_trim(card))
                        queue_flag_set_unlocked(QUEUE_FLAG_SECDISCARD,
                                                mq->queue);
@@ -209,8 +206,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock
 
        sema_init(&mq->thread_sem, 1);
 
-       mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd/%d",
-               host->index);
+       mq->thread = kthread_run(mmc_queue_thread, mq, "mmcqd/%d%s",
+               host->index, subname ? subname : "");
 
        if (IS_ERR(mq->thread)) {
                ret = PTR_ERR(mq->thread);
index 64e66e0d4994a9176662354cd123fb0cee2315a0..6223ef8dc9cd08e6b7468a286b3e43fcb96ac26f 100644 (file)
@@ -19,7 +19,8 @@ struct mmc_queue {
        unsigned int            bounce_sg_len;
 };
 
-extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *);
+extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *,
+                         const char *);
 extern void mmc_cleanup_queue(struct mmc_queue *);
 extern void mmc_queue_suspend(struct mmc_queue *);
 extern void mmc_queue_resume(struct mmc_queue *);
index a854a78610015317735c4f92078451865ce37555..7c3444a37070de9fffd24839990a06c2433ceacc 100644 (file)
@@ -1281,7 +1281,7 @@ static unsigned int mmc_mmc_erase_timeout(struct mmc_card *card,
                 */
                timeout_clks <<= 1;
                timeout_us += (timeout_clks * 1000) /
-                             (card->host->ios.clock / 1000);
+                             (mmc_host_clk_rate(card->host) / 1000);
 
                erase_timeout = timeout_us / 1000;
 
index d96741dbbfdde64d32c68a691a2f43926ba2ae07..7da522e958a094d31299713c72dcfeded8af7184 100644 (file)
@@ -711,15 +711,54 @@ static int mmc_sdio_resume(struct mmc_host *host)
 static int mmc_sdio_power_restore(struct mmc_host *host)
 {
        int ret;
+       u32 ocr;
 
        BUG_ON(!host);
        BUG_ON(!host->card);
 
        mmc_claim_host(host);
+
+       /*
+        * Reset the card by performing the same steps that are taken by
+        * mmc_rescan_try_freq() and mmc_attach_sdio() during a "normal" probe.
+        *
+        * sdio_reset() is technically not needed. Having just powered up the
+        * hardware, it should already be in reset state. However, some
+        * platforms (such as SD8686 on OLPC) do not instantly cut power,
+        * meaning that a reset is required when restoring power soon after
+        * powering off. It is harmless in other cases.
+        *
+        * The CMD5 reset (mmc_send_io_op_cond()), according to the SDIO spec,
+        * is not necessary for non-removable cards. However, it is required
+        * for OLPC SD8686 (which expects a [CMD5,5,3,7] init sequence), and
+        * harmless in other situations.
+        *
+        * With these steps taken, mmc_select_voltage() is also required to
+        * restore the correct voltage setting of the card.
+        */
+       sdio_reset(host);
+       mmc_go_idle(host);
+       mmc_send_if_cond(host, host->ocr_avail);
+
+       ret = mmc_send_io_op_cond(host, 0, &ocr);
+       if (ret)
+               goto out;
+
+       if (host->ocr_avail_sdio)
+               host->ocr_avail = host->ocr_avail_sdio;
+
+       host->ocr = mmc_select_voltage(host, ocr & ~0x7F);
+       if (!host->ocr) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        ret = mmc_sdio_init_card(host, host->ocr, host->card,
                                mmc_card_keep_power(host));
        if (!ret && host->sdio_irqs)
                mmc_signal_sdio_irq(host);
+
+out:
        mmc_release_host(host);
 
        return ret;
index 327ddb848e25a65f125c4861a6082bb26b631774..52429a98201b505fbbc7c40c6fc9a2779c64793a 100644 (file)
@@ -193,7 +193,7 @@ static int sdio_bus_remove(struct device *dev)
 
        /* Then undo the runtime PM settings in sdio_bus_probe() */
        if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD)
-               pm_runtime_put_noidle(dev);
+               pm_runtime_put_sync(dev);
 
 out:
        return ret;
index 5da5bea0f9f09ed49eedf281da1308c04a0b7341..7721de942c69e29cd0d36300eb48a695dfbdafbf 100644 (file)
@@ -1144,9 +1144,17 @@ static int __devinit mmci_probe(struct amba_device *dev,
                else if (ret != -ENOSYS)
                        goto err_gpio_cd;
 
+               /*
+                * A gpio pin that will detect cards when inserted and removed
+                * will most likely want to trigger on the edges if it is
+                * 0 when ejected and 1 when inserted (or mutatis mutandis
+                * for the inverted case) so we request triggers on both
+                * edges.
+                */
                ret = request_any_context_irq(gpio_to_irq(plat->gpio_cd),
-                                             mmci_cd_irq, 0,
-                                             DRIVER_NAME " (cd)", host);
+                               mmci_cd_irq,
+                               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+                               DRIVER_NAME " (cd)", host);
                if (ret >= 0)
                        host->gpio_cd_irq = gpio_to_irq(plat->gpio_cd);
        }
index e2aecb7f1d5cfe32aab9ffe35aabfbe0ba9a643c..ab66f2454dc48fbc5fe2d68fe51b1d2611de1f7c 100644 (file)
 #include <linux/mmc/core.h>
 #include <linux/mmc/host.h>
 
+/* For archs that don't support NO_IRQ (such as mips), provide a dummy value */
+#ifndef NO_IRQ
+#define NO_IRQ 0
+#endif
+
 MODULE_LICENSE("GPL");
 
 enum {
index 5b2e2155b413bc988cabbd5125fe5c4c64f27d5b..dedf3dab8a3ba8216bef897e9bac0b612699b127 100644 (file)
@@ -429,7 +429,6 @@ static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
                                return -EINVAL;
                        }
                }
-               mmc_slot(host).ocr_mask = mmc_regulator_get_ocrmask(reg);
 
                /* Allow an aux regulator */
                reg = regulator_get(host->dev, "vmmc_aux");
@@ -962,7 +961,8 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno)
        spin_unlock(&host->irq_lock);
 
        if (host->use_dma && dma_ch != -1) {
-               dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len,
+               dma_unmap_sg(mmc_dev(host->mmc), host->data->sg,
+                       host->data->sg_len,
                        omap_hsmmc_get_dma_dir(host, host->data));
                omap_free_dma(dma_ch);
        }
@@ -1346,7 +1346,7 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
                return;
        }
 
-       dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
+       dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
                omap_hsmmc_get_dma_dir(host, data));
 
        req_in_progress = host->req_in_progress;
index b3654293017bca33d4de5b77d0f654e07fb92031..ce500f03df859a6f9af275461d7ef29515aedb4e 100644 (file)
@@ -92,7 +92,7 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
                mmc_data->ocr_mask = p->tmio_ocr_mask;
                mmc_data->capabilities |= p->tmio_caps;
 
-               if (p->dma_slave_tx >= 0 && p->dma_slave_rx >= 0) {
+               if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {
                        priv->param_tx.slave_id = p->dma_slave_tx;
                        priv->param_rx.slave_id = p->dma_slave_rx;
                        priv->dma_priv.chan_priv_tx = &priv->param_tx;
@@ -165,13 +165,14 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)
 
        p->pdata = NULL;
 
+       tmio_mmc_host_remove(host);
+
        for (i = 0; i < 3; i++) {
                irq = platform_get_irq(pdev, i);
                if (irq >= 0)
                        free_irq(irq, host);
        }
 
-       tmio_mmc_host_remove(host);
        clk_disable(priv->clk);
        clk_put(priv->clk);
        kfree(priv);
index ad6347bb02ddd9ee20a6085185fb6ca03924d666..0b09e8239aa05d09abf3b6b376d838b2ba8d178b 100644 (file)
@@ -824,8 +824,8 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc)
        struct tmio_mmc_host *host = mmc_priv(mmc);
        struct tmio_mmc_data *pdata = host->pdata;
 
-       return ((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) ||
-               !(sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT));
+       return !((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) ||
+                (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT));
 }
 
 static int tmio_mmc_get_cd(struct mmc_host *mmc)
index cbb03305b77bb6507c5f18a3a6e9a9b23305205d..d4455ffbefd8a931317beaad43eefb563b10c62b 100644 (file)
@@ -2096,7 +2096,7 @@ static struct mmc_host_ops vub300_mmc_ops = {
 static int vub300_probe(struct usb_interface *interface,
                        const struct usb_device_id *id)
 {                              /* NOT irq */
-       struct vub300_mmc_host *vub300 = NULL;
+       struct vub300_mmc_host *vub300;
        struct usb_host_interface *iface_desc;
        struct usb_device *udev = usb_get_dev(interface_to_usbdev(interface));
        int i;
@@ -2118,23 +2118,20 @@ static int vub300_probe(struct usb_interface *interface,
        command_out_urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!command_out_urb) {
                retval = -ENOMEM;
-               dev_err(&vub300->udev->dev,
-                       "not enough memory for the command_out_urb\n");
+               dev_err(&udev->dev, "not enough memory for command_out_urb\n");
                goto error0;
        }
        command_res_urb = usb_alloc_urb(0, GFP_KERNEL);
        if (!command_res_urb) {
                retval = -ENOMEM;
-               dev_err(&vub300->udev->dev,
-                       "not enough memory for the command_res_urb\n");
+               dev_err(&udev->dev, "not enough memory for command_res_urb\n");
                goto error1;
        }
        /* this also allocates memory for our VUB300 mmc host device */
        mmc = mmc_alloc_host(sizeof(struct vub300_mmc_host), &udev->dev);
        if (!mmc) {
                retval = -ENOMEM;
-               dev_err(&vub300->udev->dev,
-                       "not enough memory for the mmc_host\n");
+               dev_err(&udev->dev, "not enough memory for the mmc_host\n");
                goto error4;
        }
        /* MMC core transfer sizes tunable parameters */
index d84f6e8903a58f6334acd9e67d1811823c73ee86..5b732988d49389c9811ae2d5c19c87ebdda92807 100644 (file)
@@ -412,7 +412,7 @@ el2_open(struct net_device *dev)
                outb_p(0x04 << ((*irqp == 9) ? 2 : *irqp), E33G_IDCFR);
                outb_p(0x00, E33G_IDCFR);
                msleep(1);
-               free_irq(*irqp, el2_probe_interrupt);
+               free_irq(*irqp, &seen);
                if (!seen)
                        continue;
 
@@ -422,6 +422,7 @@ el2_open(struct net_device *dev)
                        continue;
                if (retval < 0)
                        goto err_disable;
+               break;
        } while (*++irqp);
 
        if (*irqp == 0) {
index 68d45ba2d9b9a0844c0c1691a31e07bf7374168b..6c019e14854691ab70ebece126dcf0e8cf0d4195 100644 (file)
@@ -52,13 +52,13 @@ MODULE_DESCRIPTION(DRV_DESC);
 MODULE_ALIAS("platform:bfin_mac");
 
 #if defined(CONFIG_BFIN_MAC_USE_L1)
-# define bfin_mac_alloc(dma_handle, size)  l1_data_sram_zalloc(size)
-# define bfin_mac_free(dma_handle, ptr)    l1_data_sram_free(ptr)
+# define bfin_mac_alloc(dma_handle, size, num)  l1_data_sram_zalloc(size*num)
+# define bfin_mac_free(dma_handle, ptr, num)    l1_data_sram_free(ptr)
 #else
-# define bfin_mac_alloc(dma_handle, size) \
-       dma_alloc_coherent(NULL, size, dma_handle, GFP_KERNEL)
-# define bfin_mac_free(dma_handle, ptr) \
-       dma_free_coherent(NULL, sizeof(*ptr), ptr, dma_handle)
+# define bfin_mac_alloc(dma_handle, size, num) \
+       dma_alloc_coherent(NULL, size*num, dma_handle, GFP_KERNEL)
+# define bfin_mac_free(dma_handle, ptr, num) \
+       dma_free_coherent(NULL, sizeof(*ptr)*num, ptr, dma_handle)
 #endif
 
 #define PKT_BUF_SZ 1580
@@ -95,7 +95,7 @@ static void desc_list_free(void)
                                t = t->next;
                        }
                }
-               bfin_mac_free(dma_handle, tx_desc);
+               bfin_mac_free(dma_handle, tx_desc, CONFIG_BFIN_TX_DESC_NUM);
        }
 
        if (rx_desc) {
@@ -109,7 +109,7 @@ static void desc_list_free(void)
                                r = r->next;
                        }
                }
-               bfin_mac_free(dma_handle, rx_desc);
+               bfin_mac_free(dma_handle, rx_desc, CONFIG_BFIN_RX_DESC_NUM);
        }
 }
 
@@ -126,13 +126,13 @@ static int desc_list_init(void)
 #endif
 
        tx_desc = bfin_mac_alloc(&dma_handle,
-                               sizeof(struct net_dma_desc_tx) *
+                               sizeof(struct net_dma_desc_tx),
                                CONFIG_BFIN_TX_DESC_NUM);
        if (tx_desc == NULL)
                goto init_error;
 
        rx_desc = bfin_mac_alloc(&dma_handle,
-                               sizeof(struct net_dma_desc_rx) *
+                               sizeof(struct net_dma_desc_rx),
                                CONFIG_BFIN_RX_DESC_NUM);
        if (rx_desc == NULL)
                goto init_error;
index 652b30e525d01d8c4b547465bb66f943929fd4ea..eafe44a528ac015c8edddec6b0650a9eb526449c 100644 (file)
@@ -1297,6 +1297,7 @@ static inline int slave_enable_netpoll(struct slave *slave)
                goto out;
 
        np->dev = slave->dev;
+       strlcpy(np->dev_name, slave->dev->name, IFNAMSIZ);
        err = __netpoll_setup(np);
        if (err) {
                kfree(np);
index 7a84e45487e83ba184dcccf4def37529c4607ba9..7583a9572bcc5a55c1d4fc87378f0d1475bccc45 100644 (file)
@@ -105,7 +105,7 @@ static int do_pd_setup(struct fs_enet_private *fep)
                goto out_ep;
 
        fep->fcc.mem = (void __iomem *)cpm2_immr;
-       fpi->dpram_offset = cpm_dpalloc(128, 8);
+       fpi->dpram_offset = cpm_dpalloc(128, 32);
        if (IS_ERR_VALUE(fpi->dpram_offset)) {
                ret = fpi->dpram_offset;
                goto out_fcccp;
index 8e10d2f6a5adc8340d239c729e835fb0122b3acd..c3ecb118c1df39f925e40f023f6e2f8a63ec763f 100644 (file)
@@ -1580,12 +1580,12 @@ static netdev_tx_t hp100_start_xmit_bm(struct sk_buff *skb,
        hp100_outl(ringptr->pdl_paddr, TX_PDA_L);       /* Low Prio. Queue */
 
        lp->txrcommit++;
-       spin_unlock_irqrestore(&lp->lock, flags);
 
-       /* Update statistics */
        dev->stats.tx_packets++;
        dev->stats.tx_bytes += skb->len;
 
+       spin_unlock_irqrestore(&lp->lock, flags);
+
        return NETDEV_TX_OK;
 
 drop:
index b6060f7538dfc42d250ef9bbd59bb93221fd6fd7..a900d5bf294889578df802c280ca4388bce57631 100644 (file)
@@ -135,7 +135,7 @@ static void __devexit hplance_remove_one(struct dio_dev *d)
 }
 
 /* Initialise a single lance board at the given DIO device */
-static void __init hplance_init(struct net_device *dev, struct dio_dev *d)
+static void __devinit hplance_init(struct net_device *dev, struct dio_dev *d)
 {
         unsigned long va = (d->resource.start + DIO_VIRADDRBASE);
         struct hplance_private *lp;
index b644383017f91eba49e845048dde1e51d3241796..c0788a31ff0f4a8c0ee8b637ba335e69b7cd3056 100644 (file)
@@ -1965,11 +1965,11 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 
        netxen_tso_check(netdev, tx_ring, first_desc, skb);
 
-       netxen_nic_update_cmd_producer(adapter, tx_ring);
-
        adapter->stats.txbytes += skb->len;
        adapter->stats.xmitcalled++;
 
+       netxen_nic_update_cmd_producer(adapter, tx_ring);
+
        return NETDEV_TX_OK;
 
 drop_packet:
index 392a6c4b72e5e4decda29324c4b82708311ec7dd..a70244306c9462830c4ebde0b87334ef7667fa0e 100644 (file)
@@ -58,6 +58,7 @@ config BROADCOM_PHY
 
 config BCM63XX_PHY
        tristate "Drivers for Broadcom 63xx SOCs internal PHY"
+       depends on BCM63XX
        ---help---
          Currently supports the 6348 and 6358 PHYs.
 
index b0c9522bb535293ff72f304ddf2c77fe1a7524e6..2cd8dc5847b4432f5d0567e0cb7bc083e7a63fa3 100644 (file)
@@ -543,11 +543,20 @@ static void recalibrate(struct dp83640_clock *clock)
 
 /* time stamping methods */
 
-static void decode_evnt(struct dp83640_private *dp83640,
-                       struct phy_txts *phy_txts, u16 ests)
+static int decode_evnt(struct dp83640_private *dp83640,
+                      void *data, u16 ests)
 {
+       struct phy_txts *phy_txts;
        struct ptp_clock_event event;
        int words = (ests >> EVNT_TS_LEN_SHIFT) & EVNT_TS_LEN_MASK;
+       u16 ext_status = 0;
+
+       if (ests & MULT_EVNT) {
+               ext_status = *(u16 *) data;
+               data += sizeof(ext_status);
+       }
+
+       phy_txts = data;
 
        switch (words) { /* fall through in every case */
        case 3:
@@ -565,6 +574,9 @@ static void decode_evnt(struct dp83640_private *dp83640,
        event.timestamp = phy2txts(&dp83640->edata);
 
        ptp_clock_event(dp83640->clock->ptp_clock, &event);
+
+       words = ext_status ? words + 2 : words + 1;
+       return words * sizeof(u16);
 }
 
 static void decode_rxts(struct dp83640_private *dp83640,
@@ -643,9 +655,7 @@ static void decode_status_frame(struct dp83640_private *dp83640,
 
                } else if (PSF_EVNT == type && len >= sizeof(*phy_txts)) {
 
-                       phy_txts = (struct phy_txts *) ptr;
-                       decode_evnt(dp83640, phy_txts, ests);
-                       size = sizeof(*phy_txts);
+                       size = decode_evnt(dp83640, ptr, ests);
 
                } else {
                        size = 0;
@@ -1034,8 +1044,8 @@ static bool dp83640_rxtstamp(struct phy_device *phydev,
 
        if (is_status_frame(skb, type)) {
                decode_status_frame(dp83640, skb);
-               /* Let the stack drop this frame. */
-               return false;
+               kfree_skb(skb);
+               return true;
        }
 
        SKB_PTP_TYPE(skb) = type;
index a1b82c9c67d246c64f41ee1ec51f83b04fe0a6fa..c554a397e558c2b0fbd5ac0ff2d94523612f8a42 100644 (file)
@@ -523,7 +523,7 @@ static void ppp_async_process(unsigned long arg)
 #define PUT_BYTE(ap, buf, c, islcp)    do {            \
        if ((islcp && c < 0x20) || (ap->xaccm[c >> 5] & (1 << (c & 0x1f)))) {\
                *buf++ = PPP_ESCAPE;                    \
-               *buf++ = c ^ 0x20;                      \
+               *buf++ = c ^ PPP_TRANS;                 \
        } else                                          \
                *buf++ = c;                             \
 } while (0)
@@ -896,7 +896,7 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
                                sp = skb_put(skb, n);
                                memcpy(sp, buf, n);
                                if (ap->state & SC_ESCAPE) {
-                                       sp[0] ^= 0x20;
+                                       sp[0] ^= PPP_TRANS;
                                        ap->state &= ~SC_ESCAPE;
                                }
                        }
index 89f7540d90f909708fa318dbe9ecf6458252a922..5f597ca592bb8bf94a80861de3d315bc1b3c2026 100644 (file)
@@ -1273,7 +1273,7 @@ static int pxa168_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
        wmb();
        wrl(pep, SDMA_CMD, SDMA_CMD_TXDH | SDMA_CMD_ERD);
 
-       stats->tx_bytes += skb->len;
+       stats->tx_bytes += length;
        stats->tx_packets++;
        dev->trans_start = jiffies;
        if (pep->tx_ring_size - pep->tx_desc_count <= 1) {
index ef1ce2ebeb4a6784ecca5d3c10f7ca084308ab9a..05d81780d1fdc5becc895e15fbcf86b695ce7392 100644 (file)
@@ -1621,7 +1621,7 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
         *
         * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
         */
-       static const struct {
+       static const struct rtl_mac_info {
                u32 mask;
                u32 val;
                int mac_version;
@@ -1689,7 +1689,8 @@ static void rtl8169_get_mac_version(struct rtl8169_private *tp,
 
                /* Catch-all */
                { 0x00000000, 0x00000000,       RTL_GIGA_MAC_NONE   }
-       }, *p = mac_info;
+       };
+       const struct rtl_mac_info *p = mac_info;
        u32 reg;
 
        reg = RTL_R32(TxConfig);
@@ -3681,7 +3682,7 @@ static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz)
 
 static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
 {
-       static const struct {
+       static const struct rtl_cfg2_info {
                u32 mac_version;
                u32 clk;
                u32 val;
@@ -3690,7 +3691,8 @@ static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
                { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff },
                { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe
                { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff }
-       }, *p = cfg2_info;
+       };
+       const struct rtl_cfg2_info *p = cfg2_info;
        unsigned int i;
        u32 clk;
 
index 74e94054ab1a29d41828c7b9358518733eba0754..5235f48be1be677b7ca57fd275c21392fb846762 100644 (file)
@@ -460,7 +460,23 @@ static u32 tun_net_fix_features(struct net_device *dev, u32 features)
 
        return (features & tun->set_features) | (features & ~TUN_USER_FEATURES);
 }
-
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void tun_poll_controller(struct net_device *dev)
+{
+       /*
+        * Tun only receives frames when:
+        * 1) the char device endpoint gets data from user space
+        * 2) the tun socket gets a sendmsg call from user space
+        * Since both of those are syncronous operations, we are guaranteed
+        * never to have pending data when we poll for it
+        * so theres nothing to do here but return.
+        * We need this though so netpoll recognizes us as an interface that
+        * supports polling, which enables bridge devices in virt setups to
+        * still use netconsole
+        */
+       return;
+}
+#endif
 static const struct net_device_ops tun_netdev_ops = {
        .ndo_uninit             = tun_net_uninit,
        .ndo_open               = tun_net_open,
@@ -468,6 +484,9 @@ static const struct net_device_ops tun_netdev_ops = {
        .ndo_start_xmit         = tun_net_xmit,
        .ndo_change_mtu         = tun_net_change_mtu,
        .ndo_fix_features       = tun_net_fix_features,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = tun_poll_controller,
+#endif
 };
 
 static const struct net_device_ops tap_netdev_ops = {
@@ -480,6 +499,9 @@ static const struct net_device_ops tap_netdev_ops = {
        .ndo_set_multicast_list = tun_net_mclist,
        .ndo_set_mac_address    = eth_mac_addr,
        .ndo_validate_addr      = eth_validate_addr,
+#ifdef CONFIG_NET_POLL_CONTROLLER
+       .ndo_poll_controller    = tun_poll_controller,
+#endif
 };
 
 /* Initialize net device. */
index 9d4f9117260f0a613c7d72e86867f724f107f5ae..84d4608153c992556a2d14a4a6bab37160abbf1b 100644 (file)
@@ -385,6 +385,16 @@ config USB_NET_CX82310_ETH
          router with USB ethernet port. This driver is for routers only,
          it will not work with ADSL modems (use cxacru driver instead).
 
+config USB_NET_KALMIA
+       tristate "Samsung Kalmia based LTE USB modem"
+       depends on USB_USBNET
+       help
+         Choose this option if you have a Samsung Kalmia based USB modem
+         as Samsung GT-B3730.
+
+         To compile this driver as a module, choose M here: the
+         module will be called kalmia.
+
 config USB_HSO
        tristate "Option USB High Speed Mobile Devices"
        depends on USB && RFKILL
index c7ec8a5f0a90d46fffcaa5a34e72468584086dd0..c203fa21f6b12473faa7efe3f6e851ab6af94954 100644 (file)
@@ -23,6 +23,7 @@ obj-$(CONFIG_USB_NET_MCS7830) += mcs7830.o
 obj-$(CONFIG_USB_USBNET)       += usbnet.o
 obj-$(CONFIG_USB_NET_INT51X1)  += int51x1.o
 obj-$(CONFIG_USB_CDC_PHONET)   += cdc-phonet.o
+obj-$(CONFIG_USB_NET_KALMIA)   += kalmia.o
 obj-$(CONFIG_USB_IPHETH)       += ipheth.o
 obj-$(CONFIG_USB_SIERRA_NET)   += sierra_net.o
 obj-$(CONFIG_USB_NET_CX82310_ETH)      += cx82310_eth.o
diff --git a/drivers/net/usb/kalmia.c b/drivers/net/usb/kalmia.c
new file mode 100644 (file)
index 0000000..d965fb1
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * USB network interface driver for Samsung Kalmia based LTE USB modem like the
+ * Samsung GT-B3730 and GT-B3710.
+ *
+ * Copyright (C) 2011 Marius Bjoernstad Kotsbak <marius@kotsbak.com>
+ *
+ * Sponsored by Quicklink Video Distribution Services Ltd.
+ *
+ * Based on the cdc_eem module.
+ *
+ * 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/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ctype.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/crc32.h>
+#include <linux/usb/cdc.h>
+#include <linux/usb/usbnet.h>
+#include <linux/gfp.h>
+
+/*
+ * The Samsung Kalmia based LTE USB modems have a CDC ACM port for modem control
+ * handled by the "option" module and an ethernet data port handled by this
+ * module.
+ *
+ * The stick must first be switched into modem mode by usb_modeswitch
+ * or similar tool. Then the modem gets sent two initialization packets by
+ * this module, which gives the MAC address of the device. User space can then
+ * connect the modem using AT commands through the ACM port and then use
+ * DHCP on the network interface exposed by this module. Network packets are
+ * sent to and from the modem in a proprietary format discovered after watching
+ * the behavior of the windows driver for the modem.
+ *
+ * More information about the use of the modem is available in usb_modeswitch
+ * forum and the project page:
+ *
+ * http://www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?t=465
+ * https://github.com/mkotsbak/Samsung-GT-B3730-linux-driver
+ */
+
+/* #define     DEBUG */
+/* #define     VERBOSE */
+
+#define KALMIA_HEADER_LENGTH 6
+#define KALMIA_ALIGN_SIZE 4
+#define KALMIA_USB_TIMEOUT 10000
+
+/*-------------------------------------------------------------------------*/
+
+static int
+kalmia_send_init_packet(struct usbnet *dev, u8 *init_msg, u8 init_msg_len,
+       u8 *buffer, u8 expected_len)
+{
+       int act_len;
+       int status;
+
+       netdev_dbg(dev->net, "Sending init packet");
+
+       status = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 0x02),
+               init_msg, init_msg_len, &act_len, KALMIA_USB_TIMEOUT);
+       if (status != 0) {
+               netdev_err(dev->net,
+                       "Error sending init packet. Status %i, length %i\n",
+                       status, act_len);
+               return status;
+       }
+       else if (act_len != init_msg_len) {
+               netdev_err(dev->net,
+                       "Did not send all of init packet. Bytes sent: %i",
+                       act_len);
+       }
+       else {
+               netdev_dbg(dev->net, "Successfully sent init packet.");
+       }
+
+       status = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, 0x81),
+               buffer, expected_len, &act_len, KALMIA_USB_TIMEOUT);
+
+       if (status != 0)
+               netdev_err(dev->net,
+                       "Error receiving init result. Status %i, length %i\n",
+                       status, act_len);
+       else if (act_len != expected_len)
+               netdev_err(dev->net, "Unexpected init result length: %i\n",
+                       act_len);
+
+       return status;
+}
+
+static int
+kalmia_init_and_get_ethernet_addr(struct usbnet *dev, u8 *ethernet_addr)
+{
+       char init_msg_1[] =
+               { 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+               0x00, 0x00 };
+       char init_msg_2[] =
+               { 0x57, 0x50, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xf4,
+               0x00, 0x00 };
+       char receive_buf[28];
+       int status;
+
+       status = kalmia_send_init_packet(dev, init_msg_1, sizeof(init_msg_1)
+               / sizeof(init_msg_1[0]), receive_buf, 24);
+       if (status != 0)
+               return status;
+
+       status = kalmia_send_init_packet(dev, init_msg_2, sizeof(init_msg_2)
+               / sizeof(init_msg_2[0]), receive_buf, 28);
+       if (status != 0)
+               return status;
+
+       memcpy(ethernet_addr, receive_buf + 10, ETH_ALEN);
+
+       return status;
+}
+
+static int
+kalmia_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+       u8 status;
+       u8 ethernet_addr[ETH_ALEN];
+
+       /* Don't bind to AT command interface */
+       if (intf->cur_altsetting->desc.bInterfaceClass != USB_CLASS_VENDOR_SPEC)
+               return -EINVAL;
+
+       dev->in = usb_rcvbulkpipe(dev->udev, 0x81 & USB_ENDPOINT_NUMBER_MASK);
+       dev->out = usb_sndbulkpipe(dev->udev, 0x02 & USB_ENDPOINT_NUMBER_MASK);
+       dev->status = NULL;
+
+       dev->net->hard_header_len += KALMIA_HEADER_LENGTH;
+       dev->hard_mtu = 1400;
+       dev->rx_urb_size = dev->hard_mtu * 10; // Found as optimal after testing
+
+       status = kalmia_init_and_get_ethernet_addr(dev, ethernet_addr);
+
+       if (status < 0) {
+               usb_set_intfdata(intf, NULL);
+               usb_driver_release_interface(driver_of(intf), intf);
+               return status;
+       }
+
+       memcpy(dev->net->dev_addr, ethernet_addr, ETH_ALEN);
+       memcpy(dev->net->perm_addr, ethernet_addr, ETH_ALEN);
+
+       return status;
+}
+
+static struct sk_buff *
+kalmia_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags)
+{
+       struct sk_buff *skb2 = NULL;
+       u16 content_len;
+       unsigned char *header_start;
+       unsigned char ether_type_1, ether_type_2;
+       u8 remainder, padlen = 0;
+
+       if (!skb_cloned(skb)) {
+               int headroom = skb_headroom(skb);
+               int tailroom = skb_tailroom(skb);
+
+               if ((tailroom >= KALMIA_ALIGN_SIZE) && (headroom
+                       >= KALMIA_HEADER_LENGTH))
+                       goto done;
+
+               if ((headroom + tailroom) > (KALMIA_HEADER_LENGTH
+                       + KALMIA_ALIGN_SIZE)) {
+                       skb->data = memmove(skb->head + KALMIA_HEADER_LENGTH,
+                               skb->data, skb->len);
+                       skb_set_tail_pointer(skb, skb->len);
+                       goto done;
+               }
+       }
+
+       skb2 = skb_copy_expand(skb, KALMIA_HEADER_LENGTH,
+               KALMIA_ALIGN_SIZE, flags);
+       if (!skb2)
+               return NULL;
+
+       dev_kfree_skb_any(skb);
+       skb = skb2;
+
+       done: header_start = skb_push(skb, KALMIA_HEADER_LENGTH);
+       ether_type_1 = header_start[KALMIA_HEADER_LENGTH + 12];
+       ether_type_2 = header_start[KALMIA_HEADER_LENGTH + 13];
+
+       netdev_dbg(dev->net, "Sending etherType: %02x%02x", ether_type_1,
+               ether_type_2);
+
+       /* According to empiric data for data packages */
+       header_start[0] = 0x57;
+       header_start[1] = 0x44;
+       content_len = skb->len - KALMIA_HEADER_LENGTH;
+       header_start[2] = (content_len & 0xff); /* low byte */
+       header_start[3] = (content_len >> 8); /* high byte */
+
+       header_start[4] = ether_type_1;
+       header_start[5] = ether_type_2;
+
+       /* Align to 4 bytes by padding with zeros */
+       remainder = skb->len % KALMIA_ALIGN_SIZE;
+       if (remainder > 0) {
+               padlen = KALMIA_ALIGN_SIZE - remainder;
+               memset(skb_put(skb, padlen), 0, padlen);
+       }
+
+       netdev_dbg(
+               dev->net,
+               "Sending package with length %i and padding %i. Header: %02x:%02x:%02x:%02x:%02x:%02x.",
+               content_len, padlen, header_start[0], header_start[1],
+               header_start[2], header_start[3], header_start[4],
+               header_start[5]);
+
+       return skb;
+}
+
+static int
+kalmia_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+       /*
+        * Our task here is to strip off framing, leaving skb with one
+        * data frame for the usbnet framework code to process.
+        */
+       const u8 HEADER_END_OF_USB_PACKET[] =
+               { 0x57, 0x5a, 0x00, 0x00, 0x08, 0x00 };
+       const u8 EXPECTED_UNKNOWN_HEADER_1[] =
+               { 0x57, 0x43, 0x1e, 0x00, 0x15, 0x02 };
+       const u8 EXPECTED_UNKNOWN_HEADER_2[] =
+               { 0x57, 0x50, 0x0e, 0x00, 0x00, 0x00 };
+       u8 i = 0;
+
+       /* incomplete header? */
+       if (skb->len < KALMIA_HEADER_LENGTH)
+               return 0;
+
+       do {
+               struct sk_buff *skb2 = NULL;
+               u8 *header_start;
+               u16 usb_packet_length, ether_packet_length;
+               int is_last;
+
+               header_start = skb->data;
+
+               if (unlikely(header_start[0] != 0x57 || header_start[1] != 0x44)) {
+                       if (!memcmp(header_start, EXPECTED_UNKNOWN_HEADER_1,
+                               sizeof(EXPECTED_UNKNOWN_HEADER_1)) || !memcmp(
+                               header_start, EXPECTED_UNKNOWN_HEADER_2,
+                               sizeof(EXPECTED_UNKNOWN_HEADER_2))) {
+                               netdev_dbg(
+                                       dev->net,
+                                       "Received expected unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n",
+                                       header_start[0], header_start[1],
+                                       header_start[2], header_start[3],
+                                       header_start[4], header_start[5],
+                                       skb->len - KALMIA_HEADER_LENGTH);
+                       }
+                       else {
+                               netdev_err(
+                                       dev->net,
+                                       "Received unknown frame header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n",
+                                       header_start[0], header_start[1],
+                                       header_start[2], header_start[3],
+                                       header_start[4], header_start[5],
+                                       skb->len - KALMIA_HEADER_LENGTH);
+                               return 0;
+                       }
+               }
+               else
+                       netdev_dbg(
+                               dev->net,
+                               "Received header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n",
+                               header_start[0], header_start[1], header_start[2],
+                               header_start[3], header_start[4], header_start[5],
+                               skb->len - KALMIA_HEADER_LENGTH);
+
+               /* subtract start header and end header */
+               usb_packet_length = skb->len - (2 * KALMIA_HEADER_LENGTH);
+               ether_packet_length = header_start[2] + (header_start[3] << 8);
+               skb_pull(skb, KALMIA_HEADER_LENGTH);
+
+               /* Some small packets misses end marker */
+               if (usb_packet_length < ether_packet_length) {
+                       ether_packet_length = usb_packet_length
+                               + KALMIA_HEADER_LENGTH;
+                       is_last = true;
+               }
+               else {
+                       netdev_dbg(dev->net, "Correct package length #%i", i
+                               + 1);
+
+                       is_last = (memcmp(skb->data + ether_packet_length,
+                               HEADER_END_OF_USB_PACKET,
+                               sizeof(HEADER_END_OF_USB_PACKET)) == 0);
+                       if (!is_last) {
+                               header_start = skb->data + ether_packet_length;
+                               netdev_dbg(
+                                       dev->net,
+                                       "End header: %02x:%02x:%02x:%02x:%02x:%02x. Package length: %i\n",
+                                       header_start[0], header_start[1],
+                                       header_start[2], header_start[3],
+                                       header_start[4], header_start[5],
+                                       skb->len - KALMIA_HEADER_LENGTH);
+                       }
+               }
+
+               if (is_last) {
+                       skb2 = skb;
+               }
+               else {
+                       skb2 = skb_clone(skb, GFP_ATOMIC);
+                       if (unlikely(!skb2))
+                               return 0;
+               }
+
+               skb_trim(skb2, ether_packet_length);
+
+               if (is_last) {
+                       return 1;
+               }
+               else {
+                       usbnet_skb_return(dev, skb2);
+                       skb_pull(skb, ether_packet_length);
+               }
+
+               i++;
+       }
+       while (skb->len);
+
+       return 1;
+}
+
+static const struct driver_info kalmia_info = {
+       .description = "Samsung Kalmia LTE USB dongle",
+       .flags = FLAG_WWAN,
+       .bind = kalmia_bind,
+       .rx_fixup = kalmia_rx_fixup,
+       .tx_fixup = kalmia_tx_fixup
+};
+
+/*-------------------------------------------------------------------------*/
+
+static const struct usb_device_id products[] = {
+       /* The unswitched USB ID, to get the module auto loaded: */
+       { USB_DEVICE(0x04e8, 0x689a) },
+       /* The stick swithed into modem (by e.g. usb_modeswitch): */
+       { USB_DEVICE(0x04e8, 0x6889),
+               .driver_info = (unsigned long) &kalmia_info, },
+       { /* EMPTY == end of list */} };
+MODULE_DEVICE_TABLE( usb, products);
+
+static struct usb_driver kalmia_driver = {
+       .name = "kalmia",
+       .id_table = products,
+       .probe = usbnet_probe,
+       .disconnect = usbnet_disconnect,
+       .suspend = usbnet_suspend,
+       .resume = usbnet_resume
+};
+
+static int __init kalmia_init(void)
+{
+       return usb_register(&kalmia_driver);
+}
+module_init( kalmia_init);
+
+static void __exit kalmia_exit(void)
+{
+       usb_deregister(&kalmia_driver);
+}
+module_exit( kalmia_exit);
+
+MODULE_AUTHOR("Marius Bjoernstad Kotsbak <marius@kotsbak.com>");
+MODULE_DESCRIPTION("Samsung Kalmia USB network driver");
+MODULE_LICENSE("GPL");
index e050bd65e0378cbdd6643d893c01a4462a2dea2f..777d1a4e81b2cb0c43599e146e16d774e47abe66 100644 (file)
@@ -2203,8 +2203,10 @@ fst_open(struct net_device *dev)
 
        if (port->mode != FST_RAW) {
                err = hdlc_open(dev);
-               if (err)
+               if (err) {
+                       module_put(THIS_MODULE);
                        return err;
+               }
        }
 
        fst_openport(port);
index 660831ce293cf771dcd268bc5c9e8614d5b07923..687c1f223497e440939607e38303ca33e6fc9bcc 100644 (file)
@@ -1288,6 +1288,8 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac,
 
        *(unsigned long *) wdev_priv = (unsigned long) priv;
 
+       set_wiphy_dev(wdev->wiphy, (struct device *) priv->adapter->dev);
+
        ret = wiphy_register(wdev->wiphy);
        if (ret < 0) {
                dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n",
index 32261189bcef9065eac5cf14b961497a79a58f93..aeac3cc4dbe45d6df570a636ffafbfcc3ce104cf 100644 (file)
@@ -2474,6 +2474,7 @@ struct mwl8k_cmd_set_hw_spec {
  * faster client.
  */
 #define MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY 0x00000400
+#define MWL8K_SET_HW_SPEC_FLAG_GENERATE_CCMP_HDR       0x00000200
 #define MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT          0x00000080
 #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP      0x00000020
 #define MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON         0x00000010
@@ -2510,7 +2511,8 @@ static int mwl8k_cmd_set_hw_spec(struct ieee80211_hw *hw)
        cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT |
                                 MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP |
                                 MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON |
-                                MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY);
+                                MWL8K_SET_HW_SPEC_FLAG_ENABLE_LIFE_TIME_EXPIRY |
+                                MWL8K_SET_HW_SPEC_FLAG_GENERATE_CCMP_HDR);
        cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS);
        cmd->total_rxd = cpu_to_le32(MWL8K_RX_DESCS);
 
index 135df164a4c1e897e4d36a7d5a49336518669480..46767c53917a5e28ee8fcec10d92de6c39609eba 100644 (file)
@@ -624,7 +624,7 @@ static int pci_pm_prepare(struct device *dev)
         * system from the sleep state, we'll have to prevent it from signaling
         * wake-up.
         */
-       pm_runtime_resume(dev);
+       pm_runtime_get_sync(dev);
 
        if (drv && drv->pm && drv->pm->prepare)
                error = drv->pm->prepare(dev);
@@ -638,6 +638,8 @@ static void pci_pm_complete(struct device *dev)
 
        if (drv && drv->pm && drv->pm->complete)
                drv->pm->complete(dev);
+
+       pm_runtime_put_sync(dev);
 }
 
 #else /* !CONFIG_PM_SLEEP */
index 56098b3e17c054a678253c028221610dc17f3ff5..2c5b9b9912795c880faa882bbf4a8d9523037530 100644 (file)
@@ -3271,11 +3271,11 @@ void __init pci_register_set_vga_state(arch_set_vga_state_t func)
 }
 
 static int pci_set_vga_state_arch(struct pci_dev *dev, bool decode,
-                     unsigned int command_bits, bool change_bridge)
+                     unsigned int command_bits, u32 flags)
 {
        if (arch_set_vga_state)
                return arch_set_vga_state(dev, decode, command_bits,
-                                               change_bridge);
+                                               flags);
        return 0;
 }
 
@@ -3284,7 +3284,7 @@ static int pci_set_vga_state_arch(struct pci_dev *dev, bool decode,
  * @dev: the PCI device
  * @decode: true = enable decoding, false = disable decoding
  * @command_bits: PCI_COMMAND_IO and/or PCI_COMMAND_MEMORY
- * @change_bridge_flags: traverse ancestors and change bridges
+ * @flags: traverse ancestors and change bridges
  * CHANGE_BRIDGE_ONLY / CHANGE_BRIDGE
  */
 int pci_set_vga_state(struct pci_dev *dev, bool decode,
index 48849ffdd67214265693c92076970e00ab329d2a..bafb3c3d4a8963e6a635d94a414e290e4998af40 100644 (file)
@@ -168,7 +168,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                res->flags |= pci_calc_resource_flags(l) | IORESOURCE_SIZEALIGN;
                if (type == pci_bar_io) {
                        l &= PCI_BASE_ADDRESS_IO_MASK;
-                       mask = PCI_BASE_ADDRESS_IO_MASK & IO_SPACE_LIMIT;
+                       mask = PCI_BASE_ADDRESS_IO_MASK & (u32) IO_SPACE_LIMIT;
                } else {
                        l &= PCI_BASE_ADDRESS_MEM_MASK;
                        mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
index e8a140669f90107aba6b2780de4b90494591aa34..02145e9697a9709fbcd615fb9597033f57e491dd 100644 (file)
@@ -2761,6 +2761,8 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE823, ricoh_mmc_fixup_r5c832);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE823, ricoh_mmc_fixup_r5c832);
 #endif /*CONFIG_MMC_RICOH_MMC*/
 
 #if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP)
index 435002dfc3caef7a418944e9e967af8a27c6b822..712baab3c83d58147237384fb168a4a6c3ceba1c 100644 (file)
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/gpio.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 
index 4724ba3acf1a51c7c3e42e6aa49ea4899436911e..b2005b44e4f7cc0ee053ab9ee37896e7bce66a2f 100644 (file)
@@ -149,6 +149,7 @@ static const struct i2c_device_id ds1307_id[] = {
        { "ds1340", ds_1340 },
        { "ds3231", ds_3231 },
        { "m41t00", m41t00 },
+       { "pt7c4338", ds_1307 },
        { "rx8025", rx_8025 },
        { }
 };
index b8bc862903ae587a332bd1547fcebe2ef758b303..efd6066b5cd25d3911bd626919ba9f683cf1b3e8 100644 (file)
@@ -78,7 +78,6 @@ struct vt8500_rtc {
        void __iomem            *regbase;
        struct resource         *res;
        int                     irq_alarm;
-       int                     irq_hz;
        struct rtc_device       *rtc;
        spinlock_t              lock;           /* Protects this structure */
 };
@@ -100,10 +99,6 @@ static irqreturn_t vt8500_rtc_irq(int irq, void *dev_id)
        if (isr & 1)
                events |= RTC_AF | RTC_IRQF;
 
-       /* Only second/minute interrupts are supported */
-       if (isr & 2)
-               events |= RTC_UF | RTC_IRQF;
-
        rtc_update_irq(vt8500_rtc->rtc, 1, events);
 
        return IRQ_HANDLED;
@@ -199,27 +194,12 @@ static int vt8500_alarm_irq_enable(struct device *dev, unsigned int enabled)
        return 0;
 }
 
-static int vt8500_update_irq_enable(struct device *dev, unsigned int enabled)
-{
-       struct vt8500_rtc *vt8500_rtc = dev_get_drvdata(dev);
-       unsigned long tmp = readl(vt8500_rtc->regbase + VT8500_RTC_CR);
-
-       if (enabled)
-               tmp |= VT8500_RTC_CR_SM_SEC | VT8500_RTC_CR_SM_ENABLE;
-       else
-               tmp &= ~VT8500_RTC_CR_SM_ENABLE;
-
-       writel(tmp, vt8500_rtc->regbase + VT8500_RTC_CR);
-       return 0;
-}
-
 static const struct rtc_class_ops vt8500_rtc_ops = {
        .read_time = vt8500_rtc_read_time,
        .set_time = vt8500_rtc_set_time,
        .read_alarm = vt8500_rtc_read_alarm,
        .set_alarm = vt8500_rtc_set_alarm,
        .alarm_irq_enable = vt8500_alarm_irq_enable,
-       .update_irq_enable = vt8500_update_irq_enable,
 };
 
 static int __devinit vt8500_rtc_probe(struct platform_device *pdev)
@@ -248,13 +228,6 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev)
                goto err_free;
        }
 
-       vt8500_rtc->irq_hz = platform_get_irq(pdev, 1);
-       if (vt8500_rtc->irq_hz < 0) {
-               dev_err(&pdev->dev, "No 1Hz IRQ resource defined\n");
-               ret = -ENXIO;
-               goto err_free;
-       }
-
        vt8500_rtc->res = request_mem_region(vt8500_rtc->res->start,
                                             resource_size(vt8500_rtc->res),
                                             "vt8500-rtc");
@@ -272,9 +245,8 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev)
                goto err_release;
        }
 
-       /* Enable the second/minute interrupt generation and enable RTC */
-       writel(VT8500_RTC_CR_ENABLE | VT8500_RTC_CR_24H
-               | VT8500_RTC_CR_SM_ENABLE | VT8500_RTC_CR_SM_SEC,
+       /* Enable RTC and set it to 24-hour mode */
+       writel(VT8500_RTC_CR_ENABLE | VT8500_RTC_CR_24H,
               vt8500_rtc->regbase + VT8500_RTC_CR);
 
        vt8500_rtc->rtc = rtc_device_register("vt8500-rtc", &pdev->dev,
@@ -286,26 +258,16 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev)
                goto err_unmap;
        }
 
-       ret = request_irq(vt8500_rtc->irq_hz, vt8500_rtc_irq, 0,
-                         "rtc 1Hz", vt8500_rtc);
-       if (ret < 0) {
-               dev_err(&pdev->dev, "can't get irq %i, err %d\n",
-                       vt8500_rtc->irq_hz, ret);
-               goto err_unreg;
-       }
-
        ret = request_irq(vt8500_rtc->irq_alarm, vt8500_rtc_irq, 0,
                          "rtc alarm", vt8500_rtc);
        if (ret < 0) {
                dev_err(&pdev->dev, "can't get irq %i, err %d\n",
                        vt8500_rtc->irq_alarm, ret);
-               goto err_free_hz;
+               goto err_unreg;
        }
 
        return 0;
 
-err_free_hz:
-       free_irq(vt8500_rtc->irq_hz, vt8500_rtc);
 err_unreg:
        rtc_device_unregister(vt8500_rtc->rtc);
 err_unmap:
@@ -323,7 +285,6 @@ static int __devexit vt8500_rtc_remove(struct platform_device *pdev)
        struct vt8500_rtc *vt8500_rtc = platform_get_drvdata(pdev);
 
        free_irq(vt8500_rtc->irq_alarm, vt8500_rtc);
-       free_irq(vt8500_rtc->irq_hz, vt8500_rtc);
 
        rtc_device_unregister(vt8500_rtc->rtc);
 
index 4f64183b27fa6283c80d4fa2d37aa61c61c127fe..7e9c39951ecb87c086c9ab439df893a5c0980752 100644 (file)
@@ -635,7 +635,7 @@ static void clks_core_resume(void)
        struct clk *clkp;
 
        list_for_each_entry(clkp, &clock_list, node) {
-               if (likely(clkp->ops)) {
+               if (likely(clkp->usecount && clkp->ops)) {
                        unsigned long rate = clkp->rate;
 
                        if (likely(clkp->ops->set_parent))
index f706dba165cf6812fc364271d3086424ce12aa36..cc880c95e7de7dfee978319ebfb7aecd74a4f355 100644 (file)
@@ -681,13 +681,14 @@ static void bfin_spi_pump_transfers(unsigned long data)
        drv_data->cs_change = transfer->cs_change;
 
        /* Bits per word setup */
-       bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word;
-       if ((bits_per_word > 0) && (bits_per_word % 16 == 0)) {
+       bits_per_word = transfer->bits_per_word ? :
+               message->spi->bits_per_word ? : 8;
+       if (bits_per_word % 16 == 0) {
                drv_data->n_bytes = bits_per_word/8;
                drv_data->len = (transfer->len) >> 1;
                cr_width = BIT_CTL_WORDSIZE;
                drv_data->ops = &bfin_bfin_spi_transfer_ops_u16;
-       } else if ((bits_per_word > 0) && (bits_per_word % 8 == 0)) {
+       } else if (bits_per_word % 8 == 0) {
                drv_data->n_bytes = bits_per_word/8;
                drv_data->len = transfer->len;
                cr_width = 0;
index 0b9b85424dfaa1fdbe7b931e6fcf98f68ef9c9bf..4cc1a5bfab40c0705c31beca87757068a7b8487d 100644 (file)
@@ -81,7 +81,6 @@ struct adis16201_state {
 
 int adis16201_set_irq(struct iio_dev *indio_dev, bool enable);
 
-#ifdef CONFIG_IIO_RING_BUFFER
 enum adis16201_scan {
        ADIS16201_SCAN_SUPPLY,
        ADIS16201_SCAN_ACC_X,
@@ -92,6 +91,7 @@ enum adis16201_scan {
        ADIS16201_SCAN_INCLI_Y,
 };
 
+#ifdef CONFIG_IIO_RING_BUFFER
 void adis16201_remove_trigger(struct iio_dev *indio_dev);
 int adis16201_probe_trigger(struct iio_dev *indio_dev);
 
index 8bb8ce50c2483d339f584a2c83ad82c771ee2108..175e21bb9b403d79a0a2810c6730712791a1a62d 100644 (file)
@@ -76,7 +76,6 @@ struct adis16203_state {
 
 int adis16203_set_irq(struct iio_dev *indio_dev, bool enable);
 
-#ifdef CONFIG_IIO_RING_BUFFER
 enum adis16203_scan {
        ADIS16203_SCAN_SUPPLY,
        ADIS16203_SCAN_AUX_ADC,
@@ -85,6 +84,7 @@ enum adis16203_scan {
        ADIS16203_SCAN_INCLI_Y,
 };
 
+#ifdef CONFIG_IIO_RING_BUFFER
 void adis16203_remove_trigger(struct iio_dev *indio_dev);
 int adis16203_probe_trigger(struct iio_dev *indio_dev);
 
index dee2a2c909f5386671f593428cbfa837f37e65a6..70c2e7fa66643f7a7cdf040c62d74e977d7b9d1b 100644 (file)
@@ -386,7 +386,7 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)
         */
        se_cmd->se_tmr_req = core_tmr_alloc_req(se_cmd, (void *)tl_tmr,
                                TMR_LUN_RESET);
-       if (!se_cmd->se_tmr_req)
+       if (IS_ERR(se_cmd->se_tmr_req))
                goto release;
        /*
         * Locate the underlying TCM struct se_lun from sc->device->lun
@@ -1017,6 +1017,7 @@ static int tcm_loop_make_nexus(
        struct se_portal_group *se_tpg;
        struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
        struct tcm_loop_nexus *tl_nexus;
+       int ret = -ENOMEM;
 
        if (tl_tpg->tl_hba->tl_nexus) {
                printk(KERN_INFO "tl_tpg->tl_hba->tl_nexus already exists\n");
@@ -1033,8 +1034,10 @@ static int tcm_loop_make_nexus(
         * Initialize the struct se_session pointer
         */
        tl_nexus->se_sess = transport_init_session();
-       if (!tl_nexus->se_sess)
+       if (IS_ERR(tl_nexus->se_sess)) {
+               ret = PTR_ERR(tl_nexus->se_sess);
                goto out;
+       }
        /*
         * Since we are running in 'demo mode' this call with generate a
         * struct se_node_acl for the tcm_loop struct se_portal_group with the SCSI
@@ -1060,7 +1063,7 @@ static int tcm_loop_make_nexus(
 
 out:
        kfree(tl_nexus);
-       return -ENOMEM;
+       return ret;
 }
 
 static int tcm_loop_drop_nexus(
@@ -1140,7 +1143,7 @@ static ssize_t tcm_loop_tpg_store_nexus(
         * the fabric protocol_id set in tcm_loop_make_scsi_hba(), and call
         * tcm_loop_make_nexus()
         */
-       if (strlen(page) > TL_WWN_ADDR_LEN) {
+       if (strlen(page) >= TL_WWN_ADDR_LEN) {
                printk(KERN_ERR "Emulated NAA Sas Address: %s, exceeds"
                                " max: %d\n", page, TL_WWN_ADDR_LEN);
                return -EINVAL;
@@ -1321,7 +1324,7 @@ struct se_wwn *tcm_loop_make_scsi_hba(
        return ERR_PTR(-EINVAL);
 
 check_len:
-       if (strlen(name) > TL_WWN_ADDR_LEN) {
+       if (strlen(name) >= TL_WWN_ADDR_LEN) {
                printk(KERN_ERR "Emulated NAA %s Address: %s, exceeds"
                        " max: %d\n", name, tcm_loop_dump_proto_id(tl_hba),
                        TL_WWN_ADDR_LEN);
index ee6fad979b50c82fa9ff2fc9f8121a62f32d7bb5..25c1f49a7d8bae7ee61f20df5830ba5a782277c7 100644 (file)
@@ -304,7 +304,7 @@ struct target_fabric_configfs *target_fabric_configfs_init(
                printk(KERN_ERR "Unable to locate passed fabric name\n");
                return NULL;
        }
-       if (strlen(name) > TARGET_FABRIC_NAME_SIZE) {
+       if (strlen(name) >= TARGET_FABRIC_NAME_SIZE) {
                printk(KERN_ERR "Passed name: %s exceeds TARGET_FABRIC"
                        "_NAME_SIZE\n", name);
                return NULL;
@@ -312,7 +312,7 @@ struct target_fabric_configfs *target_fabric_configfs_init(
 
        tf = kzalloc(sizeof(struct target_fabric_configfs), GFP_KERNEL);
        if (!(tf))
-               return ERR_PTR(-ENOMEM);
+               return NULL;
 
        INIT_LIST_HEAD(&tf->tf_list);
        atomic_set(&tf->tf_access_cnt, 0);
@@ -851,7 +851,7 @@ static ssize_t target_core_dev_wwn_store_attr_vpd_unit_serial(
                return -EOPNOTSUPP;
        }
 
-       if ((strlen(page) + 1) > INQUIRY_VPD_SERIAL_LEN) {
+       if (strlen(page) >= INQUIRY_VPD_SERIAL_LEN) {
                printk(KERN_ERR "Emulated VPD Unit Serial exceeds"
                " INQUIRY_VPD_SERIAL_LEN: %d\n", INQUIRY_VPD_SERIAL_LEN);
                return -EOVERFLOW;
@@ -917,7 +917,7 @@ static ssize_t target_core_dev_wwn_show_attr_vpd_protocol_identifier(
 
                transport_dump_vpd_proto_id(vpd, buf, VPD_TMP_BUF_SIZE);
 
-               if ((len + strlen(buf) > PAGE_SIZE))
+               if ((len + strlen(buf) >= PAGE_SIZE))
                        break;
 
                len += sprintf(page+len, "%s", buf);
@@ -962,19 +962,19 @@ static ssize_t target_core_dev_wwn_show_attr_##_name(                     \
                                                                        \
                memset(buf, 0, VPD_TMP_BUF_SIZE);                       \
                transport_dump_vpd_assoc(vpd, buf, VPD_TMP_BUF_SIZE);   \
-               if ((len + strlen(buf) > PAGE_SIZE))                    \
+               if ((len + strlen(buf) >= PAGE_SIZE))                   \
                        break;                                          \
                len += sprintf(page+len, "%s", buf);                    \
                                                                        \
                memset(buf, 0, VPD_TMP_BUF_SIZE);                       \
                transport_dump_vpd_ident_type(vpd, buf, VPD_TMP_BUF_SIZE); \
-               if ((len + strlen(buf) > PAGE_SIZE))                    \
+               if ((len + strlen(buf) >= PAGE_SIZE))                   \
                        break;                                          \
                len += sprintf(page+len, "%s", buf);                    \
                                                                        \
                memset(buf, 0, VPD_TMP_BUF_SIZE);                       \
                transport_dump_vpd_ident(vpd, buf, VPD_TMP_BUF_SIZE); \
-               if ((len + strlen(buf) > PAGE_SIZE))                    \
+               if ((len + strlen(buf) >= PAGE_SIZE))                   \
                        break;                                          \
                len += sprintf(page+len, "%s", buf);                    \
        }                                                               \
@@ -1299,7 +1299,7 @@ static ssize_t target_core_dev_pr_show_attr_res_pr_registered_i_pts(
                        &i_buf[0] : "", pr_reg->pr_res_key,
                        pr_reg->pr_res_generation);
 
-               if ((len + strlen(buf) > PAGE_SIZE))
+               if ((len + strlen(buf) >= PAGE_SIZE))
                        break;
 
                len += sprintf(page+len, "%s", buf);
@@ -1496,7 +1496,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
                                ret = -ENOMEM;
                                goto out;
                        }
-                       if (strlen(i_port) > PR_APTPL_MAX_IPORT_LEN) {
+                       if (strlen(i_port) >= PR_APTPL_MAX_IPORT_LEN) {
                                printk(KERN_ERR "APTPL metadata initiator_node="
                                        " exceeds PR_APTPL_MAX_IPORT_LEN: %d\n",
                                        PR_APTPL_MAX_IPORT_LEN);
@@ -1510,7 +1510,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
                                ret = -ENOMEM;
                                goto out;
                        }
-                       if (strlen(isid) > PR_REG_ISID_LEN) {
+                       if (strlen(isid) >= PR_REG_ISID_LEN) {
                                printk(KERN_ERR "APTPL metadata initiator_isid"
                                        "= exceeds PR_REG_ISID_LEN: %d\n",
                                        PR_REG_ISID_LEN);
@@ -1571,7 +1571,7 @@ static ssize_t target_core_dev_pr_store_attr_res_aptpl_metadata(
                                ret = -ENOMEM;
                                goto out;
                        }
-                       if (strlen(t_port) > PR_APTPL_MAX_TPORT_LEN) {
+                       if (strlen(t_port) >= PR_APTPL_MAX_TPORT_LEN) {
                                printk(KERN_ERR "APTPL metadata target_node="
                                        " exceeds PR_APTPL_MAX_TPORT_LEN: %d\n",
                                        PR_APTPL_MAX_TPORT_LEN);
@@ -3052,7 +3052,7 @@ static struct config_group *target_core_call_addhbatotarget(
        int ret;
 
        memset(buf, 0, TARGET_CORE_NAME_MAX_LEN);
-       if (strlen(name) > TARGET_CORE_NAME_MAX_LEN) {
+       if (strlen(name) >= TARGET_CORE_NAME_MAX_LEN) {
                printk(KERN_ERR "Passed *name strlen(): %d exceeds"
                        " TARGET_CORE_NAME_MAX_LEN: %d\n", (int)strlen(name),
                        TARGET_CORE_NAME_MAX_LEN);
index 8407f9ca2b3163f69dc5770ad4d2ff804516a95e..ba698ea62bb2a52c19d87a6d1df7de10fcba9ecd 100644 (file)
@@ -192,7 +192,7 @@ int transport_get_lun_for_tmr(
                        &SE_NODE_ACL(se_sess)->device_list[unpacked_lun];
        if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
                se_lun = se_cmd->se_lun = se_tmr->tmr_lun = deve->se_lun;
-               dev = se_tmr->tmr_dev = se_lun->lun_se_dev;
+               dev = se_lun->lun_se_dev;
                se_cmd->pr_res_key = deve->pr_res_key;
                se_cmd->orig_fe_lun = unpacked_lun;
                se_cmd->se_orig_obj_ptr = SE_LUN(se_cmd)->lun_se_dev;
@@ -216,6 +216,7 @@ int transport_get_lun_for_tmr(
                se_cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
                return -1;
        }
+       se_tmr->tmr_dev = dev;
 
        spin_lock(&dev->se_tmr_lock);
        list_add_tail(&se_tmr->tmr_list, &dev->dev_tmr_list);
@@ -1430,7 +1431,7 @@ struct se_lun_acl *core_dev_init_initiator_node_lun_acl(
        struct se_lun_acl *lacl;
        struct se_node_acl *nacl;
 
-       if (strlen(initiatorname) > TRANSPORT_IQN_LEN) {
+       if (strlen(initiatorname) >= TRANSPORT_IQN_LEN) {
                printk(KERN_ERR "%s InitiatorName exceeds maximum size.\n",
                        TPG_TFO(tpg)->get_fabric_name());
                *ret = -EOVERFLOW;
index a79f518ca6e2b76e12312d55f536cdb732640802..b662db3a320bb96f272cbf9a831c1c8813e89952 100644 (file)
@@ -1916,7 +1916,7 @@ static int __core_scsi3_update_aptpl_buf(
                                pr_reg->pr_res_mapped_lun);
                }
 
-               if ((len + strlen(tmp) > pr_aptpl_buf_len)) {
+               if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
                        printk(KERN_ERR "Unable to update renaming"
                                " APTPL metadata\n");
                        spin_unlock(&T10_RES(su_dev)->registration_lock);
@@ -1934,7 +1934,7 @@ static int __core_scsi3_update_aptpl_buf(
                        TPG_TFO(tpg)->tpg_get_tag(tpg),
                        lun->lun_sep->sep_rtpi, lun->unpacked_lun, reg_count);
 
-               if ((len + strlen(tmp) > pr_aptpl_buf_len)) {
+               if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
                        printk(KERN_ERR "Unable to update renaming"
                                " APTPL metadata\n");
                        spin_unlock(&T10_RES(su_dev)->registration_lock);
@@ -1986,7 +1986,7 @@ static int __core_scsi3_write_aptpl_to_file(
        memset(iov, 0, sizeof(struct iovec));
        memset(path, 0, 512);
 
-       if (strlen(&wwn->unit_serial[0]) > 512) {
+       if (strlen(&wwn->unit_serial[0]) >= 512) {
                printk(KERN_ERR "WWN value for struct se_device does not fit"
                        " into path buffer\n");
                return -1;
index 59b8b9c5ad72a272e1c228474f6b241b6a70913b..179063d81cdd6f30f1af19ef3cb20c2e12b923a4 100644 (file)
@@ -75,10 +75,16 @@ void core_tmr_release_req(
 {
        struct se_device *dev = tmr->tmr_dev;
 
+       if (!dev) {
+               kmem_cache_free(se_tmr_req_cache, tmr);
+               return;
+       }
+
        spin_lock(&dev->se_tmr_lock);
        list_del(&tmr->tmr_list);
-       kmem_cache_free(se_tmr_req_cache, tmr);
        spin_unlock(&dev->se_tmr_lock);
+
+       kmem_cache_free(se_tmr_req_cache, tmr);
 }
 
 static void core_tmr_handle_tas_abort(
index 4dafeb8b56381173b733653ce0e9b1c6c9755efd..4b9b7169bdd96957d9a6054ea68ec99c897a2381 100644 (file)
@@ -536,13 +536,13 @@ EXPORT_SYMBOL(transport_register_session);
 void transport_deregister_session_configfs(struct se_session *se_sess)
 {
        struct se_node_acl *se_nacl;
-
+       unsigned long flags;
        /*
         * Used by struct se_node_acl's under ConfigFS to locate active struct se_session
         */
        se_nacl = se_sess->se_node_acl;
        if ((se_nacl)) {
-               spin_lock_irq(&se_nacl->nacl_sess_lock);
+               spin_lock_irqsave(&se_nacl->nacl_sess_lock, flags);
                list_del(&se_sess->sess_acl_list);
                /*
                 * If the session list is empty, then clear the pointer.
@@ -556,7 +556,7 @@ void transport_deregister_session_configfs(struct se_session *se_sess)
                                        se_nacl->acl_sess_list.prev,
                                        struct se_session, sess_acl_list);
                }
-               spin_unlock_irq(&se_nacl->nacl_sess_lock);
+               spin_unlock_irqrestore(&se_nacl->nacl_sess_lock, flags);
        }
 }
 EXPORT_SYMBOL(transport_deregister_session_configfs);
index defff32b7880faf26c32732c4898a87ec6ba80f4..7b82f1b7fef814b595f8cc266f182baa3f031642 100644 (file)
@@ -144,7 +144,7 @@ enum ft_cmd_state {
  */
 struct ft_cmd {
        enum ft_cmd_state state;
-       u16 lun;                        /* LUN from request */
+       u32 lun;                        /* LUN from request */
        struct ft_sess *sess;           /* session held for cmd */
        struct fc_seq *seq;             /* sequence in exchange mgr */
        struct se_cmd se_cmd;           /* Local TCM I/O descriptor */
index c056a1132ae133a5836613bb357ee24badfc3202..b2a106729d4914eca2c275adb956a944939d9b99 100644 (file)
@@ -94,29 +94,6 @@ void ft_dump_cmd(struct ft_cmd *cmd, const char *caller)
                16, 4, cmd->cdb, MAX_COMMAND_SIZE, 0);
 }
 
-/*
- * Get LUN from CDB.
- */
-static int ft_get_lun_for_cmd(struct ft_cmd *cmd, u8 *lunp)
-{
-       u64 lun;
-
-       lun = lunp[1];
-       switch (lunp[0] >> 6) {
-       case 0:
-               break;
-       case 1:
-               lun |= (lunp[0] & 0x3f) << 8;
-               break;
-       default:
-               return -1;
-       }
-       if (lun >= TRANSPORT_MAX_LUNS_PER_TPG)
-               return -1;
-       cmd->lun = lun;
-       return transport_get_lun_for_cmd(&cmd->se_cmd, NULL, lun);
-}
-
 static void ft_queue_cmd(struct ft_sess *sess, struct ft_cmd *cmd)
 {
        struct se_queue_obj *qobj;
@@ -418,6 +395,7 @@ static void ft_send_tm(struct ft_cmd *cmd)
 {
        struct se_tmr_req *tmr;
        struct fcp_cmnd *fcp;
+       struct ft_sess *sess;
        u8 tm_func;
 
        fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
@@ -425,13 +403,6 @@ static void ft_send_tm(struct ft_cmd *cmd)
        switch (fcp->fc_tm_flags) {
        case FCP_TMF_LUN_RESET:
                tm_func = TMR_LUN_RESET;
-               if (ft_get_lun_for_cmd(cmd, fcp->fc_lun) < 0) {
-                       ft_dump_cmd(cmd, __func__);
-                       transport_send_check_condition_and_sense(&cmd->se_cmd,
-                               cmd->se_cmd.scsi_sense_reason, 0);
-                       ft_sess_put(cmd->sess);
-                       return;
-               }
                break;
        case FCP_TMF_TGT_RESET:
                tm_func = TMR_TARGET_WARM_RESET;
@@ -463,6 +434,36 @@ static void ft_send_tm(struct ft_cmd *cmd)
                return;
        }
        cmd->se_cmd.se_tmr_req = tmr;
+
+       switch (fcp->fc_tm_flags) {
+       case FCP_TMF_LUN_RESET:
+               cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun);
+               if (transport_get_lun_for_tmr(&cmd->se_cmd, cmd->lun) < 0) {
+                       /*
+                        * Make sure to clean up newly allocated TMR request
+                        * since "unable to  handle TMR request because failed
+                        * to get to LUN"
+                        */
+                       FT_TM_DBG("Failed to get LUN for TMR func %d, "
+                                 "se_cmd %p, unpacked_lun %d\n",
+                                 tm_func, &cmd->se_cmd, cmd->lun);
+                       ft_dump_cmd(cmd, __func__);
+                       sess = cmd->sess;
+                       transport_send_check_condition_and_sense(&cmd->se_cmd,
+                               cmd->se_cmd.scsi_sense_reason, 0);
+                       transport_generic_free_cmd(&cmd->se_cmd, 0, 1, 0);
+                       ft_sess_put(sess);
+                       return;
+               }
+               break;
+       case FCP_TMF_TGT_RESET:
+       case FCP_TMF_CLR_TASK_SET:
+       case FCP_TMF_ABT_TASK_SET:
+       case FCP_TMF_CLR_ACA:
+               break;
+       default:
+               return;
+       }
        transport_generic_handle_tmr(&cmd->se_cmd);
 }
 
@@ -635,7 +636,8 @@ static void ft_send_cmd(struct ft_cmd *cmd)
 
        fc_seq_exch(cmd->seq)->lp->tt.seq_set_resp(cmd->seq, ft_recv_seq, cmd);
 
-       ret = ft_get_lun_for_cmd(cmd, fcp->fc_lun);
+       cmd->lun = scsilun_to_int((struct scsi_lun *)fcp->fc_lun);
+       ret = transport_get_lun_for_cmd(&cmd->se_cmd, NULL, cmd->lun);
        if (ret < 0) {
                ft_dump_cmd(cmd, __func__);
                transport_send_check_condition_and_sense(&cmd->se_cmd,
index 4c3c0efbe13f5b97158f92c51d17d46a5001ab40..8c4a24077d9d701fc6902501f9ad9f53775c24b2 100644 (file)
@@ -203,7 +203,7 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
                        /* XXX For now, initiator will retry */
                        if (printk_ratelimit())
                                printk(KERN_ERR "%s: Failed to send frame %p, "
-                                               "xid <0x%x>, remaining <0x%x>, "
+                                               "xid <0x%x>, remaining %zu, "
                                                "lso_max <0x%x>\n",
                                                __func__, fp, ep->xid,
                                                remaining, lport->lso_max);
index a3bd57f2ea3204d5c079f38aba247f40aae47e25..7491e21cc6ae4c35629614b687a424ac2917d87a 100644 (file)
@@ -229,7 +229,7 @@ static struct ft_sess *ft_sess_create(struct ft_tport *tport, u32 port_id,
                return NULL;
 
        sess->se_sess = transport_init_session();
-       if (!sess->se_sess) {
+       if (IS_ERR(sess->se_sess)) {
                kfree(sess);
                return NULL;
        }
@@ -332,7 +332,7 @@ void ft_sess_close(struct se_session *se_sess)
        lport = sess->tport->lport;
        port_id = sess->port_id;
        if (port_id == -1) {
-               mutex_lock(&ft_lport_lock);
+               mutex_unlock(&ft_lport_lock);
                return;
        }
        FT_SESS_DBG("port_id %x\n", port_id);
index 4b4968a294b293d0b17f43024487447b40bd450a..78e98a5cef964d1a980d3b4498ca5c55582ed4dc 100644 (file)
@@ -973,7 +973,7 @@ ce4100_serial_setup(struct serial_private *priv,
 
 static int
 pci_omegapci_setup(struct serial_private *priv,
-                     struct pciserial_board *board,
+                     const struct pciserial_board *board,
                      struct uart_port *port, int idx)
 {
        return setup_port(priv, port, 2, idx * 8, 0);
index 1bd28450ca40913f87503d7f75aa4ed5cd149904..a764bf99743b0b5c6be4d46fed2952cbca278d94 100644 (file)
@@ -421,7 +421,6 @@ static int max3110_main_thread(void *_max)
        int ret = 0;
        struct circ_buf *xmit = &max->con_xmit;
 
-       init_waitqueue_head(wq);
        pr_info(PR_FMT "start main thread\n");
 
        do {
@@ -823,7 +822,7 @@ static int __devinit serial_m3110_probe(struct spi_device *spi)
        res = RC_TAG;
        ret = max3110_write_then_read(max, (u8 *)&res, (u8 *)&res, 2, 0);
        if (ret < 0 || res == 0 || res == 0xffff) {
-               printk(KERN_ERR "MAX3111 deemed not present (conf reg %04x)",
+               dev_dbg(&spi->dev, "MAX3111 deemed not present (conf reg %04x)",
                                                                        res);
                ret = -ENODEV;
                goto err_get_page;
@@ -838,6 +837,8 @@ static int __devinit serial_m3110_probe(struct spi_device *spi)
        max->con_xmit.head = 0;
        max->con_xmit.tail = 0;
 
+       init_waitqueue_head(&max->wq);
+
        max->main_thread = kthread_run(max3110_main_thread,
                                        max, "max3110_main");
        if (IS_ERR(max->main_thread)) {
index f2cb7503fcb213115b3b15722495c335a0aad984..465210930890b72ecdcaf1c70167b7211f43ed9e 100644 (file)
@@ -1397,6 +1397,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
        int fifosize, base_baud;
        int port_type;
        struct pch_uart_driver_data *board;
+       const char *board_name;
 
        board = &drv_dat[id->driver_data];
        port_type = board->port_type;
@@ -1412,7 +1413,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
        base_baud = 1843200; /* 1.8432MHz */
 
        /* quirk for CM-iTC board */
-       if (strstr(dmi_get_system_info(DMI_BOARD_NAME), "CM-iTC"))
+       board_name = dmi_get_system_info(DMI_BOARD_NAME);
+       if (board_name && strstr(board_name, "CM-iTC"))
                base_baud = 192000000; /* 192.0MHz */
 
        switch (port_type) {
index e35a17687c05f77b9ecc55b4002d0b13386081b6..aa3cc465a6017eab466710433b09acfecbdcaad2 100644 (file)
@@ -375,7 +375,7 @@ static int usb_unbind_interface(struct device *dev)
                 * Just re-enable it without affecting the endpoint toggles.
                 */
                usb_enable_interface(udev, intf, false);
-       } else if (!error && !intf->dev.power.in_suspend) {
+       } else if (!error && !intf->dev.power.is_prepared) {
                r = usb_set_interface(udev, intf->altsetting[0].
                                desc.bInterfaceNumber, 0);
                if (r < 0)
@@ -960,7 +960,7 @@ void usb_rebind_intf(struct usb_interface *intf)
        }
 
        /* Try to rebind the interface */
-       if (!intf->dev.power.in_suspend) {
+       if (!intf->dev.power.is_prepared) {
                intf->needs_binding = 0;
                rc = device_attach(&intf->dev);
                if (rc < 0)
@@ -1107,7 +1107,7 @@ static int usb_resume_interface(struct usb_device *udev,
        if (intf->condition == USB_INTERFACE_UNBOUND) {
 
                /* Carry out a deferred switch to altsetting 0 */
-               if (intf->needs_altsetting0 && !intf->dev.power.in_suspend) {
+               if (intf->needs_altsetting0 && !intf->dev.power.is_prepared) {
                        usb_set_interface(udev, intf->altsetting[0].
                                        desc.bInterfaceNumber, 0);
                        intf->needs_altsetting0 = 0;
index ebb893c49e9027b9d9cb3aa897e83db394026ff0..d7aaec5667bfd6ca1e1407e52c8c503577339405 100644 (file)
@@ -248,10 +248,6 @@ static int atyfb_sync(struct fb_info *info);
 
 static int aty_init(struct fb_info *info);
 
-#ifdef CONFIG_ATARI
-static int store_video_par(char *videopar, unsigned char m64_num);
-#endif
-
 static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc);
 
 static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc);
@@ -2268,11 +2264,13 @@ error:
        return;
 }
 
+#ifdef CONFIG_PCI
 static void aty_bl_exit(struct backlight_device *bd)
 {
        backlight_device_unregister(bd);
        printk("aty: Backlight unloaded\n");
 }
+#endif /* CONFIG_PCI */
 
 #endif /* CONFIG_FB_ATY_BACKLIGHT */
 
@@ -2789,7 +2787,7 @@ aty_init_exit:
        return ret;
 }
 
-#ifdef CONFIG_ATARI
+#if defined(CONFIG_ATARI) && !defined(MODULE)
 static int __devinit store_video_par(char *video_str, unsigned char m64_num)
 {
        char *p;
@@ -2818,7 +2816,7 @@ static int __devinit store_video_par(char *video_str, unsigned char m64_num)
        phys_vmembase[m64_num] = 0;
        return -1;
 }
-#endif /* CONFIG_ATARI */
+#endif /* CONFIG_ATARI && !MODULE */
 
 /*
  * Blank the display.
index 0c9373bedd1f39d61d8b391bcc54a630d6d981c8..2d93c8d61ad5e2aa9ea2cd48d30581aad7cf8fb4 100644 (file)
@@ -302,6 +302,18 @@ config BACKLIGHT_ADP8860
          To compile this driver as a module, choose M here: the module will
          be called adp8860_bl.
 
+config BACKLIGHT_ADP8870
+       tristate "Backlight Driver for ADP8870 using WLED"
+       depends on BACKLIGHT_CLASS_DEVICE && I2C
+       select NEW_LEDS
+       select LEDS_CLASS
+       help
+         If you have a LCD backlight connected to the ADP8870,
+         say Y here to enable this driver.
+
+         To compile this driver as a module, choose M here: the module will
+         be called adp8870_bl.
+
 config BACKLIGHT_88PM860X
        tristate "Backlight Driver for 88PM8606 using WLED"
        depends on MFD_88PM860X
index b9ca8490df87850dc746e5a4661b67f5294589a4..ee72adb8786ed2f9f71de431987f0f5e11da7fc5 100644 (file)
@@ -34,6 +34,7 @@ obj-$(CONFIG_BACKLIGHT_WM831X)        += wm831x_bl.o
 obj-$(CONFIG_BACKLIGHT_ADX)    += adx_bl.o
 obj-$(CONFIG_BACKLIGHT_ADP5520)        += adp5520_bl.o
 obj-$(CONFIG_BACKLIGHT_ADP8860)        += adp8860_bl.o
+obj-$(CONFIG_BACKLIGHT_ADP8870)        += adp8870_bl.o
 obj-$(CONFIG_BACKLIGHT_88PM860X) += 88pm860x_bl.o
 obj-$(CONFIG_BACKLIGHT_PCF50633)       += pcf50633-backlight.o
 
diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c
new file mode 100644 (file)
index 0000000..05a8832
--- /dev/null
@@ -0,0 +1,1012 @@
+/*
+ * Backlight driver for Analog Devices ADP8870 Backlight Devices
+ *
+ * Copyright 2009-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pm.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/leds.h>
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+
+#include <linux/i2c/adp8870.h>
+#define ADP8870_EXT_FEATURES
+#define ADP8870_USE_LEDS
+
+
+#define ADP8870_MFDVID 0x00  /* Manufacturer and device ID */
+#define ADP8870_MDCR   0x01  /* Device mode and status */
+#define ADP8870_INT_STAT 0x02  /* Interrupts status */
+#define ADP8870_INT_EN 0x03  /* Interrupts enable */
+#define ADP8870_CFGR   0x04  /* Configuration register */
+#define ADP8870_BLSEL  0x05  /* Sink enable backlight or independent */
+#define ADP8870_PWMLED 0x06  /* PWM Enable Selection Register */
+#define ADP8870_BLOFF  0x07  /* Backlight off timeout */
+#define ADP8870_BLDIM  0x08  /* Backlight dim timeout */
+#define ADP8870_BLFR   0x09  /* Backlight fade in and out rates */
+#define ADP8870_BLMX1  0x0A  /* Backlight (Brightness Level 1-daylight) maximum current */
+#define ADP8870_BLDM1  0x0B  /* Backlight (Brightness Level 1-daylight) dim current */
+#define ADP8870_BLMX2  0x0C  /* Backlight (Brightness Level 2-bright) maximum current */
+#define ADP8870_BLDM2  0x0D  /* Backlight (Brightness Level 2-bright) dim current */
+#define ADP8870_BLMX3  0x0E  /* Backlight (Brightness Level 3-office) maximum current */
+#define ADP8870_BLDM3  0x0F  /* Backlight (Brightness Level 3-office) dim current */
+#define ADP8870_BLMX4  0x10  /* Backlight (Brightness Level 4-indoor) maximum current */
+#define ADP8870_BLDM4  0x11  /* Backlight (Brightness Level 4-indoor) dim current */
+#define ADP8870_BLMX5  0x12  /* Backlight (Brightness Level 5-dark) maximum current */
+#define ADP8870_BLDM5  0x13  /* Backlight (Brightness Level 5-dark) dim current */
+#define ADP8870_ISCLAW 0x1A  /* Independent sink current fade law register */
+#define ADP8870_ISCC   0x1B  /* Independent sink current control register */
+#define ADP8870_ISCT1  0x1C  /* Independent Sink Current Timer Register LED[7:5] */
+#define ADP8870_ISCT2  0x1D  /* Independent Sink Current Timer Register LED[4:1] */
+#define ADP8870_ISCF   0x1E  /* Independent sink current fade register */
+#define ADP8870_ISC1   0x1F  /* Independent Sink Current LED1 */
+#define ADP8870_ISC2   0x20  /* Independent Sink Current LED2 */
+#define ADP8870_ISC3   0x21  /* Independent Sink Current LED3 */
+#define ADP8870_ISC4   0x22  /* Independent Sink Current LED4 */
+#define ADP8870_ISC5   0x23  /* Independent Sink Current LED5 */
+#define ADP8870_ISC6   0x24  /* Independent Sink Current LED6 */
+#define ADP8870_ISC7   0x25  /* Independent Sink Current LED7 (Brightness Level 1-daylight) */
+#define ADP8870_ISC7_L2        0x26  /* Independent Sink Current LED7 (Brightness Level 2-bright) */
+#define ADP8870_ISC7_L3        0x27  /* Independent Sink Current LED7 (Brightness Level 3-office) */
+#define ADP8870_ISC7_L4        0x28  /* Independent Sink Current LED7 (Brightness Level 4-indoor) */
+#define ADP8870_ISC7_L5        0x29  /* Independent Sink Current LED7 (Brightness Level 5-dark) */
+#define ADP8870_CMP_CTL        0x2D  /* ALS Comparator Control Register */
+#define ADP8870_ALS1_EN        0x2E  /* Main ALS comparator level enable */
+#define ADP8870_ALS2_EN        0x2F  /* Second ALS comparator level enable */
+#define ADP8870_ALS1_STAT 0x30  /* Main ALS Comparator Status Register */
+#define ADP8870_ALS2_STAT 0x31  /* Second ALS Comparator Status Register */
+#define ADP8870_L2TRP  0x32  /* L2 comparator reference */
+#define ADP8870_L2HYS  0x33  /* L2 hysteresis */
+#define ADP8870_L3TRP  0x34  /* L3 comparator reference */
+#define ADP8870_L3HYS  0x35  /* L3 hysteresis */
+#define ADP8870_L4TRP  0x36  /* L4 comparator reference */
+#define ADP8870_L4HYS  0x37  /* L4 hysteresis */
+#define ADP8870_L5TRP  0x38  /* L5 comparator reference */
+#define ADP8870_L5HYS  0x39  /* L5 hysteresis */
+#define ADP8870_PH1LEVL        0x40  /* First phototransistor ambient light level-low byte register */
+#define ADP8870_PH1LEVH        0x41  /* First phototransistor ambient light level-high byte register */
+#define ADP8870_PH2LEVL        0x42  /* Second phototransistor ambient light level-low byte register */
+#define ADP8870_PH2LEVH        0x43  /* Second phototransistor ambient light level-high byte register */
+
+#define ADP8870_MANUFID                0x3  /* Analog Devices AD8870 Manufacturer and device ID */
+#define ADP8870_DEVID(x)       ((x) & 0xF)
+#define ADP8870_MANID(x)       ((x) >> 4)
+
+/* MDCR Device mode and status */
+#define D7ALSEN                        (1 << 7)
+#define INT_CFG                        (1 << 6)
+#define NSTBY                  (1 << 5)
+#define DIM_EN                 (1 << 4)
+#define GDWN_DIS               (1 << 3)
+#define SIS_EN                 (1 << 2)
+#define CMP_AUTOEN             (1 << 1)
+#define BLEN                   (1 << 0)
+
+/* ADP8870_ALS1_EN Main ALS comparator level enable */
+#define L5_EN                  (1 << 3)
+#define L4_EN                  (1 << 2)
+#define L3_EN                  (1 << 1)
+#define L2_EN                  (1 << 0)
+
+#define CFGR_BLV_SHIFT         3
+#define CFGR_BLV_MASK          0x7
+#define ADP8870_FLAG_LED_MASK  0xFF
+
+#define FADE_VAL(in, out)      ((0xF & (in)) | ((0xF & (out)) << 4))
+#define BL_CFGR_VAL(law, blv)  ((((blv) & CFGR_BLV_MASK) << CFGR_BLV_SHIFT) | ((0x3 & (law)) << 1))
+#define ALS_CMPR_CFG_VAL(filt) ((0x7 & (filt)) << 1)
+
+struct adp8870_bl {
+       struct i2c_client *client;
+       struct backlight_device *bl;
+       struct adp8870_led *led;
+       struct adp8870_backlight_platform_data *pdata;
+       struct mutex lock;
+       unsigned long cached_daylight_max;
+       int id;
+       int revid;
+       int current_brightness;
+};
+
+struct adp8870_led {
+       struct led_classdev     cdev;
+       struct work_struct      work;
+       struct i2c_client       *client;
+       enum led_brightness     new_brightness;
+       int                     id;
+       int                     flags;
+};
+
+static int adp8870_read(struct i2c_client *client, int reg, uint8_t *val)
+{
+       int ret;
+
+       ret = i2c_smbus_read_byte_data(client, reg);
+       if (ret < 0) {
+               dev_err(&client->dev, "failed reading at 0x%02x\n", reg);
+               return ret;
+       }
+
+       *val = ret;
+       return 0;
+}
+
+
+static int adp8870_write(struct i2c_client *client, u8 reg, u8 val)
+{
+       int ret = i2c_smbus_write_byte_data(client, reg, val);
+       if (ret)
+               dev_err(&client->dev, "failed to write\n");
+
+       return ret;
+}
+
+static int adp8870_set_bits(struct i2c_client *client, int reg, uint8_t bit_mask)
+{
+       struct adp8870_bl *data = i2c_get_clientdata(client);
+       uint8_t reg_val;
+       int ret;
+
+       mutex_lock(&data->lock);
+
+       ret = adp8870_read(client, reg, &reg_val);
+
+       if (!ret && ((reg_val & bit_mask) == 0)) {
+               reg_val |= bit_mask;
+               ret = adp8870_write(client, reg, reg_val);
+       }
+
+       mutex_unlock(&data->lock);
+       return ret;
+}
+
+static int adp8870_clr_bits(struct i2c_client *client, int reg, uint8_t bit_mask)
+{
+       struct adp8870_bl *data = i2c_get_clientdata(client);
+       uint8_t reg_val;
+       int ret;
+
+       mutex_lock(&data->lock);
+
+       ret = adp8870_read(client, reg, &reg_val);
+
+       if (!ret && (reg_val & bit_mask)) {
+               reg_val &= ~bit_mask;
+               ret = adp8870_write(client, reg, reg_val);
+       }
+
+       mutex_unlock(&data->lock);
+       return ret;
+}
+
+/*
+ * Independent sink / LED
+ */
+#if defined(ADP8870_USE_LEDS)
+static void adp8870_led_work(struct work_struct *work)
+{
+       struct adp8870_led *led = container_of(work, struct adp8870_led, work);
+       adp8870_write(led->client, ADP8870_ISC1 + led->id - 1,
+                        led->new_brightness >> 1);
+}
+
+static void adp8870_led_set(struct led_classdev *led_cdev,
+                          enum led_brightness value)
+{
+       struct adp8870_led *led;
+
+       led = container_of(led_cdev, struct adp8870_led, cdev);
+       led->new_brightness = value;
+       /*
+        * Use workqueue for IO since I2C operations can sleep.
+        */
+       schedule_work(&led->work);
+}
+
+static int adp8870_led_setup(struct adp8870_led *led)
+{
+       struct i2c_client *client = led->client;
+       int ret = 0;
+
+       ret = adp8870_write(client, ADP8870_ISC1 + led->id - 1, 0);
+       if (ret)
+               return ret;
+
+       ret = adp8870_set_bits(client, ADP8870_ISCC, 1 << (led->id - 1));
+       if (ret)
+               return ret;
+
+       if (led->id > 4)
+               ret = adp8870_set_bits(client, ADP8870_ISCT1,
+                               (led->flags & 0x3) << ((led->id - 5) * 2));
+       else
+               ret = adp8870_set_bits(client, ADP8870_ISCT2,
+                               (led->flags & 0x3) << ((led->id - 1) * 2));
+
+       return ret;
+}
+
+static int __devinit adp8870_led_probe(struct i2c_client *client)
+{
+       struct adp8870_backlight_platform_data *pdata =
+               client->dev.platform_data;
+       struct adp8870_bl *data = i2c_get_clientdata(client);
+       struct adp8870_led *led, *led_dat;
+       struct led_info *cur_led;
+       int ret, i;
+
+
+       led = kcalloc(pdata->num_leds, sizeof(*led), GFP_KERNEL);
+       if (led == NULL) {
+               dev_err(&client->dev, "failed to alloc memory\n");
+               return -ENOMEM;
+       }
+
+       ret = adp8870_write(client, ADP8870_ISCLAW, pdata->led_fade_law);
+       if (ret)
+               goto err_free;
+
+       ret = adp8870_write(client, ADP8870_ISCT1,
+                       (pdata->led_on_time & 0x3) << 6);
+       if (ret)
+               goto err_free;
+
+       ret = adp8870_write(client, ADP8870_ISCF,
+                       FADE_VAL(pdata->led_fade_in, pdata->led_fade_out));
+       if (ret)
+               goto err_free;
+
+       for (i = 0; i < pdata->num_leds; ++i) {
+               cur_led = &pdata->leds[i];
+               led_dat = &led[i];
+
+               led_dat->id = cur_led->flags & ADP8870_FLAG_LED_MASK;
+
+               if (led_dat->id > 7 || led_dat->id < 1) {
+                       dev_err(&client->dev, "Invalid LED ID %d\n",
+                               led_dat->id);
+                       goto err;
+               }
+
+               if (pdata->bl_led_assign & (1 << (led_dat->id - 1))) {
+                       dev_err(&client->dev, "LED %d used by Backlight\n",
+                               led_dat->id);
+                       goto err;
+               }
+
+               led_dat->cdev.name = cur_led->name;
+               led_dat->cdev.default_trigger = cur_led->default_trigger;
+               led_dat->cdev.brightness_set = adp8870_led_set;
+               led_dat->cdev.brightness = LED_OFF;
+               led_dat->flags = cur_led->flags >> FLAG_OFFT_SHIFT;
+               led_dat->client = client;
+               led_dat->new_brightness = LED_OFF;
+               INIT_WORK(&led_dat->work, adp8870_led_work);
+
+               ret = led_classdev_register(&client->dev, &led_dat->cdev);
+               if (ret) {
+                       dev_err(&client->dev, "failed to register LED %d\n",
+                               led_dat->id);
+                       goto err;
+               }
+
+               ret = adp8870_led_setup(led_dat);
+               if (ret) {
+                       dev_err(&client->dev, "failed to write\n");
+                       i++;
+                       goto err;
+               }
+       }
+
+       data->led = led;
+
+       return 0;
+
+ err:
+       for (i = i - 1; i >= 0; --i) {
+               led_classdev_unregister(&led[i].cdev);
+               cancel_work_sync(&led[i].work);
+       }
+
+ err_free:
+       kfree(led);
+
+       return ret;
+}
+
+static int __devexit adp8870_led_remove(struct i2c_client *client)
+{
+       struct adp8870_backlight_platform_data *pdata =
+               client->dev.platform_data;
+       struct adp8870_bl *data = i2c_get_clientdata(client);
+       int i;
+
+       for (i = 0; i < pdata->num_leds; i++) {
+               led_classdev_unregister(&data->led[i].cdev);
+               cancel_work_sync(&data->led[i].work);
+       }
+
+       kfree(data->led);
+       return 0;
+}
+#else
+static int __devinit adp8870_led_probe(struct i2c_client *client)
+{
+       return 0;
+}
+
+static int __devexit adp8870_led_remove(struct i2c_client *client)
+{
+       return 0;
+}
+#endif
+
+static int adp8870_bl_set(struct backlight_device *bl, int brightness)
+{
+       struct adp8870_bl *data = bl_get_data(bl);
+       struct i2c_client *client = data->client;
+       int ret = 0;
+
+       if (data->pdata->en_ambl_sens) {
+               if ((brightness > 0) && (brightness < ADP8870_MAX_BRIGHTNESS)) {
+                       /* Disable Ambient Light auto adjust */
+                       ret = adp8870_clr_bits(client, ADP8870_MDCR,
+                                       CMP_AUTOEN);
+                       if (ret)
+                               return ret;
+                       ret = adp8870_write(client, ADP8870_BLMX1, brightness);
+                       if (ret)
+                               return ret;
+               } else {
+                       /*
+                        * MAX_BRIGHTNESS -> Enable Ambient Light auto adjust
+                        * restore daylight l1 sysfs brightness
+                        */
+                       ret = adp8870_write(client, ADP8870_BLMX1,
+                                        data->cached_daylight_max);
+                       if (ret)
+                               return ret;
+
+                       ret = adp8870_set_bits(client, ADP8870_MDCR,
+                                        CMP_AUTOEN);
+                       if (ret)
+                               return ret;
+               }
+       } else {
+               ret = adp8870_write(client, ADP8870_BLMX1, brightness);
+               if (ret)
+                       return ret;
+       }
+
+       if (data->current_brightness && brightness == 0)
+               ret = adp8870_set_bits(client,
+                               ADP8870_MDCR, DIM_EN);
+       else if (data->current_brightness == 0 && brightness)
+               ret = adp8870_clr_bits(client,
+                               ADP8870_MDCR, DIM_EN);
+
+       if (!ret)
+               data->current_brightness = brightness;
+
+       return ret;
+}
+
+static int adp8870_bl_update_status(struct backlight_device *bl)
+{
+       int brightness = bl->props.brightness;
+       if (bl->props.power != FB_BLANK_UNBLANK)
+               brightness = 0;
+
+       if (bl->props.fb_blank != FB_BLANK_UNBLANK)
+               brightness = 0;
+
+       return adp8870_bl_set(bl, brightness);
+}
+
+static int adp8870_bl_get_brightness(struct backlight_device *bl)
+{
+       struct adp8870_bl *data = bl_get_data(bl);
+
+       return data->current_brightness;
+}
+
+static const struct backlight_ops adp8870_bl_ops = {
+       .update_status  = adp8870_bl_update_status,
+       .get_brightness = adp8870_bl_get_brightness,
+};
+
+static int adp8870_bl_setup(struct backlight_device *bl)
+{
+       struct adp8870_bl *data = bl_get_data(bl);
+       struct i2c_client *client = data->client;
+       struct adp8870_backlight_platform_data *pdata = data->pdata;
+       int ret = 0;
+
+       ret = adp8870_write(client, ADP8870_BLSEL, ~pdata->bl_led_assign);
+       if (ret)
+               return ret;
+
+       ret = adp8870_write(client, ADP8870_PWMLED, pdata->pwm_assign);
+       if (ret)
+               return ret;
+
+       ret = adp8870_write(client, ADP8870_BLMX1, pdata->l1_daylight_max);
+       if (ret)
+               return ret;
+
+       ret = adp8870_write(client, ADP8870_BLDM1, pdata->l1_daylight_dim);
+       if (ret)
+               return ret;
+
+       if (pdata->en_ambl_sens) {
+               data->cached_daylight_max = pdata->l1_daylight_max;
+               ret = adp8870_write(client, ADP8870_BLMX2,
+                                               pdata->l2_bright_max);
+               if (ret)
+                       return ret;
+               ret = adp8870_write(client, ADP8870_BLDM2,
+                                               pdata->l2_bright_dim);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_BLMX3,
+                                               pdata->l3_office_max);
+               if (ret)
+                       return ret;
+               ret = adp8870_write(client, ADP8870_BLDM3,
+                                               pdata->l3_office_dim);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_BLMX4,
+                                               pdata->l4_indoor_max);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_BLDM4,
+                                               pdata->l4_indor_dim);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_BLMX5,
+                                               pdata->l5_dark_max);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_BLDM5,
+                                               pdata->l5_dark_dim);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_L2TRP, pdata->l2_trip);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_L2HYS, pdata->l2_hyst);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_L3TRP, pdata->l3_trip);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_L3HYS, pdata->l3_hyst);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_L4TRP, pdata->l4_trip);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_L4HYS, pdata->l4_hyst);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_L5TRP, pdata->l5_trip);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_L5HYS, pdata->l5_hyst);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_ALS1_EN, L5_EN | L4_EN |
+                                               L3_EN | L2_EN);
+               if (ret)
+                       return ret;
+
+               ret = adp8870_write(client, ADP8870_CMP_CTL,
+                       ALS_CMPR_CFG_VAL(pdata->abml_filt));
+               if (ret)
+                       return ret;
+       }
+
+       ret = adp8870_write(client, ADP8870_CFGR,
+                       BL_CFGR_VAL(pdata->bl_fade_law, 0));
+       if (ret)
+               return ret;
+
+       ret = adp8870_write(client, ADP8870_BLFR, FADE_VAL(pdata->bl_fade_in,
+                       pdata->bl_fade_out));
+       if (ret)
+               return ret;
+       /*
+        * ADP8870 Rev0 requires GDWN_DIS bit set
+        */
+
+       ret = adp8870_set_bits(client, ADP8870_MDCR, BLEN | DIM_EN | NSTBY |
+                       (data->revid == 0 ? GDWN_DIS : 0));
+
+       return ret;
+}
+
+static ssize_t adp8870_show(struct device *dev, char *buf, int reg)
+{
+       struct adp8870_bl *data = dev_get_drvdata(dev);
+       int error;
+       uint8_t reg_val;
+
+       mutex_lock(&data->lock);
+       error = adp8870_read(data->client, reg, &reg_val);
+       mutex_unlock(&data->lock);
+
+       if (error < 0)
+               return error;
+
+       return sprintf(buf, "%u\n", reg_val);
+}
+
+static ssize_t adp8870_store(struct device *dev, const char *buf,
+                        size_t count, int reg)
+{
+       struct adp8870_bl *data = dev_get_drvdata(dev);
+       unsigned long val;
+       int ret;
+
+       ret = strict_strtoul(buf, 10, &val);
+       if (ret)
+               return ret;
+
+       mutex_lock(&data->lock);
+       adp8870_write(data->client, reg, val);
+       mutex_unlock(&data->lock);
+
+       return count;
+}
+
+static ssize_t adp8870_bl_l5_dark_max_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLMX5);
+}
+
+static ssize_t adp8870_bl_l5_dark_max_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLMX5);
+}
+static DEVICE_ATTR(l5_dark_max, 0664, adp8870_bl_l5_dark_max_show,
+                       adp8870_bl_l5_dark_max_store);
+
+
+static ssize_t adp8870_bl_l4_indoor_max_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLMX4);
+}
+
+static ssize_t adp8870_bl_l4_indoor_max_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLMX4);
+}
+static DEVICE_ATTR(l4_indoor_max, 0664, adp8870_bl_l4_indoor_max_show,
+                       adp8870_bl_l4_indoor_max_store);
+
+
+static ssize_t adp8870_bl_l3_office_max_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLMX3);
+}
+
+static ssize_t adp8870_bl_l3_office_max_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLMX3);
+}
+
+static DEVICE_ATTR(l3_office_max, 0664, adp8870_bl_l3_office_max_show,
+                       adp8870_bl_l3_office_max_store);
+
+static ssize_t adp8870_bl_l2_bright_max_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLMX2);
+}
+
+static ssize_t adp8870_bl_l2_bright_max_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLMX2);
+}
+static DEVICE_ATTR(l2_bright_max, 0664, adp8870_bl_l2_bright_max_show,
+                       adp8870_bl_l2_bright_max_store);
+
+static ssize_t adp8870_bl_l1_daylight_max_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLMX1);
+}
+
+static ssize_t adp8870_bl_l1_daylight_max_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct adp8870_bl *data = dev_get_drvdata(dev);
+       int ret = strict_strtoul(buf, 10, &data->cached_daylight_max);
+       if (ret)
+               return ret;
+
+       return adp8870_store(dev, buf, count, ADP8870_BLMX1);
+}
+static DEVICE_ATTR(l1_daylight_max, 0664, adp8870_bl_l1_daylight_max_show,
+                       adp8870_bl_l1_daylight_max_store);
+
+static ssize_t adp8870_bl_l5_dark_dim_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLDM5);
+}
+
+static ssize_t adp8870_bl_l5_dark_dim_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLDM5);
+}
+static DEVICE_ATTR(l5_dark_dim, 0664, adp8870_bl_l5_dark_dim_show,
+                       adp8870_bl_l5_dark_dim_store);
+
+static ssize_t adp8870_bl_l4_indoor_dim_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLDM4);
+}
+
+static ssize_t adp8870_bl_l4_indoor_dim_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLDM4);
+}
+static DEVICE_ATTR(l4_indoor_dim, 0664, adp8870_bl_l4_indoor_dim_show,
+                       adp8870_bl_l4_indoor_dim_store);
+
+
+static ssize_t adp8870_bl_l3_office_dim_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLDM3);
+}
+
+static ssize_t adp8870_bl_l3_office_dim_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLDM3);
+}
+static DEVICE_ATTR(l3_office_dim, 0664, adp8870_bl_l3_office_dim_show,
+                       adp8870_bl_l3_office_dim_store);
+
+static ssize_t adp8870_bl_l2_bright_dim_show(struct device *dev,
+                       struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLDM2);
+}
+
+static ssize_t adp8870_bl_l2_bright_dim_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLDM2);
+}
+static DEVICE_ATTR(l2_bright_dim, 0664, adp8870_bl_l2_bright_dim_show,
+                       adp8870_bl_l2_bright_dim_store);
+
+static ssize_t adp8870_bl_l1_daylight_dim_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       return adp8870_show(dev, buf, ADP8870_BLDM1);
+}
+
+static ssize_t adp8870_bl_l1_daylight_dim_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       return adp8870_store(dev, buf, count, ADP8870_BLDM1);
+}
+static DEVICE_ATTR(l1_daylight_dim, 0664, adp8870_bl_l1_daylight_dim_show,
+                       adp8870_bl_l1_daylight_dim_store);
+
+#ifdef ADP8870_EXT_FEATURES
+static ssize_t adp8870_bl_ambient_light_level_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       struct adp8870_bl *data = dev_get_drvdata(dev);
+       int error;
+       uint8_t reg_val;
+       uint16_t ret_val;
+
+       mutex_lock(&data->lock);
+       error = adp8870_read(data->client, ADP8870_PH1LEVL, &reg_val);
+       if (error < 0) {
+               mutex_unlock(&data->lock);
+               return error;
+       }
+       ret_val = reg_val;
+       error = adp8870_read(data->client, ADP8870_PH1LEVH, &reg_val);
+       mutex_unlock(&data->lock);
+
+       if (error < 0)
+               return error;
+
+       /* Return 13-bit conversion value for the first light sensor */
+       ret_val += (reg_val & 0x1F) << 8;
+
+       return sprintf(buf, "%u\n", ret_val);
+}
+static DEVICE_ATTR(ambient_light_level, 0444,
+               adp8870_bl_ambient_light_level_show, NULL);
+
+static ssize_t adp8870_bl_ambient_light_zone_show(struct device *dev,
+                                    struct device_attribute *attr, char *buf)
+{
+       struct adp8870_bl *data = dev_get_drvdata(dev);
+       int error;
+       uint8_t reg_val;
+
+       mutex_lock(&data->lock);
+       error = adp8870_read(data->client, ADP8870_CFGR, &reg_val);
+       mutex_unlock(&data->lock);
+
+       if (error < 0)
+               return error;
+
+       return sprintf(buf, "%u\n",
+               ((reg_val >> CFGR_BLV_SHIFT) & CFGR_BLV_MASK) + 1);
+}
+
+static ssize_t adp8870_bl_ambient_light_zone_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       struct adp8870_bl *data = dev_get_drvdata(dev);
+       unsigned long val;
+       uint8_t reg_val;
+       int ret;
+
+       ret = strict_strtoul(buf, 10, &val);
+       if (ret)
+               return ret;
+
+       if (val == 0) {
+               /* Enable automatic ambient light sensing */
+               adp8870_set_bits(data->client, ADP8870_MDCR, CMP_AUTOEN);
+       } else if ((val > 0) && (val < 6)) {
+               /* Disable automatic ambient light sensing */
+               adp8870_clr_bits(data->client, ADP8870_MDCR, CMP_AUTOEN);
+
+               /* Set user supplied ambient light zone */
+               mutex_lock(&data->lock);
+               adp8870_read(data->client, ADP8870_CFGR, &reg_val);
+               reg_val &= ~(CFGR_BLV_MASK << CFGR_BLV_SHIFT);
+               reg_val |= (val - 1) << CFGR_BLV_SHIFT;
+               adp8870_write(data->client, ADP8870_CFGR, reg_val);
+               mutex_unlock(&data->lock);
+       }
+
+       return count;
+}
+static DEVICE_ATTR(ambient_light_zone, 0664,
+               adp8870_bl_ambient_light_zone_show,
+               adp8870_bl_ambient_light_zone_store);
+#endif
+
+static struct attribute *adp8870_bl_attributes[] = {
+       &dev_attr_l5_dark_max.attr,
+       &dev_attr_l5_dark_dim.attr,
+       &dev_attr_l4_indoor_max.attr,
+       &dev_attr_l4_indoor_dim.attr,
+       &dev_attr_l3_office_max.attr,
+       &dev_attr_l3_office_dim.attr,
+       &dev_attr_l2_bright_max.attr,
+       &dev_attr_l2_bright_dim.attr,
+       &dev_attr_l1_daylight_max.attr,
+       &dev_attr_l1_daylight_dim.attr,
+#ifdef ADP8870_EXT_FEATURES
+       &dev_attr_ambient_light_level.attr,
+       &dev_attr_ambient_light_zone.attr,
+#endif
+       NULL
+};
+
+static const struct attribute_group adp8870_bl_attr_group = {
+       .attrs = adp8870_bl_attributes,
+};
+
+static int __devinit adp8870_probe(struct i2c_client *client,
+                                       const struct i2c_device_id *id)
+{
+       struct backlight_properties props;
+       struct backlight_device *bl;
+       struct adp8870_bl *data;
+       struct adp8870_backlight_platform_data *pdata =
+               client->dev.platform_data;
+       uint8_t reg_val;
+       int ret;
+
+       if (!i2c_check_functionality(client->adapter,
+                                       I2C_FUNC_SMBUS_BYTE_DATA)) {
+               dev_err(&client->dev, "SMBUS Byte Data not Supported\n");
+               return -EIO;
+       }
+
+       if (!pdata) {
+               dev_err(&client->dev, "no platform data?\n");
+               return -EINVAL;
+       }
+
+       ret = adp8870_read(client, ADP8870_MFDVID, &reg_val);
+       if (ret < 0)
+               return -EIO;
+
+       if (ADP8870_MANID(reg_val) != ADP8870_MANUFID) {
+               dev_err(&client->dev, "failed to probe\n");
+               return -ENODEV;
+       }
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (data == NULL)
+               return -ENOMEM;
+
+       data->revid = ADP8870_DEVID(reg_val);
+       data->client = client;
+       data->pdata = pdata;
+       data->id = id->driver_data;
+       data->current_brightness = 0;
+       i2c_set_clientdata(client, data);
+
+       mutex_init(&data->lock);
+
+       memset(&props, 0, sizeof(props));
+       props.type = BACKLIGHT_RAW;
+       props.max_brightness = props.brightness = ADP8870_MAX_BRIGHTNESS;
+       bl = backlight_device_register(dev_driver_string(&client->dev),
+                       &client->dev, data, &adp8870_bl_ops, &props);
+       if (IS_ERR(bl)) {
+               dev_err(&client->dev, "failed to register backlight\n");
+               ret = PTR_ERR(bl);
+               goto out2;
+       }
+
+       data->bl = bl;
+
+       if (pdata->en_ambl_sens)
+               ret = sysfs_create_group(&bl->dev.kobj,
+                       &adp8870_bl_attr_group);
+
+       if (ret) {
+               dev_err(&client->dev, "failed to register sysfs\n");
+               goto out1;
+       }
+
+       ret = adp8870_bl_setup(bl);
+       if (ret) {
+               ret = -EIO;
+               goto out;
+       }
+
+       backlight_update_status(bl);
+
+       dev_info(&client->dev, "Rev.%d Backlight\n", data->revid);
+
+       if (pdata->num_leds)
+               adp8870_led_probe(client);
+
+       return 0;
+
+out:
+       if (data->pdata->en_ambl_sens)
+               sysfs_remove_group(&data->bl->dev.kobj,
+                       &adp8870_bl_attr_group);
+out1:
+       backlight_device_unregister(bl);
+out2:
+       i2c_set_clientdata(client, NULL);
+       kfree(data);
+
+       return ret;
+}
+
+static int __devexit adp8870_remove(struct i2c_client *client)
+{
+       struct adp8870_bl *data = i2c_get_clientdata(client);
+
+       adp8870_clr_bits(client, ADP8870_MDCR, NSTBY);
+
+       if (data->led)
+               adp8870_led_remove(client);
+
+       if (data->pdata->en_ambl_sens)
+               sysfs_remove_group(&data->bl->dev.kobj,
+                       &adp8870_bl_attr_group);
+
+       backlight_device_unregister(data->bl);
+       i2c_set_clientdata(client, NULL);
+       kfree(data);
+
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int adp8870_i2c_suspend(struct i2c_client *client, pm_message_t message)
+{
+       adp8870_clr_bits(client, ADP8870_MDCR, NSTBY);
+
+       return 0;
+}
+
+static int adp8870_i2c_resume(struct i2c_client *client)
+{
+       adp8870_set_bits(client, ADP8870_MDCR, NSTBY);
+
+       return 0;
+}
+#else
+#define adp8870_i2c_suspend NULL
+#define adp8870_i2c_resume NULL
+#endif
+
+static const struct i2c_device_id adp8870_id[] = {
+       { "adp8870", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, adp8870_id);
+
+static struct i2c_driver adp8870_driver = {
+       .driver = {
+               .name = KBUILD_MODNAME,
+       },
+       .probe    = adp8870_probe,
+       .remove   = __devexit_p(adp8870_remove),
+       .suspend = adp8870_i2c_suspend,
+       .resume  = adp8870_i2c_resume,
+       .id_table = adp8870_id,
+};
+
+static int __init adp8870_init(void)
+{
+       return i2c_add_driver(&adp8870_driver);
+}
+module_init(adp8870_init);
+
+static void __exit adp8870_exit(void)
+{
+       i2c_del_driver(&adp8870_driver);
+}
+module_exit(adp8870_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>");
+MODULE_DESCRIPTION("ADP8870 Backlight driver");
+MODULE_ALIAS("platform:adp8870-backlight");
index 69c49dfce9cf93aa3c771dbf4af91f0669fea260..784139aed0793cab282cf52f3f3c3503a85a9a5a 100644 (file)
@@ -541,7 +541,7 @@ static int __init efifb_init(void)
         */
        ret = platform_driver_probe(&efifb_driver, efifb_probe);
        if (ret) {
-               platform_device_unregister(&efifb_driver);
+               platform_device_unregister(&efifb_device);
                return ret;
        }
 
index 0352afa49a392716762f7304cbdd00ae1770b396..4aecf213c9be46cb1f37ee38d231aabcf9d089d3 100644 (file)
@@ -235,13 +235,12 @@ static int s3c_fb_check_var(struct fb_var_screeninfo *var,
                            struct fb_info *info)
 {
        struct s3c_fb_win *win = info->par;
-       struct s3c_fb_pd_win *windata = win->windata;
        struct s3c_fb *sfb = win->parent;
 
        dev_dbg(sfb->dev, "checking parameters\n");
 
-       var->xres_virtual = max((unsigned int)windata->virtual_x, var->xres);
-       var->yres_virtual = max((unsigned int)windata->virtual_y, var->yres);
+       var->xres_virtual = max(var->xres_virtual, var->xres);
+       var->yres_virtual = max(var->yres_virtual, var->yres);
 
        if (!s3c_fb_validate_win_bpp(win, var->bits_per_pixel)) {
                dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n",
@@ -558,6 +557,13 @@ static int s3c_fb_set_par(struct fb_info *info)
        vidosd_set_alpha(win, alpha);
        vidosd_set_size(win, data);
 
+       /* Enable DMA channel for this window */
+       if (sfb->variant.has_shadowcon) {
+               data = readl(sfb->regs + SHADOWCON);
+               data |= SHADOWCON_CHx_ENABLE(win_no);
+               writel(data, sfb->regs + SHADOWCON);
+       }
+
        data = WINCONx_ENWIN;
 
        /* note, since we have to round up the bits-per-pixel, we end up
@@ -637,13 +643,6 @@ static int s3c_fb_set_par(struct fb_info *info)
        writel(data, regs + sfb->variant.wincon + (win_no * 4));
        writel(0x0, regs + sfb->variant.winmap + (win_no * 4));
 
-       /* Enable DMA channel for this window */
-       if (sfb->variant.has_shadowcon) {
-               data = readl(sfb->regs + SHADOWCON);
-               data |= SHADOWCON_CHx_ENABLE(win_no);
-               writel(data, sfb->regs + SHADOWCON);
-       }
-
        shadow_protect_win(win, 0);
 
        return 0;
@@ -1487,11 +1486,10 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev)
 
        release_mem_region(sfb->regs_res->start, resource_size(sfb->regs_res));
 
-       kfree(sfb);
-
        pm_runtime_put_sync(sfb->dev);
        pm_runtime_disable(sfb->dev);
 
+       kfree(sfb);
        return 0;
 }
 
index 6ae40b630dc9eb7c9c39641d4a0d2c27f7f1b1b3..7d54e2c612f774c292088507d24bba47e8d4f605 100644 (file)
@@ -1127,23 +1127,16 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
                struct fb_info *info = hdmi->info;
                unsigned long parent_rate = 0, hdmi_rate;
 
-               /* A device has been plugged in */
-               pm_runtime_get_sync(hdmi->dev);
-
                ret = sh_hdmi_read_edid(hdmi, &hdmi_rate, &parent_rate);
-               if (ret < 0) {
-                       pm_runtime_put(hdmi->dev);
+               if (ret < 0)
                        goto out;
-               }
 
                hdmi->hp_state = HDMI_HOTPLUG_EDID_DONE;
 
                /* Reconfigure the clock */
                ret = sh_hdmi_clk_configure(hdmi, hdmi_rate, parent_rate);
-               if (ret < 0) {
-                       pm_runtime_put(hdmi->dev);
+               if (ret < 0)
                        goto out;
-               }
 
                msleep(10);
                sh_hdmi_configure(hdmi);
@@ -1191,7 +1184,6 @@ static void sh_hdmi_edid_work_fn(struct work_struct *work)
                fb_set_suspend(hdmi->info, 1);
 
                console_unlock();
-               pm_runtime_put(hdmi->dev);
        }
 
 out:
@@ -1312,7 +1304,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
        INIT_DELAYED_WORK(&hdmi->edid_work, sh_hdmi_edid_work_fn);
 
        pm_runtime_enable(&pdev->dev);
-       pm_runtime_resume(&pdev->dev);
+       pm_runtime_get_sync(&pdev->dev);
 
        /* Product and revision IDs are 0 in sh-mobile version */
        dev_info(&pdev->dev, "Detected HDMI controller 0x%x:0x%x\n",
@@ -1340,7 +1332,7 @@ static int __init sh_hdmi_probe(struct platform_device *pdev)
 ecodec:
        free_irq(irq, hdmi);
 ereqirq:
-       pm_runtime_suspend(&pdev->dev);
+       pm_runtime_put(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
        iounmap(hdmi->base);
 emap:
@@ -1377,7 +1369,7 @@ static int __exit sh_hdmi_remove(struct platform_device *pdev)
        free_irq(irq, hdmi);
        /* Wait for already scheduled work */
        cancel_delayed_work_sync(&hdmi->edid_work);
-       pm_runtime_suspend(&pdev->dev);
+       pm_runtime_put(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
        clk_disable(hdmi->hdmi_clk);
        clk_put(hdmi->hdmi_clk);
index 00d615d7aa216d52387e8d67952851a42802a326..979d6eed9a0ff5178657ad5a36a1f203b87814b2 100644 (file)
@@ -42,7 +42,7 @@ config W1_MASTER_MXC
 
 config W1_MASTER_DS1WM
        tristate "Maxim DS1WM 1-wire busmaster"
-       depends on W1
+       depends on W1 && GENERIC_HARDIRQS
        help
          Say Y here to enable the DS1WM 1-wire driver, such as that
          in HP iPAQ devices like h5xxx, h2200, and ASIC3-based like
index 553da68bd510c8ef0c7fecc2f5676778d6525954..30df85d8fca860d69a75079951feb9bb725944f1 100644 (file)
@@ -395,9 +395,9 @@ static void unmask_evtchn(int port)
 static void xen_irq_init(unsigned irq)
 {
        struct irq_info *info;
+#ifdef CONFIG_SMP
        struct irq_desc *desc = irq_to_desc(irq);
 
-#ifdef CONFIG_SMP
        /* By default all event channels notify CPU#0. */
        cpumask_copy(desc->irq_data.affinity, cpumask_of(0));
 #endif
index 20c106f2492740f7de1615ee7712207b74a33828..1b0b19550015d2f19949b5b85d84556ecf7adb36 100644 (file)
@@ -584,11 +584,11 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
 
 success:
        d_add(dentry, inode);
-       _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%llu }",
+       _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%u }",
               fid.vnode,
               fid.unique,
               dentry->d_inode->i_ino,
-              (unsigned long long)dentry->d_inode->i_version);
+              dentry->d_inode->i_generation);
 
        return NULL;
 }
@@ -671,10 +671,10 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
                 * been deleted and replaced, and the original vnode ID has
                 * been reused */
                if (fid.unique != vnode->fid.unique) {
-                       _debug("%s: file deleted (uq %u -> %u I:%llu)",
+                       _debug("%s: file deleted (uq %u -> %u I:%u)",
                               dentry->d_name.name, fid.unique,
                               vnode->fid.unique,
-                              (unsigned long long)dentry->d_inode->i_version);
+                              dentry->d_inode->i_generation);
                        spin_lock(&vnode->lock);
                        set_bit(AFS_VNODE_DELETED, &vnode->flags);
                        spin_unlock(&vnode->lock);
index 4bd0218473a9bb407a9c86be49f0400461621f24..346e3289abd70549987ce9f490e1d8b210b66bd1 100644 (file)
@@ -89,7 +89,7 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
                        i_size_write(&vnode->vfs_inode, size);
                        vnode->vfs_inode.i_uid = status->owner;
                        vnode->vfs_inode.i_gid = status->group;
-                       vnode->vfs_inode.i_version = vnode->fid.unique;
+                       vnode->vfs_inode.i_generation = vnode->fid.unique;
                        vnode->vfs_inode.i_nlink = status->nlink;
 
                        mode = vnode->vfs_inode.i_mode;
@@ -102,6 +102,7 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp,
                vnode->vfs_inode.i_ctime.tv_sec = status->mtime_server;
                vnode->vfs_inode.i_mtime        = vnode->vfs_inode.i_ctime;
                vnode->vfs_inode.i_atime        = vnode->vfs_inode.i_ctime;
+               vnode->vfs_inode.i_version      = data_version;
        }
 
        expected_version = status->data_version;
index db66c5201474dc9b380ab21419fa61f7ff26fa78..0fdab6e03d8781d60ea7968c5c9886b555178dcd 100644 (file)
@@ -75,7 +75,8 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key)
        inode->i_ctime.tv_nsec  = 0;
        inode->i_atime          = inode->i_mtime = inode->i_ctime;
        inode->i_blocks         = 0;
-       inode->i_version        = vnode->fid.unique;
+       inode->i_generation     = vnode->fid.unique;
+       inode->i_version        = vnode->status.data_version;
        inode->i_mapping->a_ops = &afs_fs_aops;
 
        /* check to see whether a symbolic link is really a mountpoint */
@@ -100,7 +101,7 @@ static int afs_iget5_test(struct inode *inode, void *opaque)
        struct afs_iget_data *data = opaque;
 
        return inode->i_ino == data->fid.vnode &&
-               inode->i_version == data->fid.unique;
+               inode->i_generation == data->fid.unique;
 }
 
 /*
@@ -122,7 +123,7 @@ static int afs_iget5_set(struct inode *inode, void *opaque)
        struct afs_vnode *vnode = AFS_FS_I(inode);
 
        inode->i_ino = data->fid.vnode;
-       inode->i_version = data->fid.unique;
+       inode->i_generation = data->fid.unique;
        vnode->fid = data->fid;
        vnode->volume = data->volume;
 
@@ -380,8 +381,7 @@ int afs_getattr(struct vfsmount *mnt, struct dentry *dentry,
 
        inode = dentry->d_inode;
 
-       _enter("{ ino=%lu v=%llu }", inode->i_ino,
-               (unsigned long long)inode->i_version);
+       _enter("{ ino=%lu v=%u }", inode->i_ino, inode->i_generation);
 
        generic_fillattr(inode, stat);
        return 0;
index fb240e8766d63f7178374c40594881609201cae4..356dcf0929e8f0de36a166a2054e34c5ef3396c3 100644 (file)
@@ -31,8 +31,8 @@
 static void afs_i_init_once(void *foo);
 static struct dentry *afs_mount(struct file_system_type *fs_type,
                      int flags, const char *dev_name, void *data);
+static void afs_kill_super(struct super_block *sb);
 static struct inode *afs_alloc_inode(struct super_block *sb);
-static void afs_put_super(struct super_block *sb);
 static void afs_destroy_inode(struct inode *inode);
 static int afs_statfs(struct dentry *dentry, struct kstatfs *buf);
 
@@ -40,7 +40,7 @@ struct file_system_type afs_fs_type = {
        .owner          = THIS_MODULE,
        .name           = "afs",
        .mount          = afs_mount,
-       .kill_sb        = kill_anon_super,
+       .kill_sb        = afs_kill_super,
        .fs_flags       = 0,
 };
 
@@ -50,7 +50,6 @@ static const struct super_operations afs_super_ops = {
        .drop_inode     = afs_drop_inode,
        .destroy_inode  = afs_destroy_inode,
        .evict_inode    = afs_evict_inode,
-       .put_super      = afs_put_super,
        .show_options   = generic_show_options,
 };
 
@@ -282,19 +281,25 @@ static int afs_parse_device_name(struct afs_mount_params *params,
  */
 static int afs_test_super(struct super_block *sb, void *data)
 {
-       struct afs_mount_params *params = data;
+       struct afs_super_info *as1 = data;
        struct afs_super_info *as = sb->s_fs_info;
 
-       return as->volume == params->volume;
+       return as->volume == as1->volume;
+}
+
+static int afs_set_super(struct super_block *sb, void *data)
+{
+       sb->s_fs_info = data;
+       return set_anon_super(sb, NULL);
 }
 
 /*
  * fill in the superblock
  */
-static int afs_fill_super(struct super_block *sb, void *data)
+static int afs_fill_super(struct super_block *sb,
+                         struct afs_mount_params *params)
 {
-       struct afs_mount_params *params = data;
-       struct afs_super_info *as = NULL;
+       struct afs_super_info *as = sb->s_fs_info;
        struct afs_fid fid;
        struct dentry *root = NULL;
        struct inode *inode = NULL;
@@ -302,23 +307,13 @@ static int afs_fill_super(struct super_block *sb, void *data)
 
        _enter("");
 
-       /* allocate a superblock info record */
-       as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL);
-       if (!as) {
-               _leave(" = -ENOMEM");
-               return -ENOMEM;
-       }
-
-       afs_get_volume(params->volume);
-       as->volume = params->volume;
-
        /* fill in the superblock */
        sb->s_blocksize         = PAGE_CACHE_SIZE;
        sb->s_blocksize_bits    = PAGE_CACHE_SHIFT;
        sb->s_magic             = AFS_FS_MAGIC;
        sb->s_op                = &afs_super_ops;
-       sb->s_fs_info           = as;
        sb->s_bdi               = &as->volume->bdi;
+       strlcpy(sb->s_id, as->volume->vlocation->vldb.name, sizeof(sb->s_id));
 
        /* allocate the root inode and dentry */
        fid.vid         = as->volume->vid;
@@ -326,7 +321,7 @@ static int afs_fill_super(struct super_block *sb, void *data)
        fid.unique      = 1;
        inode = afs_iget(sb, params->key, &fid, NULL, NULL);
        if (IS_ERR(inode))
-               goto error_inode;
+               return PTR_ERR(inode);
 
        if (params->autocell)
                set_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(inode)->flags);
@@ -342,16 +337,8 @@ static int afs_fill_super(struct super_block *sb, void *data)
        _leave(" = 0");
        return 0;
 
-error_inode:
-       ret = PTR_ERR(inode);
-       inode = NULL;
 error:
        iput(inode);
-       afs_put_volume(as->volume);
-       kfree(as);
-
-       sb->s_fs_info = NULL;
-
        _leave(" = %d", ret);
        return ret;
 }
@@ -367,6 +354,7 @@ static struct dentry *afs_mount(struct file_system_type *fs_type,
        struct afs_volume *vol;
        struct key *key;
        char *new_opts = kstrdup(options, GFP_KERNEL);
+       struct afs_super_info *as;
        int ret;
 
        _enter(",,%s,%p", dev_name, options);
@@ -399,12 +387,22 @@ static struct dentry *afs_mount(struct file_system_type *fs_type,
                ret = PTR_ERR(vol);
                goto error;
        }
-       params.volume = vol;
+
+       /* allocate a superblock info record */
+       as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL);
+       if (!as) {
+               ret = -ENOMEM;
+               afs_put_volume(vol);
+               goto error;
+       }
+       as->volume = vol;
 
        /* allocate a deviceless superblock */
-       sb = sget(fs_type, afs_test_super, set_anon_super, &params);
+       sb = sget(fs_type, afs_test_super, afs_set_super, as);
        if (IS_ERR(sb)) {
                ret = PTR_ERR(sb);
+               afs_put_volume(vol);
+               kfree(as);
                goto error;
        }
 
@@ -422,16 +420,16 @@ static struct dentry *afs_mount(struct file_system_type *fs_type,
        } else {
                _debug("reuse");
                ASSERTCMP(sb->s_flags, &, MS_ACTIVE);
+               afs_put_volume(vol);
+               kfree(as);
        }
 
-       afs_put_volume(params.volume);
        afs_put_cell(params.cell);
        kfree(new_opts);
        _leave(" = 0 [%p]", sb);
        return dget(sb->s_root);
 
 error:
-       afs_put_volume(params.volume);
        afs_put_cell(params.cell);
        key_put(params.key);
        kfree(new_opts);
@@ -439,18 +437,12 @@ error:
        return ERR_PTR(ret);
 }
 
-/*
- * finish the unmounting process on the superblock
- */
-static void afs_put_super(struct super_block *sb)
+static void afs_kill_super(struct super_block *sb)
 {
        struct afs_super_info *as = sb->s_fs_info;
-
-       _enter("");
-
+       kill_anon_super(sb);
        afs_put_volume(as->volume);
-
-       _leave("");
+       kfree(as);
 }
 
 /*
index 789b3afb342328dcfe551d39227a81f09ffb3470..b806285ff85304bf71032c4b64cc3fb3cf49dda0 100644 (file)
@@ -84,23 +84,21 @@ void afs_put_writeback(struct afs_writeback *wb)
  * partly or wholly fill a page that's under preparation for writing
  */
 static int afs_fill_page(struct afs_vnode *vnode, struct key *key,
-                        loff_t pos, unsigned len, struct page *page)
+                        loff_t pos, struct page *page)
 {
        loff_t i_size;
-       unsigned eof;
        int ret;
+       int len;
 
-       _enter(",,%llu,%u", (unsigned long long)pos, len);
-
-       ASSERTCMP(len, <=, PAGE_CACHE_SIZE);
+       _enter(",,%llu", (unsigned long long)pos);
 
        i_size = i_size_read(&vnode->vfs_inode);
-       if (pos + len > i_size)
-               eof = i_size;
+       if (pos + PAGE_CACHE_SIZE > i_size)
+               len = i_size - pos;
        else
-               eof = PAGE_CACHE_SIZE;
+               len = PAGE_CACHE_SIZE;
 
-       ret = afs_vnode_fetch_data(vnode, key, 0, eof, page);
+       ret = afs_vnode_fetch_data(vnode, key, pos, len, page);
        if (ret < 0) {
                if (ret == -ENOENT) {
                        _debug("got NOENT from server"
@@ -153,9 +151,8 @@ int afs_write_begin(struct file *file, struct address_space *mapping,
        *pagep = page;
        /* page won't leak in error case: it eventually gets cleaned off LRU */
 
-       if (!PageUptodate(page)) {
-               _debug("not up to date");
-               ret = afs_fill_page(vnode, key, pos, len, page);
+       if (!PageUptodate(page) && len != PAGE_CACHE_SIZE) {
+               ret = afs_fill_page(vnode, key, index << PAGE_CACHE_SHIFT, page);
                if (ret < 0) {
                        kfree(candidate);
                        _leave(" = %d [prep]", ret);
index 9ad2369d9e35e0651885a78dc3648ef9dbe8c412..bfcb18feb1df32b91a9db144f3f74f5873c85866 100644 (file)
@@ -231,9 +231,6 @@ static int bad_inode_readlink(struct dentry *dentry, char __user *buffer,
 
 static int bad_inode_permission(struct inode *inode, int mask, unsigned int flags)
 {
-       if (flags & IPERM_FLAG_RCU)
-               return -ECHILD;
-
        return -EIO;
 }
 
index 1a2421f908f0a471f028d7e0f320caeed18592bd..610e8e0b04b88946721eb58b78791bab0e72440b 100644 (file)
@@ -762,7 +762,19 @@ static struct block_device *bd_start_claiming(struct block_device *bdev,
        if (!disk)
                return ERR_PTR(-ENXIO);
 
-       whole = bdget_disk(disk, 0);
+       /*
+        * Normally, @bdev should equal what's returned from bdget_disk()
+        * if partno is 0; however, some drivers (floppy) use multiple
+        * bdev's for the same physical device and @bdev may be one of the
+        * aliases.  Keep @bdev if partno is 0.  This means claimer
+        * tracking is broken for those devices but it has always been that
+        * way.
+        */
+       if (partno)
+               whole = bdget_disk(disk, 0);
+       else
+               whole = bdgrab(bdev);
+
        module_put(disk->fops->owner);
        put_disk(disk);
        if (!whole)
index 378b5b4443f3a6991e1313d4009b89160d16539e..f30ac05dbda7d1a60048aee7422026754b49b885 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef __BTRFS_CTREE__
 #define __BTRFS_CTREE__
 
-#include <linux/version.h>
 #include <linux/mm.h>
 #include <linux/highmem.h>
 #include <linux/fs.h>
@@ -967,6 +966,12 @@ struct btrfs_fs_info {
        struct srcu_struct subvol_srcu;
 
        spinlock_t trans_lock;
+       /*
+        * the reloc mutex goes with the trans lock, it is taken
+        * during commit to protect us from the relocation code
+        */
+       struct mutex reloc_mutex;
+
        struct list_head trans_list;
        struct list_head hashers;
        struct list_head dead_roots;
@@ -1172,6 +1177,14 @@ struct btrfs_root {
        u32 type;
 
        u64 highest_objectid;
+
+       /* btrfs_record_root_in_trans is a multi-step process,
+        * and it can race with the balancing code.   But the
+        * race is very small, and only the first time the root
+        * is added to each transaction.  So in_trans_setup
+        * is used to tell us when more checks are required
+        */
+       unsigned long in_trans_setup;
        int ref_cows;
        int track_dirty;
        int in_radix;
@@ -1181,7 +1194,6 @@ struct btrfs_root {
        struct btrfs_key defrag_max;
        int defrag_running;
        char *name;
-       int in_sysfs;
 
        /* the dirty list is only used by non-reference counted roots */
        struct list_head dirty_list;
index 6462c29d2d37fcc8ec779f1d6d3b6817003a68c2..98c68e658a9b2eb08a8ba99d0b5691f16fc8a67d 100644 (file)
@@ -82,19 +82,16 @@ static inline struct btrfs_delayed_root *btrfs_get_delayed_root(
        return root->fs_info->delayed_root;
 }
 
-static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node(
-                                                       struct inode *inode)
+static struct btrfs_delayed_node *btrfs_get_delayed_node(struct inode *inode)
 {
-       struct btrfs_delayed_node *node;
        struct btrfs_inode *btrfs_inode = BTRFS_I(inode);
        struct btrfs_root *root = btrfs_inode->root;
        u64 ino = btrfs_ino(inode);
-       int ret;
+       struct btrfs_delayed_node *node;
 
-again:
        node = ACCESS_ONCE(btrfs_inode->delayed_node);
        if (node) {
-               atomic_inc(&node->refs);        /* can be accessed */
+               atomic_inc(&node->refs);
                return node;
        }
 
@@ -102,8 +99,10 @@ again:
        node = radix_tree_lookup(&root->delayed_nodes_tree, ino);
        if (node) {
                if (btrfs_inode->delayed_node) {
+                       atomic_inc(&node->refs);        /* can be accessed */
+                       BUG_ON(btrfs_inode->delayed_node != node);
                        spin_unlock(&root->inode_lock);
-                       goto again;
+                       return node;
                }
                btrfs_inode->delayed_node = node;
                atomic_inc(&node->refs);        /* can be accessed */
@@ -113,6 +112,23 @@ again:
        }
        spin_unlock(&root->inode_lock);
 
+       return NULL;
+}
+
+static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node(
+                                                       struct inode *inode)
+{
+       struct btrfs_delayed_node *node;
+       struct btrfs_inode *btrfs_inode = BTRFS_I(inode);
+       struct btrfs_root *root = btrfs_inode->root;
+       u64 ino = btrfs_ino(inode);
+       int ret;
+
+again:
+       node = btrfs_get_delayed_node(inode);
+       if (node)
+               return node;
+
        node = kmem_cache_alloc(delayed_node_cache, GFP_NOFS);
        if (!node)
                return ERR_PTR(-ENOMEM);
@@ -297,7 +313,6 @@ struct btrfs_delayed_item *btrfs_alloc_delayed_item(u32 data_len)
                item->data_len = data_len;
                item->ins_or_del = 0;
                item->bytes_reserved = 0;
-               item->block_rsv = NULL;
                item->delayed_node = NULL;
                atomic_set(&item->refs, 1);
        }
@@ -549,19 +564,6 @@ struct btrfs_delayed_item *__btrfs_next_delayed_item(
        return next;
 }
 
-static inline struct btrfs_delayed_node *btrfs_get_delayed_node(
-                                                       struct inode *inode)
-{
-       struct btrfs_inode *btrfs_inode = BTRFS_I(inode);
-       struct btrfs_delayed_node *delayed_node;
-
-       delayed_node = btrfs_inode->delayed_node;
-       if (delayed_node)
-               atomic_inc(&delayed_node->refs);
-
-       return delayed_node;
-}
-
 static inline struct btrfs_root *btrfs_get_fs_root(struct btrfs_root *root,
                                                   u64 root_id)
 {
@@ -593,10 +595,8 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans,
 
        num_bytes = btrfs_calc_trans_metadata_size(root, 1);
        ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes);
-       if (!ret) {
+       if (!ret)
                item->bytes_reserved = num_bytes;
-               item->block_rsv = dst_rsv;
-       }
 
        return ret;
 }
@@ -604,10 +604,13 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans,
 static void btrfs_delayed_item_release_metadata(struct btrfs_root *root,
                                                struct btrfs_delayed_item *item)
 {
+       struct btrfs_block_rsv *rsv;
+
        if (!item->bytes_reserved)
                return;
 
-       btrfs_block_rsv_release(root, item->block_rsv,
+       rsv = &root->fs_info->global_block_rsv;
+       btrfs_block_rsv_release(root, rsv,
                                item->bytes_reserved);
 }
 
@@ -1014,6 +1017,7 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
        struct btrfs_delayed_root *delayed_root;
        struct btrfs_delayed_node *curr_node, *prev_node;
        struct btrfs_path *path;
+       struct btrfs_block_rsv *block_rsv;
        int ret = 0;
 
        path = btrfs_alloc_path();
@@ -1021,6 +1025,9 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
                return -ENOMEM;
        path->leave_spinning = 1;
 
+       block_rsv = trans->block_rsv;
+       trans->block_rsv = &root->fs_info->global_block_rsv;
+
        delayed_root = btrfs_get_delayed_root(root);
 
        curr_node = btrfs_first_delayed_node(delayed_root);
@@ -1045,6 +1052,7 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans,
        }
 
        btrfs_free_path(path);
+       trans->block_rsv = block_rsv;
        return ret;
 }
 
@@ -1052,6 +1060,7 @@ static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans,
                                              struct btrfs_delayed_node *node)
 {
        struct btrfs_path *path;
+       struct btrfs_block_rsv *block_rsv;
        int ret;
 
        path = btrfs_alloc_path();
@@ -1059,6 +1068,9 @@ static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans,
                return -ENOMEM;
        path->leave_spinning = 1;
 
+       block_rsv = trans->block_rsv;
+       trans->block_rsv = &node->root->fs_info->global_block_rsv;
+
        ret = btrfs_insert_delayed_items(trans, path, node->root, node);
        if (!ret)
                ret = btrfs_delete_delayed_items(trans, path, node->root, node);
@@ -1066,6 +1078,7 @@ static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans,
                ret = btrfs_update_delayed_inode(trans, node->root, path, node);
        btrfs_free_path(path);
 
+       trans->block_rsv = block_rsv;
        return ret;
 }
 
@@ -1116,6 +1129,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work)
        struct btrfs_path *path;
        struct btrfs_delayed_node *delayed_node = NULL;
        struct btrfs_root *root;
+       struct btrfs_block_rsv *block_rsv;
        unsigned long nr = 0;
        int need_requeue = 0;
        int ret;
@@ -1134,6 +1148,9 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work)
        if (IS_ERR(trans))
                goto free_path;
 
+       block_rsv = trans->block_rsv;
+       trans->block_rsv = &root->fs_info->global_block_rsv;
+
        ret = btrfs_insert_delayed_items(trans, path, root, delayed_node);
        if (!ret)
                ret = btrfs_delete_delayed_items(trans, path, root,
@@ -1176,6 +1193,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work)
 
        nr = trans->blocks_used;
 
+       trans->block_rsv = block_rsv;
        btrfs_end_transaction_dmeta(trans, root);
        __btrfs_btree_balance_dirty(root, nr);
 free_path:
@@ -1222,6 +1240,13 @@ again:
        return 0;
 }
 
+void btrfs_assert_delayed_root_empty(struct btrfs_root *root)
+{
+       struct btrfs_delayed_root *delayed_root;
+       delayed_root = btrfs_get_delayed_root(root);
+       WARN_ON(btrfs_first_delayed_node(delayed_root));
+}
+
 void btrfs_balance_delayed_items(struct btrfs_root *root)
 {
        struct btrfs_delayed_root *delayed_root;
@@ -1382,8 +1407,7 @@ end:
 
 int btrfs_inode_delayed_dir_index_count(struct inode *inode)
 {
-       struct btrfs_delayed_node *delayed_node = BTRFS_I(inode)->delayed_node;
-       int ret = 0;
+       struct btrfs_delayed_node *delayed_node = btrfs_get_delayed_node(inode);
 
        if (!delayed_node)
                return -ENOENT;
@@ -1393,11 +1417,14 @@ int btrfs_inode_delayed_dir_index_count(struct inode *inode)
         * a new directory index is added into the delayed node and index_cnt
         * is updated now. So we needn't lock the delayed node.
         */
-       if (!delayed_node->index_cnt)
+       if (!delayed_node->index_cnt) {
+               btrfs_release_delayed_node(delayed_node);
                return -EINVAL;
+       }
 
        BTRFS_I(inode)->index_cnt = delayed_node->index_cnt;
-       return ret;
+       btrfs_release_delayed_node(delayed_node);
+       return 0;
 }
 
 void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list,
@@ -1591,6 +1618,57 @@ static void fill_stack_inode_item(struct btrfs_trans_handle *trans,
                                      inode->i_ctime.tv_nsec);
 }
 
+int btrfs_fill_inode(struct inode *inode, u32 *rdev)
+{
+       struct btrfs_delayed_node *delayed_node;
+       struct btrfs_inode_item *inode_item;
+       struct btrfs_timespec *tspec;
+
+       delayed_node = btrfs_get_delayed_node(inode);
+       if (!delayed_node)
+               return -ENOENT;
+
+       mutex_lock(&delayed_node->mutex);
+       if (!delayed_node->inode_dirty) {
+               mutex_unlock(&delayed_node->mutex);
+               btrfs_release_delayed_node(delayed_node);
+               return -ENOENT;
+       }
+
+       inode_item = &delayed_node->inode_item;
+
+       inode->i_uid = btrfs_stack_inode_uid(inode_item);
+       inode->i_gid = btrfs_stack_inode_gid(inode_item);
+       btrfs_i_size_write(inode, btrfs_stack_inode_size(inode_item));
+       inode->i_mode = btrfs_stack_inode_mode(inode_item);
+       inode->i_nlink = btrfs_stack_inode_nlink(inode_item);
+       inode_set_bytes(inode, btrfs_stack_inode_nbytes(inode_item));
+       BTRFS_I(inode)->generation = btrfs_stack_inode_generation(inode_item);
+       BTRFS_I(inode)->sequence = btrfs_stack_inode_sequence(inode_item);
+       inode->i_rdev = 0;
+       *rdev = btrfs_stack_inode_rdev(inode_item);
+       BTRFS_I(inode)->flags = btrfs_stack_inode_flags(inode_item);
+
+       tspec = btrfs_inode_atime(inode_item);
+       inode->i_atime.tv_sec = btrfs_stack_timespec_sec(tspec);
+       inode->i_atime.tv_nsec = btrfs_stack_timespec_nsec(tspec);
+
+       tspec = btrfs_inode_mtime(inode_item);
+       inode->i_mtime.tv_sec = btrfs_stack_timespec_sec(tspec);
+       inode->i_mtime.tv_nsec = btrfs_stack_timespec_nsec(tspec);
+
+       tspec = btrfs_inode_ctime(inode_item);
+       inode->i_ctime.tv_sec = btrfs_stack_timespec_sec(tspec);
+       inode->i_ctime.tv_nsec = btrfs_stack_timespec_nsec(tspec);
+
+       inode->i_generation = BTRFS_I(inode)->generation;
+       BTRFS_I(inode)->index_cnt = (u64)-1;
+
+       mutex_unlock(&delayed_node->mutex);
+       btrfs_release_delayed_node(delayed_node);
+       return 0;
+}
+
 int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans,
                               struct btrfs_root *root, struct inode *inode)
 {
index eb7d240aa6485db61c8d13299519abc9b81d3cc0..8d27af4bd8b99f00f073d18125589fa39e2269fa 100644 (file)
@@ -75,7 +75,6 @@ struct btrfs_delayed_item {
        struct list_head tree_list;     /* used for batch insert/delete items */
        struct list_head readdir_list;  /* used for readdir items */
        u64 bytes_reserved;
-       struct btrfs_block_rsv *block_rsv;
        struct btrfs_delayed_node *delayed_node;
        atomic_t refs;
        int ins_or_del;
@@ -120,6 +119,7 @@ void btrfs_kill_delayed_inode_items(struct inode *inode);
 
 int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans,
                               struct btrfs_root *root, struct inode *inode);
+int btrfs_fill_inode(struct inode *inode, u32 *rdev);
 
 /* Used for drop dead root */
 void btrfs_kill_all_delayed_nodes(struct btrfs_root *root);
@@ -138,4 +138,8 @@ int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent,
 /* for init */
 int __init btrfs_delayed_inode_init(void);
 void btrfs_delayed_inode_exit(void);
+
+/* for debugging */
+void btrfs_assert_delayed_root_empty(struct btrfs_root *root);
+
 #endif
index 9f68c68986535fbdbd21f01abad64906e19fde68..1ac8db5dc0a31b9a742099956b121cd75ba0a1a6 100644 (file)
@@ -1044,7 +1044,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
        root->last_trans = 0;
        root->highest_objectid = 0;
        root->name = NULL;
-       root->in_sysfs = 0;
        root->inode_tree = RB_ROOT;
        INIT_RADIX_TREE(&root->delayed_nodes_tree, GFP_ATOMIC);
        root->block_rsv = NULL;
@@ -1300,19 +1299,21 @@ again:
                return root;
 
        root->free_ino_ctl = kzalloc(sizeof(*root->free_ino_ctl), GFP_NOFS);
-       if (!root->free_ino_ctl)
-               goto fail;
        root->free_ino_pinned = kzalloc(sizeof(*root->free_ino_pinned),
                                        GFP_NOFS);
-       if (!root->free_ino_pinned)
+       if (!root->free_ino_pinned || !root->free_ino_ctl) {
+               ret = -ENOMEM;
                goto fail;
+       }
 
        btrfs_init_free_ino_ctl(root);
        mutex_init(&root->fs_commit_mutex);
        spin_lock_init(&root->cache_lock);
        init_waitqueue_head(&root->cache_wait);
 
-       set_anon_super(&root->anon_super, NULL);
+       ret = set_anon_super(&root->anon_super, NULL);
+       if (ret)
+               goto fail;
 
        if (btrfs_root_refs(&root->root_item) == 0) {
                ret = -ENOENT;
@@ -1618,6 +1619,7 @@ struct btrfs_root *open_ctree(struct super_block *sb,
        spin_lock_init(&fs_info->fs_roots_radix_lock);
        spin_lock_init(&fs_info->delayed_iput_lock);
        spin_lock_init(&fs_info->defrag_inodes_lock);
+       mutex_init(&fs_info->reloc_mutex);
 
        init_completion(&fs_info->kobj_unregister);
        fs_info->tree_root = tree_root;
index b42efc2ded513ec10c38eb7ebcee9247d2f2c825..71cd456fdb60360d44edd113ab7c593bdacfa658 100644 (file)
@@ -3314,10 +3314,6 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans,
        if (reserved == 0)
                return 0;
 
-       /* nothing to shrink - nothing to reclaim */
-       if (root->fs_info->delalloc_bytes == 0)
-               return 0;
-
        max_reclaim = min(reserved, to_reclaim);
 
        while (loops < 1024) {
@@ -4846,7 +4842,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
                                     u64 num_bytes, u64 empty_size,
                                     u64 search_start, u64 search_end,
                                     u64 hint_byte, struct btrfs_key *ins,
-                                    int data)
+                                    u64 data)
 {
        int ret = 0;
        struct btrfs_root *root = orig_root->fs_info->extent_root;
@@ -4873,7 +4869,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans,
 
        space_info = __find_space_info(root->fs_info, data);
        if (!space_info) {
-               printk(KERN_ERR "No space info for %d\n", data);
+               printk(KERN_ERR "No space info for %llu\n", data);
                return -ENOSPC;
        }
 
index 9f985a429877fdd5d04100514f3ff4a5f2abeb18..bf0d61567f3d65a24e9d11802acdd0c8c5abf32b 100644 (file)
@@ -1893,9 +1893,12 @@ void __btrfs_remove_free_space_cache_locked(struct btrfs_free_space_ctl *ctl)
 
        while ((node = rb_last(&ctl->free_space_offset)) != NULL) {
                info = rb_entry(node, struct btrfs_free_space, offset_index);
-               unlink_free_space(ctl, info);
-               kfree(info->bitmap);
-               kmem_cache_free(btrfs_free_space_cachep, info);
+               if (!info->bitmap) {
+                       unlink_free_space(ctl, info);
+                       kmem_cache_free(btrfs_free_space_cachep, info);
+               } else {
+                       free_bitmap(ctl, info);
+               }
                if (need_resched()) {
                        spin_unlock(&ctl->tree_lock);
                        cond_resched();
index 751ddf8fc58a152fd442979cb758637cbcf01bc0..d340f63d8f07b2cf7c0e087fdf92ba384e31662e 100644 (file)
@@ -2509,6 +2509,11 @@ static void btrfs_read_locked_inode(struct inode *inode)
        int maybe_acls;
        u32 rdev;
        int ret;
+       bool filled = false;
+
+       ret = btrfs_fill_inode(inode, &rdev);
+       if (!ret)
+               filled = true;
 
        path = btrfs_alloc_path();
        BUG_ON(!path);
@@ -2520,6 +2525,10 @@ static void btrfs_read_locked_inode(struct inode *inode)
                goto make_bad;
 
        leaf = path->nodes[0];
+
+       if (filled)
+               goto cache_acl;
+
        inode_item = btrfs_item_ptr(leaf, path->slots[0],
                                    struct btrfs_inode_item);
        if (!leaf->map_token)
@@ -2556,7 +2565,7 @@ static void btrfs_read_locked_inode(struct inode *inode)
 
        BTRFS_I(inode)->index_cnt = (u64)-1;
        BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item);
-
+cache_acl:
        /*
         * try to precache a NULL acl entry for files that don't have
         * any xattrs or acls
@@ -2572,7 +2581,6 @@ static void btrfs_read_locked_inode(struct inode *inode)
        }
 
        btrfs_free_path(path);
-       inode_item = NULL;
 
        switch (inode->i_mode & S_IFMT) {
        case S_IFREG:
@@ -3076,6 +3084,7 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
        ret = btrfs_update_inode(trans, root, dir);
        BUG_ON(ret);
 
+       btrfs_free_path(path);
        return 0;
 }
 
@@ -4519,6 +4528,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
        inode_tree_add(inode);
 
        trace_btrfs_inode_new(inode);
+       btrfs_set_inode_last_trans(trans, inode);
 
        return inode;
 fail:
index b793d112d1f65c80b95e06be70233cd5f5aa2654..a3c4751e07db0d7704e8ac1aa3269d7c75e3c48a 100644 (file)
@@ -482,8 +482,10 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry,
        ret = btrfs_snap_reserve_metadata(trans, pending_snapshot);
        BUG_ON(ret);
 
+       spin_lock(&root->fs_info->trans_lock);
        list_add(&pending_snapshot->list,
                 &trans->transaction->pending_snapshots);
+       spin_unlock(&root->fs_info->trans_lock);
        if (async_transid) {
                *async_transid = trans->transid;
                ret = btrfs_commit_transaction_async(trans,
index b1ef27cc673b8abc9e135b05e0da24ff7a0c7bb2..5e0a3dc79a453f3930e9c749c1cf08c63e5c7c6a 100644 (file)
@@ -1368,7 +1368,7 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
        int ret;
 
        if (!root->reloc_root)
-               return 0;
+               goto out;
 
        reloc_root = root->reloc_root;
        root_item = &reloc_root->root_item;
@@ -1390,6 +1390,8 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
        ret = btrfs_update_root(trans, root->fs_info->tree_root,
                                &reloc_root->root_key, root_item);
        BUG_ON(ret);
+
+out:
        return 0;
 }
 
@@ -2142,10 +2144,11 @@ int prepare_to_merge(struct reloc_control *rc, int err)
        u64 num_bytes = 0;
        int ret;
 
-       spin_lock(&root->fs_info->trans_lock);
+       mutex_lock(&root->fs_info->reloc_mutex);
        rc->merging_rsv_size += root->nodesize * (BTRFS_MAX_LEVEL - 1) * 2;
        rc->merging_rsv_size += rc->nodes_relocated * 2;
-       spin_unlock(&root->fs_info->trans_lock);
+       mutex_unlock(&root->fs_info->reloc_mutex);
+
 again:
        if (!err) {
                num_bytes = rc->merging_rsv_size;
@@ -2214,9 +2217,16 @@ int merge_reloc_roots(struct reloc_control *rc)
        int ret;
 again:
        root = rc->extent_root;
-       spin_lock(&root->fs_info->trans_lock);
+
+       /*
+        * this serializes us with btrfs_record_root_in_transaction,
+        * we have to make sure nobody is in the middle of
+        * adding their roots to the list while we are
+        * doing this splice
+        */
+       mutex_lock(&root->fs_info->reloc_mutex);
        list_splice_init(&rc->reloc_roots, &reloc_roots);
-       spin_unlock(&root->fs_info->trans_lock);
+       mutex_unlock(&root->fs_info->reloc_mutex);
 
        while (!list_empty(&reloc_roots)) {
                found = 1;
@@ -3590,17 +3600,19 @@ next:
 static void set_reloc_control(struct reloc_control *rc)
 {
        struct btrfs_fs_info *fs_info = rc->extent_root->fs_info;
-       spin_lock(&fs_info->trans_lock);
+
+       mutex_lock(&fs_info->reloc_mutex);
        fs_info->reloc_ctl = rc;
-       spin_unlock(&fs_info->trans_lock);
+       mutex_unlock(&fs_info->reloc_mutex);
 }
 
 static void unset_reloc_control(struct reloc_control *rc)
 {
        struct btrfs_fs_info *fs_info = rc->extent_root->fs_info;
-       spin_lock(&fs_info->trans_lock);
+
+       mutex_lock(&fs_info->reloc_mutex);
        fs_info->reloc_ctl = NULL;
-       spin_unlock(&fs_info->trans_lock);
+       mutex_unlock(&fs_info->reloc_mutex);
 }
 
 static int check_extent_flags(u64 flags)
index c3c223ae66918d9e244fc909c4d6b7836490ef95..daac9ae6d7319b4f2cc68c0893a86c7d779e6516 100644 (file)
 #include "disk-io.h"
 #include "transaction.h"
 
-static ssize_t root_blocks_used_show(struct btrfs_root *root, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%llu\n",
-               (unsigned long long)btrfs_root_used(&root->root_item));
-}
-
-static ssize_t root_block_limit_show(struct btrfs_root *root, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%llu\n",
-               (unsigned long long)btrfs_root_limit(&root->root_item));
-}
-
-static ssize_t super_blocks_used_show(struct btrfs_fs_info *fs, char *buf)
-{
-
-       return snprintf(buf, PAGE_SIZE, "%llu\n",
-               (unsigned long long)btrfs_super_bytes_used(&fs->super_copy));
-}
-
-static ssize_t super_total_blocks_show(struct btrfs_fs_info *fs, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%llu\n",
-               (unsigned long long)btrfs_super_total_bytes(&fs->super_copy));
-}
-
-static ssize_t super_blocksize_show(struct btrfs_fs_info *fs, char *buf)
-{
-       return snprintf(buf, PAGE_SIZE, "%llu\n",
-               (unsigned long long)btrfs_super_sectorsize(&fs->super_copy));
-}
-
-/* this is for root attrs (subvols/snapshots) */
-struct btrfs_root_attr {
-       struct attribute attr;
-       ssize_t (*show)(struct btrfs_root *, char *);
-       ssize_t (*store)(struct btrfs_root *, const char *, size_t);
-};
-
-#define ROOT_ATTR(name, mode, show, store) \
-static struct btrfs_root_attr btrfs_root_attr_##name = __ATTR(name, mode, \
-                                                             show, store)
-
-ROOT_ATTR(blocks_used, 0444,   root_blocks_used_show,  NULL);
-ROOT_ATTR(block_limit, 0644,   root_block_limit_show,  NULL);
-
-static struct attribute *btrfs_root_attrs[] = {
-       &btrfs_root_attr_blocks_used.attr,
-       &btrfs_root_attr_block_limit.attr,
-       NULL,
-};
-
-/* this is for super attrs (actual full fs) */
-struct btrfs_super_attr {
-       struct attribute attr;
-       ssize_t (*show)(struct btrfs_fs_info *, char *);
-       ssize_t (*store)(struct btrfs_fs_info *, const char *, size_t);
-};
-
-#define SUPER_ATTR(name, mode, show, store) \
-static struct btrfs_super_attr btrfs_super_attr_##name = __ATTR(name, mode, \
-                                                               show, store)
-
-SUPER_ATTR(blocks_used,                0444,   super_blocks_used_show,         NULL);
-SUPER_ATTR(total_blocks,       0444,   super_total_blocks_show,        NULL);
-SUPER_ATTR(blocksize,          0444,   super_blocksize_show,           NULL);
-
-static struct attribute *btrfs_super_attrs[] = {
-       &btrfs_super_attr_blocks_used.attr,
-       &btrfs_super_attr_total_blocks.attr,
-       &btrfs_super_attr_blocksize.attr,
-       NULL,
-};
-
-static ssize_t btrfs_super_attr_show(struct kobject *kobj,
-                                   struct attribute *attr, char *buf)
-{
-       struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info,
-                                               super_kobj);
-       struct btrfs_super_attr *a = container_of(attr,
-                                                 struct btrfs_super_attr,
-                                                 attr);
-
-       return a->show ? a->show(fs, buf) : 0;
-}
-
-static ssize_t btrfs_super_attr_store(struct kobject *kobj,
-                                    struct attribute *attr,
-                                    const char *buf, size_t len)
-{
-       struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info,
-                                               super_kobj);
-       struct btrfs_super_attr *a = container_of(attr,
-                                                 struct btrfs_super_attr,
-                                                 attr);
-
-       return a->store ? a->store(fs, buf, len) : 0;
-}
-
-static ssize_t btrfs_root_attr_show(struct kobject *kobj,
-                                   struct attribute *attr, char *buf)
-{
-       struct btrfs_root *root = container_of(kobj, struct btrfs_root,
-                                               root_kobj);
-       struct btrfs_root_attr *a = container_of(attr,
-                                                struct btrfs_root_attr,
-                                                attr);
-
-       return a->show ? a->show(root, buf) : 0;
-}
-
-static ssize_t btrfs_root_attr_store(struct kobject *kobj,
-                                    struct attribute *attr,
-                                    const char *buf, size_t len)
-{
-       struct btrfs_root *root = container_of(kobj, struct btrfs_root,
-                                               root_kobj);
-       struct btrfs_root_attr *a = container_of(attr,
-                                                struct btrfs_root_attr,
-                                                attr);
-       return a->store ? a->store(root, buf, len) : 0;
-}
-
-static void btrfs_super_release(struct kobject *kobj)
-{
-       struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info,
-                                               super_kobj);
-       complete(&fs->kobj_unregister);
-}
-
-static void btrfs_root_release(struct kobject *kobj)
-{
-       struct btrfs_root *root = container_of(kobj, struct btrfs_root,
-                                               root_kobj);
-       complete(&root->kobj_unregister);
-}
-
-static const struct sysfs_ops btrfs_super_attr_ops = {
-       .show   = btrfs_super_attr_show,
-       .store  = btrfs_super_attr_store,
-};
-
-static const struct sysfs_ops btrfs_root_attr_ops = {
-       .show   = btrfs_root_attr_show,
-       .store  = btrfs_root_attr_store,
-};
-
 /* /sys/fs/btrfs/ entry */
 static struct kset *btrfs_kset;
 
index 2b3590b9fe98a6107efc9a7b13ce053e499c049e..51dcec86757f071654bc3866123e65157ef0286b 100644 (file)
@@ -126,28 +126,85 @@ static noinline int join_transaction(struct btrfs_root *root, int nofail)
  * to make sure the old root from before we joined the transaction is deleted
  * when the transaction commits
  */
-int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
+static int record_root_in_trans(struct btrfs_trans_handle *trans,
                               struct btrfs_root *root)
 {
        if (root->ref_cows && root->last_trans < trans->transid) {
                WARN_ON(root == root->fs_info->extent_root);
                WARN_ON(root->commit_root != root->node);
 
+               /*
+                * see below for in_trans_setup usage rules
+                * we have the reloc mutex held now, so there
+                * is only one writer in this function
+                */
+               root->in_trans_setup = 1;
+
+               /* make sure readers find in_trans_setup before
+                * they find our root->last_trans update
+                */
+               smp_wmb();
+
                spin_lock(&root->fs_info->fs_roots_radix_lock);
                if (root->last_trans == trans->transid) {
                        spin_unlock(&root->fs_info->fs_roots_radix_lock);
                        return 0;
                }
-               root->last_trans = trans->transid;
                radix_tree_tag_set(&root->fs_info->fs_roots_radix,
                           (unsigned long)root->root_key.objectid,
                           BTRFS_ROOT_TRANS_TAG);
                spin_unlock(&root->fs_info->fs_roots_radix_lock);
+               root->last_trans = trans->transid;
+
+               /* this is pretty tricky.  We don't want to
+                * take the relocation lock in btrfs_record_root_in_trans
+                * unless we're really doing the first setup for this root in
+                * this transaction.
+                *
+                * Normally we'd use root->last_trans as a flag to decide
+                * if we want to take the expensive mutex.
+                *
+                * But, we have to set root->last_trans before we
+                * init the relocation root, otherwise, we trip over warnings
+                * in ctree.c.  The solution used here is to flag ourselves
+                * with root->in_trans_setup.  When this is 1, we're still
+                * fixing up the reloc trees and everyone must wait.
+                *
+                * When this is zero, they can trust root->last_trans and fly
+                * through btrfs_record_root_in_trans without having to take the
+                * lock.  smp_wmb() makes sure that all the writes above are
+                * done before we pop in the zero below
+                */
                btrfs_init_reloc_root(trans, root);
+               smp_wmb();
+               root->in_trans_setup = 0;
        }
        return 0;
 }
 
+
+int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans,
+                              struct btrfs_root *root)
+{
+       if (!root->ref_cows)
+               return 0;
+
+       /*
+        * see record_root_in_trans for comments about in_trans_setup usage
+        * and barriers
+        */
+       smp_rmb();
+       if (root->last_trans == trans->transid &&
+           !root->in_trans_setup)
+               return 0;
+
+       mutex_lock(&root->fs_info->reloc_mutex);
+       record_root_in_trans(trans, root);
+       mutex_unlock(&root->fs_info->reloc_mutex);
+
+       return 0;
+}
+
 /* wait for commit against the current transaction to become unblocked
  * when this is done, it is safe to start a new transaction, but the current
  * transaction might not be fully on disk.
@@ -882,7 +939,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        parent = dget_parent(dentry);
        parent_inode = parent->d_inode;
        parent_root = BTRFS_I(parent_inode)->root;
-       btrfs_record_root_in_trans(trans, parent_root);
+       record_root_in_trans(trans, parent_root);
 
        /*
         * insert the directory item
@@ -900,7 +957,16 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        ret = btrfs_update_inode(trans, parent_root, parent_inode);
        BUG_ON(ret);
 
-       btrfs_record_root_in_trans(trans, root);
+       /*
+        * pull in the delayed directory update
+        * and the delayed inode item
+        * otherwise we corrupt the FS during
+        * snapshot
+        */
+       ret = btrfs_run_delayed_items(trans, root);
+       BUG_ON(ret);
+
+       record_root_in_trans(trans, root);
        btrfs_set_root_last_snapshot(&root->root_item, trans->transid);
        memcpy(new_root_item, &root->root_item, sizeof(*new_root_item));
        btrfs_check_and_init_root_item(new_root_item);
@@ -961,14 +1027,6 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans,
        int ret;
 
        list_for_each_entry(pending, head, list) {
-               /*
-                * We must deal with the delayed items before creating
-                * snapshots, or we will create a snapthot with inconsistent
-                * information.
-               */
-               ret = btrfs_run_delayed_items(trans, fs_info->fs_root);
-               BUG_ON(ret);
-
                ret = create_pending_snapshot(trans, fs_info, pending);
                BUG_ON(ret);
        }
@@ -1241,21 +1299,42 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
                        schedule_timeout(1);
 
                finish_wait(&cur_trans->writer_wait, &wait);
-               spin_lock(&root->fs_info->trans_lock);
-               root->fs_info->trans_no_join = 1;
-               spin_unlock(&root->fs_info->trans_lock);
        } while (atomic_read(&cur_trans->num_writers) > 1 ||
                 (should_grow && cur_trans->num_joined != joined));
 
-       ret = create_pending_snapshots(trans, root->fs_info);
-       BUG_ON(ret);
+       /*
+        * Ok now we need to make sure to block out any other joins while we
+        * commit the transaction.  We could have started a join before setting
+        * no_join so make sure to wait for num_writers to == 1 again.
+        */
+       spin_lock(&root->fs_info->trans_lock);
+       root->fs_info->trans_no_join = 1;
+       spin_unlock(&root->fs_info->trans_lock);
+       wait_event(cur_trans->writer_wait,
+                  atomic_read(&cur_trans->num_writers) == 1);
+
+       /*
+        * the reloc mutex makes sure that we stop
+        * the balancing code from coming in and moving
+        * extents around in the middle of the commit
+        */
+       mutex_lock(&root->fs_info->reloc_mutex);
 
        ret = btrfs_run_delayed_items(trans, root);
        BUG_ON(ret);
 
+       ret = create_pending_snapshots(trans, root->fs_info);
+       BUG_ON(ret);
+
        ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1);
        BUG_ON(ret);
 
+       /*
+        * make sure none of the code above managed to slip in a
+        * delayed item
+        */
+       btrfs_assert_delayed_root_empty(root);
+
        WARN_ON(cur_trans != trans->transaction);
 
        btrfs_scrub_pause(root);
@@ -1312,6 +1391,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
        root->fs_info->running_transaction = NULL;
        root->fs_info->trans_no_join = 0;
        spin_unlock(&root->fs_info->trans_lock);
+       mutex_unlock(&root->fs_info->reloc_mutex);
 
        wake_up(&root->fs_info->transaction_wait);
 
index 592396c6dc47465bccf4422d6259d0dfe2885e0c..4ce8a9f41d1ec3916753bd610183a82b4dc6aa21 100644 (file)
@@ -3177,7 +3177,7 @@ again:
                tmp_key.offset = (u64)-1;
 
                wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key);
-               BUG_ON(!wc.replay_dest);
+               BUG_ON(IS_ERR_OR_NULL(wc.replay_dest));
 
                wc.replay_dest->log_root = log;
                btrfs_record_root_in_trans(trans, wc.replay_dest);
index 49c9aada0374b4c8b407d1110d37203f26339b62..1a80b048ade822849b88fb51003e5244c80872f5 100644 (file)
@@ -1902,10 +1902,8 @@ int __block_write_begin(struct page *page, loff_t pos, unsigned len,
                if (!buffer_uptodate(*wait_bh))
                        err = -EIO;
        }
-       if (unlikely(err)) {
+       if (unlikely(err))
                page_zero_new_buffers(page, from, to);
-               ClearPageUptodate(page);
-       }
        return err;
 }
 EXPORT_SYMBOL(__block_write_begin);
index 53ed1ad2c112808ea27c92dce5fff5ebefad8651..f66cc1625150839244870bb6bbb3d27893b7ec82 100644 (file)
@@ -156,6 +156,6 @@ config CIFS_ACL
 
 config CIFS_NFSD_EXPORT
          bool "Allow nfsd to export CIFS file system (EXPERIMENTAL)"
-         depends on CIFS && EXPERIMENTAL
+         depends on CIFS && EXPERIMENTAL && BROKEN
          help
           Allows NFS server to export a CIFS mounted share (nfsd over cifs)
index dd8584d35a14df875e09b4716f041d87f028e70a..545509c3313b0a8e1061742e5360c8d665c2e94c 100644 (file)
@@ -92,7 +92,7 @@ static uint16_t cifs_server_get_key(const void *cookie_netfs_data,
                break;
 
        default:
-               cERROR(1, "CIFS: Unknown network family '%d'", sa->sa_family);
+               cERROR(1, "Unknown network family '%d'", sa->sa_family);
                key_len = 0;
                break;
        }
@@ -152,7 +152,7 @@ static uint16_t cifs_super_get_key(const void *cookie_netfs_data, void *buffer,
 
        sharename = extract_sharename(tcon->treeName);
        if (IS_ERR(sharename)) {
-               cFYI(1, "CIFS: couldn't extract sharename\n");
+               cFYI(1, "%s: couldn't extract sharename\n", __func__);
                sharename = NULL;
                return 0;
        }
@@ -302,7 +302,7 @@ static void cifs_fscache_inode_now_uncached(void *cookie_netfs_data)
        pagevec_init(&pvec, 0);
        first = 0;
 
-       cFYI(1, "cifs inode 0x%p now uncached", cifsi);
+       cFYI(1, "%s: cifs inode 0x%p now uncached", __func__, cifsi);
 
        for (;;) {
                nr_pages = pagevec_lookup(&pvec,
index ffb1459dc6ecf04f2da417a85c734374177f45ce..7260e11e21f8429304b519b2ec0f5aeb477ce0b9 100644 (file)
@@ -42,6 +42,7 @@
 #define CIFS_MOUNT_MULTIUSER   0x20000 /* multiuser mount */
 #define CIFS_MOUNT_STRICT_IO   0x40000 /* strict cache mode */
 #define CIFS_MOUNT_RWPIDFORWARD        0x80000 /* use pid forwarding for rw */
+#define CIFS_MOUNT_POSIXACL    0x100000 /* mirror of MS_POSIXACL in mnt_cifs_flags */
 
 struct cifs_sb_info {
        struct rb_root tlink_tree;
index 989442dcfb45d5af094d619d468b648094820908..35f9154615fa5ca7cc01fe857324b640b9533245 100644 (file)
@@ -104,8 +104,7 @@ cifs_sb_deactive(struct super_block *sb)
 }
 
 static int
-cifs_read_super(struct super_block *sb, struct smb_vol *volume_info,
-               const char *devname, int silent)
+cifs_read_super(struct super_block *sb)
 {
        struct inode *inode;
        struct cifs_sb_info *cifs_sb;
@@ -113,22 +112,16 @@ cifs_read_super(struct super_block *sb, struct smb_vol *volume_info,
 
        cifs_sb = CIFS_SB(sb);
 
-       spin_lock_init(&cifs_sb->tlink_tree_lock);
-       cifs_sb->tlink_tree = RB_ROOT;
+       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL)
+               sb->s_flags |= MS_POSIXACL;
 
-       rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
-       if (rc)
-               return rc;
-
-       cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages;
+       if (cifs_sb_master_tcon(cifs_sb)->ses->capabilities & CAP_LARGE_FILES)
+               sb->s_maxbytes = MAX_LFS_FILESIZE;
+       else
+               sb->s_maxbytes = MAX_NON_LFS;
 
-       rc = cifs_mount(sb, cifs_sb, volume_info, devname);
-
-       if (rc) {
-               if (!silent)
-                       cERROR(1, "cifs_mount failed w/return code = %d", rc);
-               goto out_mount_failed;
-       }
+       /* BB FIXME fix time_gran to be larger for LANMAN sessions */
+       sb->s_time_gran = 100;
 
        sb->s_magic = CIFS_MAGIC_NUMBER;
        sb->s_op = &cifs_super_ops;
@@ -170,37 +163,14 @@ out_no_root:
        if (inode)
                iput(inode);
 
-       cifs_umount(sb, cifs_sb);
-
-out_mount_failed:
-       bdi_destroy(&cifs_sb->bdi);
        return rc;
 }
 
-static void
-cifs_put_super(struct super_block *sb)
+static void cifs_kill_sb(struct super_block *sb)
 {
-       int rc = 0;
-       struct cifs_sb_info *cifs_sb;
-
-       cFYI(1, "In cifs_put_super");
-       cifs_sb = CIFS_SB(sb);
-       if (cifs_sb == NULL) {
-               cFYI(1, "Empty cifs superblock info passed to unmount");
-               return;
-       }
-
-       rc = cifs_umount(sb, cifs_sb);
-       if (rc)
-               cERROR(1, "cifs_umount failed with return code %d", rc);
-       if (cifs_sb->mountdata) {
-               kfree(cifs_sb->mountdata);
-               cifs_sb->mountdata = NULL;
-       }
-
-       unload_nls(cifs_sb->local_nls);
-       bdi_destroy(&cifs_sb->bdi);
-       kfree(cifs_sb);
+       struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+       kill_anon_super(sb);
+       cifs_umount(cifs_sb);
 }
 
 static int
@@ -257,9 +227,6 @@ static int cifs_permission(struct inode *inode, int mask, unsigned int flags)
 {
        struct cifs_sb_info *cifs_sb;
 
-       if (flags & IPERM_FLAG_RCU)
-               return -ECHILD;
-
        cifs_sb = CIFS_SB(inode->i_sb);
 
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) {
@@ -352,6 +319,37 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server)
        }
 }
 
+static void
+cifs_show_security(struct seq_file *s, struct TCP_Server_Info *server)
+{
+       seq_printf(s, ",sec=");
+
+       switch (server->secType) {
+       case LANMAN:
+               seq_printf(s, "lanman");
+               break;
+       case NTLMv2:
+               seq_printf(s, "ntlmv2");
+               break;
+       case NTLM:
+               seq_printf(s, "ntlm");
+               break;
+       case Kerberos:
+               seq_printf(s, "krb5");
+               break;
+       case RawNTLMSSP:
+               seq_printf(s, "ntlmssp");
+               break;
+       default:
+               /* shouldn't ever happen */
+               seq_printf(s, "unknown");
+               break;
+       }
+
+       if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+               seq_printf(s, "i");
+}
+
 /*
  * cifs_show_options() is for displaying mount options in /proc/mounts.
  * Not all settable options are displayed but most of the important
@@ -365,6 +363,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
        struct sockaddr *srcaddr;
        srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr;
 
+       cifs_show_security(s, tcon->ses->server);
+
        seq_printf(s, ",unc=%s", tcon->treeName);
 
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)
@@ -518,7 +518,6 @@ static int cifs_drop_inode(struct inode *inode)
 }
 
 static const struct super_operations cifs_super_ops = {
-       .put_super = cifs_put_super,
        .statfs = cifs_statfs,
        .alloc_inode = cifs_alloc_inode,
        .destroy_inode = cifs_destroy_inode,
@@ -555,7 +554,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
        full_path = cifs_build_path_to_root(vol, cifs_sb,
                                            cifs_sb_master_tcon(cifs_sb));
        if (full_path == NULL)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        cFYI(1, "Get root dentry for %s", full_path);
 
@@ -584,7 +583,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
                        dchild = d_alloc(dparent, &name);
                        if (dchild == NULL) {
                                dput(dparent);
-                               dparent = NULL;
+                               dparent = ERR_PTR(-ENOMEM);
                                goto out;
                        }
                }
@@ -602,7 +601,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
                        if (rc) {
                                dput(dchild);
                                dput(dparent);
-                               dparent = NULL;
+                               dparent = ERR_PTR(rc);
                                goto out;
                        }
                        alias = d_materialise_unique(dchild, inode);
@@ -610,7 +609,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
                                dput(dchild);
                                if (IS_ERR(alias)) {
                                        dput(dparent);
-                                       dparent = NULL;
+                                       dparent = ERR_PTR(-EINVAL); /* XXX */
                                        goto out;
                                }
                                dchild = alias;
@@ -630,6 +629,13 @@ out:
        return dparent;
 }
 
+static int cifs_set_super(struct super_block *sb, void *data)
+{
+       struct cifs_mnt_data *mnt_data = data;
+       sb->s_fs_info = mnt_data->cifs_sb;
+       return set_anon_super(sb, NULL);
+}
+
 static struct dentry *
 cifs_do_mount(struct file_system_type *fs_type,
              int flags, const char *dev_name, void *data)
@@ -650,75 +656,73 @@ cifs_do_mount(struct file_system_type *fs_type,
        cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL);
        if (cifs_sb == NULL) {
                root = ERR_PTR(-ENOMEM);
-               goto out;
+               goto out_nls;
+       }
+
+       cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL);
+       if (cifs_sb->mountdata == NULL) {
+               root = ERR_PTR(-ENOMEM);
+               goto out_cifs_sb;
        }
 
        cifs_setup_cifs_sb(volume_info, cifs_sb);
 
+       rc = cifs_mount(cifs_sb, volume_info);
+       if (rc) {
+               if (!(flags & MS_SILENT))
+                       cERROR(1, "cifs_mount failed w/return code = %d", rc);
+               root = ERR_PTR(rc);
+               goto out_mountdata;
+       }
+
        mnt_data.vol = volume_info;
        mnt_data.cifs_sb = cifs_sb;
        mnt_data.flags = flags;
 
-       sb = sget(fs_type, cifs_match_super, set_anon_super, &mnt_data);
+       sb = sget(fs_type, cifs_match_super, cifs_set_super, &mnt_data);
        if (IS_ERR(sb)) {
                root = ERR_CAST(sb);
-               goto out_cifs_sb;
+               cifs_umount(cifs_sb);
+               goto out;
        }
 
-       if (sb->s_fs_info) {
+       if (sb->s_root) {
                cFYI(1, "Use existing superblock");
-               goto out_shared;
-       }
-
-       /*
-        * Copy mount params for use in submounts. Better to do
-        * the copy here and deal with the error before cleanup gets
-        * complicated post-mount.
-        */
-       cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL);
-       if (cifs_sb->mountdata == NULL) {
-               root = ERR_PTR(-ENOMEM);
-               goto out_super;
-       }
-
-       sb->s_flags = flags;
-       /* BB should we make this contingent on mount parm? */
-       sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
-       sb->s_fs_info = cifs_sb;
+               cifs_umount(cifs_sb);
+       } else {
+               sb->s_flags = flags;
+               /* BB should we make this contingent on mount parm? */
+               sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
+
+               rc = cifs_read_super(sb);
+               if (rc) {
+                       root = ERR_PTR(rc);
+                       goto out_super;
+               }
 
-       rc = cifs_read_super(sb, volume_info, dev_name,
-                            flags & MS_SILENT ? 1 : 0);
-       if (rc) {
-               root = ERR_PTR(rc);
-               goto out_super;
+               sb->s_flags |= MS_ACTIVE;
        }
 
-       sb->s_flags |= MS_ACTIVE;
-
        root = cifs_get_root(volume_info, sb);
-       if (root == NULL)
+       if (IS_ERR(root))
                goto out_super;
 
        cFYI(1, "dentry root is: %p", root);
        goto out;
 
-out_shared:
-       root = cifs_get_root(volume_info, sb);
-       if (root)
-               cFYI(1, "dentry root is: %p", root);
-       goto out;
-
 out_super:
-       kfree(cifs_sb->mountdata);
        deactivate_locked_super(sb);
-
-out_cifs_sb:
-       unload_nls(cifs_sb->local_nls);
-       kfree(cifs_sb);
-
 out:
        cifs_cleanup_volume_info(&volume_info);
        return root;
+
+out_mountdata:
+       kfree(cifs_sb->mountdata);
+out_cifs_sb:
+       kfree(cifs_sb);
+out_nls:
+       unload_nls(volume_info->local_nls);
+       goto out;
 }
 
 static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
@@ -807,7 +811,7 @@ struct file_system_type cifs_fs_type = {
        .owner = THIS_MODULE,
        .name = "cifs",
        .mount = cifs_do_mount,
-       .kill_sb = kill_anon_super,
+       .kill_sb = cifs_kill_sb,
        /*  .fs_flags */
 };
 const struct inode_operations cifs_dir_inode_ops = {
index 64313f778ebfcd50c456c2b7b92ebcc6c82fb364..0900e1658c967de0fc2f4d70cc7645c9363a5d30 100644 (file)
@@ -129,5 +129,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
 extern const struct export_operations cifs_export_ops;
 #endif /* CIFS_NFSD_EXPORT */
 
-#define CIFS_VERSION   "1.72"
+#define CIFS_VERSION   "1.73"
 #endif                         /* _CIFSFS_H */
index 953f84413c771b1cb0e3bb404a4349f7d90b08fa..257f312ede422d6e5c1592954bb9467f602c6e6a 100644 (file)
@@ -157,9 +157,8 @@ extern int cifs_match_super(struct super_block *, void *);
 extern void cifs_cleanup_volume_info(struct smb_vol **pvolume_info);
 extern int cifs_setup_volume_info(struct smb_vol **pvolume_info,
                                  char *mount_data, const char *devname);
-extern int cifs_mount(struct super_block *, struct cifs_sb_info *,
-                     struct smb_vol *, const char *);
-extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
+extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *);
+extern void cifs_umount(struct cifs_sb_info *);
 extern void cifs_dfs_release_automount_timer(void);
 void cifs_proc_init(void);
 void cifs_proc_clean(void);
@@ -218,7 +217,8 @@ extern int get_dfs_path(int xid, struct cifs_ses *pSesInfo,
                        struct dfs_info3_param **preferrals,
                        int remap);
 extern void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon,
-                                struct super_block *sb, struct smb_vol *vol);
+                                struct cifs_sb_info *cifs_sb,
+                                struct smb_vol *vol);
 extern int CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon,
                        struct kstatfs *FSData);
 extern int SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon,
index bb659eb738100036dc726790b7be947df253cb27..7f540df5252786b41d0af7c6bf3846a825069cb4 100644 (file)
@@ -152,7 +152,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
                mid_entry->callback(mid_entry);
        }
 
-       while (server->tcpStatus == CifsNeedReconnect) {
+       do {
                try_to_freeze();
 
                /* we should try only the port we connected to before */
@@ -167,7 +167,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
                                server->tcpStatus = CifsNeedNegotiate;
                        spin_unlock(&GlobalMid_Lock);
                }
-       }
+       } while (server->tcpStatus == CifsNeedReconnect);
 
        return rc;
 }
@@ -2149,7 +2149,10 @@ cifs_put_tlink(struct tcon_link *tlink)
 }
 
 static inline struct tcon_link *
-cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb);
+cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
+{
+       return cifs_sb->master_tlink;
+}
 
 static int
 compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data)
@@ -2543,7 +2546,7 @@ ip_connect(struct TCP_Server_Info *server)
 }
 
 void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon,
-                         struct super_block *sb, struct smb_vol *vol_info)
+                         struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info)
 {
        /* if we are reconnecting then should we check to see if
         * any requested capabilities changed locally e.g. via
@@ -2597,22 +2600,23 @@ void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon,
                        cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
                else if (CIFS_UNIX_POSIX_ACL_CAP & cap) {
                        cFYI(1, "negotiated posix acl support");
-                       if (sb)
-                               sb->s_flags |= MS_POSIXACL;
+                       if (cifs_sb)
+                               cifs_sb->mnt_cifs_flags |=
+                                       CIFS_MOUNT_POSIXACL;
                }
 
                if (vol_info && vol_info->posix_paths == 0)
                        cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP;
                else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) {
                        cFYI(1, "negotiate posix pathnames");
-                       if (sb)
-                               CIFS_SB(sb)->mnt_cifs_flags |=
+                       if (cifs_sb)
+                               cifs_sb->mnt_cifs_flags |=
                                        CIFS_MOUNT_POSIX_PATHS;
                }
 
-               if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) {
+               if (cifs_sb && (cifs_sb->rsize > 127 * 1024)) {
                        if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) {
-                               CIFS_SB(sb)->rsize = 127 * 1024;
+                               cifs_sb->rsize = 127 * 1024;
                                cFYI(DBG2, "larger reads not supported by srv");
                        }
                }
@@ -2659,6 +2663,9 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
 {
        INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks);
 
+       spin_lock_init(&cifs_sb->tlink_tree_lock);
+       cifs_sb->tlink_tree = RB_ROOT;
+
        if (pvolume_info->rsize > CIFSMaxBufSize) {
                cERROR(1, "rsize %d too large, using MaxBufSize",
                        pvolume_info->rsize);
@@ -2747,21 +2754,21 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info,
 
 /*
  * When the server supports very large writes via POSIX extensions, we can
- * allow up to 2^24 - PAGE_CACHE_SIZE.
+ * allow up to 2^24-1, minus the size of a WRITE_AND_X header, not including
+ * the RFC1001 length.
  *
  * Note that this might make for "interesting" allocation problems during
- * writeback however (as we have to allocate an array of pointers for the
- * pages). A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
+ * writeback however as we have to allocate an array of pointers for the
+ * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096.
  */
-#define CIFS_MAX_WSIZE ((1<<24) - PAGE_CACHE_SIZE)
+#define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4)
 
 /*
- * When the server doesn't allow large posix writes, default to a wsize of
- * 128k - PAGE_CACHE_SIZE -- one page less than the largest frame size
- * described in RFC1001. This allows space for the header without going over
- * that by default.
+ * When the server doesn't allow large posix writes, only allow a wsize of
+ * 128k minus the size of the WRITE_AND_X header. That allows for a write up
+ * to the maximum size described by RFC1002.
  */
-#define CIFS_MAX_RFC1001_WSIZE (128 * 1024 - PAGE_CACHE_SIZE)
+#define CIFS_MAX_RFC1002_WSIZE (128 * 1024 - sizeof(WRITE_REQ) + 4)
 
 /*
  * The default wsize is 1M. find_get_pages seems to return a maximum of 256
@@ -2780,11 +2787,18 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info)
 
        /* can server support 24-bit write sizes? (via UNIX extensions) */
        if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
-               wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1001_WSIZE);
+               wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
 
-       /* no CAP_LARGE_WRITE_X? Limit it to 16 bits */
-       if (!(server->capabilities & CAP_LARGE_WRITE_X))
-               wsize = min_t(unsigned int, wsize, USHRT_MAX);
+       /*
+        * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
+        * Limit it to max buffer offered by the server, minus the size of the
+        * WRITEX header, not including the 4 byte RFC1001 length.
+        */
+       if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
+           (!(server->capabilities & CAP_UNIX) &&
+            (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
+               wsize = min_t(unsigned int, wsize,
+                               server->maxBuf - sizeof(WRITE_REQ) + 4);
 
        /* hard limit of CIFS_MAX_WSIZE */
        wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
@@ -2934,7 +2948,11 @@ int cifs_setup_volume_info(struct smb_vol **pvolume_info, char *mount_data,
 
        if (volume_info->nullauth) {
                cFYI(1, "null user");
-               volume_info->username = "";
+               volume_info->username = kzalloc(1, GFP_KERNEL);
+               if (volume_info->username == NULL) {
+                       rc = -ENOMEM;
+                       goto out;
+               }
        } else if (volume_info->username) {
                /* BB fixme parse for domain name here */
                cFYI(1, "Username: %s", volume_info->username);
@@ -2968,8 +2986,7 @@ out:
 }
 
 int
-cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
-          struct smb_vol *volume_info, const char *devname)
+cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
 {
        int rc = 0;
        int xid;
@@ -2980,6 +2997,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
        struct tcon_link *tlink;
 #ifdef CONFIG_CIFS_DFS_UPCALL
        int referral_walks_count = 0;
+
+       rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY);
+       if (rc)
+               return rc;
+
+       cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages;
+
 try_mount_again:
        /* cleanup activities if we're chasing a referral */
        if (referral_walks_count) {
@@ -3004,6 +3028,7 @@ try_mount_again:
        srvTcp = cifs_get_tcp_session(volume_info);
        if (IS_ERR(srvTcp)) {
                rc = PTR_ERR(srvTcp);
+               bdi_destroy(&cifs_sb->bdi);
                goto out;
        }
 
@@ -3015,14 +3040,6 @@ try_mount_again:
                goto mount_fail_check;
        }
 
-       if (pSesInfo->capabilities & CAP_LARGE_FILES)
-               sb->s_maxbytes = MAX_LFS_FILESIZE;
-       else
-               sb->s_maxbytes = MAX_NON_LFS;
-
-       /* BB FIXME fix time_gran to be larger for LANMAN sessions */
-       sb->s_time_gran = 100;
-
        /* search for existing tcon to this server share */
        tcon = cifs_get_tcon(pSesInfo, volume_info);
        if (IS_ERR(tcon)) {
@@ -3035,7 +3052,7 @@ try_mount_again:
        if (tcon->ses->capabilities & CAP_UNIX) {
                /* reset of caps checks mount to see if unix extensions
                   disabled for just this mount */
-               reset_cifs_unix_caps(xid, tcon, sb, volume_info);
+               reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info);
                if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
                    (le64_to_cpu(tcon->fsUnixInfo.Capability) &
                     CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
@@ -3158,6 +3175,7 @@ mount_fail_check:
                        cifs_put_smb_ses(pSesInfo);
                else
                        cifs_put_tcp_session(srvTcp);
+               bdi_destroy(&cifs_sb->bdi);
                goto out;
        }
 
@@ -3171,6 +3189,10 @@ out:
        return rc;
 }
 
+/*
+ * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon
+ * pointer may be NULL.
+ */
 int
 CIFSTCon(unsigned int xid, struct cifs_ses *ses,
         const char *tree, struct cifs_tcon *tcon,
@@ -3205,7 +3227,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses,
        pSMB->AndXCommand = 0xFF;
        pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO);
        bcc_ptr = &pSMB->Password[0];
-       if ((ses->server->sec_mode) & SECMODE_USER) {
+       if (!tcon || (ses->server->sec_mode & SECMODE_USER)) {
                pSMB->PasswordLength = cpu_to_le16(1);  /* minimum */
                *bcc_ptr = 0; /* password is null byte */
                bcc_ptr++;              /* skip password */
@@ -3328,8 +3350,8 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses,
        return rc;
 }
 
-int
-cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
+void
+cifs_umount(struct cifs_sb_info *cifs_sb)
 {
        struct rb_root *root = &cifs_sb->tlink_tree;
        struct rb_node *node;
@@ -3350,7 +3372,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
        }
        spin_unlock(&cifs_sb->tlink_tree_lock);
 
-       return 0;
+       bdi_destroy(&cifs_sb->bdi);
+       kfree(cifs_sb->mountdata);
+       unload_nls(cifs_sb->local_nls);
+       kfree(cifs_sb);
 }
 
 int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses)
@@ -3371,7 +3396,7 @@ int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses)
        }
        if (rc == 0) {
                spin_lock(&GlobalMid_Lock);
-               if (server->tcpStatus != CifsExiting)
+               if (server->tcpStatus == CifsNeedNegotiate)
                        server->tcpStatus = CifsGood;
                else
                        rc = -EHOSTDOWN;
@@ -3484,12 +3509,6 @@ out:
        return tcon;
 }
 
-static inline struct tcon_link *
-cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb)
-{
-       return cifs_sb->master_tlink;
-}
-
 struct cifs_tcon *
 cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb)
 {
index d368a47ba5ebf317b377a0c34b0aeb2938a6c871..816696621ec9ea1be2d5b351ac4fc17d0e8f41aa 100644 (file)
@@ -28,14 +28,14 @@ void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server)
        server->fscache =
                fscache_acquire_cookie(cifs_fscache_netfs.primary_index,
                                &cifs_fscache_server_index_def, server);
-       cFYI(1, "CIFS: get client cookie (0x%p/0x%p)", server,
-                               server->fscache);
+       cFYI(1, "%s: (0x%p/0x%p)", __func__, server,
+                       server->fscache);
 }
 
 void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server)
 {
-       cFYI(1, "CIFS: release client cookie (0x%p/0x%p)", server,
-                               server->fscache);
+       cFYI(1, "%s: (0x%p/0x%p)", __func__, server,
+                       server->fscache);
        fscache_relinquish_cookie(server->fscache, 0);
        server->fscache = NULL;
 }
@@ -47,13 +47,13 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
        tcon->fscache =
                fscache_acquire_cookie(server->fscache,
                                &cifs_fscache_super_index_def, tcon);
-       cFYI(1, "CIFS: get superblock cookie (0x%p/0x%p)",
-                               server->fscache, tcon->fscache);
+       cFYI(1, "%s: (0x%p/0x%p)", __func__, server->fscache,
+                       tcon->fscache);
 }
 
 void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
 {
-       cFYI(1, "CIFS: releasing superblock cookie (0x%p)", tcon->fscache);
+       cFYI(1, "%s: (0x%p)", __func__, tcon->fscache);
        fscache_relinquish_cookie(tcon->fscache, 0);
        tcon->fscache = NULL;
 }
@@ -70,8 +70,8 @@ static void cifs_fscache_enable_inode_cookie(struct inode *inode)
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) {
                cifsi->fscache = fscache_acquire_cookie(tcon->fscache,
                                &cifs_fscache_inode_object_def, cifsi);
-               cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache,
-                               cifsi->fscache);
+               cFYI(1, "%s: got FH cookie (0x%p/0x%p)", __func__,
+                               tcon->fscache, cifsi->fscache);
        }
 }
 
@@ -80,8 +80,7 @@ void cifs_fscache_release_inode_cookie(struct inode *inode)
        struct cifsInodeInfo *cifsi = CIFS_I(inode);
 
        if (cifsi->fscache) {
-               cFYI(1, "CIFS releasing inode cookie (0x%p)",
-                               cifsi->fscache);
+               cFYI(1, "%s: (0x%p)", __func__, cifsi->fscache);
                fscache_relinquish_cookie(cifsi->fscache, 0);
                cifsi->fscache = NULL;
        }
@@ -92,8 +91,7 @@ static void cifs_fscache_disable_inode_cookie(struct inode *inode)
        struct cifsInodeInfo *cifsi = CIFS_I(inode);
 
        if (cifsi->fscache) {
-               cFYI(1, "CIFS disabling inode cookie (0x%p)",
-                               cifsi->fscache);
+               cFYI(1, "%s: (0x%p)", __func__, cifsi->fscache);
                fscache_relinquish_cookie(cifsi->fscache, 1);
                cifsi->fscache = NULL;
        }
@@ -121,8 +119,8 @@ void cifs_fscache_reset_inode_cookie(struct inode *inode)
                                        cifs_sb_master_tcon(cifs_sb)->fscache,
                                        &cifs_fscache_inode_object_def,
                                        cifsi);
-               cFYI(1, "CIFS: new cookie 0x%p oldcookie 0x%p",
-                               cifsi->fscache, old);
+               cFYI(1, "%s: new cookie 0x%p oldcookie 0x%p",
+                               __func__, cifsi->fscache, old);
        }
 }
 
@@ -132,8 +130,8 @@ int cifs_fscache_release_page(struct page *page, gfp_t gfp)
                struct inode *inode = page->mapping->host;
                struct cifsInodeInfo *cifsi = CIFS_I(inode);
 
-               cFYI(1, "CIFS: fscache release page (0x%p/0x%p)",
-                               page, cifsi->fscache);
+               cFYI(1, "%s: (0x%p/0x%p)", __func__, page,
+                               cifsi->fscache);
                if (!fscache_maybe_release_page(cifsi->fscache, page, gfp))
                        return 0;
        }
@@ -144,8 +142,7 @@ int cifs_fscache_release_page(struct page *page, gfp_t gfp)
 static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx,
                                                int error)
 {
-       cFYI(1, "CFS: readpage_from_fscache_complete (0x%p/%d)",
-                       page, error);
+       cFYI(1, "%s: (0x%p/%d)", __func__, page, error);
        if (!error)
                SetPageUptodate(page);
        unlock_page(page);
@@ -158,7 +155,7 @@ int __cifs_readpage_from_fscache(struct inode *inode, struct page *page)
 {
        int ret;
 
-       cFYI(1, "CIFS: readpage_from_fscache(fsc:%p, p:%p, i:0x%p",
+       cFYI(1, "%s: (fsc:%p, p:%p, i:0x%p", __func__,
                        CIFS_I(inode)->fscache, page, inode);
        ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page,
                                         cifs_readpage_from_fscache_complete,
@@ -167,11 +164,11 @@ int __cifs_readpage_from_fscache(struct inode *inode, struct page *page)
        switch (ret) {
 
        case 0: /* page found in fscache, read submitted */
-               cFYI(1, "CIFS: readpage_from_fscache: submitted");
+               cFYI(1, "%s: submitted", __func__);
                return ret;
        case -ENOBUFS:  /* page won't be cached */
        case -ENODATA:  /* page not in cache */
-               cFYI(1, "CIFS: readpage_from_fscache %d", ret);
+               cFYI(1, "%s: %d", __func__, ret);
                return 1;
 
        default:
@@ -190,7 +187,7 @@ int __cifs_readpages_from_fscache(struct inode *inode,
 {
        int ret;
 
-       cFYI(1, "CIFS: __cifs_readpages_from_fscache (0x%p/%u/0x%p)",
+       cFYI(1, "%s: (0x%p/%u/0x%p)", __func__,
                        CIFS_I(inode)->fscache, *nr_pages, inode);
        ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping,
                                          pages, nr_pages,
@@ -199,12 +196,12 @@ int __cifs_readpages_from_fscache(struct inode *inode,
                                          mapping_gfp_mask(mapping));
        switch (ret) {
        case 0: /* read submitted to the cache for all pages */
-               cFYI(1, "CIFS: readpages_from_fscache: submitted");
+               cFYI(1, "%s: submitted", __func__);
                return ret;
 
        case -ENOBUFS:  /* some pages are not cached and can't be */
        case -ENODATA:  /* some pages are not cached */
-               cFYI(1, "CIFS: readpages_from_fscache: no page");
+               cFYI(1, "%s: no page", __func__);
                return 1;
 
        default:
@@ -218,7 +215,7 @@ void __cifs_readpage_to_fscache(struct inode *inode, struct page *page)
 {
        int ret;
 
-       cFYI(1, "CIFS: readpage_to_fscache(fsc: %p, p: %p, i: %p",
+       cFYI(1, "%s: (fsc: %p, p: %p, i: %p)", __func__,
                        CIFS_I(inode)->fscache, page, inode);
        ret = fscache_write_page(CIFS_I(inode)->fscache, page, GFP_KERNEL);
        if (ret != 0)
@@ -230,7 +227,7 @@ void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode)
        struct cifsInodeInfo *cifsi = CIFS_I(inode);
        struct fscache_cookie *cookie = cifsi->fscache;
 
-       cFYI(1, "CIFS: fscache invalidatepage (0x%p/0x%p)", page, cookie);
+       cFYI(1, "%s: (0x%p/0x%p)", __func__, page, cookie);
        fscache_wait_on_page_write(cookie, page);
        fscache_uncache_page(cookie, page);
 }
index 1525d5e662b65cd11649587458013bd47dc7fc2a..1c5b770c314135a3ed932c88260470f13edd6008 100644 (file)
@@ -90,12 +90,10 @@ smbhash(unsigned char *out, const unsigned char *in, unsigned char *key)
        sg_init_one(&sgout, out, 8);
 
        rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, 8);
-       if (rc) {
+       if (rc)
                cERROR(1, "could not encrypt crypt key rc: %d\n", rc);
-               crypto_free_blkcipher(tfm_des);
-               goto smbhash_err;
-       }
 
+       crypto_free_blkcipher(tfm_des);
 smbhash_err:
        return rc;
 }
index 6cbb3afb36dc2b28b9aa3f2b585c195330894699..cb140ef293e46e8739669f2e69eea701d8213874 100644 (file)
@@ -43,8 +43,6 @@ const struct file_operations coda_ioctl_operations = {
 /* the coda pioctl inode ops */
 static int coda_ioctl_permission(struct inode *inode, int mask, unsigned int flags)
 {
-       if (flags & IPERM_FLAG_RCU)
-               return -ECHILD;
        return (mask & MAY_EXEC) ? -EACCES : 0;
 }
 
index 97e0d52d72fdd65a365f3cab7027ae22c230582e..6075a1e727aee13dd3cd492b61d55edd81ee258e 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1996,7 +1996,7 @@ static void wait_for_dump_helpers(struct file *file)
  * is a special value that we use to trap recursive
  * core dumps
  */
-static int umh_pipe_setup(struct subprocess_info *info)
+static int umh_pipe_setup(struct subprocess_info *info, struct cred *new)
 {
        struct file *rp, *wp;
        struct fdtable *fdt;
index 2e29abb30f7629903f11d493bc685e3877f49917..095c36f3b6129e97db937f30a969174c4facacf1 100644 (file)
@@ -125,7 +125,7 @@ struct ext4_ext_path {
  * positive retcode - signal for ext4_ext_walk_space(), see below
  * callback must return valid extent (passed or newly created)
  */
-typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *,
+typedef int (*ext_prepare_callback)(struct inode *, ext4_lblk_t,
                                        struct ext4_ext_cache *,
                                        struct ext4_extent *, void *);
 
@@ -133,8 +133,11 @@ typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *,
 #define EXT_BREAK      1
 #define EXT_REPEAT     2
 
-/* Maximum logical block in a file; ext4_extent's ee_block is __le32 */
-#define EXT_MAX_BLOCK  0xffffffff
+/*
+ * Maximum number of logical blocks in a file; ext4_extent's ee_block is
+ * __le32.
+ */
+#define EXT_MAX_BLOCKS 0xffffffff
 
 /*
  * EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an
index 5199bac7fc625d5a19ad5934417f724fb699fe22..f815cc81e7a287bd7198dc874d7954938c188464 100644 (file)
@@ -1408,7 +1408,7 @@ got_index:
 
 /*
  * ext4_ext_next_allocated_block:
- * returns allocated block in subsequent extent or EXT_MAX_BLOCK.
+ * returns allocated block in subsequent extent or EXT_MAX_BLOCKS.
  * NOTE: it considers block number from index entry as
  * allocated block. Thus, index entries have to be consistent
  * with leaves.
@@ -1422,7 +1422,7 @@ ext4_ext_next_allocated_block(struct ext4_ext_path *path)
        depth = path->p_depth;
 
        if (depth == 0 && path->p_ext == NULL)
-               return EXT_MAX_BLOCK;
+               return EXT_MAX_BLOCKS;
 
        while (depth >= 0) {
                if (depth == path->p_depth) {
@@ -1439,12 +1439,12 @@ ext4_ext_next_allocated_block(struct ext4_ext_path *path)
                depth--;
        }
 
-       return EXT_MAX_BLOCK;
+       return EXT_MAX_BLOCKS;
 }
 
 /*
  * ext4_ext_next_leaf_block:
- * returns first allocated block from next leaf or EXT_MAX_BLOCK
+ * returns first allocated block from next leaf or EXT_MAX_BLOCKS
  */
 static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode,
                                        struct ext4_ext_path *path)
@@ -1456,7 +1456,7 @@ static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode,
 
        /* zero-tree has no leaf blocks at all */
        if (depth == 0)
-               return EXT_MAX_BLOCK;
+               return EXT_MAX_BLOCKS;
 
        /* go to index block */
        depth--;
@@ -1469,7 +1469,7 @@ static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode,
                depth--;
        }
 
-       return EXT_MAX_BLOCK;
+       return EXT_MAX_BLOCKS;
 }
 
 /*
@@ -1677,13 +1677,13 @@ static unsigned int ext4_ext_check_overlap(struct inode *inode,
         */
        if (b2 < b1) {
                b2 = ext4_ext_next_allocated_block(path);
-               if (b2 == EXT_MAX_BLOCK)
+               if (b2 == EXT_MAX_BLOCKS)
                        goto out;
        }
 
        /* check for wrap through zero on extent logical start block*/
        if (b1 + len1 < b1) {
-               len1 = EXT_MAX_BLOCK - b1;
+               len1 = EXT_MAX_BLOCKS - b1;
                newext->ee_len = cpu_to_le16(len1);
                ret = 1;
        }
@@ -1767,7 +1767,7 @@ repeat:
        fex = EXT_LAST_EXTENT(eh);
        next = ext4_ext_next_leaf_block(inode, path);
        if (le32_to_cpu(newext->ee_block) > le32_to_cpu(fex->ee_block)
-           && next != EXT_MAX_BLOCK) {
+           && next != EXT_MAX_BLOCKS) {
                ext_debug("next leaf block - %d\n", next);
                BUG_ON(npath != NULL);
                npath = ext4_ext_find_extent(inode, next, NULL);
@@ -1887,7 +1887,7 @@ static int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block,
        BUG_ON(func == NULL);
        BUG_ON(inode == NULL);
 
-       while (block < last && block != EXT_MAX_BLOCK) {
+       while (block < last && block != EXT_MAX_BLOCKS) {
                num = last - block;
                /* find extent for this block */
                down_read(&EXT4_I(inode)->i_data_sem);
@@ -1958,7 +1958,7 @@ static int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block,
                        err = -EIO;
                        break;
                }
-               err = func(inode, path, &cbex, ex, cbdata);
+               err = func(inode, next, &cbex, ex, cbdata);
                ext4_ext_drop_refs(path);
 
                if (err < 0)
@@ -2020,7 +2020,7 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path,
        if (ex == NULL) {
                /* there is no extent yet, so gap is [0;-] */
                lblock = 0;
-               len = EXT_MAX_BLOCK;
+               len = EXT_MAX_BLOCKS;
                ext_debug("cache gap(whole file):");
        } else if (block < le32_to_cpu(ex->ee_block)) {
                lblock = block;
@@ -2350,7 +2350,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
                         * never happen because at least one of the end points
                         * needs to be on the edge of the extent.
                         */
-                       if (end == EXT_MAX_BLOCK) {
+                       if (end == EXT_MAX_BLOCKS - 1) {
                                ext_debug("  bad truncate %u:%u\n",
                                                start, end);
                                block = 0;
@@ -2398,7 +2398,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
                         * If this is a truncate, this condition
                         * should never happen
                         */
-                       if (end == EXT_MAX_BLOCK) {
+                       if (end == EXT_MAX_BLOCKS - 1) {
                                ext_debug("  bad truncate %u:%u\n",
                                        start, end);
                                err = -EIO;
@@ -2478,7 +2478,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
                 * we need to remove it from the leaf
                 */
                if (num == 0) {
-                       if (end != EXT_MAX_BLOCK) {
+                       if (end != EXT_MAX_BLOCKS - 1) {
                                /*
                                 * For hole punching, we need to scoot all the
                                 * extents up when an extent is removed so that
@@ -3699,7 +3699,7 @@ void ext4_ext_truncate(struct inode *inode)
 
        last_block = (inode->i_size + sb->s_blocksize - 1)
                        >> EXT4_BLOCK_SIZE_BITS(sb);
-       err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCK);
+       err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1);
 
        /* In a multi-transaction truncate, we only make the final
         * transaction synchronous.
@@ -3914,14 +3914,13 @@ int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
 /*
  * Callback function called for each extent to gather FIEMAP information.
  */
-static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path,
+static int ext4_ext_fiemap_cb(struct inode *inode, ext4_lblk_t next,
                       struct ext4_ext_cache *newex, struct ext4_extent *ex,
                       void *data)
 {
        __u64   logical;
        __u64   physical;
        __u64   length;
-       loff_t  size;
        __u32   flags = 0;
        int             ret = 0;
        struct fiemap_extent_info *fieinfo = data;
@@ -4103,8 +4102,7 @@ found_delayed_extent:
        if (ex && ext4_ext_is_uninitialized(ex))
                flags |= FIEMAP_EXTENT_UNWRITTEN;
 
-       size = i_size_read(inode);
-       if (logical + length >= size)
+       if (next == EXT_MAX_BLOCKS)
                flags |= FIEMAP_EXTENT_LAST;
 
        ret = fiemap_fill_next_extent(fieinfo, logical, physical,
@@ -4347,8 +4345,8 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
 
                start_blk = start >> inode->i_sb->s_blocksize_bits;
                last_blk = (start + len - 1) >> inode->i_sb->s_blocksize_bits;
-               if (last_blk >= EXT_MAX_BLOCK)
-                       last_blk = EXT_MAX_BLOCK-1;
+               if (last_blk >= EXT_MAX_BLOCKS)
+                       last_blk = EXT_MAX_BLOCKS-1;
                len_blks = ((ext4_lblk_t) last_blk) - start_blk + 1;
 
                /*
index a5763e3505ba59cc330e2cecbcf54c5eb23d8410..e3126c0510066fec7fe8bd0d46123aa1af16388c 100644 (file)
@@ -2634,7 +2634,7 @@ static int ext4_writepage(struct page *page,
        struct buffer_head *page_bufs = NULL;
        struct inode *inode = page->mapping->host;
 
-       trace_ext4_writepage(inode, page);
+       trace_ext4_writepage(page);
        size = i_size_read(inode);
        if (page->index == size >> PAGE_CACHE_SHIFT)
                len = size & ~PAGE_CACHE_MASK;
index 859f2ae8864e6af2b85dc62135f7f89cb0258d4f..6ed859d56850494d440dbbacc56967c4538fc659 100644 (file)
@@ -3578,8 +3578,8 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh,
                free += next - bit;
 
                trace_ext4_mballoc_discard(sb, NULL, group, bit, next - bit);
-               trace_ext4_mb_release_inode_pa(sb, pa->pa_inode, pa,
-                                              grp_blk_start + bit, next - bit);
+               trace_ext4_mb_release_inode_pa(pa, grp_blk_start + bit,
+                                              next - bit);
                mb_free_blocks(pa->pa_inode, e4b, bit, next - bit);
                bit = next + 1;
        }
@@ -3608,7 +3608,7 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b,
        ext4_group_t group;
        ext4_grpblk_t bit;
 
-       trace_ext4_mb_release_group_pa(sb, pa);
+       trace_ext4_mb_release_group_pa(pa);
        BUG_ON(pa->pa_deleted == 0);
        ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit);
        BUG_ON(group != e4b->bd_group && pa->pa_len != 0);
@@ -4448,7 +4448,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b,
  * @inode:             inode
  * @block:             start physical block to free
  * @count:             number of blocks to count
- * @metadata:          Are these metadata blocks
+ * @flags:             flags used by ext4_free_blocks
  */
 void ext4_free_blocks(handle_t *handle, struct inode *inode,
                      struct buffer_head *bh, ext4_fsblk_t block,
index 2b8304bf3c50e1d1363287e79a66d5641fccceaa..f57455a1b1b281bdf21e12f63bc46087abe58194 100644 (file)
@@ -1002,12 +1002,12 @@ mext_check_arguments(struct inode *orig_inode,
                return -EINVAL;
        }
 
-       if ((orig_start > EXT_MAX_BLOCK) ||
-           (donor_start > EXT_MAX_BLOCK) ||
-           (*len > EXT_MAX_BLOCK) ||
-           (orig_start + *len > EXT_MAX_BLOCK))  {
+       if ((orig_start >= EXT_MAX_BLOCKS) ||
+           (donor_start >= EXT_MAX_BLOCKS) ||
+           (*len > EXT_MAX_BLOCKS) ||
+           (orig_start + *len >= EXT_MAX_BLOCKS))  {
                ext4_debug("ext4 move extent: Can't handle over [%u] blocks "
-                       "[ino:orig %lu, donor %lu]\n", EXT_MAX_BLOCK,
+                       "[ino:orig %lu, donor %lu]\n", EXT_MAX_BLOCKS,
                        orig_inode->i_ino, donor_inode->i_ino);
                return -EINVAL;
        }
index cc5c157aa11df4cef77167e870dd64c6273cd4fa..9ea71aa864b3a620667aed2c7fbbe5348341d312 100644 (file)
@@ -2243,6 +2243,12 @@ static void ext4_orphan_cleanup(struct super_block *sb,
  * in the vfs.  ext4 inode has 48 bits of i_block in fsblock units,
  * so that won't be a limiting factor.
  *
+ * However there is other limiting factor. We do store extents in the form
+ * of starting block and length, hence the resulting length of the extent
+ * covering maximum file size must fit into on-disk format containers as
+ * well. Given that length is always by 1 unit bigger than max unit (because
+ * we count 0 as well) we have to lower the s_maxbytes by one fs block.
+ *
  * Note, this does *not* consider any metadata overhead for vfs i_blocks.
  */
 static loff_t ext4_max_size(int blkbits, int has_huge_files)
@@ -2264,10 +2270,13 @@ static loff_t ext4_max_size(int blkbits, int has_huge_files)
                upper_limit <<= blkbits;
        }
 
-       /* 32-bit extent-start container, ee_block */
-       res = 1LL << 32;
+       /*
+        * 32-bit extent-start container, ee_block. We lower the maxbytes
+        * by one fs block, so ee_len can cover the extent of maximum file
+        * size
+        */
+       res = (1LL << 32) - 1;
        res <<= blkbits;
-       res -= 1;
 
        /* Sanity check against vm- & vfs- imposed limits */
        if (res > upper_limit)
index 0f7e88a7803f39e52b778eb30652654d7d61d2d1..43566d17d1b85643820f0c943f35f866869b9a80 100644 (file)
@@ -423,7 +423,14 @@ EXPORT_SYMBOL(remove_inode_hash);
 void end_writeback(struct inode *inode)
 {
        might_sleep();
+       /*
+        * We have to cycle tree_lock here because reclaim can be still in the
+        * process of removing the last page (in __delete_from_page_cache())
+        * and we must not free mapping under it.
+        */
+       spin_lock_irq(&inode->i_data.tree_lock);
        BUG_ON(inode->i_data.nrpages);
+       spin_unlock_irq(&inode->i_data.tree_lock);
        BUG_ON(!list_empty(&inode->i_data.private_list));
        BUG_ON(!(inode->i_state & I_FREEING));
        BUG_ON(inode->i_state & I_CLEAR);
index 3db5ba4568fc8efd30025a9e9906eb01a47f9c45..b3cc8586984e9748ff3c66e6c8703fa84c822c1c 100644 (file)
@@ -974,7 +974,7 @@ out_no_inode:
 out_no_read:
        printk(KERN_WARNING "%s: bread failed, dev=%s, iso_blknum=%d, block=%d\n",
                __func__, s->s_id, iso_blknum, block);
-       goto out_freesbi;
+       goto out_freebh;
 out_bad_zone_size:
        printk(KERN_WARNING "ISOFS: Bad logical zone size %ld\n",
                sbi->s_log_zone_size);
@@ -989,6 +989,7 @@ out_unknown_format:
 
 out_freebh:
        brelse(bh);
+       brelse(pri_bh);
 out_freesbi:
        kfree(opt.iocharset);
        kfree(sbi);
index 6a79fd0a1a32cdd018fea9879a6026e4dcf9c8b6..2c62c5aae82ff8936ae30036fe595aff68ab6877 100644 (file)
@@ -97,10 +97,14 @@ static int __try_to_free_cp_buf(struct journal_head *jh)
 
        if (jh->b_jlist == BJ_None && !buffer_locked(bh) &&
            !buffer_dirty(bh) && !buffer_write_io_error(bh)) {
+               /*
+                * Get our reference so that bh cannot be freed before
+                * we unlock it
+                */
+               get_bh(bh);
                JBUFFER_TRACE(jh, "remove from checkpoint list");
                ret = __jbd2_journal_remove_checkpoint(jh) + 1;
                jbd_unlock_bh_state(bh);
-               jbd2_journal_remove_journal_head(bh);
                BUFFER_TRACE(bh, "release");
                __brelse(bh);
        } else {
@@ -223,8 +227,8 @@ restart:
                        spin_lock(&journal->j_list_lock);
                        goto restart;
                }
+               get_bh(bh);
                if (buffer_locked(bh)) {
-                       atomic_inc(&bh->b_count);
                        spin_unlock(&journal->j_list_lock);
                        jbd_unlock_bh_state(bh);
                        wait_on_buffer(bh);
@@ -243,7 +247,6 @@ restart:
                 */
                released = __jbd2_journal_remove_checkpoint(jh);
                jbd_unlock_bh_state(bh);
-               jbd2_journal_remove_journal_head(bh);
                __brelse(bh);
        }
 
@@ -284,7 +287,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
        int ret = 0;
 
        if (buffer_locked(bh)) {
-               atomic_inc(&bh->b_count);
+               get_bh(bh);
                spin_unlock(&journal->j_list_lock);
                jbd_unlock_bh_state(bh);
                wait_on_buffer(bh);
@@ -316,12 +319,12 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh,
                ret = 1;
                if (unlikely(buffer_write_io_error(bh)))
                        ret = -EIO;
+               get_bh(bh);
                J_ASSERT_JH(jh, !buffer_jbddirty(bh));
                BUFFER_TRACE(bh, "remove from checkpoint");
                __jbd2_journal_remove_checkpoint(jh);
                spin_unlock(&journal->j_list_lock);
                jbd_unlock_bh_state(bh);
-               jbd2_journal_remove_journal_head(bh);
                __brelse(bh);
        } else {
                /*
@@ -554,7 +557,8 @@ int jbd2_cleanup_journal_tail(journal_t *journal)
 /*
  * journal_clean_one_cp_list
  *
- * Find all the written-back checkpoint buffers in the given list and release them.
+ * Find all the written-back checkpoint buffers in the given list and
+ * release them.
  *
  * Called with the journal locked.
  * Called with j_list_lock held.
@@ -663,8 +667,8 @@ out:
  * checkpoint lists.
  *
  * The function returns 1 if it frees the transaction, 0 otherwise.
+ * The function can free jh and bh.
  *
- * This function is called with the journal locked.
  * This function is called with j_list_lock held.
  * This function is called with jbd_lock_bh_state(jh2bh(jh))
  */
@@ -684,13 +688,14 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
        }
        journal = transaction->t_journal;
 
+       JBUFFER_TRACE(jh, "removing from transaction");
        __buffer_unlink(jh);
        jh->b_cp_transaction = NULL;
+       jbd2_journal_put_journal_head(jh);
 
        if (transaction->t_checkpoint_list != NULL ||
            transaction->t_checkpoint_io_list != NULL)
                goto out;
-       JBUFFER_TRACE(jh, "transaction has no more buffers");
 
        /*
         * There is one special case to worry about: if we have just pulled the
@@ -701,10 +706,8 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
         * The locking here around t_state is a bit sleazy.
         * See the comment at the end of jbd2_journal_commit_transaction().
         */
-       if (transaction->t_state != T_FINISHED) {
-               JBUFFER_TRACE(jh, "belongs to running/committing transaction");
+       if (transaction->t_state != T_FINISHED)
                goto out;
-       }
 
        /* OK, that was the last buffer for the transaction: we can now
           safely remove this transaction from the log */
@@ -723,7 +726,6 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
        wake_up(&journal->j_wait_logspace);
        ret = 1;
 out:
-       JBUFFER_TRACE(jh, "exit");
        return ret;
 }
 
@@ -742,6 +744,8 @@ void __jbd2_journal_insert_checkpoint(struct journal_head *jh,
        J_ASSERT_JH(jh, buffer_dirty(jh2bh(jh)) || buffer_jbddirty(jh2bh(jh)));
        J_ASSERT_JH(jh, jh->b_cp_transaction == NULL);
 
+       /* Get reference for checkpointing transaction */
+       jbd2_journal_grab_journal_head(jh2bh(jh));
        jh->b_cp_transaction = transaction;
 
        if (!transaction->t_checkpoint_list) {
index 7f21cf3aaf92e66d892259289cae31553423312b..eef6979821a4c8db91f48854c46f81c291ef4c27 100644 (file)
@@ -848,10 +848,16 @@ restart_loop:
        while (commit_transaction->t_forget) {
                transaction_t *cp_transaction;
                struct buffer_head *bh;
+               int try_to_free = 0;
 
                jh = commit_transaction->t_forget;
                spin_unlock(&journal->j_list_lock);
                bh = jh2bh(jh);
+               /*
+                * Get a reference so that bh cannot be freed before we are
+                * done with it.
+                */
+               get_bh(bh);
                jbd_lock_bh_state(bh);
                J_ASSERT_JH(jh, jh->b_transaction == commit_transaction);
 
@@ -914,28 +920,27 @@ restart_loop:
                        __jbd2_journal_insert_checkpoint(jh, commit_transaction);
                        if (is_journal_aborted(journal))
                                clear_buffer_jbddirty(bh);
-                       JBUFFER_TRACE(jh, "refile for checkpoint writeback");
-                       __jbd2_journal_refile_buffer(jh);
-                       jbd_unlock_bh_state(bh);
                } else {
                        J_ASSERT_BH(bh, !buffer_dirty(bh));
-                       /* The buffer on BJ_Forget list and not jbddirty means
+                       /*
+                        * The buffer on BJ_Forget list and not jbddirty means
                         * it has been freed by this transaction and hence it
                         * could not have been reallocated until this
                         * transaction has committed. *BUT* it could be
                         * reallocated once we have written all the data to
                         * disk and before we process the buffer on BJ_Forget
-                        * list. */
-                       JBUFFER_TRACE(jh, "refile or unfile freed buffer");
-                       __jbd2_journal_refile_buffer(jh);
-                       if (!jh->b_transaction) {
-                               jbd_unlock_bh_state(bh);
-                                /* needs a brelse */
-                               jbd2_journal_remove_journal_head(bh);
-                               release_buffer_page(bh);
-                       } else
-                               jbd_unlock_bh_state(bh);
+                        * list.
+                        */
+                       if (!jh->b_next_transaction)
+                               try_to_free = 1;
                }
+               JBUFFER_TRACE(jh, "refile or unfile buffer");
+               __jbd2_journal_refile_buffer(jh);
+               jbd_unlock_bh_state(bh);
+               if (try_to_free)
+                       release_buffer_page(bh);        /* Drops bh reference */
+               else
+                       __brelse(bh);
                cond_resched_lock(&journal->j_list_lock);
        }
        spin_unlock(&journal->j_list_lock);
index 9a78269903041934f0896148e1999e8467fd0872..0dfa5b598e68fa3f358f043c442eb39558bf6f52 100644 (file)
@@ -2078,10 +2078,9 @@ static void journal_free_journal_head(struct journal_head *jh)
  * When a buffer has its BH_JBD bit set it is immune from being released by
  * core kernel code, mainly via ->b_count.
  *
- * A journal_head may be detached from its buffer_head when the journal_head's
- * b_transaction, b_cp_transaction and b_next_transaction pointers are NULL.
- * Various places in JBD call jbd2_journal_remove_journal_head() to indicate that the
- * journal_head can be dropped if needed.
+ * A journal_head is detached from its buffer_head when the journal_head's
+ * b_jcount reaches zero. Running transaction (b_transaction) and checkpoint
+ * transaction (b_cp_transaction) hold their references to b_jcount.
  *
  * Various places in the kernel want to attach a journal_head to a buffer_head
  * _before_ attaching the journal_head to a transaction.  To protect the
@@ -2094,17 +2093,16 @@ static void journal_free_journal_head(struct journal_head *jh)
  *     (Attach a journal_head if needed.  Increments b_jcount)
  *     struct journal_head *jh = jbd2_journal_add_journal_head(bh);
  *     ...
+ *      (Get another reference for transaction)
+ *     jbd2_journal_grab_journal_head(bh);
  *     jh->b_transaction = xxx;
+ *     (Put original reference)
  *     jbd2_journal_put_journal_head(jh);
- *
- * Now, the journal_head's b_jcount is zero, but it is safe from being released
- * because it has a non-zero b_transaction.
  */
 
 /*
  * Give a buffer_head a journal_head.
  *
- * Doesn't need the journal lock.
  * May sleep.
  */
 struct journal_head *jbd2_journal_add_journal_head(struct buffer_head *bh)
@@ -2168,61 +2166,29 @@ static void __journal_remove_journal_head(struct buffer_head *bh)
        struct journal_head *jh = bh2jh(bh);
 
        J_ASSERT_JH(jh, jh->b_jcount >= 0);
-
-       get_bh(bh);
-       if (jh->b_jcount == 0) {
-               if (jh->b_transaction == NULL &&
-                               jh->b_next_transaction == NULL &&
-                               jh->b_cp_transaction == NULL) {
-                       J_ASSERT_JH(jh, jh->b_jlist == BJ_None);
-                       J_ASSERT_BH(bh, buffer_jbd(bh));
-                       J_ASSERT_BH(bh, jh2bh(jh) == bh);
-                       BUFFER_TRACE(bh, "remove journal_head");
-                       if (jh->b_frozen_data) {
-                               printk(KERN_WARNING "%s: freeing "
-                                               "b_frozen_data\n",
-                                               __func__);
-                               jbd2_free(jh->b_frozen_data, bh->b_size);
-                       }
-                       if (jh->b_committed_data) {
-                               printk(KERN_WARNING "%s: freeing "
-                                               "b_committed_data\n",
-                                               __func__);
-                               jbd2_free(jh->b_committed_data, bh->b_size);
-                       }
-                       bh->b_private = NULL;
-                       jh->b_bh = NULL;        /* debug, really */
-                       clear_buffer_jbd(bh);
-                       __brelse(bh);
-                       journal_free_journal_head(jh);
-               } else {
-                       BUFFER_TRACE(bh, "journal_head was locked");
-               }
+       J_ASSERT_JH(jh, jh->b_transaction == NULL);
+       J_ASSERT_JH(jh, jh->b_next_transaction == NULL);
+       J_ASSERT_JH(jh, jh->b_cp_transaction == NULL);
+       J_ASSERT_JH(jh, jh->b_jlist == BJ_None);
+       J_ASSERT_BH(bh, buffer_jbd(bh));
+       J_ASSERT_BH(bh, jh2bh(jh) == bh);
+       BUFFER_TRACE(bh, "remove journal_head");
+       if (jh->b_frozen_data) {
+               printk(KERN_WARNING "%s: freeing b_frozen_data\n", __func__);
+               jbd2_free(jh->b_frozen_data, bh->b_size);
        }
+       if (jh->b_committed_data) {
+               printk(KERN_WARNING "%s: freeing b_committed_data\n", __func__);
+               jbd2_free(jh->b_committed_data, bh->b_size);
+       }
+       bh->b_private = NULL;
+       jh->b_bh = NULL;        /* debug, really */
+       clear_buffer_jbd(bh);
+       journal_free_journal_head(jh);
 }
 
 /*
- * jbd2_journal_remove_journal_head(): if the buffer isn't attached to a transaction
- * and has a zero b_jcount then remove and release its journal_head.   If we did
- * see that the buffer is not used by any transaction we also "logically"
- * decrement ->b_count.
- *
- * We in fact take an additional increment on ->b_count as a convenience,
- * because the caller usually wants to do additional things with the bh
- * after calling here.
- * The caller of jbd2_journal_remove_journal_head() *must* run __brelse(bh) at some
- * time.  Once the caller has run __brelse(), the buffer is eligible for
- * reaping by try_to_free_buffers().
- */
-void jbd2_journal_remove_journal_head(struct buffer_head *bh)
-{
-       jbd_lock_bh_journal_head(bh);
-       __journal_remove_journal_head(bh);
-       jbd_unlock_bh_journal_head(bh);
-}
-
-/*
- * Drop a reference on the passed journal_head.  If it fell to zero then try to
+ * Drop a reference on the passed journal_head.  If it fell to zero then
  * release the journal_head from the buffer_head.
  */
 void jbd2_journal_put_journal_head(struct journal_head *jh)
@@ -2232,11 +2198,12 @@ void jbd2_journal_put_journal_head(struct journal_head *jh)
        jbd_lock_bh_journal_head(bh);
        J_ASSERT_JH(jh, jh->b_jcount > 0);
        --jh->b_jcount;
-       if (!jh->b_jcount && !jh->b_transaction) {
+       if (!jh->b_jcount) {
                __journal_remove_journal_head(bh);
+               jbd_unlock_bh_journal_head(bh);
                __brelse(bh);
-       }
-       jbd_unlock_bh_journal_head(bh);
+       } else
+               jbd_unlock_bh_journal_head(bh);
 }
 
 /*
index 3eec82d32fd4c6886fdf823e7d3690ca2e665162..2d7109414cdd6b7a4d21bdb2e738ff20581523a4 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/module.h>
 
 static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh);
+static void __jbd2_journal_unfile_buffer(struct journal_head *jh);
 
 /*
  * jbd2_get_transaction: obtain a new transaction_t object.
@@ -764,7 +765,6 @@ repeat:
        if (!jh->b_transaction) {
                JBUFFER_TRACE(jh, "no transaction");
                J_ASSERT_JH(jh, !jh->b_next_transaction);
-               jh->b_transaction = transaction;
                JBUFFER_TRACE(jh, "file as BJ_Reserved");
                spin_lock(&journal->j_list_lock);
                __jbd2_journal_file_buffer(jh, transaction, BJ_Reserved);
@@ -814,7 +814,6 @@ out:
  * int jbd2_journal_get_write_access() - notify intent to modify a buffer for metadata (not data) update.
  * @handle: transaction to add buffer modifications to
  * @bh:     bh to be used for metadata writes
- * @credits: variable that will receive credits for the buffer
  *
  * Returns an error code or 0 on success.
  *
@@ -896,8 +895,6 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh)
                 * committed and so it's safe to clear the dirty bit.
                 */
                clear_buffer_dirty(jh2bh(jh));
-               jh->b_transaction = transaction;
-
                /* first access by this transaction */
                jh->b_modified = 0;
 
@@ -932,7 +929,6 @@ out:
  *     non-rewindable consequences
  * @handle: transaction
  * @bh: buffer to undo
- * @credits: store the number of taken credits here (if not NULL)
  *
  * Sometimes there is a need to distinguish between metadata which has
  * been committed to disk and that which has not.  The ext3fs code uses
@@ -1232,8 +1228,6 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh)
                        __jbd2_journal_file_buffer(jh, transaction, BJ_Forget);
                } else {
                        __jbd2_journal_unfile_buffer(jh);
-                       jbd2_journal_remove_journal_head(bh);
-                       __brelse(bh);
                        if (!buffer_jbd(bh)) {
                                spin_unlock(&journal->j_list_lock);
                                jbd_unlock_bh_state(bh);
@@ -1556,19 +1550,32 @@ void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh)
                mark_buffer_dirty(bh);  /* Expose it to the VM */
 }
 
-void __jbd2_journal_unfile_buffer(struct journal_head *jh)
+/*
+ * Remove buffer from all transactions.
+ *
+ * Called with bh_state lock and j_list_lock
+ *
+ * jh and bh may be already freed when this function returns.
+ */
+static void __jbd2_journal_unfile_buffer(struct journal_head *jh)
 {
        __jbd2_journal_temp_unlink_buffer(jh);
        jh->b_transaction = NULL;
+       jbd2_journal_put_journal_head(jh);
 }
 
 void jbd2_journal_unfile_buffer(journal_t *journal, struct journal_head *jh)
 {
-       jbd_lock_bh_state(jh2bh(jh));
+       struct buffer_head *bh = jh2bh(jh);
+
+       /* Get reference so that buffer cannot be freed before we unlock it */
+       get_bh(bh);
+       jbd_lock_bh_state(bh);
        spin_lock(&journal->j_list_lock);
        __jbd2_journal_unfile_buffer(jh);
        spin_unlock(&journal->j_list_lock);
-       jbd_unlock_bh_state(jh2bh(jh));
+       jbd_unlock_bh_state(bh);
+       __brelse(bh);
 }
 
 /*
@@ -1595,8 +1602,6 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh)
                if (jh->b_jlist == BJ_None) {
                        JBUFFER_TRACE(jh, "remove from checkpoint list");
                        __jbd2_journal_remove_checkpoint(jh);
-                       jbd2_journal_remove_journal_head(bh);
-                       __brelse(bh);
                }
        }
        spin_unlock(&journal->j_list_lock);
@@ -1659,7 +1664,6 @@ int jbd2_journal_try_to_free_buffers(journal_t *journal,
                /*
                 * We take our own ref against the journal_head here to avoid
                 * having to add tons of locking around each instance of
-                * jbd2_journal_remove_journal_head() and
                 * jbd2_journal_put_journal_head().
                 */
                jh = jbd2_journal_grab_journal_head(bh);
@@ -1697,10 +1701,9 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
        int may_free = 1;
        struct buffer_head *bh = jh2bh(jh);
 
-       __jbd2_journal_unfile_buffer(jh);
-
        if (jh->b_cp_transaction) {
                JBUFFER_TRACE(jh, "on running+cp transaction");
+               __jbd2_journal_temp_unlink_buffer(jh);
                /*
                 * We don't want to write the buffer anymore, clear the
                 * bit so that we don't confuse checks in
@@ -1711,8 +1714,7 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction)
                may_free = 0;
        } else {
                JBUFFER_TRACE(jh, "on running transaction");
-               jbd2_journal_remove_journal_head(bh);
-               __brelse(bh);
+               __jbd2_journal_unfile_buffer(jh);
        }
        return may_free;
 }
@@ -1990,6 +1992,8 @@ void __jbd2_journal_file_buffer(struct journal_head *jh,
 
        if (jh->b_transaction)
                __jbd2_journal_temp_unlink_buffer(jh);
+       else
+               jbd2_journal_grab_journal_head(bh);
        jh->b_transaction = transaction;
 
        switch (jlist) {
@@ -2041,9 +2045,10 @@ void jbd2_journal_file_buffer(struct journal_head *jh,
  * already started to be used by a subsequent transaction, refile the
  * buffer on that transaction's metadata list.
  *
- * Called under journal->j_list_lock
- *
+ * Called under j_list_lock
  * Called under jbd_lock_bh_state(jh2bh(jh))
+ *
+ * jh and bh may be already free when this function returns
  */
 void __jbd2_journal_refile_buffer(struct journal_head *jh)
 {
@@ -2067,6 +2072,11 @@ void __jbd2_journal_refile_buffer(struct journal_head *jh)
 
        was_dirty = test_clear_buffer_jbddirty(bh);
        __jbd2_journal_temp_unlink_buffer(jh);
+       /*
+        * We set b_transaction here because b_next_transaction will inherit
+        * our jh reference and thus __jbd2_journal_file_buffer() must not
+        * take a new one.
+        */
        jh->b_transaction = jh->b_next_transaction;
        jh->b_next_transaction = NULL;
        if (buffer_freed(bh))
@@ -2083,30 +2093,21 @@ void __jbd2_journal_refile_buffer(struct journal_head *jh)
 }
 
 /*
- * For the unlocked version of this call, also make sure that any
- * hanging journal_head is cleaned up if necessary.
- *
- * __jbd2_journal_refile_buffer is usually called as part of a single locked
- * operation on a buffer_head, in which the caller is probably going to
- * be hooking the journal_head onto other lists.  In that case it is up
- * to the caller to remove the journal_head if necessary.  For the
- * unlocked jbd2_journal_refile_buffer call, the caller isn't going to be
- * doing anything else to the buffer so we need to do the cleanup
- * ourselves to avoid a jh leak.
- *
- * *** The journal_head may be freed by this call! ***
+ * __jbd2_journal_refile_buffer() with necessary locking added. We take our
+ * bh reference so that we can safely unlock bh.
+ *
+ * The jh and bh may be freed by this call.
  */
 void jbd2_journal_refile_buffer(journal_t *journal, struct journal_head *jh)
 {
        struct buffer_head *bh = jh2bh(jh);
 
+       /* Get reference so that buffer cannot be freed before we unlock it */
+       get_bh(bh);
        jbd_lock_bh_state(bh);
        spin_lock(&journal->j_list_lock);
-
        __jbd2_journal_refile_buffer(jh);
        jbd_unlock_bh_state(bh);
-       jbd2_journal_remove_journal_head(bh);
-
        spin_unlock(&journal->j_list_lock);
        __brelse(bh);
 }
index c5ce6c1d1ff406c567d0b59d0ffe03ed11b8daa5..2f3f531f36064772dfd4e934847dd5c33fd1cbe4 100644 (file)
@@ -66,9 +66,9 @@ static int jfs_open(struct inode *inode, struct file *file)
                struct jfs_inode_info *ji = JFS_IP(inode);
                spin_lock_irq(&ji->ag_lock);
                if (ji->active_ag == -1) {
-                       ji->active_ag = ji->agno;
-                       atomic_inc(
-                           &JFS_SBI(inode->i_sb)->bmap->db_active[ji->agno]);
+                       struct jfs_sb_info *jfs_sb = JFS_SBI(inode->i_sb);
+                       ji->active_ag = BLKTOAG(addressPXD(&ji->ixpxd), jfs_sb);
+                       atomic_inc( &jfs_sb->bmap->db_active[ji->active_ag]);
                }
                spin_unlock_irq(&ji->ag_lock);
        }
index ed53a4740168bc2d7692ea07531663049d991dfe..b78b2f978f043dae0f18c24713532218b3201582 100644 (file)
@@ -397,7 +397,7 @@ int diRead(struct inode *ip)
        release_metapage(mp);
 
        /* set the ag for the inode */
-       JFS_IP(ip)->agno = BLKTOAG(agstart, sbi);
+       JFS_IP(ip)->agstart = agstart;
        JFS_IP(ip)->active_ag = -1;
 
        return (rc);
@@ -901,7 +901,7 @@ int diFree(struct inode *ip)
 
        /* get the allocation group for this ino.
         */
-       agno = JFS_IP(ip)->agno;
+       agno = BLKTOAG(JFS_IP(ip)->agstart, JFS_SBI(ip->i_sb));
 
        /* Lock the AG specific inode map information
         */
@@ -1315,12 +1315,11 @@ int diFree(struct inode *ip)
 static inline void
 diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp)
 {
-       struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);
        struct jfs_inode_info *jfs_ip = JFS_IP(ip);
 
        ip->i_ino = (iagno << L2INOSPERIAG) + ino;
        jfs_ip->ixpxd = iagp->inoext[extno];
-       jfs_ip->agno = BLKTOAG(le64_to_cpu(iagp->agstart), sbi);
+       jfs_ip->agstart = le64_to_cpu(iagp->agstart);
        jfs_ip->active_ag = -1;
 }
 
@@ -1379,7 +1378,7 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip)
         */
 
        /* get the ag number of this iag */
-       agno = JFS_IP(pip)->agno;
+       agno = BLKTOAG(JFS_IP(pip)->agstart, JFS_SBI(pip->i_sb));
 
        if (atomic_read(&JFS_SBI(pip->i_sb)->bmap->db_active[agno])) {
                /*
@@ -2921,10 +2920,9 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap)
                        continue;
                }
 
-               /* agstart that computes to the same ag is treated as same; */
                agstart = le64_to_cpu(iagp->agstart);
-               /* iagp->agstart = agstart & ~(mp->db_agsize - 1); */
                n = agstart >> mp->db_agl2size;
+               iagp->agstart = cpu_to_le64((s64)n << mp->db_agl2size);
 
                /* compute backed inodes */
                numinos = (EXTSPERIAG - le32_to_cpu(iagp->nfreeexts))
index 1439f119ec830876ded18b7c5bf66b2ed1fdc80d..584a4a1a6e81478a2e212b2f20ec08400159e946 100644 (file)
@@ -50,8 +50,9 @@ struct jfs_inode_info {
        short   btindex;        /* btpage entry index*/
        struct inode *ipimap;   /* inode map                    */
        unsigned long cflag;    /* commit flags         */
+       u64     agstart;        /* agstart of the containing IAG */
        u16     bxflag;         /* xflag of pseudo buffer?      */
-       unchar  agno;           /* ag number                    */
+       unchar  pad;
        signed char active_ag;  /* ag currently allocating from */
        lid_t   blid;           /* lid of pseudo buffer?        */
        lid_t   atlhead;        /* anonymous tlock list head    */
index 8ea5efb5a34e3c5ccc01d24d4764469b20a71ddc..8d0c1c7c08204177e5f6f6127daa5caa7c545757 100644 (file)
@@ -80,7 +80,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize)
        int log_formatted = 0;
        struct inode *iplist[1];
        struct jfs_superblock *j_sb, *j_sb2;
-       uint old_agsize;
+       s64 old_agsize;
        int agsizechanged = 0;
        struct buffer_head *bh, *bh2;
 
index adb45ec9038cc95530e5d1be50d521a927110ac2..e374050a911c6141342bf5b464bb04fca396ce3e 100644 (file)
@@ -708,7 +708,13 @@ static void nlmclnt_unlock_callback(struct rpc_task *task, void *data)
 
        if (task->tk_status < 0) {
                dprintk("lockd: unlock failed (err = %d)\n", -task->tk_status);
-               goto retry_rebind;
+               switch (task->tk_status) {
+               case -EACCES:
+               case -EIO:
+                       goto die;
+               default:
+                       goto retry_rebind;
+               }
        }
        if (status == NLM_LCK_DENIED_GRACE_PERIOD) {
                rpc_delay(task, NLMCLNT_GRACE_WAIT);
index 9ed89d1663f839c86b84e133617a47f4d855ee25..1afae26cf2364936d3053801c41f12cbb06f29d9 100644 (file)
@@ -555,13 +555,6 @@ static int logfs_symlink(struct inode *dir, struct dentry *dentry,
        return __logfs_create(dir, dentry, inode, target, destlen);
 }
 
-static int logfs_permission(struct inode *inode, int mask, unsigned int flags)
-{
-       if (flags & IPERM_FLAG_RCU)
-               return -ECHILD;
-       return generic_permission(inode, mask, flags, NULL);
-}
-
 static int logfs_link(struct dentry *old_dentry, struct inode *dir,
                struct dentry *dentry)
 {
@@ -820,7 +813,6 @@ const struct inode_operations logfs_dir_iops = {
        .mknod          = logfs_mknod,
        .rename         = logfs_rename,
        .rmdir          = logfs_rmdir,
-       .permission     = logfs_permission,
        .symlink        = logfs_symlink,
        .unlink         = logfs_unlink,
 };
index 9802345df5e78c86396fa05f4c29c760e3a270a9..0223c41fb1146cb529a92c784912498e15829a00 100644 (file)
@@ -238,7 +238,8 @@ int generic_permission(struct inode *inode, int mask, unsigned int flags,
 
        /*
         * Read/write DACs are always overridable.
-        * Executable DACs are overridable if at least one exec bit is set.
+        * Executable DACs are overridable for all directories and
+        * for non-directories that have least one exec bit set.
         */
        if (!(mask & MAY_EXEC) || execute_ok(inode))
                if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE))
@@ -812,6 +813,11 @@ static int follow_automount(struct path *path, unsigned flags,
        if (!mnt) /* mount collision */
                return 0;
 
+       if (!*need_mntput) {
+               /* lock_mount() may release path->mnt on error */
+               mntget(path->mnt);
+               *need_mntput = true;
+       }
        err = finish_automount(mnt, path);
 
        switch (err) {
@@ -819,12 +825,9 @@ static int follow_automount(struct path *path, unsigned flags,
                /* Someone else made a mount here whilst we were busy */
                return 0;
        case 0:
-               dput(path->dentry);
-               if (*need_mntput)
-                       mntput(path->mnt);
+               path_put(path);
                path->mnt = mnt;
                path->dentry = dget(mnt->mnt_root);
-               *need_mntput = true;
                return 0;
        default:
                return err;
@@ -844,9 +847,10 @@ static int follow_automount(struct path *path, unsigned flags,
  */
 static int follow_managed(struct path *path, unsigned flags)
 {
+       struct vfsmount *mnt = path->mnt; /* held by caller, must be left alone */
        unsigned managed;
        bool need_mntput = false;
-       int ret;
+       int ret = 0;
 
        /* Given that we're not holding a lock here, we retain the value in a
         * local variable for each dentry as we look at it so that we don't see
@@ -861,7 +865,7 @@ static int follow_managed(struct path *path, unsigned flags)
                        BUG_ON(!path->dentry->d_op->d_manage);
                        ret = path->dentry->d_op->d_manage(path->dentry, false);
                        if (ret < 0)
-                               return ret == -EISDIR ? 0 : ret;
+                               break;
                }
 
                /* Transit to a mounted filesystem. */
@@ -887,14 +891,19 @@ static int follow_managed(struct path *path, unsigned flags)
                if (managed & DCACHE_NEED_AUTOMOUNT) {
                        ret = follow_automount(path, flags, &need_mntput);
                        if (ret < 0)
-                               return ret == -EISDIR ? 0 : ret;
+                               break;
                        continue;
                }
 
                /* We didn't change the current path point */
                break;
        }
-       return 0;
+
+       if (need_mntput && path->mnt == mnt)
+               mntput(path->mnt);
+       if (ret == -EISDIR)
+               ret = 0;
+       return ret;
 }
 
 int follow_down_one(struct path *path)
@@ -1003,9 +1012,6 @@ failed:
  * Follow down to the covering mount currently visible to userspace.  At each
  * point, the filesystem owning that dentry may be queried as to whether the
  * caller is permitted to proceed or not.
- *
- * Care must be taken as namespace_sem may be held (indicated by mounting_here
- * being true).
  */
 int follow_down(struct path *path)
 {
@@ -2713,8 +2719,10 @@ static long do_unlinkat(int dfd, const char __user *pathname)
        error = PTR_ERR(dentry);
        if (!IS_ERR(dentry)) {
                /* Why not before? Because we want correct error value */
+               if (nd.last.name[nd.last.len])
+                       goto slashes;
                inode = dentry->d_inode;
-               if (nd.last.name[nd.last.len] || !inode)
+               if (!inode)
                        goto slashes;
                ihold(inode);
                error = mnt_want_write(nd.path.mnt);
index 144f2a3c718575cf0b3448118cd881600339e5b6..6f4850deb272857ae5829251d64bf7aabf702130 100644 (file)
@@ -256,7 +256,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
 
        nfs_attr_check_mountpoint(sb, fattr);
 
-       if ((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0 && (fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0)
+       if (((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0) &&
+           !nfs_attr_use_mounted_on_fileid(fattr))
                goto out_no_inode;
        if ((fattr->valid & NFS_ATTR_FATTR_TYPE) == 0)
                goto out_no_inode;
@@ -1294,7 +1295,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                if (new_isize != cur_isize) {
                        /* Do we perhaps have any outstanding writes, or has
                         * the file grown beyond our last write? */
-                       if (nfsi->npages == 0 || new_isize > cur_isize) {
+                       if ((nfsi->npages == 0 && !test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) ||
+                            new_isize > cur_isize) {
                                i_size_write(inode, new_isize);
                                invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
                        }
index b9056cbe68d6c0f8f6c9db7b22c5563d5fc1f7d7..2a55347a2daa85f66aa24b44d7bb7c93efe1d409 100644 (file)
@@ -45,6 +45,17 @@ static inline void nfs_attr_check_mountpoint(struct super_block *parent, struct
                fattr->valid |= NFS_ATTR_FATTR_MOUNTPOINT;
 }
 
+static inline int nfs_attr_use_mounted_on_fileid(struct nfs_fattr *fattr)
+{
+       if (((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) == 0) ||
+           (((fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0) &&
+            ((fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) == 0)))
+               return 0;
+
+       fattr->fileid = fattr->mounted_on_fileid;
+       return 1;
+}
+
 struct nfs_clone_mount {
        const struct super_block *sb;
        const struct dentry *dentry;
index 426908809c9738601f00cbf25fd220512f2141c1..0bafcc91c27f8d8513dc1a7c8776fefd3411eee2 100644 (file)
@@ -30,6 +30,7 @@
  */
 
 #include <linux/nfs_fs.h>
+#include <linux/nfs_page.h>
 
 #include "internal.h"
 #include "nfs4filelayout.h"
@@ -552,13 +553,18 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
                __func__, nfl_util, fl->num_fh, fl->first_stripe_index,
                fl->pattern_offset);
 
-       if (!fl->num_fh)
+       /* Note that a zero value for num_fh is legal for STRIPE_SPARSE.
+        * Futher checking is done in filelayout_check_layout */
+       if (fl->num_fh < 0 || fl->num_fh >
+           max(NFS4_PNFS_MAX_STRIPE_CNT, NFS4_PNFS_MAX_MULTI_CNT))
                goto out_err;
 
-       fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
-                              gfp_flags);
-       if (!fl->fh_array)
-               goto out_err;
+       if (fl->num_fh > 0) {
+               fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
+                                      gfp_flags);
+               if (!fl->fh_array)
+                       goto out_err;
+       }
 
        for (i = 0; i < fl->num_fh; i++) {
                /* Do we want to use a mempool here? */
@@ -661,8 +667,9 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
        u64 p_stripe, r_stripe;
        u32 stripe_unit;
 
-       if (!pnfs_generic_pg_test(pgio, prev, req))
-               return 0;
+       if (!pnfs_generic_pg_test(pgio, prev, req) ||
+           !nfs_generic_pg_test(pgio, prev, req))
+               return false;
 
        if (!pgio->pg_lseg)
                return 1;
index d2c4b59c896d3dda94980f789d91601f184cc53d..5879b23e0c99a1b0dfcff8c072bb0432ade497bf 100644 (file)
@@ -2265,12 +2265,14 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
        return nfs4_map_errors(status);
 }
 
+static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr);
 /*
  * Get locations and (maybe) other attributes of a referral.
  * Note that we'll actually follow the referral later when
  * we detect fsid mismatch in inode revalidation
  */
-static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct nfs_fattr *fattr, struct nfs_fh *fhandle)
+static int nfs4_get_referral(struct inode *dir, const struct qstr *name,
+                            struct nfs_fattr *fattr, struct nfs_fh *fhandle)
 {
        int status = -ENOMEM;
        struct page *page = NULL;
@@ -2288,15 +2290,16 @@ static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct
                goto out;
        /* Make sure server returned a different fsid for the referral */
        if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) {
-               dprintk("%s: server did not return a different fsid for a referral at %s\n", __func__, name->name);
+               dprintk("%s: server did not return a different fsid for"
+                       " a referral at %s\n", __func__, name->name);
                status = -EIO;
                goto out;
        }
+       /* Fixup attributes for the nfs_lookup() call to nfs_fhget() */
+       nfs_fixup_referral_attributes(&locations->fattr);
 
+       /* replace the lookup nfs_fattr with the locations nfs_fattr */
        memcpy(fattr, &locations->fattr, sizeof(struct nfs_fattr));
-       fattr->valid |= NFS_ATTR_FATTR_V4_REFERRAL;
-       if (!fattr->mode)
-               fattr->mode = S_IFDIR;
        memset(fhandle, 0, sizeof(struct nfs_fh));
 out:
        if (page)
@@ -4667,11 +4670,15 @@ static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list,
        return len;
 }
 
+/*
+ * nfs_fhget will use either the mounted_on_fileid or the fileid
+ */
 static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr)
 {
-       if (!((fattr->valid & NFS_ATTR_FATTR_FILEID) &&
-               (fattr->valid & NFS_ATTR_FATTR_FSID) &&
-               (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)))
+       if (!(((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) ||
+              (fattr->valid & NFS_ATTR_FATTR_FILEID)) &&
+             (fattr->valid & NFS_ATTR_FATTR_FSID) &&
+             (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)))
                return;
 
        fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE |
@@ -4686,7 +4693,6 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
        struct nfs_server *server = NFS_SERVER(dir);
        u32 bitmask[2] = {
                [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS,
-               [1] = FATTR4_WORD1_MOUNTED_ON_FILEID,
        };
        struct nfs4_fs_locations_arg args = {
                .dir_fh = NFS_FH(dir),
@@ -4705,11 +4711,18 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
        int status;
 
        dprintk("%s: start\n", __func__);
+
+       /* Ask for the fileid of the absent filesystem if mounted_on_fileid
+        * is not supported */
+       if (NFS_SERVER(dir)->attr_bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
+               bitmask[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID;
+       else
+               bitmask[0] |= FATTR4_WORD0_FILEID;
+
        nfs_fattr_init(&fs_locations->fattr);
        fs_locations->server = server;
        fs_locations->nlocations = 0;
        status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
-       nfs_fixup_referral_attributes(&fs_locations->fattr);
        dprintk("%s: returned status = %d\n", __func__, status);
        return status;
 }
@@ -5098,7 +5111,6 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
        if (mxresp_sz == 0)
                mxresp_sz = NFS_MAX_FILE_IO_SIZE;
        /* Fore channel attributes */
-       args->fc_attrs.headerpadsz = 0;
        args->fc_attrs.max_rqst_sz = mxrqst_sz;
        args->fc_attrs.max_resp_sz = mxresp_sz;
        args->fc_attrs.max_ops = NFS4_MAX_OPS;
@@ -5111,7 +5123,6 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args)
                args->fc_attrs.max_ops, args->fc_attrs.max_reqs);
 
        /* Back channel attributes */
-       args->bc_attrs.headerpadsz = 0;
        args->bc_attrs.max_rqst_sz = PAGE_SIZE;
        args->bc_attrs.max_resp_sz = PAGE_SIZE;
        args->bc_attrs.max_resp_sz_cached = 0;
@@ -5131,8 +5142,6 @@ static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args
        struct nfs4_channel_attrs *sent = &args->fc_attrs;
        struct nfs4_channel_attrs *rcvd = &session->fc_attrs;
 
-       if (rcvd->headerpadsz > sent->headerpadsz)
-               return -EINVAL;
        if (rcvd->max_resp_sz > sent->max_resp_sz)
                return -EINVAL;
        /*
@@ -5697,6 +5706,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
 {
        struct nfs4_layoutreturn *lrp = calldata;
        struct nfs_server *server;
+       struct pnfs_layout_hdr *lo = NFS_I(lrp->args.inode)->layout;
 
        dprintk("--> %s\n", __func__);
 
@@ -5708,16 +5718,15 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata)
                nfs_restart_rpc(task, lrp->clp);
                return;
        }
+       spin_lock(&lo->plh_inode->i_lock);
        if (task->tk_status == 0) {
-               struct pnfs_layout_hdr *lo = NFS_I(lrp->args.inode)->layout;
-
                if (lrp->res.lrs_present) {
-                       spin_lock(&lo->plh_inode->i_lock);
                        pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
-                       spin_unlock(&lo->plh_inode->i_lock);
                } else
                        BUG_ON(!list_empty(&lo->plh_segs));
        }
+       lo->plh_block_lgets--;
+       spin_unlock(&lo->plh_inode->i_lock);
        dprintk("<-- %s\n", __func__);
 }
 
index d869a5e5464b46cf0276e8df3466dcfafd83acda..6870bc61ceec4083f80818c4a31f934dab3227b1 100644 (file)
@@ -255,7 +255,7 @@ static int nfs4_stat_to_errno(int);
 #define decode_fs_locations_maxsz \
                                (0)
 #define encode_secinfo_maxsz   (op_encode_hdr_maxsz + nfs4_name_maxsz)
-#define decode_secinfo_maxsz   (op_decode_hdr_maxsz + 4 + (NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)))
+#define decode_secinfo_maxsz   (op_decode_hdr_maxsz + 1 + ((NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)) / 4))
 
 #if defined(CONFIG_NFS_V4_1)
 #define NFS4_MAX_MACHINE_NAME_LEN (64)
@@ -1725,7 +1725,7 @@ static void encode_create_session(struct xdr_stream *xdr,
        *p++ = cpu_to_be32(args->flags);                        /*flags */
 
        /* Fore Channel */
-       *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */
+       *p++ = cpu_to_be32(0);                          /* header padding size */
        *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */
        *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */
        *p++ = cpu_to_be32(max_resp_sz_cached);         /* Max resp sz cached */
@@ -1734,7 +1734,7 @@ static void encode_create_session(struct xdr_stream *xdr,
        *p++ = cpu_to_be32(0);                          /* rdmachannel_attrs */
 
        /* Back Channel */
-       *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */
+       *p++ = cpu_to_be32(0);                          /* header padding size */
        *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */
        *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */
        *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached);  /* Max resp sz cached */
@@ -3098,7 +3098,7 @@ out_overflow:
        return -EIO;
 }
 
-static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap)
+static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res)
 {
        __be32 *p;
 
@@ -3109,7 +3109,7 @@ static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap)
                if (unlikely(!p))
                        goto out_overflow;
                bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
-               return -be32_to_cpup(p);
+               *res = -be32_to_cpup(p);
        }
        return 0;
 out_overflow:
@@ -4070,6 +4070,7 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
        int status;
        umode_t fmode = 0;
        uint32_t type;
+       int32_t err;
 
        status = decode_attr_type(xdr, bitmap, &type);
        if (status < 0)
@@ -4095,13 +4096,12 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
                goto xdr_error;
        fattr->valid |= status;
 
-       status = decode_attr_error(xdr, bitmap);
-       if (status == -NFS4ERR_WRONGSEC) {
-               nfs_fixup_secinfo_attributes(fattr, fh);
-               status = 0;
-       }
+       err = 0;
+       status = decode_attr_error(xdr, bitmap, &err);
        if (status < 0)
                goto xdr_error;
+       if (err == -NFS4ERR_WRONGSEC)
+               nfs_fixup_secinfo_attributes(fattr, fh);
 
        status = decode_attr_filehandle(xdr, bitmap, fh);
        if (status < 0)
@@ -4997,12 +4997,14 @@ static int decode_chan_attrs(struct xdr_stream *xdr,
                             struct nfs4_channel_attrs *attrs)
 {
        __be32 *p;
-       u32 nr_attrs;
+       u32 nr_attrs, val;
 
        p = xdr_inline_decode(xdr, 28);
        if (unlikely(!p))
                goto out_overflow;
-       attrs->headerpadsz = be32_to_cpup(p++);
+       val = be32_to_cpup(p++);        /* headerpadsz */
+       if (val)
+               return -EINVAL;         /* no support for header padding yet */
        attrs->max_rqst_sz = be32_to_cpup(p++);
        attrs->max_resp_sz = be32_to_cpup(p++);
        attrs->max_resp_sz_cached = be32_to_cpup(p++);
index 9cf208df1f2594b0ecbfc61e673e97c32844156a..8ff2ea3f10ef865ecd2b60ee89122afb159f6cdc 100644 (file)
@@ -108,7 +108,6 @@ _dev_list_add(const struct nfs_server *nfss,
                de = n;
        }
 
-       atomic_inc(&de->id_node.ref);
        return de;
 }
 
@@ -1001,6 +1000,9 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio,
        if (!pnfs_generic_pg_test(pgio, prev, req))
                return false;
 
+       if (pgio->pg_lseg == NULL)
+               return true;
+
        return pgio->pg_count + req->wb_bytes <=
                        OBJIO_LSEG(pgio->pg_lseg)->max_io_size;
 }
index dc3956c0de80df2c6360c97f54e75663b6505924..1d06f8e2adeaec53fd8dc71c4e1a9cae2baef9c3 100644 (file)
@@ -291,7 +291,7 @@ objlayout_read_done(struct objlayout_io_state *state, ssize_t status, bool sync)
        struct nfs_read_data *rdata;
 
        state->status = status;
-       dprintk("%s: Begin status=%ld eof=%d\n", __func__, status, eof);
+       dprintk("%s: Begin status=%zd eof=%d\n", __func__, status, eof);
        rdata = state->rpcdata;
        rdata->task.tk_status = status;
        if (status >= 0) {
index 7913961aff225995fda011973ed048276ae826e9..009855716286bf098eba9ac20a6c04db201d3d06 100644 (file)
@@ -204,7 +204,7 @@ nfs_wait_on_request(struct nfs_page *req)
                        TASK_UNINTERRUPTIBLE);
 }
 
-static bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_page *prev, struct nfs_page *req)
+bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_page *prev, struct nfs_page *req)
 {
        /*
         * FIXME: ideally we should be able to coalesce all requests
@@ -218,6 +218,7 @@ static bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_p
 
        return desc->pg_count + req->wb_bytes <= desc->pg_bsize;
 }
+EXPORT_SYMBOL_GPL(nfs_generic_pg_test);
 
 /**
  * nfs_pageio_init - initialise a page io descriptor
index 8c1309d852a6f4709a53c4fb6e7470371aaf1ea8..29c0ca7fc347cdf8cebf6bd83960de18942ca4e4 100644 (file)
@@ -634,14 +634,16 @@ _pnfs_return_layout(struct inode *ino)
 
        spin_lock(&ino->i_lock);
        lo = nfsi->layout;
-       if (!lo || !mark_matching_lsegs_invalid(lo, &tmp_list, NULL)) {
+       if (!lo) {
                spin_unlock(&ino->i_lock);
-               dprintk("%s: no layout segments to return\n", __func__);
-               goto out;
+               dprintk("%s: no layout to return\n", __func__);
+               return status;
        }
        stateid = nfsi->layout->plh_stateid;
        /* Reference matched in nfs4_layoutreturn_release */
        get_layout_hdr(lo);
+       mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
+       lo->plh_block_lgets++;
        spin_unlock(&ino->i_lock);
        pnfs_free_lseg_list(&tmp_list);
 
@@ -650,6 +652,9 @@ _pnfs_return_layout(struct inode *ino)
        lrp = kzalloc(sizeof(*lrp), GFP_KERNEL);
        if (unlikely(lrp == NULL)) {
                status = -ENOMEM;
+               set_bit(NFS_LAYOUT_RW_FAILED, &lo->plh_flags);
+               set_bit(NFS_LAYOUT_RO_FAILED, &lo->plh_flags);
+               put_layout_hdr(lo);
                goto out;
        }
 
@@ -887,7 +892,7 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo,
                        ret = get_lseg(lseg);
                        break;
                }
-               if (cmp_layout(range, &lseg->pls_range) > 0)
+               if (lseg->pls_range.offset > range->offset)
                        break;
        }
 
@@ -1059,23 +1064,36 @@ pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev,
                gfp_flags = GFP_NOFS;
        }
 
-       if (pgio->pg_count == prev->wb_bytes) {
+       if (pgio->pg_lseg == NULL) {
+               if (pgio->pg_count != prev->wb_bytes)
+                       return true;
                /* This is first coelesce call for a series of nfs_pages */
                pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                                   prev->wb_context,
-                                                  req_offset(req),
+                                                  req_offset(prev),
                                                   pgio->pg_count,
                                                   access_type,
                                                   gfp_flags);
-               return true;
+               if (pgio->pg_lseg == NULL)
+                       return true;
        }
 
-       if (pgio->pg_lseg &&
-           req_offset(req) > end_offset(pgio->pg_lseg->pls_range.offset,
-                                        pgio->pg_lseg->pls_range.length))
-               return false;
-
-       return true;
+       /*
+        * Test if a nfs_page is fully contained in the pnfs_layout_range.
+        * Note that this test makes several assumptions:
+        * - that the previous nfs_page in the struct nfs_pageio_descriptor
+        *   is known to lie within the range.
+        *   - that the nfs_page being tested is known to be contiguous with the
+        *   previous nfs_page.
+        *   - Layout ranges are page aligned, so we only have to test the
+        *   start offset of the request.
+        *
+        * Please also note that 'end_offset' is actually the offset of the
+        * first byte that lies outside the pnfs_layout_range. FIXME?
+        *
+        */
+       return req_offset(req) < end_offset(pgio->pg_lseg->pls_range.offset,
+                                        pgio->pg_lseg->pls_range.length);
 }
 EXPORT_SYMBOL_GPL(pnfs_generic_pg_test);
 
index 48d0a8e4d06212264469df6b4c21acba110597f0..96bf4e6f45beda6d9646c5b19a48d13ef1ec3f5d 100644 (file)
@@ -186,6 +186,7 @@ int pnfs_ld_read_done(struct nfs_read_data *);
 /* pnfs_dev.c */
 struct nfs4_deviceid_node {
        struct hlist_node               node;
+       struct hlist_node               tmpnode;
        const struct pnfs_layoutdriver_type *ld;
        const struct nfs_client         *nfs_client;
        struct nfs4_deviceid            deviceid;
index c65e133ce9c071d17e26729fe767b23f4271b445..f0f8e1e22f6c945119ff359491dce07b79a0cf69 100644 (file)
@@ -174,6 +174,7 @@ nfs4_init_deviceid_node(struct nfs4_deviceid_node *d,
                        const struct nfs4_deviceid *id)
 {
        INIT_HLIST_NODE(&d->node);
+       INIT_HLIST_NODE(&d->tmpnode);
        d->ld = ld;
        d->nfs_client = nfs_client;
        d->deviceid = *id;
@@ -208,6 +209,7 @@ nfs4_insert_deviceid_node(struct nfs4_deviceid_node *new)
 
        hlist_add_head_rcu(&new->node, &nfs4_deviceid_cache[hash]);
        spin_unlock(&nfs4_deviceid_lock);
+       atomic_inc(&new->ref);
 
        return new;
 }
@@ -238,24 +240,29 @@ static void
 _deviceid_purge_client(const struct nfs_client *clp, long hash)
 {
        struct nfs4_deviceid_node *d;
-       struct hlist_node *n, *next;
+       struct hlist_node *n;
        HLIST_HEAD(tmp);
 
+       spin_lock(&nfs4_deviceid_lock);
        rcu_read_lock();
        hlist_for_each_entry_rcu(d, n, &nfs4_deviceid_cache[hash], node)
                if (d->nfs_client == clp && atomic_read(&d->ref)) {
                        hlist_del_init_rcu(&d->node);
-                       hlist_add_head(&d->node, &tmp);
+                       hlist_add_head(&d->tmpnode, &tmp);
                }
        rcu_read_unlock();
+       spin_unlock(&nfs4_deviceid_lock);
 
        if (hlist_empty(&tmp))
                return;
 
        synchronize_rcu();
-       hlist_for_each_entry_safe(d, n, next, &tmp, node)
+       while (!hlist_empty(&tmp)) {
+               d = hlist_entry(tmp.first, struct nfs4_deviceid_node, tmpnode);
+               hlist_del(&d->tmpnode);
                if (atomic_dec_and_test(&d->ref))
                        d->ld->free_deviceid_node(d);
+       }
 }
 
 void
@@ -263,8 +270,8 @@ nfs4_deviceid_purge_client(const struct nfs_client *clp)
 {
        long h;
 
-       spin_lock(&nfs4_deviceid_lock);
+       if (!(clp->cl_exchange_flags & EXCHGID4_FLAG_USE_PNFS_MDS))
+               return;
        for (h = 0; h < NFS4_DEVICE_ID_HASH_SIZE; h++)
                _deviceid_purge_client(clp, h);
-       spin_unlock(&nfs4_deviceid_lock);
 }
index 18b3e8975fe05c2364dd507d50b364b4c13b0dfd..fbb2a5ef5817cfa8c3800c0a1205562ae47549db 100644 (file)
@@ -82,6 +82,7 @@ config NFSD_V4
        select NFSD_V3
        select FS_POSIX_ACL
        select SUNRPC_GSS
+       select CRYPTO
        help
          This option enables support in your system's NFS server for
          version 4 of the NFS protocol (RFC 3530).
index 1f5eae40f34ef4aa57174be24445a39854906e71..2b1449dd2f495b4c6389399b8e29e0da7165d2c2 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/lockd/lockd.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/gss_api.h>
+#include <linux/sunrpc/gss_krb5_enctypes.h>
 
 #include "idmap.h"
 #include "nfsd.h"
@@ -189,18 +190,10 @@ static struct file_operations export_features_operations = {
        .release        = single_release,
 };
 
-#ifdef CONFIG_SUNRPC_GSS
+#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
 static int supported_enctypes_show(struct seq_file *m, void *v)
 {
-       struct gss_api_mech *k5mech;
-
-       k5mech = gss_mech_get_by_name("krb5");
-       if (k5mech == NULL)
-               goto out;
-       if (k5mech->gm_upcall_enctypes != NULL)
-               seq_printf(m, k5mech->gm_upcall_enctypes);
-       gss_mech_put(k5mech);
-out:
+       seq_printf(m, KRB5_SUPPORTED_ENCTYPES);
        return 0;
 }
 
@@ -215,7 +208,7 @@ static struct file_operations supported_enctypes_ops = {
        .llseek         = seq_lseek,
        .release        = single_release,
 };
-#endif /* CONFIG_SUNRPC_GSS */
+#endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
 
 extern int nfsd_pool_stats_open(struct inode *inode, struct file *file);
 extern int nfsd_pool_stats_release(struct inode *inode, struct file *file);
@@ -1427,9 +1420,9 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
                [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
                [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
                [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
-#ifdef CONFIG_SUNRPC_GSS
+#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
                [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO},
-#endif /* CONFIG_SUNRPC_GSS */
+#endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
 #ifdef CONFIG_NFSD_V4
                [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
                [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR},
index d5718273bb32f216922c474635ad479c7912064d..fd0acca5370a5da699fe62a5d94d0b6e81f67b78 100644 (file)
@@ -696,7 +696,15 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor
 }
 #endif /* CONFIG_NFSD_V3 */
 
+static int nfsd_open_break_lease(struct inode *inode, int access)
+{
+       unsigned int mode;
 
+       if (access & NFSD_MAY_NOT_BREAK_LEASE)
+               return 0;
+       mode = (access & NFSD_MAY_WRITE) ? O_WRONLY : O_RDONLY;
+       return break_lease(inode, mode | O_NONBLOCK);
+}
 
 /*
  * Open an existing file or directory.
@@ -744,12 +752,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
        if (!inode->i_fop)
                goto out;
 
-       /*
-        * Check to see if there are any leases on this file.
-        * This may block while leases are broken.
-        */
-       if (!(access & NFSD_MAY_NOT_BREAK_LEASE))
-               host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? O_WRONLY : 0));
+       host_err = nfsd_open_break_lease(inode, access);
        if (host_err) /* NOMEM or WOULDBLOCK */
                goto out_nfserr;
 
@@ -1660,8 +1663,10 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
        if (!dold->d_inode)
                goto out_drop_write;
        host_err = nfsd_break_lease(dold->d_inode);
-       if (host_err)
+       if (host_err) {
+               err = nfserrno(host_err);
                goto out_drop_write;
+       }
        host_err = vfs_link(dold, dirp, dnew);
        if (!host_err) {
                err = nfserrno(commit_metadata(ffhp));
index b954878ad6cef17094d7337f41823bd73fe48e14..b9b45fc2903e6c38f52410a23bbe258032edd872 100644 (file)
@@ -801,12 +801,7 @@ out_err:
 
 int nilfs_permission(struct inode *inode, int mask, unsigned int flags)
 {
-       struct nilfs_root *root;
-
-       if (flags & IPERM_FLAG_RCU)
-               return -ECHILD;
-
-       root = NILFS_I(inode)->i_root;
+       struct nilfs_root *root = NILFS_I(inode)->i_root;
        if ((mask & MAY_WRITE) && root &&
            root->cno != NILFS_CPTREE_CURRENT_CNO)
                return -EROFS; /* snapshot is not writable */
index d738a7e493ddc07ed1b4b1fb7a30198b3d477c5f..2c6d95257a4d5c7a61bf39b895c5ebbd647cc49b 100644 (file)
@@ -4,7 +4,6 @@
  * Released under GPL v2.
  */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
index bc71f120100d4332aaaf1799dca7379e59afa4c1..1b626e14e8b5b991a43a4a3d4fd7898e9b8d3654 100644 (file)
@@ -2209,11 +2209,7 @@ static const struct file_operations proc_fd_operations = {
  */
 static int proc_fd_permission(struct inode *inode, int mask, unsigned int flags)
 {
-       int rv;
-
-       if (flags & IPERM_FLAG_RCU)
-               return -ECHILD;
-       rv = generic_permission(inode, mask, flags, NULL);
+       int rv = generic_permission(inode, mask, flags, NULL);
        if (rv == 0)
                return 0;
        if (task_pid(current) == proc_pid(inode))
index 781dec5bd682c30435c852c98d08814f2a511f93..be177f702acbc9bc352c0e13f5b37aeedbf6dd25 100644 (file)
@@ -38,18 +38,21 @@ static struct dentry *proc_ns_instantiate(struct inode *dir,
        struct inode *inode;
        struct proc_inode *ei;
        struct dentry *error = ERR_PTR(-ENOENT);
+       void *ns;
 
        inode = proc_pid_make_inode(dir->i_sb, task);
        if (!inode)
                goto out;
 
+       ns = ns_ops->get(task);
+       if (!ns)
+               goto out_iput;
+
        ei = PROC_I(inode);
        inode->i_mode = S_IFREG|S_IRUSR;
        inode->i_fop  = &ns_file_operations;
        ei->ns_ops    = ns_ops;
-       ei->ns        = ns_ops->get(task);
-       if (!ei->ns)
-               goto out_iput;
+       ei->ns        = ns;
 
        dentry->d_op = &pid_dentry_operations;
        d_add(dentry, inode);
index f50133c11c2458a223f4575aa3b04e884cafd60d..d167de365a8de0f52ae880e0b88c75750109d981 100644 (file)
@@ -304,9 +304,6 @@ static int proc_sys_permission(struct inode *inode, int mask,unsigned int flags)
        struct ctl_table *table;
        int error;
 
-       if (flags & IPERM_FLAG_RCU)
-               return -ECHILD;
-
        /* Executable files are not allowed under /proc/sys/ */
        if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode))
                return -EACCES;
index a9000e9cfee54ac804eb71e75d0b72bf989041ed..d6c3b416529b9709f2db526be706dbb415902ea3 100644 (file)
@@ -28,11 +28,12 @@ static int proc_test_super(struct super_block *sb, void *data)
 
 static int proc_set_super(struct super_block *sb, void *data)
 {
-       struct pid_namespace *ns;
-
-       ns = (struct pid_namespace *)data;
-       sb->s_fs_info = get_pid_ns(ns);
-       return set_anon_super(sb, NULL);
+       int err = set_anon_super(sb, NULL);
+       if (!err) {
+               struct pid_namespace *ns = (struct pid_namespace *)data;
+               sb->s_fs_info = get_pid_ns(ns);
+       }
+       return err;
 }
 
 static struct dentry *proc_mount(struct file_system_type *fs_type,
index e8a62f41b458010b6922c763b6644b230b96fac4..d78089690965b3540344ea8fafbd9403fe825cf8 100644 (file)
@@ -954,8 +954,6 @@ static int xattr_mount_check(struct super_block *s)
 
 int reiserfs_permission(struct inode *inode, int mask, unsigned int flags)
 {
-       if (flags & IPERM_FLAG_RCU)
-               return -ECHILD;
        /*
         * We don't do permission checks on the internal objects.
         * Permissions are determined by the "owning" object.
index f0511e8169679fa3872938a2a9e0e9c19998049b..eed99428f1046d6a3dbd6191340d9d70e18b7ce0 100644 (file)
@@ -27,14 +27,18 @@ static unsigned long romfs_get_unmapped_area(struct file *file,
 {
        struct inode *inode = file->f_mapping->host;
        struct mtd_info *mtd = inode->i_sb->s_mtd;
-       unsigned long isize, offset;
+       unsigned long isize, offset, maxpages, lpages;
 
        if (!mtd)
                goto cant_map_directly;
 
+       /* the mapping mustn't extend beyond the EOF */
+       lpages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT;
        isize = i_size_read(inode);
        offset = pgoff << PAGE_SHIFT;
-       if (offset > isize || len > isize || offset > isize - len)
+
+       maxpages = (isize + PAGE_SIZE - 1) >> PAGE_SHIFT;
+       if ((pgoff >= maxpages) || (maxpages - pgoff < lpages))
                return (unsigned long) -EINVAL;
 
        /* we need to call down to the MTD layer to do the actual mapping */
index 266895783b477a94e64248217483ec52f02c75fb..e34f0d99ea4ec5a7b3361b1fc0cd02fad2d23410 100644 (file)
@@ -95,6 +95,14 @@ static int sysfs_set_super(struct super_block *sb, void *data)
        return error;
 }
 
+static void free_sysfs_super_info(struct sysfs_super_info *info)
+{
+       int type;
+       for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++)
+               kobj_ns_drop(type, info->ns[type]);
+       kfree(info);
+}
+
 static struct dentry *sysfs_mount(struct file_system_type *fs_type,
        int flags, const char *dev_name, void *data)
 {
@@ -108,11 +116,11 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
                return ERR_PTR(-ENOMEM);
 
        for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++)
-               info->ns[type] = kobj_ns_current(type);
+               info->ns[type] = kobj_ns_grab_current(type);
 
        sb = sget(fs_type, sysfs_test_super, sysfs_set_super, info);
        if (IS_ERR(sb) || sb->s_fs_info != info)
-               kfree(info);
+               free_sysfs_super_info(info);
        if (IS_ERR(sb))
                return ERR_CAST(sb);
        if (!sb->s_root) {
@@ -131,12 +139,11 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
 static void sysfs_kill_sb(struct super_block *sb)
 {
        struct sysfs_super_info *info = sysfs_info(sb);
-
        /* Remove the superblock from fs_supers/s_instances
         * so we can't find it, before freeing sysfs_super_info.
         */
        kill_anon_super(sb);
-       kfree(info);
+       free_sysfs_super_info(info);
 }
 
 static struct file_system_type sysfs_fs_type = {
@@ -145,28 +152,6 @@ static struct file_system_type sysfs_fs_type = {
        .kill_sb        = sysfs_kill_sb,
 };
 
-void sysfs_exit_ns(enum kobj_ns_type type, const void *ns)
-{
-       struct super_block *sb;
-
-       mutex_lock(&sysfs_mutex);
-       spin_lock(&sb_lock);
-       list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) {
-               struct sysfs_super_info *info = sysfs_info(sb);
-               /*
-                * If we see a superblock on the fs_supers/s_instances
-                * list the unmount has not completed and sb->s_fs_info
-                * points to a valid struct sysfs_super_info.
-                */
-               /* Ignore superblocks with the wrong ns */
-               if (info->ns[type] != ns)
-                       continue;
-               info->ns[type] = NULL;
-       }
-       spin_unlock(&sb_lock);
-       mutex_unlock(&sysfs_mutex);
-}
-
 int __init sysfs_init(void)
 {
        int err = -ENOMEM;
index 3d28af31d86300ecbddde7b4dc9d7eb25a255dc6..2ed2404f3113be24b1c77fa55e47f5126578e9e9 100644 (file)
@@ -136,7 +136,7 @@ struct sysfs_addrm_cxt {
  * instance).
  */
 struct sysfs_super_info {
-       const void *ns[KOBJ_NS_TYPES];
+       void *ns[KOBJ_NS_TYPES];
 };
 #define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info))
 extern struct sysfs_dirent sysfs_root;
index f67acbdda5e8c13fce54e51f72fe0882f2fa94da..dffeb3795af1d4204f8554447dbb2d2c33992429 100644 (file)
@@ -61,7 +61,9 @@ static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr)
 
 /*
  * Called when the clock was set to cancel the timers in the cancel
- * list.
+ * list. This will wake up processes waiting on these timers. The
+ * wake-up requires ctx->ticks to be non zero, therefore we increment
+ * it before calling wake_up_locked().
  */
 void timerfd_clock_was_set(void)
 {
@@ -76,6 +78,7 @@ void timerfd_clock_was_set(void)
                spin_lock_irqsave(&ctx->wqh.lock, flags);
                if (ctx->moffs.tv64 != moffs.tv64) {
                        ctx->moffs.tv64 = KTIME_MAX;
+                       ctx->ticks++;
                        wake_up_locked(&ctx->wqh);
                }
                spin_unlock_irqrestore(&ctx->wqh.lock, flags);
index b5aeb5a8ebed11f0448c8ff8ed20db57b5178a69..529be058202938cf1226ec8644401951df8ab032 100644 (file)
@@ -1848,7 +1848,6 @@ static void ubifs_put_super(struct super_block *sb)
        bdi_destroy(&c->bdi);
        ubi_close_volume(c->ubi);
        mutex_unlock(&c->umount_mutex);
-       kfree(c);
 }
 
 static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data)
@@ -1971,61 +1970,65 @@ static struct ubi_volume_desc *open_ubi(const char *name, int mode)
        return ERR_PTR(-EINVAL);
 }
 
-static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
+static struct ubifs_info *alloc_ubifs_info(struct ubi_volume_desc *ubi)
 {
-       struct ubi_volume_desc *ubi = sb->s_fs_info;
        struct ubifs_info *c;
-       struct inode *root;
-       int err;
 
        c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL);
-       if (!c)
-               return -ENOMEM;
+       if (c) {
+               spin_lock_init(&c->cnt_lock);
+               spin_lock_init(&c->cs_lock);
+               spin_lock_init(&c->buds_lock);
+               spin_lock_init(&c->space_lock);
+               spin_lock_init(&c->orphan_lock);
+               init_rwsem(&c->commit_sem);
+               mutex_init(&c->lp_mutex);
+               mutex_init(&c->tnc_mutex);
+               mutex_init(&c->log_mutex);
+               mutex_init(&c->mst_mutex);
+               mutex_init(&c->umount_mutex);
+               mutex_init(&c->bu_mutex);
+               mutex_init(&c->write_reserve_mutex);
+               init_waitqueue_head(&c->cmt_wq);
+               c->buds = RB_ROOT;
+               c->old_idx = RB_ROOT;
+               c->size_tree = RB_ROOT;
+               c->orph_tree = RB_ROOT;
+               INIT_LIST_HEAD(&c->infos_list);
+               INIT_LIST_HEAD(&c->idx_gc);
+               INIT_LIST_HEAD(&c->replay_list);
+               INIT_LIST_HEAD(&c->replay_buds);
+               INIT_LIST_HEAD(&c->uncat_list);
+               INIT_LIST_HEAD(&c->empty_list);
+               INIT_LIST_HEAD(&c->freeable_list);
+               INIT_LIST_HEAD(&c->frdi_idx_list);
+               INIT_LIST_HEAD(&c->unclean_leb_list);
+               INIT_LIST_HEAD(&c->old_buds);
+               INIT_LIST_HEAD(&c->orph_list);
+               INIT_LIST_HEAD(&c->orph_new);
+               c->no_chk_data_crc = 1;
+
+               c->highest_inum = UBIFS_FIRST_INO;
+               c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM;
+
+               ubi_get_volume_info(ubi, &c->vi);
+               ubi_get_device_info(c->vi.ubi_num, &c->di);
+       }
+       return c;
+}
 
-       spin_lock_init(&c->cnt_lock);
-       spin_lock_init(&c->cs_lock);
-       spin_lock_init(&c->buds_lock);
-       spin_lock_init(&c->space_lock);
-       spin_lock_init(&c->orphan_lock);
-       init_rwsem(&c->commit_sem);
-       mutex_init(&c->lp_mutex);
-       mutex_init(&c->tnc_mutex);
-       mutex_init(&c->log_mutex);
-       mutex_init(&c->mst_mutex);
-       mutex_init(&c->umount_mutex);
-       mutex_init(&c->bu_mutex);
-       mutex_init(&c->write_reserve_mutex);
-       init_waitqueue_head(&c->cmt_wq);
-       c->buds = RB_ROOT;
-       c->old_idx = RB_ROOT;
-       c->size_tree = RB_ROOT;
-       c->orph_tree = RB_ROOT;
-       INIT_LIST_HEAD(&c->infos_list);
-       INIT_LIST_HEAD(&c->idx_gc);
-       INIT_LIST_HEAD(&c->replay_list);
-       INIT_LIST_HEAD(&c->replay_buds);
-       INIT_LIST_HEAD(&c->uncat_list);
-       INIT_LIST_HEAD(&c->empty_list);
-       INIT_LIST_HEAD(&c->freeable_list);
-       INIT_LIST_HEAD(&c->frdi_idx_list);
-       INIT_LIST_HEAD(&c->unclean_leb_list);
-       INIT_LIST_HEAD(&c->old_buds);
-       INIT_LIST_HEAD(&c->orph_list);
-       INIT_LIST_HEAD(&c->orph_new);
-       c->no_chk_data_crc = 1;
+static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
+{
+       struct ubifs_info *c = sb->s_fs_info;
+       struct inode *root;
+       int err;
 
        c->vfs_sb = sb;
-       c->highest_inum = UBIFS_FIRST_INO;
-       c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM;
-
-       ubi_get_volume_info(ubi, &c->vi);
-       ubi_get_device_info(c->vi.ubi_num, &c->di);
-
        /* Re-open the UBI device in read-write mode */
        c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READWRITE);
        if (IS_ERR(c->ubi)) {
                err = PTR_ERR(c->ubi);
-               goto out_free;
+               goto out;
        }
 
        /*
@@ -2091,24 +2094,29 @@ out_bdi:
        bdi_destroy(&c->bdi);
 out_close:
        ubi_close_volume(c->ubi);
-out_free:
-       kfree(c);
+out:
        return err;
 }
 
 static int sb_test(struct super_block *sb, void *data)
 {
-       dev_t *dev = data;
+       struct ubifs_info *c1 = data;
        struct ubifs_info *c = sb->s_fs_info;
 
-       return c->vi.cdev == *dev;
+       return c->vi.cdev == c1->vi.cdev;
+}
+
+static int sb_set(struct super_block *sb, void *data)
+{
+       sb->s_fs_info = data;
+       return set_anon_super(sb, NULL);
 }
 
 static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
                        const char *name, void *data)
 {
        struct ubi_volume_desc *ubi;
-       struct ubi_volume_info vi;
+       struct ubifs_info *c;
        struct super_block *sb;
        int err;
 
@@ -2125,19 +2133,25 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
                        name, (int)PTR_ERR(ubi));
                return ERR_CAST(ubi);
        }
-       ubi_get_volume_info(ubi, &vi);
 
-       dbg_gen("opened ubi%d_%d", vi.ubi_num, vi.vol_id);
+       c = alloc_ubifs_info(ubi);
+       if (!c) {
+               err = -ENOMEM;
+               goto out_close;
+       }
+
+       dbg_gen("opened ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
 
-       sb = sget(fs_type, &sb_test, &set_anon_super, &vi.cdev);
+       sb = sget(fs_type, sb_test, sb_set, c);
        if (IS_ERR(sb)) {
                err = PTR_ERR(sb);
+               kfree(c);
                goto out_close;
        }
 
        if (sb->s_root) {
                struct ubifs_info *c1 = sb->s_fs_info;
-
+               kfree(c);
                /* A new mount point for already mounted UBIFS */
                dbg_gen("this ubi volume is already mounted");
                if (!!(flags & MS_RDONLY) != c1->ro_mount) {
@@ -2146,11 +2160,6 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
                }
        } else {
                sb->s_flags = flags;
-               /*
-                * Pass 'ubi' to 'fill_super()' in sb->s_fs_info where it is
-                * replaced by 'c'.
-                */
-               sb->s_fs_info = ubi;
                err = ubifs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
                if (err)
                        goto out_deact;
@@ -2170,11 +2179,18 @@ out_close:
        return ERR_PTR(err);
 }
 
+static void kill_ubifs_super(struct super_block *s)
+{
+       struct ubifs_info *c = s->s_fs_info;
+       kill_anon_super(s);
+       kfree(c);
+}
+
 static struct file_system_type ubifs_fs_type = {
        .name    = "ubifs",
        .owner   = THIS_MODULE,
        .mount   = ubifs_mount,
-       .kill_sb = kill_anon_super,
+       .kill_sb = kill_ubifs_super,
 };
 
 /*
index f4213ba1ff853dad53d16d27b6cd713f01784ea7..7f782af286bfa0edd73a125cdcb892339025913a 100644 (file)
@@ -131,19 +131,34 @@ xfs_file_fsync(
 {
        struct inode            *inode = file->f_mapping->host;
        struct xfs_inode        *ip = XFS_I(inode);
+       struct xfs_mount        *mp = ip->i_mount;
        struct xfs_trans        *tp;
        int                     error = 0;
        int                     log_flushed = 0;
 
        trace_xfs_file_fsync(ip);
 
-       if (XFS_FORCED_SHUTDOWN(ip->i_mount))
+       if (XFS_FORCED_SHUTDOWN(mp))
                return -XFS_ERROR(EIO);
 
        xfs_iflags_clear(ip, XFS_ITRUNCATED);
 
        xfs_ioend_wait(ip);
 
+       if (mp->m_flags & XFS_MOUNT_BARRIER) {
+               /*
+                * If we have an RT and/or log subvolume we need to make sure
+                * to flush the write cache the device used for file data
+                * first.  This is to ensure newly written file data make
+                * it to disk before logging the new inode size in case of
+                * an extending write.
+                */
+               if (XFS_IS_REALTIME_INODE(ip))
+                       xfs_blkdev_issue_flush(mp->m_rtdev_targp);
+               else if (mp->m_logdev_targp != mp->m_ddev_targp)
+                       xfs_blkdev_issue_flush(mp->m_ddev_targp);
+       }
+
        /*
         * We always need to make sure that the required inode state is safe on
         * disk.  The inode might be clean but we still might need to force the
@@ -175,9 +190,9 @@ xfs_file_fsync(
                 * updates.  The sync transaction will also force the log.
                 */
                xfs_iunlock(ip, XFS_ILOCK_SHARED);
-               tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_FSYNC_TS);
+               tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS);
                error = xfs_trans_reserve(tp, 0,
-                               XFS_FSYNC_TS_LOG_RES(ip->i_mount), 0, 0, 0);
+                               XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0);
                if (error) {
                        xfs_trans_cancel(tp, 0);
                        return -error;
@@ -209,28 +224,25 @@ xfs_file_fsync(
                 * force the log.
                 */
                if (xfs_ipincount(ip)) {
-                       error = _xfs_log_force_lsn(ip->i_mount,
+                       error = _xfs_log_force_lsn(mp,
                                        ip->i_itemp->ili_last_lsn,
                                        XFS_LOG_SYNC, &log_flushed);
                }
                xfs_iunlock(ip, XFS_ILOCK_SHARED);
        }
 
-       if (ip->i_mount->m_flags & XFS_MOUNT_BARRIER) {
-               /*
-                * If the log write didn't issue an ordered tag we need
-                * to flush the disk cache for the data device now.
-                */
-               if (!log_flushed)
-                       xfs_blkdev_issue_flush(ip->i_mount->m_ddev_targp);
-
-               /*
-                * If this inode is on the RT dev we need to flush that
-                * cache as well.
-                */
-               if (XFS_IS_REALTIME_INODE(ip))
-                       xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp);
-       }
+       /*
+        * If we only have a single device, and the log force about was
+        * a no-op we might have to flush the data device cache here.
+        * This can only happen for fdatasync/O_DSYNC if we were overwriting
+        * an already allocated file and thus do not have any metadata to
+        * commit.
+        */
+       if ((mp->m_flags & XFS_MOUNT_BARRIER) &&
+           mp->m_logdev_targp == mp->m_ddev_targp &&
+           !XFS_IS_REALTIME_INODE(ip) &&
+           !log_flushed)
+               xfs_blkdev_issue_flush(mp->m_ddev_targp);
 
        return -error;
 }
index dd21784525a8096ef76f6d6cd14c80a319918839..d44d92cd12b17c7645156b4754c39ea29b5b10e5 100644 (file)
@@ -182,7 +182,7 @@ xfs_vn_mknod(
        if (IS_POSIXACL(dir)) {
                default_acl = xfs_get_acl(dir, ACL_TYPE_DEFAULT);
                if (IS_ERR(default_acl))
-                       return -PTR_ERR(default_acl);
+                       return PTR_ERR(default_acl);
 
                if (!default_acl)
                        mode &= ~current_umask();
index 1e3a7ce804dce2feb1956036eec54ac7ed27da36..a1a881e68a9aa86a1aa76c27931e02202a57a08d 100644 (file)
@@ -627,68 +627,6 @@ xfs_blkdev_put(
                blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);
 }
 
-/*
- * Try to write out the superblock using barriers.
- */
-STATIC int
-xfs_barrier_test(
-       xfs_mount_t     *mp)
-{
-       xfs_buf_t       *sbp = xfs_getsb(mp, 0);
-       int             error;
-
-       XFS_BUF_UNDONE(sbp);
-       XFS_BUF_UNREAD(sbp);
-       XFS_BUF_UNDELAYWRITE(sbp);
-       XFS_BUF_WRITE(sbp);
-       XFS_BUF_UNASYNC(sbp);
-       XFS_BUF_ORDERED(sbp);
-
-       xfsbdstrat(mp, sbp);
-       error = xfs_buf_iowait(sbp);
-
-       /*
-        * Clear all the flags we set and possible error state in the
-        * buffer.  We only did the write to try out whether barriers
-        * worked and shouldn't leave any traces in the superblock
-        * buffer.
-        */
-       XFS_BUF_DONE(sbp);
-       XFS_BUF_ERROR(sbp, 0);
-       XFS_BUF_UNORDERED(sbp);
-
-       xfs_buf_relse(sbp);
-       return error;
-}
-
-STATIC void
-xfs_mountfs_check_barriers(xfs_mount_t *mp)
-{
-       int error;
-
-       if (mp->m_logdev_targp != mp->m_ddev_targp) {
-               xfs_notice(mp,
-                 "Disabling barriers, not supported with external log device");
-               mp->m_flags &= ~XFS_MOUNT_BARRIER;
-               return;
-       }
-
-       if (xfs_readonly_buftarg(mp->m_ddev_targp)) {
-               xfs_notice(mp,
-                       "Disabling barriers, underlying device is readonly");
-               mp->m_flags &= ~XFS_MOUNT_BARRIER;
-               return;
-       }
-
-       error = xfs_barrier_test(mp);
-       if (error) {
-               xfs_notice(mp,
-                       "Disabling barriers, trial barrier write failed");
-               mp->m_flags &= ~XFS_MOUNT_BARRIER;
-               return;
-       }
-}
-
 void
 xfs_blkdev_issue_flush(
        xfs_buftarg_t           *buftarg)
@@ -1240,14 +1178,6 @@ xfs_fs_remount(
                switch (token) {
                case Opt_barrier:
                        mp->m_flags |= XFS_MOUNT_BARRIER;
-
-                       /*
-                        * Test if barriers are actually working if we can,
-                        * else delay this check until the filesystem is
-                        * marked writeable.
-                        */
-                       if (!(mp->m_flags & XFS_MOUNT_RDONLY))
-                               xfs_mountfs_check_barriers(mp);
                        break;
                case Opt_nobarrier:
                        mp->m_flags &= ~XFS_MOUNT_BARRIER;
@@ -1282,8 +1212,6 @@ xfs_fs_remount(
        /* ro -> rw */
        if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) {
                mp->m_flags &= ~XFS_MOUNT_RDONLY;
-               if (mp->m_flags & XFS_MOUNT_BARRIER)
-                       xfs_mountfs_check_barriers(mp);
 
                /*
                 * If this is the first remount to writeable state we
@@ -1465,9 +1393,6 @@ xfs_fs_fill_super(
        if (error)
                goto out_free_sb;
 
-       if (mp->m_flags & XFS_MOUNT_BARRIER)
-               xfs_mountfs_check_barriers(mp);
-
        error = xfs_filestream_mount(mp);
        if (error)
                goto out_free_sb;
index c8637537881082a58fb30efbb56abef66d2b26f4..01d2072fb6d4580ca6ceb7f77a20eed67c94cf1c 100644 (file)
@@ -489,6 +489,13 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags)
        args.total = 0;
        args.whichfork = XFS_ATTR_FORK;
 
+       /*
+        * we have no control over the attribute names that userspace passes us
+        * to remove, so we have to allow the name lookup prior to attribute
+        * removal to fail.
+        */
+       args.op_flags = XFS_DA_OP_OKNOENT;
+
        /*
         * Attach the dquots to the inode.
         */
index cb9b6d1469f7579256061f6de61755c0d6b63df6..3631783b2b5385ee939a61e5cafd5b06ef6b0a45 100644 (file)
@@ -253,16 +253,21 @@ xfs_iget_cache_hit(
                        rcu_read_lock();
                        spin_lock(&ip->i_flags_lock);
 
-                       ip->i_flags &= ~XFS_INEW;
-                       ip->i_flags |= XFS_IRECLAIMABLE;
-                       __xfs_inode_set_reclaim_tag(pag, ip);
+                       ip->i_flags &= ~(XFS_INEW | XFS_IRECLAIM);
+                       ASSERT(ip->i_flags & XFS_IRECLAIMABLE);
                        trace_xfs_iget_reclaim_fail(ip);
                        goto out_error;
                }
 
                spin_lock(&pag->pag_ici_lock);
                spin_lock(&ip->i_flags_lock);
-               ip->i_flags &= ~(XFS_IRECLAIMABLE | XFS_IRECLAIM);
+
+               /*
+                * Clear the per-lifetime state in the inode as we are now
+                * effectively a new inode and need to return to the initial
+                * state before reuse occurs.
+                */
+               ip->i_flags &= ~XFS_IRECLAIM_RESET_FLAGS;
                ip->i_flags |= XFS_INEW;
                __xfs_inode_clear_reclaim_tag(mp, pag, ip);
                inode->i_state = I_NEW;
index 3ae6d58e54739b42b8ff5ff49dfaad7648201add..964cfea776868684afb26f818b8a761ce652b1b5 100644 (file)
@@ -383,6 +383,16 @@ static inline void xfs_ifunlock(xfs_inode_t *ip)
 #define XFS_ITRUNCATED         0x0020  /* truncated down so flush-on-close */
 #define XFS_IDIRTY_RELEASE     0x0040  /* dirty release already seen */
 
+/*
+ * Per-lifetime flags need to be reset when re-using a reclaimable inode during
+ * inode lookup. Thi prevents unintended behaviour on the new inode from
+ * ocurring.
+ */
+#define XFS_IRECLAIM_RESET_FLAGS       \
+       (XFS_IRECLAIMABLE | XFS_IRECLAIM | \
+        XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | \
+        XFS_IFILESTREAM);
+
 /*
  * Flags for inode locking.
  * Bit ranges: 1<<1  - 1<<16-1 -- iolock/ilock modes (bitfield)
index 211930246f2073f4759a569936b79ab387003e21..41d5b8f2bf92d3fd3fae9773f667a0bf1cb42381 100644 (file)
@@ -1372,8 +1372,17 @@ xlog_sync(xlog_t         *log,
        XFS_BUF_ASYNC(bp);
        bp->b_flags |= XBF_LOG_BUFFER;
 
-       if (log->l_mp->m_flags & XFS_MOUNT_BARRIER)
+       if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) {
+               /*
+                * If we have an external log device, flush the data device
+                * before flushing the log to make sure all meta data
+                * written back from the AIL actually made it to disk
+                * before writing out the new log tail LSN in the log buffer.
+                */
+               if (log->l_mp->m_logdev_targp != log->l_mp->m_ddev_targp)
+                       xfs_blkdev_issue_flush(log->l_mp->m_ddev_targp);
                XFS_BUF_ORDERED(bp);
+       }
 
        ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1);
        ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize);
index b7a5fe7c52c895776f125d53851d40c48795dce7..619720705bc6843e4624ce02c27829fa32256ba9 100644 (file)
@@ -960,8 +960,11 @@ xfs_release(
                 * be exposed to that problem.
                 */
                truncated = xfs_iflags_test_and_clear(ip, XFS_ITRUNCATED);
-               if (truncated && VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0)
-                       xfs_flush_pages(ip, 0, -1, XBF_ASYNC, FI_NONE);
+               if (truncated) {
+                       xfs_iflags_clear(ip, XFS_IDIRTY_RELEASE);
+                       if (VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0)
+                               xfs_flush_pages(ip, 0, -1, XBF_ASYNC, FI_NONE);
+               }
        }
 
        if (ip->i_d.di_nlink == 0)
index fcdcb5d5c99539871c448411dbdb0fddd2be56b8..d494001b12260a2f56b9337e01226f17dcee3634 100644 (file)
@@ -170,16 +170,6 @@ extern int __gpio_cansleep(unsigned gpio);
 
 extern int __gpio_to_irq(unsigned gpio);
 
-#define GPIOF_DIR_OUT  (0 << 0)
-#define GPIOF_DIR_IN   (1 << 0)
-
-#define GPIOF_INIT_LOW (0 << 1)
-#define GPIOF_INIT_HIGH        (1 << 1)
-
-#define GPIOF_IN               (GPIOF_DIR_IN)
-#define GPIOF_OUT_INIT_LOW     (GPIOF_DIR_OUT | GPIOF_INIT_LOW)
-#define GPIOF_OUT_INIT_HIGH    (GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
-
 /**
  * struct gpio - a structure describing a GPIO with configuration
  * @gpio:      the GPIO number
index e9b8e5926befb7b38b03218ffd0f9e6d2d75d454..76bff2bff15e346532be60dc1ce1a13aff070471 100644 (file)
@@ -88,7 +88,7 @@ static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm,
        pmd_t pmd = *pmdp;
        pmd_clear(mm, address, pmdp);
        return pmd;
-})
+}
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 #endif
 
index 9573e0ce312080caf9bcbcb72cd804e2ed200871..33d12f87f0e01735d41a800a73b7ea5ddc9b31a6 100644 (file)
@@ -520,6 +520,8 @@ struct drm_connector {
        uint32_t encoder_ids[DRM_CONNECTOR_MAX_ENCODER];
        uint32_t force_encoder_id;
        struct drm_encoder *encoder; /* currently active encoder */
+
+       int null_edid_counter; /* needed to workaround some HW bugs where we get all 0s */
 };
 
 /**
index 2a7cea53ca0d3d047617d1fff5f6e3848493a60f..6395692b2e7a9dec9725dcf42dbf244585f7c83e 100644 (file)
@@ -167,7 +167,7 @@ enum rq_flag_bits {
        (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER)
 #define REQ_COMMON_MASK \
        (REQ_WRITE | REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_DISCARD | \
-        REQ_NOIDLE | REQ_FLUSH | REQ_FUA)
+        REQ_NOIDLE | REQ_FLUSH | REQ_FUA | REQ_SECURE)
 #define REQ_CLONE_MASK         REQ_COMMON_MASK
 
 #define REQ_RAHEAD             (1 << __REQ_RAHEAD)
index b22fb0d3db0f5fb0fa364bbae9e12ee46b8e918a..8c7c2de7631a6fb59ab8f4e86334516a7f07e7d1 100644 (file)
@@ -169,7 +169,8 @@ extern void blk_trace_shutdown(struct request_queue *);
 extern int do_blk_trace_setup(struct request_queue *q, char *name,
                              dev_t dev, struct block_device *bdev,
                              struct blk_user_trace_setup *buts);
-extern void __trace_note_message(struct blk_trace *, const char *fmt, ...);
+extern __attribute__((format(printf, 2, 3)))
+void __trace_note_message(struct blk_trace *, const char *fmt, ...);
 
 /**
  * blk_add_trace_msg - Add a (simple) message to the blktrace stream
index d4646b48dc4a7b0074dc7491e7f66186f398e70e..18a1baf31f2d531493526a48132dc38a5f2f0f03 100644 (file)
@@ -188,6 +188,7 @@ struct clocksource {
 #ifdef CONFIG_CLOCKSOURCE_WATCHDOG
        /* Watchdog related data, used by the framework */
        struct list_head wd_list;
+       cycle_t cs_last;
        cycle_t wd_last;
 #endif
 } ____cacheline_aligned;
index ddcb7db38e67cc1f822d9cca89c7253a0883a63e..846bb1792572e3cb5cd88eae67e0150a4423d8c2 100644 (file)
@@ -467,6 +467,8 @@ asmlinkage long compat_sys_setsockopt(int fd, int level, int optname,
                                      char __user *optval, unsigned int optlen);
 asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg,
                                   unsigned flags);
+asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg,
+                                   unsigned vlen, unsigned int flags);
 asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg,
                                   unsigned int flags);
 asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len,
index c66111affca9a6e93f246b66f39ff5e4b998da58..e4f62d8896b7c9adf3cfb745cbf4c79ec5603d4d 100644 (file)
@@ -530,7 +530,6 @@ struct device_dma_parameters {
  * @dma_mem:   Internal for coherent mem override.
  * @archdata:  For arch-specific additions.
  * @of_node:   Associated device tree node.
- * @of_match:  Matching of_device_id from driver.
  * @devt:      For creating the sysfs "dev".
  * @devres_lock: Spinlock to protect the resource of the device.
  * @devres_head: The resources list of the device.
@@ -654,13 +653,13 @@ static inline int device_is_registered(struct device *dev)
 
 static inline void device_enable_async_suspend(struct device *dev)
 {
-       if (!dev->power.in_suspend)
+       if (!dev->power.is_prepared)
                dev->power.async_suspend = true;
 }
 
 static inline void device_disable_async_suspend(struct device *dev)
 {
-       if (!dev->power.in_suspend)
+       if (!dev->power.is_prepared)
                dev->power.async_suspend = false;
 }
 
index 0b0d9c39ed670d10c1ddf7d9863fbbb67cfd356b..7aad1f440867e796ed6f5d2c811771e700e7ad15 100644 (file)
@@ -2,8 +2,16 @@
 #include <linux/fs.h>
 
 #ifdef CONFIG_CGROUP_DEVICE
-extern int devcgroup_inode_permission(struct inode *inode, int mask);
+extern int __devcgroup_inode_permission(struct inode *inode, int mask);
 extern int devcgroup_inode_mknod(int mode, dev_t dev);
+static inline int devcgroup_inode_permission(struct inode *inode, int mask)
+{
+       if (likely(!inode->i_rdev))
+               return 0;
+       if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode))
+               return 0;
+       return __devcgroup_inode_permission(inode, mask);
+}
 #else
 static inline int devcgroup_inode_permission(struct inode *inode, int mask)
 { return 0; }
index 1c777878f1ea5d375be6f04f3364ac2fb9d6c8ba..b5b979247863718f10da2764b3eab280a3005e9f 100644 (file)
@@ -639,6 +639,7 @@ struct address_space {
        struct prio_tree_root   i_mmap;         /* tree of private and shared mappings */
        struct list_head        i_mmap_nonlinear;/*list VM_NONLINEAR mappings */
        struct mutex            i_mmap_mutex;   /* protect tree, count, list */
+       /* Protected by tree_lock together with the radix tree */
        unsigned long           nrpages;        /* number of total pages */
        pgoff_t                 writeback_index;/* writeback starts here */
        const struct address_space_operations *a_ops;   /* methods */
@@ -744,7 +745,7 @@ struct inode {
 
        spinlock_t              i_lock; /* i_blocks, i_bytes, maybe i_size */
        unsigned int            i_flags;
-       unsigned int            i_state;
+       unsigned long           i_state;
 #ifdef CONFIG_SECURITY
        void                    *i_security;
 #endif
index 32d47e710661e55879b5473f9850316948f484fe..17b5a0d80e4239cc10fceb670be29dbf4e49a0f0 100644 (file)
@@ -3,6 +3,17 @@
 
 /* see Documentation/gpio.txt */
 
+/* make these flag values available regardless of GPIO kconfig options */
+#define GPIOF_DIR_OUT  (0 << 0)
+#define GPIOF_DIR_IN   (1 << 0)
+
+#define GPIOF_INIT_LOW (0 << 1)
+#define GPIOF_INIT_HIGH        (1 << 1)
+
+#define GPIOF_IN               (GPIOF_DIR_IN)
+#define GPIOF_OUT_INIT_LOW     (GPIOF_DIR_OUT | GPIOF_INIT_LOW)
+#define GPIOF_OUT_INIT_HIGH    (GPIOF_DIR_OUT | GPIOF_INIT_HIGH)
+
 #ifdef CONFIG_GENERIC_GPIO
 #include <asm/gpio.h>
 
index 51932e5acf7ce8cd44b57c0a7fe2288013d1967d..fd0dc30c9f154af94155b8c8c47e0a228fbd2573 100644 (file)
@@ -135,6 +135,7 @@ struct hrtimer_sleeper {
  * @cpu_base:          per cpu clock base
  * @index:             clock type index for per_cpu support when moving a
  *                     timer to a base on another cpu.
+ * @clockid:           clock id for per_cpu support
  * @active:            red black tree root node for the active timers
  * @resolution:                the resolution of the clock, in nanoseconds
  * @get_time:          function to retrieve the current time of the clock
diff --git a/include/linux/i2c/adp8870.h b/include/linux/i2c/adp8870.h
new file mode 100644 (file)
index 0000000..624dcec
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * Definitions and platform data for Analog Devices
+ * Backlight drivers ADP8870
+ *
+ * Copyright 2009-2010 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __LINUX_I2C_ADP8870_H
+#define __LINUX_I2C_ADP8870_H
+
+#define ID_ADP8870             8870
+
+#define ADP8870_MAX_BRIGHTNESS 0x7F
+#define FLAG_OFFT_SHIFT 8
+
+/*
+ * LEDs subdevice platform data
+ */
+
+#define ADP8870_LED_DIS_BLINK  (0 << FLAG_OFFT_SHIFT)
+#define ADP8870_LED_OFFT_600ms (1 << FLAG_OFFT_SHIFT)
+#define ADP8870_LED_OFFT_1200ms        (2 << FLAG_OFFT_SHIFT)
+#define ADP8870_LED_OFFT_1800ms        (3 << FLAG_OFFT_SHIFT)
+
+#define ADP8870_LED_ONT_200ms  0
+#define ADP8870_LED_ONT_600ms  1
+#define ADP8870_LED_ONT_800ms  2
+#define ADP8870_LED_ONT_1200ms 3
+
+#define ADP8870_LED_D7         (7)
+#define ADP8870_LED_D6         (6)
+#define ADP8870_LED_D5         (5)
+#define ADP8870_LED_D4         (4)
+#define ADP8870_LED_D3         (3)
+#define ADP8870_LED_D2         (2)
+#define ADP8870_LED_D1         (1)
+
+/*
+ * Backlight subdevice platform data
+ */
+
+#define ADP8870_BL_D7          (1 << 6)
+#define ADP8870_BL_D6          (1 << 5)
+#define ADP8870_BL_D5          (1 << 4)
+#define ADP8870_BL_D4          (1 << 3)
+#define ADP8870_BL_D3          (1 << 2)
+#define ADP8870_BL_D2          (1 << 1)
+#define ADP8870_BL_D1          (1 << 0)
+
+#define ADP8870_FADE_T_DIS     0       /* Fade Timer Disabled */
+#define ADP8870_FADE_T_300ms   1       /* 0.3 Sec */
+#define ADP8870_FADE_T_600ms   2
+#define ADP8870_FADE_T_900ms   3
+#define ADP8870_FADE_T_1200ms  4
+#define ADP8870_FADE_T_1500ms  5
+#define ADP8870_FADE_T_1800ms  6
+#define ADP8870_FADE_T_2100ms  7
+#define ADP8870_FADE_T_2400ms  8
+#define ADP8870_FADE_T_2700ms  9
+#define ADP8870_FADE_T_3000ms  10
+#define ADP8870_FADE_T_3500ms  11
+#define ADP8870_FADE_T_4000ms  12
+#define ADP8870_FADE_T_4500ms  13
+#define ADP8870_FADE_T_5000ms  14
+#define ADP8870_FADE_T_5500ms  15      /* 5.5 Sec */
+
+#define ADP8870_FADE_LAW_LINEAR        0
+#define ADP8870_FADE_LAW_SQUARE        1
+#define ADP8870_FADE_LAW_CUBIC1        2
+#define ADP8870_FADE_LAW_CUBIC2        3
+
+#define ADP8870_BL_AMBL_FILT_80ms      0       /* Light sensor filter time */
+#define ADP8870_BL_AMBL_FILT_160ms     1
+#define ADP8870_BL_AMBL_FILT_320ms     2
+#define ADP8870_BL_AMBL_FILT_640ms     3
+#define ADP8870_BL_AMBL_FILT_1280ms    4
+#define ADP8870_BL_AMBL_FILT_2560ms    5
+#define ADP8870_BL_AMBL_FILT_5120ms    6
+#define ADP8870_BL_AMBL_FILT_10240ms   7       /* 10.24 sec */
+
+/*
+ * Blacklight current 0..30mA
+ */
+#define ADP8870_BL_CUR_mA(I)           ((I * 127) / 30)
+
+/*
+ * L2 comparator current 0..1106uA
+ */
+#define ADP8870_L2_COMP_CURR_uA(I)     ((I * 255) / 1106)
+
+/*
+ * L3 comparator current 0..551uA
+ */
+#define ADP8870_L3_COMP_CURR_uA(I)     ((I * 255) / 551)
+
+/*
+ * L4 comparator current 0..275uA
+ */
+#define ADP8870_L4_COMP_CURR_uA(I)     ((I * 255) / 275)
+
+/*
+ * L5 comparator current 0..138uA
+ */
+#define ADP8870_L5_COMP_CURR_uA(I)     ((I * 255) / 138)
+
+struct adp8870_backlight_platform_data {
+       u8 bl_led_assign;       /* 1 = Backlight 0 = Individual LED */
+       u8 pwm_assign;          /* 1 = Enables PWM mode */
+
+       u8 bl_fade_in;          /* Backlight Fade-In Timer */
+       u8 bl_fade_out;         /* Backlight Fade-Out Timer */
+       u8 bl_fade_law;         /* fade-on/fade-off transfer characteristic */
+
+       u8 en_ambl_sens;        /* 1 = enable ambient light sensor */
+       u8 abml_filt;           /* Light sensor filter time */
+
+       u8 l1_daylight_max;     /* use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l1_daylight_dim;     /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l2_bright_max;       /* use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l2_bright_dim;       /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l3_office_max;       /* use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l3_office_dim;       /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l4_indoor_max;       /* use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l4_indor_dim;        /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l5_dark_max;         /* use BL_CUR_mA(I) 0 <= I <= 30 mA */
+       u8 l5_dark_dim;         /* typ = 0, use BL_CUR_mA(I) 0 <= I <= 30 mA */
+
+       u8 l2_trip;             /* use L2_COMP_CURR_uA(I) 0 <= I <= 1106 uA */
+       u8 l2_hyst;             /* use L2_COMP_CURR_uA(I) 0 <= I <= 1106 uA */
+       u8 l3_trip;             /* use L3_COMP_CURR_uA(I) 0 <= I <= 551 uA */
+       u8 l3_hyst;             /* use L3_COMP_CURR_uA(I) 0 <= I <= 551 uA */
+       u8 l4_trip;             /* use L4_COMP_CURR_uA(I) 0 <= I <= 275 uA */
+       u8 l4_hyst;             /* use L4_COMP_CURR_uA(I) 0 <= I <= 275 uA */
+       u8 l5_trip;             /* use L5_COMP_CURR_uA(I) 0 <= I <= 138 uA */
+       u8 l5_hyst;             /* use L6_COMP_CURR_uA(I) 0 <= I <= 138 uA */
+
+       /**
+        * Independent Current Sinks / LEDS
+        * Sinks not assigned to the Backlight can be exposed to
+        * user space using the LEDS CLASS interface
+        */
+
+       int num_leds;
+       struct led_info *leds;
+       u8 led_fade_in;         /* LED Fade-In Timer */
+       u8 led_fade_out;        /* LED Fade-Out Timer */
+       u8 led_fade_law;        /* fade-on/fade-off transfer characteristic */
+       u8 led_on_time;
+};
+
+#endif /* __LINUX_I2C_ADP8870_H */
index 649dc7f12925d0ac7a9152e7e9f7e79b269b3ec6..5d253cd93691d2bec2a12b34fe2791f61e57a09f 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __SH_KEYSC_H__
 #define __SH_KEYSC_H__
 
-#define SH_KEYSC_MAXKEYS 49
+#define SH_KEYSC_MAXKEYS 64
 
 struct sh_keysc_info {
        enum { SH_KEYSC_MODE_1, SH_KEYSC_MODE_2, SH_KEYSC_MODE_3,
index 6c12989839d9093f970b9f90d8dffe44dec6f7a2..f6efed0039edfdb06cbe1430588e51bf2db07aca 100644 (file)
@@ -414,6 +414,7 @@ enum
        TASKLET_SOFTIRQ,
        SCHED_SOFTIRQ,
        HRTIMER_SOFTIRQ,
+       RCU_SOFTIRQ,    /* Preferable RCU should always be the last softirq */
 
        NR_SOFTIRQS
 };
index 4ecb7b16b278061a280d8f29bdeb7c88eae24979..d087c2e7b2aa0303a22b181cdc617a67e99cff80 100644 (file)
@@ -1024,7 +1024,6 @@ struct journal_s
 
 /* Filing buffers */
 extern void jbd2_journal_unfile_buffer(journal_t *, struct journal_head *);
-extern void __jbd2_journal_unfile_buffer(struct journal_head *);
 extern void __jbd2_journal_refile_buffer(struct journal_head *);
 extern void jbd2_journal_refile_buffer(journal_t *, struct journal_head *);
 extern void __jbd2_journal_file_buffer(struct journal_head *, transaction_t *, int);
@@ -1165,7 +1164,6 @@ extern void          jbd2_journal_release_jbd_inode(journal_t *journal, struct jbd2_in
  */
 struct journal_head *jbd2_journal_add_journal_head(struct buffer_head *bh);
 struct journal_head *jbd2_journal_grab_journal_head(struct buffer_head *bh);
-void jbd2_journal_remove_journal_head(struct buffer_head *bh);
 void jbd2_journal_put_journal_head(struct journal_head *jh);
 
 /*
index fb0e7329fee1a5ad370b2e5284ceb681670c7395..953352a88336c0385e2e385f93e41c278513be7b 100644 (file)
@@ -671,8 +671,8 @@ struct sysinfo {
 
 #ifdef __CHECKER__
 #define BUILD_BUG_ON_NOT_POWER_OF_2(n)
-#define BUILD_BUG_ON_ZERO(e)
-#define BUILD_BUG_ON_NULL(e)
+#define BUILD_BUG_ON_ZERO(e) (0)
+#define BUILD_BUG_ON_NULL(e) ((void*)0)
 #define BUILD_BUG_ON(condition)
 #else /* __CHECKER__ */
 
index d4a5c84c503d7307a577474bc0eb4d75cb7265f3..0da38cf7db7bddc8841d14620a9e831866afcfd2 100644 (file)
@@ -45,7 +45,7 @@ static inline int request_module_nowait(const char *name, ...) { return -ENOSYS;
 #endif
 
 
-struct key;
+struct cred;
 struct file;
 
 enum umh_wait {
@@ -62,7 +62,7 @@ struct subprocess_info {
        char **envp;
        enum umh_wait wait;
        int retval;
-       int (*init)(struct subprocess_info *info);
+       int (*init)(struct subprocess_info *info, struct cred *new);
        void (*cleanup)(struct subprocess_info *info);
        void *data;
 };
@@ -73,7 +73,7 @@ struct subprocess_info *call_usermodehelper_setup(char *path, char **argv,
 
 /* Set various pieces of state into the subprocess_info structure */
 void call_usermodehelper_setfns(struct subprocess_info *info,
-                   int (*init)(struct subprocess_info *info),
+                   int (*init)(struct subprocess_info *info, struct cred *new),
                    void (*cleanup)(struct subprocess_info *info),
                    void *data);
 
@@ -87,7 +87,7 @@ void call_usermodehelper_freeinfo(struct subprocess_info *info);
 static inline int
 call_usermodehelper_fns(char *path, char **argv, char **envp,
                        enum umh_wait wait,
-                       int (*init)(struct subprocess_info *info),
+                       int (*init)(struct subprocess_info *info, struct cred *new),
                        void (*cleanup)(struct subprocess_info *), void *data)
 {
        struct subprocess_info *info;
index 2a0d7d651dc34f98daff0d111c5e458339006945..ee0c952188de2c99281fd7567f701893e90a47dd 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef _LINUX_KMSG_DUMP_H
 #define _LINUX_KMSG_DUMP_H
 
+#include <linux/errno.h>
 #include <linux/list.h>
 
 enum kmsg_dump_reason {
index 82cb5bf461fb4ace0c8fa5dc8e68c44a0e5fca19..f66b065a8b5ff1af1efdc698aadc248a79175917 100644 (file)
@@ -32,15 +32,17 @@ enum kobj_ns_type {
 
 /*
  * Callbacks so sysfs can determine namespaces
- *   @current_ns: return calling task's namespace
+ *   @grab_current_ns: return a new reference to calling task's namespace
  *   @netlink_ns: return namespace to which a sock belongs (right?)
  *   @initial_ns: return the initial namespace (i.e. init_net_ns)
+ *   @drop_ns: drops a reference to namespace
  */
 struct kobj_ns_type_operations {
        enum kobj_ns_type type;
-       const void *(*current_ns)(void);
+       void *(*grab_current_ns)(void);
        const void *(*netlink_ns)(struct sock *sk);
        const void *(*initial_ns)(void);
+       void (*drop_ns)(void *);
 };
 
 int kobj_ns_type_register(const struct kobj_ns_type_operations *ops);
@@ -48,9 +50,9 @@ int kobj_ns_type_registered(enum kobj_ns_type type);
 const struct kobj_ns_type_operations *kobj_child_ns_ops(struct kobject *parent);
 const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj);
 
-const void *kobj_ns_current(enum kobj_ns_type type);
+void *kobj_ns_grab_current(enum kobj_ns_type type);
 const void *kobj_ns_netlink(enum kobj_ns_type type, struct sock *sk);
 const void *kobj_ns_initial(enum kobj_ns_type type);
-void kobj_ns_exit(enum kobj_ns_type type, const void *ns);
+void kobj_ns_drop(enum kobj_ns_type type, void *ns);
 
 #endif /* _LINUX_KOBJECT_NS_H */
index 9724a38ee69d5c9e292aa75c8fcc092486ebdbe7..50940da6adf36d7a544c32448b6873f83cef2224 100644 (file)
@@ -84,6 +84,7 @@ int task_in_mem_cgroup(struct task_struct *task, const struct mem_cgroup *mem);
 
 extern struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page);
 extern struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p);
+extern struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm);
 
 static inline
 int mm_match_cgroup(const struct mm_struct *mm, const struct mem_cgroup *cgroup)
@@ -246,6 +247,11 @@ static inline struct mem_cgroup *try_get_mem_cgroup_from_page(struct page *page)
        return NULL;
 }
 
+static inline struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
+{
+       return NULL;
+}
+
 static inline int mm_match_cgroup(struct mm_struct *mm, struct mem_cgroup *mem)
 {
        return 1;
index c928dac6cad0c3b1022ebdca9d53ecef1865b797..9f7c3ebcbbad9d7d985c1d41a5a50adf8463854f 100644 (file)
@@ -647,6 +647,13 @@ typedef struct pglist_data {
 #endif
 #define nid_page_nr(nid, pagenr)       pgdat_page_nr(NODE_DATA(nid),(pagenr))
 
+#define node_start_pfn(nid)    (NODE_DATA(nid)->node_start_pfn)
+
+#define node_end_pfn(nid) ({\
+       pg_data_t *__pgdat = NODE_DATA(nid);\
+       __pgdat->node_start_pfn + __pgdat->node_spanned_pages;\
+})
+
 #include <linux/memory_hotplug.h>
 
 extern struct mutex zonelists_mutex;
index 3a34e80ae92fbf3d3920d172898ef3123c43708a..25311b3bedf855574eb79170ea7b25d98962b0d6 100644 (file)
@@ -92,6 +92,9 @@ extern        int nfs_pageio_add_request(struct nfs_pageio_descriptor *,
                                   struct nfs_page *);
 extern void nfs_pageio_complete(struct nfs_pageio_descriptor *desc);
 extern void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *, pgoff_t);
+extern bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc,
+                               struct nfs_page *prev,
+                               struct nfs_page *req);
 extern  int nfs_wait_on_request(struct nfs_page *);
 extern void nfs_unlock_request(struct nfs_page *req);
 extern int nfs_set_page_tag_locked(struct nfs_page *req);
index 5e8444a11adf0a6cb7a545657df9a47b2376bd0b..00848d86ffb250fe50b7e5090986646aac43aa47 100644 (file)
@@ -158,7 +158,6 @@ struct nfs_seqid;
 
 /* nfs41 sessions channel attributes */
 struct nfs4_channel_attrs {
-       u32                     headerpadsz;
        u32                     max_rqst_sz;
        u32                     max_resp_sz;
        u32                     max_resp_sz_cached;
index a311008af5e1538c262990459fb2daefe7d8dddb..f8910e15556617e90fa7bb39365c47767e82d451 100644 (file)
 #define PCI_DEVICE_ID_RICOH_RL5C476    0x0476
 #define PCI_DEVICE_ID_RICOH_RL5C478    0x0478
 #define PCI_DEVICE_ID_RICOH_R5C822     0x0822
+#define PCI_DEVICE_ID_RICOH_R5CE823    0xe823
 #define PCI_DEVICE_ID_RICOH_R5C832     0x0832
 #define PCI_DEVICE_ID_RICOH_R5C843     0x0843
 
index 3160648ccdda1ffe47312d3b2e90b368f36898f3..411e4f4be52b984fa22f9a36502a8c2b79b18b4a 100644 (file)
@@ -425,7 +425,8 @@ struct dev_pm_info {
        pm_message_t            power_state;
        unsigned int            can_wakeup:1;
        unsigned int            async_suspend:1;
-       unsigned int            in_suspend:1;   /* Owned by the PM core */
+       bool                    is_prepared:1;  /* Owned by the PM core */
+       bool                    is_suspended:1; /* Ditto */
        spinlock_t              lock;
 #ifdef CONFIG_PM_SLEEP
        struct list_head        entry;
index 2b7fec840517ff00ae46d14b0662bbf85bb4dc62..aa08fa8fd79b9c85bd3adaa68e22631b0f425e97 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/swap.h>
 #include <linux/mempolicy.h>
+#include <linux/pagemap.h>
 #include <linux/percpu_counter.h>
 
 /* inode in-kernel data */
@@ -45,7 +46,27 @@ static inline struct shmem_inode_info *SHMEM_I(struct inode *inode)
        return container_of(inode, struct shmem_inode_info, vfs_inode);
 }
 
+/*
+ * Functions in mm/shmem.c called directly from elsewhere:
+ */
 extern int init_tmpfs(void);
 extern int shmem_fill_super(struct super_block *sb, void *data, int silent);
+extern struct file *shmem_file_setup(const char *name,
+                                       loff_t size, unsigned long flags);
+extern int shmem_zero_setup(struct vm_area_struct *);
+extern int shmem_lock(struct file *file, int lock, struct user_struct *user);
+extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
+                                       pgoff_t index, gfp_t gfp_mask);
+extern void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end);
+extern int shmem_unuse(swp_entry_t entry, struct page *page);
+extern void mem_cgroup_get_shmem_target(struct inode *inode, pgoff_t pgoff,
+                                       struct page **pagep, swp_entry_t *ent);
+
+static inline struct page *shmem_read_mapping_page(
+                               struct address_space *mapping, pgoff_t index)
+{
+       return shmem_read_mapping_page_gfp(mapping, index,
+                                       mapping_gfp_mask(mapping));
+}
 
 #endif
index 7ad824d510a2138bca6b7e3d1ec8aae4c0ac014a..8cc38d3bab0c57a79f68fe53e4915f9393335cba 100644 (file)
@@ -85,12 +85,15 @@ int smp_call_function_any(const struct cpumask *mask,
  * Generic and arch helpers
  */
 #ifdef CONFIG_USE_GENERIC_SMP_HELPERS
+void __init call_function_init(void);
 void generic_smp_call_function_single_interrupt(void);
 void generic_smp_call_function_interrupt(void);
 void ipi_call_lock(void);
 void ipi_call_unlock(void);
 void ipi_call_lock_irq(void);
 void ipi_call_unlock_irq(void);
+#else
+static inline void call_function_init(void) { }
 #endif
 
 /*
@@ -134,7 +137,7 @@ static inline void smp_send_reschedule(int cpu) { }
 #define smp_prepare_boot_cpu()                 do {} while (0)
 #define smp_call_function_many(mask, func, info, wait) \
                        (up_smp_call_function(func, info))
-static inline void init_call_single_data(void) { }
+static inline void call_function_init(void) { }
 
 static inline int
 smp_call_function_any(const struct cpumask *mask, smp_call_func_t func,
diff --git a/include/linux/sunrpc/gss_krb5_enctypes.h b/include/linux/sunrpc/gss_krb5_enctypes.h
new file mode 100644 (file)
index 0000000..ec6234e
--- /dev/null
@@ -0,0 +1,4 @@
+/*
+ * Dumb way to share this static piece of information with nfsd
+ */
+#define KRB5_SUPPORTED_ENCTYPES "18,17,16,23,3,1,2"
index f73c482ec9c6080cc5201c047546928c53c8b723..fe2d8e6b923b416908220e2ef70bed01dee60897 100644 (file)
@@ -84,7 +84,8 @@ struct rpc_task {
 #endif
        unsigned char           tk_priority : 2,/* Task priority */
                                tk_garb_retry : 2,
-                               tk_cred_retry : 2;
+                               tk_cred_retry : 2,
+                               tk_rebind_retry : 2;
 };
 #define tk_xprt                        tk_client->cl_xprt
 
index 384eb5fe530b8e90c44c9f65ebb719f965cf65df..a273468f82858d6af3b61aa35b2db536385cbf05 100644 (file)
@@ -300,16 +300,6 @@ static inline void scan_unevictable_unregister_node(struct node *node)
 extern int kswapd_run(int nid);
 extern void kswapd_stop(int nid);
 
-#ifdef CONFIG_MMU
-/* linux/mm/shmem.c */
-extern int shmem_unuse(swp_entry_t entry, struct page *page);
-#endif /* CONFIG_MMU */
-
-#ifdef CONFIG_CGROUP_MEM_RES_CTLR
-extern void mem_cgroup_get_shmem_target(struct inode *inode, pgoff_t pgoff,
-                                       struct page **pagep, swp_entry_t *ent);
-#endif
-
 #ifdef CONFIG_SWAP
 /* linux/mm/page_io.c */
 extern int swap_readpage(struct page *);
@@ -358,6 +348,7 @@ struct backing_dev_info;
 extern struct mm_struct *swap_token_mm;
 extern void grab_swap_token(struct mm_struct *);
 extern void __put_swap_token(struct mm_struct *);
+extern void disable_swap_token(struct mem_cgroup *memcg);
 
 static inline int has_swap_token(struct mm_struct *mm)
 {
@@ -370,11 +361,6 @@ static inline void put_swap_token(struct mm_struct *mm)
                __put_swap_token(mm);
 }
 
-static inline void disable_swap_token(void)
-{
-       put_swap_token(swap_token_mm);
-}
-
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR
 extern void
 mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout);
@@ -500,7 +486,7 @@ static inline int has_swap_token(struct mm_struct *mm)
        return 0;
 }
 
-static inline void disable_swap_token(void)
+static inline void disable_swap_token(struct mem_cgroup *memcg)
 {
 }
 
index c3acda60eee0819f9735e059b925ed739bf5831e..e2696d76a59956eeea4bb3431fddc3b7ecbc4780 100644 (file)
@@ -177,9 +177,6 @@ struct sysfs_dirent *sysfs_get_dirent(struct sysfs_dirent *parent_sd,
 struct sysfs_dirent *sysfs_get(struct sysfs_dirent *sd);
 void sysfs_put(struct sysfs_dirent *sd);
 
-/* Called to clear a ns tag when it is no longer valid */
-void sysfs_exit_ns(enum kobj_ns_type type, const void *tag);
-
 int __must_check sysfs_init(void);
 
 #else /* CONFIG_SYSFS */
@@ -338,10 +335,6 @@ static inline void sysfs_put(struct sysfs_dirent *sd)
 {
 }
 
-static inline void sysfs_exit_ns(int type, const void *tag)
-{
-}
-
 static inline int __must_check sysfs_init(void)
 {
        return 0;
index b91a40e847d236d9046dc3154a7e7a58ea594776..fc839bfa7935aff66380a22e9b95589127ec66d2 100644 (file)
@@ -60,7 +60,7 @@ int arch_update_cpu_topology(void);
  * (in whatever arch specific measurement units returned by node_distance())
  * then switch on zone reclaim on boot.
  */
-#define RECLAIM_DISTANCE 20
+#define RECLAIM_DISTANCE 30
 #endif
 #ifndef PENALTY_FOR_NODE_WITH_CPUS
 #define PENALTY_FOR_NODE_WITH_CPUS     (1)
index 73eb1ed36ec4cdb19b92a33b146b632ac9378f38..6ddbd86377dec3375549f2f02ef5c7c47fa9bfb3 100644 (file)
@@ -9,7 +9,7 @@
 #endif
 
 #ifndef UTS_NODENAME
-#define UTS_NODENAME "(none)"  /* set by sethostname() */
+#define UTS_NODENAME CONFIG_DEFAULT_HOSTNAME /* set by sethostname() */
 #endif
 
 #ifndef UTS_DOMAINNAME
index 2bf9ed9ef26b266a583550238e8433861d218c80..aef430d779bdd07542f5be64967c8f5c8fb9d809 100644 (file)
@@ -35,8 +35,11 @@ struct netns_ipvs;
 #define NETDEV_HASHENTRIES (1 << NETDEV_HASHBITS)
 
 struct net {
+       atomic_t                passive;        /* To decided when the network
+                                                * namespace should be freed.
+                                                */
        atomic_t                count;          /* To decided when the network
-                                                *  namespace should be freed.
+                                                *  namespace should be shut down.
                                                 */
 #ifdef NETNS_REFCNT_DEBUG
        atomic_t                use_count;      /* To track references we
@@ -154,6 +157,9 @@ int net_eq(const struct net *net1, const struct net *net2)
 {
        return net1 == net2;
 }
+
+extern void net_drop_ns(void *);
+
 #else
 
 static inline struct net *get_net(struct net *net)
@@ -175,6 +181,8 @@ int net_eq(const struct net *net1, const struct net *net2)
 {
        return 1;
 }
+
+#define net_drop_ns NULL
 #endif
 
 
index c7c42e7acc31004d10ba3adaa0f42c1e9131b127..5d4f8e586e32e6489da5fb7ff5d1525a5b8fe1b1 100644 (file)
@@ -307,6 +307,12 @@ static inline int nf_ct_is_untracked(const struct nf_conn *ct)
        return test_bit(IPS_UNTRACKED_BIT, &ct->status);
 }
 
+/* Packet is received from loopback */
+static inline bool nf_is_loopback_packet(const struct sk_buff *skb)
+{
+       return skb->dev && skb->skb_iif && skb->dev->flags & IFF_LOOPBACK;
+}
+
 extern int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp);
 extern unsigned int nf_conntrack_htable_size;
 extern unsigned int nf_conntrack_max;
index f2046e404a610da5c095abfcc88872b5ac1c5c42..c0b938cb4b1ac196448494bfe1f8aed36a13caeb 100644 (file)
@@ -178,7 +178,6 @@ struct sock_common {
   *    @sk_dst_cache: destination cache
   *    @sk_dst_lock: destination cache lock
   *    @sk_policy: flow policy
-  *    @sk_rmem_alloc: receive queue bytes committed
   *    @sk_receive_queue: incoming packets
   *    @sk_wmem_alloc: transmit queue bytes committed
   *    @sk_write_queue: Packet sending queue
index f1de3e0c75bcad1da0cbed760272fe5e190bccdc..3a4bd3a3c68d25cb2ccd6896a2750a761668937a 100644 (file)
@@ -248,8 +248,7 @@ typedef int (*hw_write_t)(void *,const char* ,int);
 extern struct snd_ac97_bus_ops soc_ac97_ops;
 
 enum snd_soc_control_type {
-       SND_SOC_CUSTOM = 1,
-       SND_SOC_I2C,
+       SND_SOC_I2C = 1,
        SND_SOC_SPI,
 };
 
index e09592d2f916adfdf041272e3b7a672379f7eea1..5ce2b2f5f524de65de6902a97232886196d7575f 100644 (file)
@@ -26,7 +26,7 @@ TRACE_EVENT(ext4_free_inode,
                __field(        umode_t, mode                   )
                __field(        uid_t,  uid                     )
                __field(        gid_t,  gid                     )
-               __field(        blkcnt_t, blocks                )
+               __field(        __u64, blocks                   )
        ),
 
        TP_fast_assign(
@@ -40,9 +40,8 @@ TRACE_EVENT(ext4_free_inode,
 
        TP_printk("dev %d,%d ino %lu mode 0%o uid %u gid %u blocks %llu",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
-                 (unsigned long) __entry->ino,
-                 __entry->mode, __entry->uid, __entry->gid,
-                 (unsigned long long) __entry->blocks)
+                 (unsigned long) __entry->ino, __entry->mode,
+                 __entry->uid, __entry->gid, __entry->blocks)
 );
 
 TRACE_EVENT(ext4_request_inode,
@@ -178,7 +177,7 @@ TRACE_EVENT(ext4_begin_ordered_truncate,
        TP_printk("dev %d,%d ino %lu new_size %lld",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
-                 (long long) __entry->new_size)
+                 __entry->new_size)
 );
 
 DECLARE_EVENT_CLASS(ext4__write_begin,
@@ -204,7 +203,7 @@ DECLARE_EVENT_CLASS(ext4__write_begin,
                __entry->flags  = flags;
        ),
 
-       TP_printk("dev %d,%d ino %lu pos %llu len %u flags %u",
+       TP_printk("dev %d,%d ino %lu pos %lld len %u flags %u",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
                  __entry->pos, __entry->len, __entry->flags)
@@ -248,7 +247,7 @@ DECLARE_EVENT_CLASS(ext4__write_end,
                __entry->copied = copied;
        ),
 
-       TP_printk("dev %d,%d ino %lu pos %llu len %u copied %u",
+       TP_printk("dev %d,%d ino %lu pos %lld len %u copied %u",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
                  __entry->pos, __entry->len, __entry->copied)
@@ -286,29 +285,6 @@ DEFINE_EVENT(ext4__write_end, ext4_da_write_end,
        TP_ARGS(inode, pos, len, copied)
 );
 
-TRACE_EVENT(ext4_writepage,
-       TP_PROTO(struct inode *inode, struct page *page),
-
-       TP_ARGS(inode, page),
-
-       TP_STRUCT__entry(
-               __field(        dev_t,  dev                     )
-               __field(        ino_t,  ino                     )
-               __field(        pgoff_t, index                  )
-
-       ),
-
-       TP_fast_assign(
-               __entry->dev    = inode->i_sb->s_dev;
-               __entry->ino    = inode->i_ino;
-               __entry->index  = page->index;
-       ),
-
-       TP_printk("dev %d,%d ino %lu page_index %lu",
-                 MAJOR(__entry->dev), MINOR(__entry->dev),
-                 (unsigned long) __entry->ino, __entry->index)
-);
-
 TRACE_EVENT(ext4_da_writepages,
        TP_PROTO(struct inode *inode, struct writeback_control *wbc),
 
@@ -341,7 +317,7 @@ TRACE_EVENT(ext4_da_writepages,
        ),
 
        TP_printk("dev %d,%d ino %lu nr_to_write %ld pages_skipped %ld "
-                 "range_start %llu range_end %llu sync_mode %d"
+                 "range_start %lld range_end %lld sync_mode %d"
                  "for_kupdate %d range_cyclic %d writeback_index %lu",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino, __entry->nr_to_write,
@@ -449,7 +425,14 @@ DECLARE_EVENT_CLASS(ext4__page_op,
        TP_printk("dev %d,%d ino %lu page_index %lu",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
-                 __entry->index)
+                 (unsigned long) __entry->index)
+);
+
+DEFINE_EVENT(ext4__page_op, ext4_writepage,
+
+       TP_PROTO(struct page *page),
+
+       TP_ARGS(page)
 );
 
 DEFINE_EVENT(ext4__page_op, ext4_readpage,
@@ -489,7 +472,7 @@ TRACE_EVENT(ext4_invalidatepage,
        TP_printk("dev %d,%d ino %lu page_index %lu offset %lu",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
-                 __entry->index, __entry->offset)
+                 (unsigned long) __entry->index, __entry->offset)
 );
 
 TRACE_EVENT(ext4_discard_blocks,
@@ -562,12 +545,10 @@ DEFINE_EVENT(ext4__mb_new_pa, ext4_mb_new_group_pa,
 );
 
 TRACE_EVENT(ext4_mb_release_inode_pa,
-       TP_PROTO(struct super_block *sb,
-                struct inode *inode,
-                struct ext4_prealloc_space *pa,
+       TP_PROTO(struct ext4_prealloc_space *pa,
                 unsigned long long block, unsigned int count),
 
-       TP_ARGS(sb, inode, pa, block, count),
+       TP_ARGS(pa, block, count),
 
        TP_STRUCT__entry(
                __field(        dev_t,  dev                     )
@@ -578,8 +559,8 @@ TRACE_EVENT(ext4_mb_release_inode_pa,
        ),
 
        TP_fast_assign(
-               __entry->dev            = sb->s_dev;
-               __entry->ino            = inode->i_ino;
+               __entry->dev            = pa->pa_inode->i_sb->s_dev;
+               __entry->ino            = pa->pa_inode->i_ino;
                __entry->block          = block;
                __entry->count          = count;
        ),
@@ -591,10 +572,9 @@ TRACE_EVENT(ext4_mb_release_inode_pa,
 );
 
 TRACE_EVENT(ext4_mb_release_group_pa,
-       TP_PROTO(struct super_block *sb,
-                struct ext4_prealloc_space *pa),
+       TP_PROTO(struct ext4_prealloc_space *pa),
 
-       TP_ARGS(sb, pa),
+       TP_ARGS(pa),
 
        TP_STRUCT__entry(
                __field(        dev_t,  dev                     )
@@ -604,7 +584,7 @@ TRACE_EVENT(ext4_mb_release_group_pa,
        ),
 
        TP_fast_assign(
-               __entry->dev            = sb->s_dev;
+               __entry->dev            = pa->pa_inode->i_sb->s_dev;
                __entry->pa_pstart      = pa->pa_pstart;
                __entry->pa_len         = pa->pa_len;
        ),
@@ -666,10 +646,10 @@ TRACE_EVENT(ext4_request_blocks,
                __field(        ino_t,  ino                     )
                __field(        unsigned int, flags             )
                __field(        unsigned int, len               )
-               __field(        __u64,  logical                 )
+               __field(        __u32,  logical                 )
+               __field(        __u32,  lleft                   )
+               __field(        __u32,  lright                  )
                __field(        __u64,  goal                    )
-               __field(        __u64,  lleft                   )
-               __field(        __u64,  lright                  )
                __field(        __u64,  pleft                   )
                __field(        __u64,  pright                  )
        ),
@@ -687,17 +667,13 @@ TRACE_EVENT(ext4_request_blocks,
                __entry->pright = ar->pright;
        ),
 
-       TP_printk("dev %d,%d ino %lu flags %u len %u lblk %llu goal %llu "
-                 "lleft %llu lright %llu pleft %llu pright %llu ",
+       TP_printk("dev %d,%d ino %lu flags %u len %u lblk %u goal %llu "
+                 "lleft %u lright %u pleft %llu pright %llu ",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
-                 (unsigned long) __entry->ino,
-                 __entry->flags, __entry->len,
-                 (unsigned long long) __entry->logical,
-                 (unsigned long long) __entry->goal,
-                 (unsigned long long) __entry->lleft,
-                 (unsigned long long) __entry->lright,
-                 (unsigned long long) __entry->pleft,
-                 (unsigned long long) __entry->pright)
+                 (unsigned long) __entry->ino, __entry->flags,
+                 __entry->len, __entry->logical, __entry->goal,
+                 __entry->lleft, __entry->lright, __entry->pleft,
+                 __entry->pright)
 );
 
 TRACE_EVENT(ext4_allocate_blocks,
@@ -711,10 +687,10 @@ TRACE_EVENT(ext4_allocate_blocks,
                __field(        __u64,  block                   )
                __field(        unsigned int, flags             )
                __field(        unsigned int, len               )
-               __field(        __u64,  logical                 )
+               __field(        __u32,  logical                 )
+               __field(        __u32,  lleft                   )
+               __field(        __u32,  lright                  )
                __field(        __u64,  goal                    )
-               __field(        __u64,  lleft                   )
-               __field(        __u64,  lright                  )
                __field(        __u64,  pleft                   )
                __field(        __u64,  pright                  )
        ),
@@ -733,17 +709,13 @@ TRACE_EVENT(ext4_allocate_blocks,
                __entry->pright = ar->pright;
        ),
 
-       TP_printk("dev %d,%d ino %lu flags %u len %u block %llu lblk %llu "
-                 "goal %llu lleft %llu lright %llu pleft %llu pright %llu",
+       TP_printk("dev %d,%d ino %lu flags %u len %u block %llu lblk %u "
+                 "goal %llu lleft %u lright %u pleft %llu pright %llu",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
-                 (unsigned long) __entry->ino,
-                 __entry->flags, __entry->len, __entry->block,
-                 (unsigned long long) __entry->logical,
-                 (unsigned long long) __entry->goal,
-                 (unsigned long long) __entry->lleft,
-                 (unsigned long long) __entry->lright,
-                 (unsigned long long) __entry->pleft,
-                 (unsigned long long) __entry->pright)
+                 (unsigned long) __entry->ino, __entry->flags,
+                 __entry->len, __entry->block, __entry->logical,
+                 __entry->goal,  __entry->lleft, __entry->lright,
+                 __entry->pleft, __entry->pright)
 );
 
 TRACE_EVENT(ext4_free_blocks,
@@ -755,10 +727,10 @@ TRACE_EVENT(ext4_free_blocks,
        TP_STRUCT__entry(
                __field(        dev_t,  dev                     )
                __field(        ino_t,  ino                     )
-               __field(      umode_t, mode                     )
+               __field(        umode_t, mode                   )
                __field(        __u64,  block                   )
                __field(        unsigned long,  count           )
-               __field(         int,   flags                   )
+               __field(        int,    flags                   )
        ),
 
        TP_fast_assign(
@@ -798,7 +770,7 @@ TRACE_EVENT(ext4_sync_file_enter,
                __entry->parent         = dentry->d_parent->d_inode->i_ino;
        ),
 
-       TP_printk("dev %d,%d ino %ld parent %ld datasync %d ",
+       TP_printk("dev %d,%d ino %lu parent %lu datasync %d ",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
                  (unsigned long) __entry->parent, __entry->datasync)
@@ -821,7 +793,7 @@ TRACE_EVENT(ext4_sync_file_exit,
                __entry->dev            = inode->i_sb->s_dev;
        ),
 
-       TP_printk("dev %d,%d ino %ld ret %d",
+       TP_printk("dev %d,%d ino %lu ret %d",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
                  __entry->ret)
@@ -1005,7 +977,7 @@ DECLARE_EVENT_CLASS(ext4__mballoc,
                __entry->result_len     = len;
        ),
 
-       TP_printk("dev %d,%d inode %lu extent %u/%d/%u ",
+       TP_printk("dev %d,%d inode %lu extent %u/%d/%d ",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
                  __entry->result_group, __entry->result_start,
@@ -1093,7 +1065,7 @@ TRACE_EVENT(ext4_da_update_reserve_space,
                  "allocated_meta_blocks %d",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
-                 __entry->mode,  (unsigned long long) __entry->i_blocks,
+                 __entry->mode, __entry->i_blocks,
                  __entry->used_blocks, __entry->reserved_data_blocks,
                  __entry->reserved_meta_blocks, __entry->allocated_meta_blocks)
 );
@@ -1127,7 +1099,7 @@ TRACE_EVENT(ext4_da_reserve_space,
                  "reserved_data_blocks %d reserved_meta_blocks %d",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
-                 __entry->mode, (unsigned long long) __entry->i_blocks,
+                 __entry->mode, __entry->i_blocks,
                  __entry->md_needed, __entry->reserved_data_blocks,
                  __entry->reserved_meta_blocks)
 );
@@ -1164,7 +1136,7 @@ TRACE_EVENT(ext4_da_release_space,
                  "allocated_meta_blocks %d",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
-                 __entry->mode, (unsigned long long) __entry->i_blocks,
+                 __entry->mode, __entry->i_blocks,
                  __entry->freed_blocks, __entry->reserved_data_blocks,
                  __entry->reserved_meta_blocks, __entry->allocated_meta_blocks)
 );
@@ -1239,14 +1211,15 @@ TRACE_EVENT(ext4_direct_IO_enter,
                __entry->rw     = rw;
        ),
 
-       TP_printk("dev %d,%d ino %lu pos %llu len %lu rw %d",
+       TP_printk("dev %d,%d ino %lu pos %lld len %lu rw %d",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
-                 (unsigned long long) __entry->pos, __entry->len, __entry->rw)
+                 __entry->pos, __entry->len, __entry->rw)
 );
 
 TRACE_EVENT(ext4_direct_IO_exit,
-       TP_PROTO(struct inode *inode, loff_t offset, unsigned long len, int rw, int ret),
+       TP_PROTO(struct inode *inode, loff_t offset, unsigned long len,
+                int rw, int ret),
 
        TP_ARGS(inode, offset, len, rw, ret),
 
@@ -1268,10 +1241,10 @@ TRACE_EVENT(ext4_direct_IO_exit,
                __entry->ret    = ret;
        ),
 
-       TP_printk("dev %d,%d ino %lu pos %llu len %lu rw %d ret %d",
+       TP_printk("dev %d,%d ino %lu pos %lld len %lu rw %d ret %d",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
-                 (unsigned long long) __entry->pos, __entry->len,
+                 __entry->pos, __entry->len,
                  __entry->rw, __entry->ret)
 );
 
@@ -1296,15 +1269,15 @@ TRACE_EVENT(ext4_fallocate_enter,
                __entry->mode   = mode;
        ),
 
-       TP_printk("dev %d,%d ino %ld pos %llu len %llu mode %d",
+       TP_printk("dev %d,%d ino %lu pos %lld len %lld mode %d",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
-                 (unsigned long) __entry->ino,
-                 (unsigned long long) __entry->pos,
-                 (unsigned long long) __entry->len, __entry->mode)
+                 (unsigned long) __entry->ino, __entry->pos,
+                 __entry->len, __entry->mode)
 );
 
 TRACE_EVENT(ext4_fallocate_exit,
-       TP_PROTO(struct inode *inode, loff_t offset, unsigned int max_blocks, int ret),
+       TP_PROTO(struct inode *inode, loff_t offset,
+                unsigned int max_blocks, int ret),
 
        TP_ARGS(inode, offset, max_blocks, ret),
 
@@ -1312,7 +1285,7 @@ TRACE_EVENT(ext4_fallocate_exit,
                __field(        ino_t,  ino                     )
                __field(        dev_t,  dev                     )
                __field(        loff_t, pos                     )
-               __field(        unsigned,       blocks          )
+               __field(        unsigned int,   blocks          )
                __field(        int,    ret                     )
        ),
 
@@ -1324,10 +1297,10 @@ TRACE_EVENT(ext4_fallocate_exit,
                __entry->ret    = ret;
        ),
 
-       TP_printk("dev %d,%d ino %ld pos %llu blocks %d ret %d",
+       TP_printk("dev %d,%d ino %lu pos %lld blocks %u ret %d",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
-                 (unsigned long long) __entry->pos, __entry->blocks,
+                 __entry->pos, __entry->blocks,
                  __entry->ret)
 );
 
@@ -1350,7 +1323,7 @@ TRACE_EVENT(ext4_unlink_enter,
                __entry->dev            = dentry->d_inode->i_sb->s_dev;
        ),
 
-       TP_printk("dev %d,%d ino %ld size %lld parent %ld",
+       TP_printk("dev %d,%d ino %lu size %lld parent %lu",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino, __entry->size,
                  (unsigned long) __entry->parent)
@@ -1373,7 +1346,7 @@ TRACE_EVENT(ext4_unlink_exit,
                __entry->ret            = ret;
        ),
 
-       TP_printk("dev %d,%d ino %ld ret %d",
+       TP_printk("dev %d,%d ino %lu ret %d",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
                  __entry->ret)
@@ -1387,7 +1360,7 @@ DECLARE_EVENT_CLASS(ext4__truncate,
        TP_STRUCT__entry(
                __field(        ino_t,          ino             )
                __field(        dev_t,          dev             )
-               __field(        blkcnt_t,       blocks          )
+               __field(        __u64,          blocks          )
        ),
 
        TP_fast_assign(
@@ -1396,9 +1369,9 @@ DECLARE_EVENT_CLASS(ext4__truncate,
                __entry->blocks = inode->i_blocks;
        ),
 
-       TP_printk("dev %d,%d ino %lu blocks %lu",
+       TP_printk("dev %d,%d ino %lu blocks %llu",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
-                 (unsigned long) __entry->ino, (unsigned long) __entry->blocks)
+                 (unsigned long) __entry->ino, __entry->blocks)
 );
 
 DEFINE_EVENT(ext4__truncate, ext4_truncate_enter,
@@ -1417,7 +1390,7 @@ DEFINE_EVENT(ext4__truncate, ext4_truncate_exit,
 
 DECLARE_EVENT_CLASS(ext4__map_blocks_enter,
        TP_PROTO(struct inode *inode, ext4_lblk_t lblk,
-                unsigned len, unsigned flags),
+                unsigned int len, unsigned int flags),
 
        TP_ARGS(inode, lblk, len, flags),
 
@@ -1425,8 +1398,8 @@ DECLARE_EVENT_CLASS(ext4__map_blocks_enter,
                __field(        ino_t,          ino             )
                __field(        dev_t,          dev             )
                __field(        ext4_lblk_t,    lblk            )
-               __field(        unsigned,       len             )
-               __field(        unsigned,       flags           )
+               __field(        unsigned int,   len             )
+               __field(        unsigned int,   flags           )
        ),
 
        TP_fast_assign(
@@ -1440,7 +1413,7 @@ DECLARE_EVENT_CLASS(ext4__map_blocks_enter,
        TP_printk("dev %d,%d ino %lu lblk %u len %u flags %u",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
-                 (unsigned) __entry->lblk, __entry->len, __entry->flags)
+                 __entry->lblk, __entry->len, __entry->flags)
 );
 
 DEFINE_EVENT(ext4__map_blocks_enter, ext4_ext_map_blocks_enter,
@@ -1459,7 +1432,7 @@ DEFINE_EVENT(ext4__map_blocks_enter, ext4_ind_map_blocks_enter,
 
 DECLARE_EVENT_CLASS(ext4__map_blocks_exit,
        TP_PROTO(struct inode *inode, ext4_lblk_t lblk,
-                ext4_fsblk_t pblk, unsigned len, int ret),
+                ext4_fsblk_t pblk, unsigned int len, int ret),
 
        TP_ARGS(inode, lblk, pblk, len, ret),
 
@@ -1468,7 +1441,7 @@ DECLARE_EVENT_CLASS(ext4__map_blocks_exit,
                __field(        dev_t,          dev             )
                __field(        ext4_lblk_t,    lblk            )
                __field(        ext4_fsblk_t,   pblk            )
-               __field(        unsigned,       len             )
+               __field(        unsigned int,   len             )
                __field(        int,            ret             )
        ),
 
@@ -1484,7 +1457,7 @@ DECLARE_EVENT_CLASS(ext4__map_blocks_exit,
        TP_printk("dev %d,%d ino %lu lblk %u pblk %llu len %u ret %d",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
-                 (unsigned) __entry->lblk, (unsigned long long) __entry->pblk,
+                 __entry->lblk, __entry->pblk,
                  __entry->len, __entry->ret)
 );
 
@@ -1524,7 +1497,7 @@ TRACE_EVENT(ext4_ext_load_extent,
        TP_printk("dev %d,%d ino %lu lblk %u pblk %llu",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  (unsigned long) __entry->ino,
-                 (unsigned) __entry->lblk, (unsigned long long) __entry->pblk)
+                 __entry->lblk, __entry->pblk)
 );
 
 TRACE_EVENT(ext4_load_inode,
index ae045ca7d356033d49c8a9650a618c206503f68c..1c09820df58564f8d0430d996998edc6f8d893c0 100644 (file)
@@ -20,7 +20,8 @@ struct softirq_action;
                         softirq_name(BLOCK_IOPOLL),    \
                         softirq_name(TASKLET),         \
                         softirq_name(SCHED),           \
-                        softirq_name(HRTIMER))
+                        softirq_name(HRTIMER),         \
+                        softirq_name(RCU))
 
 /**
  * irq_handler_entry - called immediately before the irq action handler
index ea422aaa23e12a2397e08a167e36dd65ce7041cf..b2c33bd955faa4536082e62e6c9f17946994afde 100644 (file)
@@ -6,6 +6,8 @@
 
 #include <linux/types.h>
 #include <linux/tracepoint.h>
+#include <linux/mm.h>
+#include <linux/memcontrol.h>
 #include "gfpflags.h"
 
 #define RECLAIM_WB_ANON                0x0001u
@@ -310,6 +312,87 @@ TRACE_EVENT(mm_vmscan_lru_shrink_inactive,
                show_reclaim_flags(__entry->reclaim_flags))
 );
 
+TRACE_EVENT(replace_swap_token,
+       TP_PROTO(struct mm_struct *old_mm,
+                struct mm_struct *new_mm),
+
+       TP_ARGS(old_mm, new_mm),
+
+       TP_STRUCT__entry(
+               __field(struct mm_struct*,      old_mm)
+               __field(unsigned int,           old_prio)
+               __field(struct mm_struct*,      new_mm)
+               __field(unsigned int,           new_prio)
+       ),
+
+       TP_fast_assign(
+               __entry->old_mm   = old_mm;
+               __entry->old_prio = old_mm ? old_mm->token_priority : 0;
+               __entry->new_mm   = new_mm;
+               __entry->new_prio = new_mm->token_priority;
+       ),
+
+       TP_printk("old_token_mm=%p old_prio=%u new_token_mm=%p new_prio=%u",
+                 __entry->old_mm, __entry->old_prio,
+                 __entry->new_mm, __entry->new_prio)
+);
+
+DECLARE_EVENT_CLASS(put_swap_token_template,
+       TP_PROTO(struct mm_struct *swap_token_mm),
+
+       TP_ARGS(swap_token_mm),
+
+       TP_STRUCT__entry(
+               __field(struct mm_struct*, swap_token_mm)
+       ),
+
+       TP_fast_assign(
+               __entry->swap_token_mm = swap_token_mm;
+       ),
+
+       TP_printk("token_mm=%p", __entry->swap_token_mm)
+);
+
+DEFINE_EVENT(put_swap_token_template, put_swap_token,
+       TP_PROTO(struct mm_struct *swap_token_mm),
+       TP_ARGS(swap_token_mm)
+);
+
+DEFINE_EVENT_CONDITION(put_swap_token_template, disable_swap_token,
+       TP_PROTO(struct mm_struct *swap_token_mm),
+       TP_ARGS(swap_token_mm),
+       TP_CONDITION(swap_token_mm != NULL)
+);
+
+TRACE_EVENT_CONDITION(update_swap_token_priority,
+       TP_PROTO(struct mm_struct *mm,
+                unsigned int old_prio,
+                struct mm_struct *swap_token_mm),
+
+       TP_ARGS(mm, old_prio, swap_token_mm),
+
+       TP_CONDITION(mm->token_priority != old_prio),
+
+       TP_STRUCT__entry(
+               __field(struct mm_struct*, mm)
+               __field(unsigned int, old_prio)
+               __field(unsigned int, new_prio)
+               __field(struct mm_struct*, swap_token_mm)
+               __field(unsigned int, swap_token_prio)
+       ),
+
+       TP_fast_assign(
+               __entry->mm             = mm;
+               __entry->old_prio       = old_prio;
+               __entry->new_prio       = mm->token_priority;
+               __entry->swap_token_mm  = swap_token_mm;
+               __entry->swap_token_prio = swap_token_mm ? swap_token_mm->token_priority : 0;
+       ),
+
+       TP_printk("mm=%p old_prio=%u new_prio=%u swap_token_mm=%p token_prio=%u",
+                 __entry->mm, __entry->old_prio, __entry->new_prio,
+                 __entry->swap_token_mm, __entry->swap_token_prio)
+);
 
 #endif /* _TRACE_VMSCAN_H */
 
index 9d2a378cd668b43deaddfd6ee9fc04dc31960bc2..4fe9168149fce13e7c171ee5f61a9636bbdc1b73 100644 (file)
@@ -19,7 +19,6 @@ config DEFCONFIG_LIST
 config CONSTRUCTORS
        bool
        depends on !UML
-       default y
 
 config HAVE_IRQ_WORK
        bool
@@ -204,6 +203,15 @@ config KERNEL_LZO
 
 endchoice
 
+config DEFAULT_HOSTNAME
+       string "Default hostname"
+       default "(none)"
+       help
+         This option determines the default system hostname before userspace
+         calls sethostname(2). The kernel traditionally uses "(none)" here,
+         but you may wish to use a different default here to make a minimal
+         system more usable with less configuration.
+
 config SWAP
        bool "Support for paging of anonymous memory (swap)"
        depends on MMU && BLOCK
index cfd7000c9d7108085b337876893fa6e91910dc04..aae2f40fea4cbea200f0658c7f6afddb60f1d934 100644 (file)
@@ -93,9 +93,6 @@ static unsigned long __cpuinit calibrate_delay_direct(void)
                 * If the upper limit and lower limit of the timer_rate is
                 * >= 12.5% apart, redo calibration.
                 */
-               printk(KERN_DEBUG "calibrate_delay_direct() timer_rate_max=%lu "
-                           "timer_rate_min=%lu pre_start=%lu pre_end=%lu\n",
-                         timer_rate_max, timer_rate_min, pre_start, pre_end);
                if (start >= post_end)
                        printk(KERN_NOTICE "calibrate_delay_direct() ignoring "
                                        "timer_rate as we had a TSC wrap around"
@@ -248,30 +245,32 @@ recalibrate:
 
 void __cpuinit calibrate_delay(void)
 {
+       unsigned long lpj;
        static bool printed;
 
        if (preset_lpj) {
-               loops_per_jiffy = preset_lpj;
+               lpj = preset_lpj;
                if (!printed)
                        pr_info("Calibrating delay loop (skipped) "
                                "preset value.. ");
        } else if ((!printed) && lpj_fine) {
-               loops_per_jiffy = lpj_fine;
+               lpj = lpj_fine;
                pr_info("Calibrating delay loop (skipped), "
                        "value calculated using timer frequency.. ");
-       } else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) {
+       } else if ((lpj = calibrate_delay_direct()) != 0) {
                if (!printed)
                        pr_info("Calibrating delay using timer "
                                "specific routine.. ");
        } else {
                if (!printed)
                        pr_info("Calibrating delay loop... ");
-               loops_per_jiffy = calibrate_delay_converge();
+               lpj = calibrate_delay_converge();
        }
        if (!printed)
                pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
-                       loops_per_jiffy/(500000/HZ),
-                       (loops_per_jiffy/(5000/HZ)) % 100, loops_per_jiffy);
+                       lpj/(500000/HZ),
+                       (lpj/(5000/HZ)) % 100, lpj);
 
+       loops_per_jiffy = lpj;
        printed = true;
 }
index cafba67c13bf8b57493e49b0501ef4265e76204b..d7211faed2adfb295caf46bbb9c70835f622eabe 100644 (file)
@@ -542,6 +542,7 @@ asmlinkage void __init start_kernel(void)
        timekeeping_init();
        time_init();
        profile_init();
+       call_function_init();
        if (!irqs_disabled())
                printk(KERN_CRIT "start_kernel(): bug: interrupts were "
                                 "enabled early\n");
index 20a406471525af2087cf914d8569d401306b3a5b..f2b321bae44037c08d4b09b90b8610a80b979eb7 100644 (file)
@@ -561,29 +561,28 @@ void exit_files(struct task_struct *tsk)
 
 #ifdef CONFIG_MM_OWNER
 /*
- * Task p is exiting and it owned mm, lets find a new owner for it
+ * A task is exiting.   If it owned this mm, find a new owner for the mm.
  */
-static inline int
-mm_need_new_owner(struct mm_struct *mm, struct task_struct *p)
-{
-       /*
-        * If there are other users of the mm and the owner (us) is exiting
-        * we need to find a new owner to take on the responsibility.
-        */
-       if (atomic_read(&mm->mm_users) <= 1)
-               return 0;
-       if (mm->owner != p)
-               return 0;
-       return 1;
-}
-
 void mm_update_next_owner(struct mm_struct *mm)
 {
        struct task_struct *c, *g, *p = current;
 
 retry:
-       if (!mm_need_new_owner(mm, p))
+       /*
+        * If the exiting or execing task is not the owner, it's
+        * someone else's problem.
+        */
+       if (mm->owner != p)
                return;
+       /*
+        * The current owner is exiting/execing and there are no other
+        * candidates.  Do not leave the mm pointing to a possibly
+        * freed task structure.
+        */
+       if (atomic_read(&mm->mm_users) <= 1) {
+               mm->owner = NULL;
+               return;
+       }
 
        read_lock(&tasklist_lock);
        /*
index b8cadf70b1fbd109c4ca56f78f6f9a685e2f9974..5bf924d80b5c64be2888be0afd65008260e8db01 100644 (file)
@@ -2,7 +2,8 @@ menu "GCOV-based kernel profiling"
 
 config GCOV_KERNEL
        bool "Enable gcov-based kernel profiling"
-       depends on DEBUG_FS && CONSTRUCTORS
+       depends on DEBUG_FS
+       select CONSTRUCTORS
        default n
        ---help---
        This option enables gcov-based code profiling (e.g. for code coverage
index ad6a81c58b44e2d5ae57c5dbe866da1cf1008a03..47613dfb7b28c340825493ed36a4c3347a39290d 100644 (file)
@@ -156,12 +156,6 @@ static int ____call_usermodehelper(void *data)
         */
        set_user_nice(current, 0);
 
-       if (sub_info->init) {
-               retval = sub_info->init(sub_info);
-               if (retval)
-                       goto fail;
-       }
-
        retval = -ENOMEM;
        new = prepare_kernel_cred(current);
        if (!new)
@@ -173,6 +167,14 @@ static int ____call_usermodehelper(void *data)
                                             new->cap_inheritable);
        spin_unlock(&umh_sysctl_lock);
 
+       if (sub_info->init) {
+               retval = sub_info->init(sub_info, new);
+               if (retval) {
+                       abort_creds(new);
+                       goto fail;
+               }
+       }
+
        commit_creds(new);
 
        retval = kernel_execve(sub_info->path,
@@ -388,7 +390,7 @@ EXPORT_SYMBOL(call_usermodehelper_setup);
  * context in which call_usermodehelper_exec is called.
  */
 void call_usermodehelper_setfns(struct subprocess_info *info,
-                   int (*init)(struct subprocess_info *info),
+                   int (*init)(struct subprocess_info *info, struct cred *new),
                    void (*cleanup)(struct subprocess_info *info),
                    void *data)
 {
index 7d02d33be699f97d4956c76ea71b939bb0832d06..42ddbc6f0de6ffcf2d245dd9c8ec253c2780ffab 100644 (file)
@@ -113,8 +113,10 @@ static int snapshot_open(struct inode *inode, struct file *filp)
                if (error)
                        pm_notifier_call_chain(PM_POST_RESTORE);
        }
-       if (error)
+       if (error) {
+               free_basic_memory_bitmaps();
                atomic_inc(&snapshot_device_available);
+       }
        data->frozen = 0;
        data->ready = 0;
        data->platform_support = 0;
index 89419ff92e996c1e52fade38475ba14604a8f7bd..7e59ffb3d0ba487c0474270a476b25cbc96d2ac1 100644 (file)
@@ -87,6 +87,8 @@ static struct rcu_state *rcu_state;
 int rcu_scheduler_active __read_mostly;
 EXPORT_SYMBOL_GPL(rcu_scheduler_active);
 
+#ifdef CONFIG_RCU_BOOST
+
 /*
  * Control variables for per-CPU and per-rcu_node kthreads.  These
  * handle all flavors of RCU.
@@ -98,8 +100,11 @@ DEFINE_PER_CPU(unsigned int, rcu_cpu_kthread_loops);
 DEFINE_PER_CPU(char, rcu_cpu_has_work);
 static char rcu_kthreads_spawnable;
 
+#endif /* #ifdef CONFIG_RCU_BOOST */
+
 static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu);
-static void invoke_rcu_cpu_kthread(void);
+static void invoke_rcu_core(void);
+static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp);
 
 #define RCU_KTHREAD_PRIO 1     /* RT priority for per-CPU kthreads. */
 
@@ -1088,14 +1093,8 @@ static void __rcu_offline_cpu(int cpu, struct rcu_state *rsp)
        int need_report = 0;
        struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
        struct rcu_node *rnp;
-       struct task_struct *t;
 
-       /* Stop the CPU's kthread. */
-       t = per_cpu(rcu_cpu_kthread_task, cpu);
-       if (t != NULL) {
-               per_cpu(rcu_cpu_kthread_task, cpu) = NULL;
-               kthread_stop(t);
-       }
+       rcu_stop_cpu_kthread(cpu);
 
        /* Exclude any attempts to start a new grace period. */
        raw_spin_lock_irqsave(&rsp->onofflock, flags);
@@ -1231,7 +1230,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
 
        /* Re-raise the RCU softirq if there are callbacks remaining. */
        if (cpu_has_callbacks_ready_to_invoke(rdp))
-               invoke_rcu_cpu_kthread();
+               invoke_rcu_core();
 }
 
 /*
@@ -1277,7 +1276,7 @@ void rcu_check_callbacks(int cpu, int user)
        }
        rcu_preempt_check_callbacks(cpu);
        if (rcu_pending(cpu))
-               invoke_rcu_cpu_kthread();
+               invoke_rcu_core();
 }
 
 #ifdef CONFIG_SMP
@@ -1442,13 +1441,14 @@ __rcu_process_callbacks(struct rcu_state *rsp, struct rcu_data *rdp)
        }
 
        /* If there are callbacks ready, invoke them. */
-       rcu_do_batch(rsp, rdp);
+       if (cpu_has_callbacks_ready_to_invoke(rdp))
+               invoke_rcu_callbacks(rsp, rdp);
 }
 
 /*
  * Do softirq processing for the current CPU.
  */
-static void rcu_process_callbacks(void)
+static void rcu_process_callbacks(struct softirq_action *unused)
 {
        __rcu_process_callbacks(&rcu_sched_state,
                                &__get_cpu_var(rcu_sched_data));
@@ -1465,342 +1465,20 @@ static void rcu_process_callbacks(void)
  * the current CPU with interrupts disabled, the rcu_cpu_kthread_task
  * cannot disappear out from under us.
  */
-static void invoke_rcu_cpu_kthread(void)
-{
-       unsigned long flags;
-
-       local_irq_save(flags);
-       __this_cpu_write(rcu_cpu_has_work, 1);
-       if (__this_cpu_read(rcu_cpu_kthread_task) == NULL) {
-               local_irq_restore(flags);
-               return;
-       }
-       wake_up_process(__this_cpu_read(rcu_cpu_kthread_task));
-       local_irq_restore(flags);
-}
-
-/*
- * Wake up the specified per-rcu_node-structure kthread.
- * Because the per-rcu_node kthreads are immortal, we don't need
- * to do anything to keep them alive.
- */
-static void invoke_rcu_node_kthread(struct rcu_node *rnp)
-{
-       struct task_struct *t;
-
-       t = rnp->node_kthread_task;
-       if (t != NULL)
-               wake_up_process(t);
-}
-
-/*
- * Set the specified CPU's kthread to run RT or not, as specified by
- * the to_rt argument.  The CPU-hotplug locks are held, so the task
- * is not going away.
- */
-static void rcu_cpu_kthread_setrt(int cpu, int to_rt)
-{
-       int policy;
-       struct sched_param sp;
-       struct task_struct *t;
-
-       t = per_cpu(rcu_cpu_kthread_task, cpu);
-       if (t == NULL)
-               return;
-       if (to_rt) {
-               policy = SCHED_FIFO;
-               sp.sched_priority = RCU_KTHREAD_PRIO;
-       } else {
-               policy = SCHED_NORMAL;
-               sp.sched_priority = 0;
-       }
-       sched_setscheduler_nocheck(t, policy, &sp);
-}
-
-/*
- * Timer handler to initiate the waking up of per-CPU kthreads that
- * have yielded the CPU due to excess numbers of RCU callbacks.
- * We wake up the per-rcu_node kthread, which in turn will wake up
- * the booster kthread.
- */
-static void rcu_cpu_kthread_timer(unsigned long arg)
-{
-       struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, arg);
-       struct rcu_node *rnp = rdp->mynode;
-
-       atomic_or(rdp->grpmask, &rnp->wakemask);
-       invoke_rcu_node_kthread(rnp);
-}
-
-/*
- * Drop to non-real-time priority and yield, but only after posting a
- * timer that will cause us to regain our real-time priority if we
- * remain preempted.  Either way, we restore our real-time priority
- * before returning.
- */
-static void rcu_yield(void (*f)(unsigned long), unsigned long arg)
-{
-       struct sched_param sp;
-       struct timer_list yield_timer;
-
-       setup_timer_on_stack(&yield_timer, f, arg);
-       mod_timer(&yield_timer, jiffies + 2);
-       sp.sched_priority = 0;
-       sched_setscheduler_nocheck(current, SCHED_NORMAL, &sp);
-       set_user_nice(current, 19);
-       schedule();
-       sp.sched_priority = RCU_KTHREAD_PRIO;
-       sched_setscheduler_nocheck(current, SCHED_FIFO, &sp);
-       del_timer(&yield_timer);
-}
-
-/*
- * Handle cases where the rcu_cpu_kthread() ends up on the wrong CPU.
- * This can happen while the corresponding CPU is either coming online
- * or going offline.  We cannot wait until the CPU is fully online
- * before starting the kthread, because the various notifier functions
- * can wait for RCU grace periods.  So we park rcu_cpu_kthread() until
- * the corresponding CPU is online.
- *
- * Return 1 if the kthread needs to stop, 0 otherwise.
- *
- * Caller must disable bh.  This function can momentarily enable it.
- */
-static int rcu_cpu_kthread_should_stop(int cpu)
-{
-       while (cpu_is_offline(cpu) ||
-              !cpumask_equal(&current->cpus_allowed, cpumask_of(cpu)) ||
-              smp_processor_id() != cpu) {
-               if (kthread_should_stop())
-                       return 1;
-               per_cpu(rcu_cpu_kthread_status, cpu) = RCU_KTHREAD_OFFCPU;
-               per_cpu(rcu_cpu_kthread_cpu, cpu) = raw_smp_processor_id();
-               local_bh_enable();
-               schedule_timeout_uninterruptible(1);
-               if (!cpumask_equal(&current->cpus_allowed, cpumask_of(cpu)))
-                       set_cpus_allowed_ptr(current, cpumask_of(cpu));
-               local_bh_disable();
-       }
-       per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu;
-       return 0;
-}
-
-/*
- * Per-CPU kernel thread that invokes RCU callbacks.  This replaces the
- * earlier RCU softirq.
- */
-static int rcu_cpu_kthread(void *arg)
-{
-       int cpu = (int)(long)arg;
-       unsigned long flags;
-       int spincnt = 0;
-       unsigned int *statusp = &per_cpu(rcu_cpu_kthread_status, cpu);
-       char work;
-       char *workp = &per_cpu(rcu_cpu_has_work, cpu);
-
-       for (;;) {
-               *statusp = RCU_KTHREAD_WAITING;
-               rcu_wait(*workp != 0 || kthread_should_stop());
-               local_bh_disable();
-               if (rcu_cpu_kthread_should_stop(cpu)) {
-                       local_bh_enable();
-                       break;
-               }
-               *statusp = RCU_KTHREAD_RUNNING;
-               per_cpu(rcu_cpu_kthread_loops, cpu)++;
-               local_irq_save(flags);
-               work = *workp;
-               *workp = 0;
-               local_irq_restore(flags);
-               if (work)
-                       rcu_process_callbacks();
-               local_bh_enable();
-               if (*workp != 0)
-                       spincnt++;
-               else
-                       spincnt = 0;
-               if (spincnt > 10) {
-                       *statusp = RCU_KTHREAD_YIELDING;
-                       rcu_yield(rcu_cpu_kthread_timer, (unsigned long)cpu);
-                       spincnt = 0;
-               }
-       }
-       *statusp = RCU_KTHREAD_STOPPED;
-       return 0;
-}
-
-/*
- * Spawn a per-CPU kthread, setting up affinity and priority.
- * Because the CPU hotplug lock is held, no other CPU will be attempting
- * to manipulate rcu_cpu_kthread_task.  There might be another CPU
- * attempting to access it during boot, but the locking in kthread_bind()
- * will enforce sufficient ordering.
- */
-static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu)
+static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp)
 {
-       struct sched_param sp;
-       struct task_struct *t;
-
-       if (!rcu_kthreads_spawnable ||
-           per_cpu(rcu_cpu_kthread_task, cpu) != NULL)
-               return 0;
-       t = kthread_create(rcu_cpu_kthread, (void *)(long)cpu, "rcuc%d", cpu);
-       if (IS_ERR(t))
-               return PTR_ERR(t);
-       kthread_bind(t, cpu);
-       per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu;
-       WARN_ON_ONCE(per_cpu(rcu_cpu_kthread_task, cpu) != NULL);
-       per_cpu(rcu_cpu_kthread_task, cpu) = t;
-       sp.sched_priority = RCU_KTHREAD_PRIO;
-       sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
-       return 0;
-}
-
-/*
- * Per-rcu_node kthread, which is in charge of waking up the per-CPU
- * kthreads when needed.  We ignore requests to wake up kthreads
- * for offline CPUs, which is OK because force_quiescent_state()
- * takes care of this case.
- */
-static int rcu_node_kthread(void *arg)
-{
-       int cpu;
-       unsigned long flags;
-       unsigned long mask;
-       struct rcu_node *rnp = (struct rcu_node *)arg;
-       struct sched_param sp;
-       struct task_struct *t;
-
-       for (;;) {
-               rnp->node_kthread_status = RCU_KTHREAD_WAITING;
-               rcu_wait(atomic_read(&rnp->wakemask) != 0);
-               rnp->node_kthread_status = RCU_KTHREAD_RUNNING;
-               raw_spin_lock_irqsave(&rnp->lock, flags);
-               mask = atomic_xchg(&rnp->wakemask, 0);
-               rcu_initiate_boost(rnp, flags); /* releases rnp->lock. */
-               for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1) {
-                       if ((mask & 0x1) == 0)
-                               continue;
-                       preempt_disable();
-                       t = per_cpu(rcu_cpu_kthread_task, cpu);
-                       if (!cpu_online(cpu) || t == NULL) {
-                               preempt_enable();
-                               continue;
-                       }
-                       per_cpu(rcu_cpu_has_work, cpu) = 1;
-                       sp.sched_priority = RCU_KTHREAD_PRIO;
-                       sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
-                       preempt_enable();
-               }
-       }
-       /* NOTREACHED */
-       rnp->node_kthread_status = RCU_KTHREAD_STOPPED;
-       return 0;
-}
-
-/*
- * Set the per-rcu_node kthread's affinity to cover all CPUs that are
- * served by the rcu_node in question.  The CPU hotplug lock is still
- * held, so the value of rnp->qsmaskinit will be stable.
- *
- * We don't include outgoingcpu in the affinity set, use -1 if there is
- * no outgoing CPU.  If there are no CPUs left in the affinity set,
- * this function allows the kthread to execute on any CPU.
- */
-static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu)
-{
-       cpumask_var_t cm;
-       int cpu;
-       unsigned long mask = rnp->qsmaskinit;
-
-       if (rnp->node_kthread_task == NULL)
-               return;
-       if (!alloc_cpumask_var(&cm, GFP_KERNEL))
+       if (likely(!rsp->boost)) {
+               rcu_do_batch(rsp, rdp);
                return;
-       cpumask_clear(cm);
-       for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1)
-               if ((mask & 0x1) && cpu != outgoingcpu)
-                       cpumask_set_cpu(cpu, cm);
-       if (cpumask_weight(cm) == 0) {
-               cpumask_setall(cm);
-               for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++)
-                       cpumask_clear_cpu(cpu, cm);
-               WARN_ON_ONCE(cpumask_weight(cm) == 0);
        }
-       set_cpus_allowed_ptr(rnp->node_kthread_task, cm);
-       rcu_boost_kthread_setaffinity(rnp, cm);
-       free_cpumask_var(cm);
+       invoke_rcu_callbacks_kthread();
 }
 
-/*
- * Spawn a per-rcu_node kthread, setting priority and affinity.
- * Called during boot before online/offline can happen, or, if
- * during runtime, with the main CPU-hotplug locks held.  So only
- * one of these can be executing at a time.
- */
-static int __cpuinit rcu_spawn_one_node_kthread(struct rcu_state *rsp,
-                                               struct rcu_node *rnp)
+static void invoke_rcu_core(void)
 {
-       unsigned long flags;
-       int rnp_index = rnp - &rsp->node[0];
-       struct sched_param sp;
-       struct task_struct *t;
-
-       if (!rcu_kthreads_spawnable ||
-           rnp->qsmaskinit == 0)
-               return 0;
-       if (rnp->node_kthread_task == NULL) {
-               t = kthread_create(rcu_node_kthread, (void *)rnp,
-                                  "rcun%d", rnp_index);
-               if (IS_ERR(t))
-                       return PTR_ERR(t);
-               raw_spin_lock_irqsave(&rnp->lock, flags);
-               rnp->node_kthread_task = t;
-               raw_spin_unlock_irqrestore(&rnp->lock, flags);
-               sp.sched_priority = 99;
-               sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
-       }
-       return rcu_spawn_one_boost_kthread(rsp, rnp, rnp_index);
+       raise_softirq(RCU_SOFTIRQ);
 }
 
-static void rcu_wake_one_boost_kthread(struct rcu_node *rnp);
-
-/*
- * Spawn all kthreads -- called as soon as the scheduler is running.
- */
-static int __init rcu_spawn_kthreads(void)
-{
-       int cpu;
-       struct rcu_node *rnp;
-       struct task_struct *t;
-
-       rcu_kthreads_spawnable = 1;
-       for_each_possible_cpu(cpu) {
-               per_cpu(rcu_cpu_has_work, cpu) = 0;
-               if (cpu_online(cpu)) {
-                       (void)rcu_spawn_one_cpu_kthread(cpu);
-                       t = per_cpu(rcu_cpu_kthread_task, cpu);
-                       if (t)
-                               wake_up_process(t);
-               }
-       }
-       rnp = rcu_get_root(rcu_state);
-       (void)rcu_spawn_one_node_kthread(rcu_state, rnp);
-       if (rnp->node_kthread_task)
-               wake_up_process(rnp->node_kthread_task);
-       if (NUM_RCU_NODES > 1) {
-               rcu_for_each_leaf_node(rcu_state, rnp) {
-                       (void)rcu_spawn_one_node_kthread(rcu_state, rnp);
-                       t = rnp->node_kthread_task;
-                       if (t)
-                               wake_up_process(t);
-                       rcu_wake_one_boost_kthread(rnp);
-               }
-       }
-       return 0;
-}
-early_initcall(rcu_spawn_kthreads);
-
 static void
 __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
           struct rcu_state *rsp)
@@ -2207,44 +1885,6 @@ static void __cpuinit rcu_prepare_cpu(int cpu)
        rcu_preempt_init_percpu_data(cpu);
 }
 
-static void __cpuinit rcu_prepare_kthreads(int cpu)
-{
-       struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu);
-       struct rcu_node *rnp = rdp->mynode;
-
-       /* Fire up the incoming CPU's kthread and leaf rcu_node kthread. */
-       if (rcu_kthreads_spawnable) {
-               (void)rcu_spawn_one_cpu_kthread(cpu);
-               if (rnp->node_kthread_task == NULL)
-                       (void)rcu_spawn_one_node_kthread(rcu_state, rnp);
-       }
-}
-
-/*
- * kthread_create() creates threads in TASK_UNINTERRUPTIBLE state,
- * but the RCU threads are woken on demand, and if demand is low this
- * could be a while triggering the hung task watchdog.
- *
- * In order to avoid this, poke all tasks once the CPU is fully
- * up and running.
- */
-static void __cpuinit rcu_online_kthreads(int cpu)
-{
-       struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu);
-       struct rcu_node *rnp = rdp->mynode;
-       struct task_struct *t;
-
-       t = per_cpu(rcu_cpu_kthread_task, cpu);
-       if (t)
-               wake_up_process(t);
-
-       t = rnp->node_kthread_task;
-       if (t)
-               wake_up_process(t);
-
-       rcu_wake_one_boost_kthread(rnp);
-}
-
 /*
  * Handle CPU online/offline notification events.
  */
@@ -2262,7 +1902,6 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
                rcu_prepare_kthreads(cpu);
                break;
        case CPU_ONLINE:
-               rcu_online_kthreads(cpu);
        case CPU_DOWN_FAILED:
                rcu_node_kthread_setaffinity(rnp, -1);
                rcu_cpu_kthread_setrt(cpu, 1);
@@ -2410,6 +2049,7 @@ void __init rcu_init(void)
        rcu_init_one(&rcu_sched_state, &rcu_sched_data);
        rcu_init_one(&rcu_bh_state, &rcu_bh_data);
        __rcu_init_preempt();
+        open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
 
        /*
         * We don't need protection against CPU-hotplug here because
index 7b9a08b4aaea01d48eacb8781296a7be205fb898..01b2ccda26fbf82880cc1d4a50bf9f2877e91bba 100644 (file)
@@ -369,6 +369,7 @@ struct rcu_state {
                                                /*  period because */
                                                /*  force_quiescent_state() */
                                                /*  was running. */
+       u8      boost;                          /* Subject to priority boost. */
        unsigned long gpnum;                    /* Current gp number. */
        unsigned long completed;                /* # of last completed gp. */
 
@@ -426,6 +427,7 @@ static int rcu_preempt_blocked_readers_cgp(struct rcu_node *rnp);
 #ifdef CONFIG_HOTPLUG_CPU
 static void rcu_report_unblock_qs_rnp(struct rcu_node *rnp,
                                      unsigned long flags);
+static void rcu_stop_cpu_kthread(int cpu);
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
 static void rcu_print_detail_task_stall(struct rcu_state *rsp);
 static void rcu_print_task_stall(struct rcu_node *rnp);
@@ -450,11 +452,19 @@ static void rcu_preempt_send_cbs_to_online(void);
 static void __init __rcu_init_preempt(void);
 static void rcu_needs_cpu_flush(void);
 static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags);
+static void rcu_preempt_boost_start_gp(struct rcu_node *rnp);
+static void invoke_rcu_callbacks_kthread(void);
+#ifdef CONFIG_RCU_BOOST
+static void rcu_preempt_do_callbacks(void);
 static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp,
                                          cpumask_var_t cm);
-static void rcu_preempt_boost_start_gp(struct rcu_node *rnp);
 static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
                                                 struct rcu_node *rnp,
                                                 int rnp_index);
+static void invoke_rcu_node_kthread(struct rcu_node *rnp);
+static void rcu_yield(void (*f)(unsigned long), unsigned long arg);
+#endif /* #ifdef CONFIG_RCU_BOOST */
+static void rcu_cpu_kthread_setrt(int cpu, int to_rt);
+static void __cpuinit rcu_prepare_kthreads(int cpu);
 
 #endif /* #ifndef RCU_TREE_NONCORE */
index c8bff3099a89eeeccf9e3d330a16f6c4d9a2c340..14dc7dd0090220f717f83f666fb2a30a32f66143 100644 (file)
@@ -602,6 +602,15 @@ static void rcu_preempt_process_callbacks(void)
                                &__get_cpu_var(rcu_preempt_data));
 }
 
+#ifdef CONFIG_RCU_BOOST
+
+static void rcu_preempt_do_callbacks(void)
+{
+       rcu_do_batch(&rcu_preempt_state, &__get_cpu_var(rcu_preempt_data));
+}
+
+#endif /* #ifdef CONFIG_RCU_BOOST */
+
 /*
  * Queue a preemptible-RCU callback for invocation after a grace period.
  */
@@ -1248,6 +1257,23 @@ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags)
        }
 }
 
+/*
+ * Wake up the per-CPU kthread to invoke RCU callbacks.
+ */
+static void invoke_rcu_callbacks_kthread(void)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       __this_cpu_write(rcu_cpu_has_work, 1);
+       if (__this_cpu_read(rcu_cpu_kthread_task) == NULL) {
+               local_irq_restore(flags);
+               return;
+       }
+       wake_up_process(__this_cpu_read(rcu_cpu_kthread_task));
+       local_irq_restore(flags);
+}
+
 /*
  * Set the affinity of the boost kthread.  The CPU-hotplug locks are
  * held, so no one should be messing with the existence of the boost
@@ -1288,6 +1314,7 @@ static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
 
        if (&rcu_preempt_state != rsp)
                return 0;
+       rsp->boost = 1;
        if (rnp->boost_kthread_task != NULL)
                return 0;
        t = kthread_create(rcu_boost_kthread, (void *)rnp,
@@ -1299,13 +1326,372 @@ static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
        sp.sched_priority = RCU_KTHREAD_PRIO;
        sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
+       wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */
        return 0;
 }
 
-static void __cpuinit rcu_wake_one_boost_kthread(struct rcu_node *rnp)
+#ifdef CONFIG_HOTPLUG_CPU
+
+/*
+ * Stop the RCU's per-CPU kthread when its CPU goes offline,.
+ */
+static void rcu_stop_cpu_kthread(int cpu)
 {
-       if (rnp->boost_kthread_task)
-               wake_up_process(rnp->boost_kthread_task);
+       struct task_struct *t;
+
+       /* Stop the CPU's kthread. */
+       t = per_cpu(rcu_cpu_kthread_task, cpu);
+       if (t != NULL) {
+               per_cpu(rcu_cpu_kthread_task, cpu) = NULL;
+               kthread_stop(t);
+       }
+}
+
+#endif /* #ifdef CONFIG_HOTPLUG_CPU */
+
+static void rcu_kthread_do_work(void)
+{
+       rcu_do_batch(&rcu_sched_state, &__get_cpu_var(rcu_sched_data));
+       rcu_do_batch(&rcu_bh_state, &__get_cpu_var(rcu_bh_data));
+       rcu_preempt_do_callbacks();
+}
+
+/*
+ * Wake up the specified per-rcu_node-structure kthread.
+ * Because the per-rcu_node kthreads are immortal, we don't need
+ * to do anything to keep them alive.
+ */
+static void invoke_rcu_node_kthread(struct rcu_node *rnp)
+{
+       struct task_struct *t;
+
+       t = rnp->node_kthread_task;
+       if (t != NULL)
+               wake_up_process(t);
+}
+
+/*
+ * Set the specified CPU's kthread to run RT or not, as specified by
+ * the to_rt argument.  The CPU-hotplug locks are held, so the task
+ * is not going away.
+ */
+static void rcu_cpu_kthread_setrt(int cpu, int to_rt)
+{
+       int policy;
+       struct sched_param sp;
+       struct task_struct *t;
+
+       t = per_cpu(rcu_cpu_kthread_task, cpu);
+       if (t == NULL)
+               return;
+       if (to_rt) {
+               policy = SCHED_FIFO;
+               sp.sched_priority = RCU_KTHREAD_PRIO;
+       } else {
+               policy = SCHED_NORMAL;
+               sp.sched_priority = 0;
+       }
+       sched_setscheduler_nocheck(t, policy, &sp);
+}
+
+/*
+ * Timer handler to initiate the waking up of per-CPU kthreads that
+ * have yielded the CPU due to excess numbers of RCU callbacks.
+ * We wake up the per-rcu_node kthread, which in turn will wake up
+ * the booster kthread.
+ */
+static void rcu_cpu_kthread_timer(unsigned long arg)
+{
+       struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, arg);
+       struct rcu_node *rnp = rdp->mynode;
+
+       atomic_or(rdp->grpmask, &rnp->wakemask);
+       invoke_rcu_node_kthread(rnp);
+}
+
+/*
+ * Drop to non-real-time priority and yield, but only after posting a
+ * timer that will cause us to regain our real-time priority if we
+ * remain preempted.  Either way, we restore our real-time priority
+ * before returning.
+ */
+static void rcu_yield(void (*f)(unsigned long), unsigned long arg)
+{
+       struct sched_param sp;
+       struct timer_list yield_timer;
+
+       setup_timer_on_stack(&yield_timer, f, arg);
+       mod_timer(&yield_timer, jiffies + 2);
+       sp.sched_priority = 0;
+       sched_setscheduler_nocheck(current, SCHED_NORMAL, &sp);
+       set_user_nice(current, 19);
+       schedule();
+       sp.sched_priority = RCU_KTHREAD_PRIO;
+       sched_setscheduler_nocheck(current, SCHED_FIFO, &sp);
+       del_timer(&yield_timer);
+}
+
+/*
+ * Handle cases where the rcu_cpu_kthread() ends up on the wrong CPU.
+ * This can happen while the corresponding CPU is either coming online
+ * or going offline.  We cannot wait until the CPU is fully online
+ * before starting the kthread, because the various notifier functions
+ * can wait for RCU grace periods.  So we park rcu_cpu_kthread() until
+ * the corresponding CPU is online.
+ *
+ * Return 1 if the kthread needs to stop, 0 otherwise.
+ *
+ * Caller must disable bh.  This function can momentarily enable it.
+ */
+static int rcu_cpu_kthread_should_stop(int cpu)
+{
+       while (cpu_is_offline(cpu) ||
+              !cpumask_equal(&current->cpus_allowed, cpumask_of(cpu)) ||
+              smp_processor_id() != cpu) {
+               if (kthread_should_stop())
+                       return 1;
+               per_cpu(rcu_cpu_kthread_status, cpu) = RCU_KTHREAD_OFFCPU;
+               per_cpu(rcu_cpu_kthread_cpu, cpu) = raw_smp_processor_id();
+               local_bh_enable();
+               schedule_timeout_uninterruptible(1);
+               if (!cpumask_equal(&current->cpus_allowed, cpumask_of(cpu)))
+                       set_cpus_allowed_ptr(current, cpumask_of(cpu));
+               local_bh_disable();
+       }
+       per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu;
+       return 0;
+}
+
+/*
+ * Per-CPU kernel thread that invokes RCU callbacks.  This replaces the
+ * earlier RCU softirq.
+ */
+static int rcu_cpu_kthread(void *arg)
+{
+       int cpu = (int)(long)arg;
+       unsigned long flags;
+       int spincnt = 0;
+       unsigned int *statusp = &per_cpu(rcu_cpu_kthread_status, cpu);
+       char work;
+       char *workp = &per_cpu(rcu_cpu_has_work, cpu);
+
+       for (;;) {
+               *statusp = RCU_KTHREAD_WAITING;
+               rcu_wait(*workp != 0 || kthread_should_stop());
+               local_bh_disable();
+               if (rcu_cpu_kthread_should_stop(cpu)) {
+                       local_bh_enable();
+                       break;
+               }
+               *statusp = RCU_KTHREAD_RUNNING;
+               per_cpu(rcu_cpu_kthread_loops, cpu)++;
+               local_irq_save(flags);
+               work = *workp;
+               *workp = 0;
+               local_irq_restore(flags);
+               if (work)
+                       rcu_kthread_do_work();
+               local_bh_enable();
+               if (*workp != 0)
+                       spincnt++;
+               else
+                       spincnt = 0;
+               if (spincnt > 10) {
+                       *statusp = RCU_KTHREAD_YIELDING;
+                       rcu_yield(rcu_cpu_kthread_timer, (unsigned long)cpu);
+                       spincnt = 0;
+               }
+       }
+       *statusp = RCU_KTHREAD_STOPPED;
+       return 0;
+}
+
+/*
+ * Spawn a per-CPU kthread, setting up affinity and priority.
+ * Because the CPU hotplug lock is held, no other CPU will be attempting
+ * to manipulate rcu_cpu_kthread_task.  There might be another CPU
+ * attempting to access it during boot, but the locking in kthread_bind()
+ * will enforce sufficient ordering.
+ *
+ * Please note that we cannot simply refuse to wake up the per-CPU
+ * kthread because kthreads are created in TASK_UNINTERRUPTIBLE state,
+ * which can result in softlockup complaints if the task ends up being
+ * idle for more than a couple of minutes.
+ *
+ * However, please note also that we cannot bind the per-CPU kthread to its
+ * CPU until that CPU is fully online.  We also cannot wait until the
+ * CPU is fully online before we create its per-CPU kthread, as this would
+ * deadlock the system when CPU notifiers tried waiting for grace
+ * periods.  So we bind the per-CPU kthread to its CPU only if the CPU
+ * is online.  If its CPU is not yet fully online, then the code in
+ * rcu_cpu_kthread() will wait until it is fully online, and then do
+ * the binding.
+ */
+static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu)
+{
+       struct sched_param sp;
+       struct task_struct *t;
+
+       if (!rcu_kthreads_spawnable ||
+           per_cpu(rcu_cpu_kthread_task, cpu) != NULL)
+               return 0;
+       t = kthread_create(rcu_cpu_kthread, (void *)(long)cpu, "rcuc%d", cpu);
+       if (IS_ERR(t))
+               return PTR_ERR(t);
+       if (cpu_online(cpu))
+               kthread_bind(t, cpu);
+       per_cpu(rcu_cpu_kthread_cpu, cpu) = cpu;
+       WARN_ON_ONCE(per_cpu(rcu_cpu_kthread_task, cpu) != NULL);
+       sp.sched_priority = RCU_KTHREAD_PRIO;
+       sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
+       per_cpu(rcu_cpu_kthread_task, cpu) = t;
+       wake_up_process(t); /* Get to TASK_INTERRUPTIBLE quickly. */
+       return 0;
+}
+
+/*
+ * Per-rcu_node kthread, which is in charge of waking up the per-CPU
+ * kthreads when needed.  We ignore requests to wake up kthreads
+ * for offline CPUs, which is OK because force_quiescent_state()
+ * takes care of this case.
+ */
+static int rcu_node_kthread(void *arg)
+{
+       int cpu;
+       unsigned long flags;
+       unsigned long mask;
+       struct rcu_node *rnp = (struct rcu_node *)arg;
+       struct sched_param sp;
+       struct task_struct *t;
+
+       for (;;) {
+               rnp->node_kthread_status = RCU_KTHREAD_WAITING;
+               rcu_wait(atomic_read(&rnp->wakemask) != 0);
+               rnp->node_kthread_status = RCU_KTHREAD_RUNNING;
+               raw_spin_lock_irqsave(&rnp->lock, flags);
+               mask = atomic_xchg(&rnp->wakemask, 0);
+               rcu_initiate_boost(rnp, flags); /* releases rnp->lock. */
+               for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1) {
+                       if ((mask & 0x1) == 0)
+                               continue;
+                       preempt_disable();
+                       t = per_cpu(rcu_cpu_kthread_task, cpu);
+                       if (!cpu_online(cpu) || t == NULL) {
+                               preempt_enable();
+                               continue;
+                       }
+                       per_cpu(rcu_cpu_has_work, cpu) = 1;
+                       sp.sched_priority = RCU_KTHREAD_PRIO;
+                       sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
+                       preempt_enable();
+               }
+       }
+       /* NOTREACHED */
+       rnp->node_kthread_status = RCU_KTHREAD_STOPPED;
+       return 0;
+}
+
+/*
+ * Set the per-rcu_node kthread's affinity to cover all CPUs that are
+ * served by the rcu_node in question.  The CPU hotplug lock is still
+ * held, so the value of rnp->qsmaskinit will be stable.
+ *
+ * We don't include outgoingcpu in the affinity set, use -1 if there is
+ * no outgoing CPU.  If there are no CPUs left in the affinity set,
+ * this function allows the kthread to execute on any CPU.
+ */
+static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu)
+{
+       cpumask_var_t cm;
+       int cpu;
+       unsigned long mask = rnp->qsmaskinit;
+
+       if (rnp->node_kthread_task == NULL)
+               return;
+       if (!alloc_cpumask_var(&cm, GFP_KERNEL))
+               return;
+       cpumask_clear(cm);
+       for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++, mask >>= 1)
+               if ((mask & 0x1) && cpu != outgoingcpu)
+                       cpumask_set_cpu(cpu, cm);
+       if (cpumask_weight(cm) == 0) {
+               cpumask_setall(cm);
+               for (cpu = rnp->grplo; cpu <= rnp->grphi; cpu++)
+                       cpumask_clear_cpu(cpu, cm);
+               WARN_ON_ONCE(cpumask_weight(cm) == 0);
+       }
+       set_cpus_allowed_ptr(rnp->node_kthread_task, cm);
+       rcu_boost_kthread_setaffinity(rnp, cm);
+       free_cpumask_var(cm);
+}
+
+/*
+ * Spawn a per-rcu_node kthread, setting priority and affinity.
+ * Called during boot before online/offline can happen, or, if
+ * during runtime, with the main CPU-hotplug locks held.  So only
+ * one of these can be executing at a time.
+ */
+static int __cpuinit rcu_spawn_one_node_kthread(struct rcu_state *rsp,
+                                               struct rcu_node *rnp)
+{
+       unsigned long flags;
+       int rnp_index = rnp - &rsp->node[0];
+       struct sched_param sp;
+       struct task_struct *t;
+
+       if (!rcu_kthreads_spawnable ||
+           rnp->qsmaskinit == 0)
+               return 0;
+       if (rnp->node_kthread_task == NULL) {
+               t = kthread_create(rcu_node_kthread, (void *)rnp,
+                                  "rcun%d", rnp_index);
+               if (IS_ERR(t))
+                       return PTR_ERR(t);
+               raw_spin_lock_irqsave(&rnp->lock, flags);
+               rnp->node_kthread_task = t;
+               raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               sp.sched_priority = 99;
+               sched_setscheduler_nocheck(t, SCHED_FIFO, &sp);
+               wake_up_process(t); /* get to TASK_INTERRUPTIBLE quickly. */
+       }
+       return rcu_spawn_one_boost_kthread(rsp, rnp, rnp_index);
+}
+
+/*
+ * Spawn all kthreads -- called as soon as the scheduler is running.
+ */
+static int __init rcu_spawn_kthreads(void)
+{
+       int cpu;
+       struct rcu_node *rnp;
+
+       rcu_kthreads_spawnable = 1;
+       for_each_possible_cpu(cpu) {
+               per_cpu(rcu_cpu_has_work, cpu) = 0;
+               if (cpu_online(cpu))
+                       (void)rcu_spawn_one_cpu_kthread(cpu);
+       }
+       rnp = rcu_get_root(rcu_state);
+       (void)rcu_spawn_one_node_kthread(rcu_state, rnp);
+       if (NUM_RCU_NODES > 1) {
+               rcu_for_each_leaf_node(rcu_state, rnp)
+                       (void)rcu_spawn_one_node_kthread(rcu_state, rnp);
+       }
+       return 0;
+}
+early_initcall(rcu_spawn_kthreads);
+
+static void __cpuinit rcu_prepare_kthreads(int cpu)
+{
+       struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu);
+       struct rcu_node *rnp = rdp->mynode;
+
+       /* Fire up the incoming CPU's kthread and leaf rcu_node kthread. */
+       if (rcu_kthreads_spawnable) {
+               (void)rcu_spawn_one_cpu_kthread(cpu);
+               if (rnp->node_kthread_task == NULL)
+                       (void)rcu_spawn_one_node_kthread(rcu_state, rnp);
+       }
 }
 
 #else /* #ifdef CONFIG_RCU_BOOST */
@@ -1315,23 +1701,32 @@ static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags)
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
 }
 
-static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp,
-                                         cpumask_var_t cm)
+static void invoke_rcu_callbacks_kthread(void)
 {
+       WARN_ON_ONCE(1);
 }
 
 static void rcu_preempt_boost_start_gp(struct rcu_node *rnp)
 {
 }
 
-static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp,
-                                                struct rcu_node *rnp,
-                                                int rnp_index)
+#ifdef CONFIG_HOTPLUG_CPU
+
+static void rcu_stop_cpu_kthread(int cpu)
+{
+}
+
+#endif /* #ifdef CONFIG_HOTPLUG_CPU */
+
+static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu)
+{
+}
+
+static void rcu_cpu_kthread_setrt(int cpu, int to_rt)
 {
-       return 0;
 }
 
-static void __cpuinit rcu_wake_one_boost_kthread(struct rcu_node *rnp)
+static void __cpuinit rcu_prepare_kthreads(int cpu)
 {
 }
 
@@ -1509,7 +1904,7 @@ static DEFINE_PER_CPU(unsigned long, rcu_dyntick_holdoff);
  *
  * Because it is not legal to invoke rcu_process_callbacks() with irqs
  * disabled, we do one pass of force_quiescent_state(), then do a
- * invoke_rcu_cpu_kthread() to cause rcu_process_callbacks() to be invoked
+ * invoke_rcu_core() to cause rcu_process_callbacks() to be invoked
  * later.  The per-cpu rcu_dyntick_drain variable controls the sequencing.
  */
 int rcu_needs_cpu(int cpu)
@@ -1560,7 +1955,7 @@ int rcu_needs_cpu(int cpu)
 
        /* If RCU callbacks are still pending, RCU still needs this CPU. */
        if (c)
-               invoke_rcu_cpu_kthread();
+               invoke_rcu_core();
        return c;
 }
 
index 9678cc3650f5e9c8f4e3eb409d26e9c4e784e7d5..4e144876dc68208b89931518c2d64d1433def061 100644 (file)
@@ -46,6 +46,8 @@
 #define RCU_TREE_NONCORE
 #include "rcutree.h"
 
+#ifdef CONFIG_RCU_BOOST
+
 DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_status);
 DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_cpu);
 DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_loops);
@@ -58,6 +60,8 @@ static char convert_kthread_status(unsigned int kthread_status)
        return "SRWOY"[kthread_status];
 }
 
+#endif /* #ifdef CONFIG_RCU_BOOST */
+
 static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)
 {
        if (!rdp->beenonline)
@@ -76,7 +80,7 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)
                   rdp->dynticks_fqs);
 #endif /* #ifdef CONFIG_NO_HZ */
        seq_printf(m, " of=%lu ri=%lu", rdp->offline_fqs, rdp->resched_ipi);
-       seq_printf(m, " ql=%ld qs=%c%c%c%c kt=%d/%c/%d ktl=%x b=%ld",
+       seq_printf(m, " ql=%ld qs=%c%c%c%c",
                   rdp->qlen,
                   ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] !=
                        rdp->nxttail[RCU_NEXT_TAIL]],
@@ -84,13 +88,16 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)
                        rdp->nxttail[RCU_NEXT_READY_TAIL]],
                   ".W"[rdp->nxttail[RCU_DONE_TAIL] !=
                        rdp->nxttail[RCU_WAIT_TAIL]],
-                  ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]],
+                  ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]]);
+#ifdef CONFIG_RCU_BOOST
+       seq_printf(m, " kt=%d/%c/%d ktl=%x",
                   per_cpu(rcu_cpu_has_work, rdp->cpu),
                   convert_kthread_status(per_cpu(rcu_cpu_kthread_status,
                                          rdp->cpu)),
                   per_cpu(rcu_cpu_kthread_cpu, rdp->cpu),
-                  per_cpu(rcu_cpu_kthread_loops, rdp->cpu) & 0xffff,
-                  rdp->blimit);
+                  per_cpu(rcu_cpu_kthread_loops, rdp->cpu) & 0xffff);
+#endif /* #ifdef CONFIG_RCU_BOOST */
+       seq_printf(m, " b=%ld", rdp->blimit);
        seq_printf(m, " ci=%lu co=%lu ca=%lu\n",
                   rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
 }
@@ -147,18 +154,21 @@ static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp)
                   rdp->dynticks_fqs);
 #endif /* #ifdef CONFIG_NO_HZ */
        seq_printf(m, ",%lu,%lu", rdp->offline_fqs, rdp->resched_ipi);
-       seq_printf(m, ",%ld,\"%c%c%c%c\",%d,\"%c\",%ld", rdp->qlen,
+       seq_printf(m, ",%ld,\"%c%c%c%c\"", rdp->qlen,
                   ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] !=
                        rdp->nxttail[RCU_NEXT_TAIL]],
                   ".R"[rdp->nxttail[RCU_WAIT_TAIL] !=
                        rdp->nxttail[RCU_NEXT_READY_TAIL]],
                   ".W"[rdp->nxttail[RCU_DONE_TAIL] !=
                        rdp->nxttail[RCU_WAIT_TAIL]],
-                  ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]],
+                  ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]]);
+#ifdef CONFIG_RCU_BOOST
+       seq_printf(m, ",%d,\"%c\"",
                   per_cpu(rcu_cpu_has_work, rdp->cpu),
                   convert_kthread_status(per_cpu(rcu_cpu_kthread_status,
-                                         rdp->cpu)),
-                  rdp->blimit);
+                                         rdp->cpu)));
+#endif /* #ifdef CONFIG_RCU_BOOST */
+       seq_printf(m, ",%ld", rdp->blimit);
        seq_printf(m, ",%lu,%lu,%lu\n",
                   rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
 }
@@ -169,7 +179,11 @@ static int show_rcudata_csv(struct seq_file *m, void *unused)
 #ifdef CONFIG_NO_HZ
        seq_puts(m, "\"dt\",\"dt nesting\",\"dt NMI nesting\",\"df\",");
 #endif /* #ifdef CONFIG_NO_HZ */
-       seq_puts(m, "\"of\",\"ri\",\"ql\",\"b\",\"ci\",\"co\",\"ca\"\n");
+       seq_puts(m, "\"of\",\"ri\",\"ql\",\"qs\"");
+#ifdef CONFIG_RCU_BOOST
+       seq_puts(m, "\"kt\",\"ktl\"");
+#endif /* #ifdef CONFIG_RCU_BOOST */
+       seq_puts(m, ",\"b\",\"ci\",\"co\",\"ca\"\n");
 #ifdef CONFIG_TREE_PREEMPT_RCU
        seq_puts(m, "\"rcu_preempt:\"\n");
        PRINT_RCU_DATA(rcu_preempt_data, print_one_rcu_data_csv, m);
index 88725c939e0b8000253905332db8725507781f48..10d018212bab8b1ad2f53e1ed388a4bbd56d4656 100644 (file)
@@ -1096,7 +1096,7 @@ static void check_preempt_curr_rt(struct rq *rq, struct task_struct *p, int flag
         * to move current somewhere else, making room for our non-migratable
         * task.
         */
-       if (p->prio == rq->curr->prio && !need_resched())
+       if (p->prio == rq->curr->prio && !test_tsk_need_resched(rq->curr))
                check_preempt_equal_prio(rq, p);
 #endif
 }
@@ -1239,6 +1239,10 @@ static int find_lowest_rq(struct task_struct *task)
        int this_cpu = smp_processor_id();
        int cpu      = task_cpu(task);
 
+       /* Make sure the mask is initialized first */
+       if (unlikely(!lowest_mask))
+               return -1;
+
        if (task->rt.nr_cpus_allowed == 1)
                return -1; /* No other targets possible */
 
index 86c32b884f8efbb8f071b6343b3c37667b4e8fa3..ff7678603328b3ba5e00c74dc9fd08bcbf113987 100644 (file)
@@ -2365,7 +2365,7 @@ int sigprocmask(int how, sigset_t *set, sigset_t *oldset)
 /**
  *  sys_rt_sigprocmask - change the list of currently blocked signals
  *  @how: whether to add, remove, or set signals
- *  @set: stores pending signals
+ *  @nset: stores pending signals
  *  @oset: previous value of signal mask if non-null
  *  @sigsetsize: size of sigset_t type
  */
index 73a1951935581f48915d77e8409a3049b78de8df..fb67dfa8394edc70174a51fd93b72965a3929b71 100644 (file)
@@ -74,7 +74,7 @@ static struct notifier_block __cpuinitdata hotplug_cfd_notifier = {
        .notifier_call          = hotplug_cfd,
 };
 
-static int __cpuinit init_call_single_data(void)
+void __init call_function_init(void)
 {
        void *cpu = (void *)(long)smp_processor_id();
        int i;
@@ -88,10 +88,7 @@ static int __cpuinit init_call_single_data(void)
 
        hotplug_cfd(&hotplug_cfd_notifier, CPU_UP_PREPARE, cpu);
        register_cpu_notifier(&hotplug_cfd_notifier);
-
-       return 0;
 }
-early_initcall(init_call_single_data);
 
 /*
  * csd_lock/csd_unlock used to serialize access to per-cpu csd resources
index 13960170cad4d91f0ec00dba8e0132d64e7c68fd..40cf63ddd4b3d740d2620ddbf1fa245830b1d703 100644 (file)
@@ -58,7 +58,7 @@ DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
 
 char *softirq_to_name[NR_SOFTIRQS] = {
        "HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL",
-       "TASKLET", "SCHED", "HRTIMER"
+       "TASKLET", "SCHED", "HRTIMER", "RCU"
 };
 
 /*
index 9ffea360a778a3ebf2890fdff5c1b79ddc5542c6..fc0f220054172bb4a0f8b1edcd0f3cf9b50202f2 100644 (file)
@@ -285,16 +285,18 @@ ret:
 static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd)
 {
        struct listener_list *listeners;
-       struct listener *s, *tmp;
+       struct listener *s, *tmp, *s2;
        unsigned int cpu;
 
        if (!cpumask_subset(mask, cpu_possible_mask))
                return -EINVAL;
 
+       s = NULL;
        if (isadd == REGISTER) {
                for_each_cpu(cpu, mask) {
-                       s = kmalloc_node(sizeof(struct listener), GFP_KERNEL,
-                                        cpu_to_node(cpu));
+                       if (!s)
+                               s = kmalloc_node(sizeof(struct listener),
+                                                GFP_KERNEL, cpu_to_node(cpu));
                        if (!s)
                                goto cleanup;
                        s->pid = pid;
@@ -303,9 +305,16 @@ static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd)
 
                        listeners = &per_cpu(listener_array, cpu);
                        down_write(&listeners->sem);
+                       list_for_each_entry_safe(s2, tmp, &listeners->list, list) {
+                               if (s2->pid == pid)
+                                       goto next_cpu;
+                       }
                        list_add(&s->list, &listeners->list);
+                       s = NULL;
+next_cpu:
                        up_write(&listeners->sem);
                }
+               kfree(s);
                return 0;
        }
 
index 2d966244ea60d0a8dcf963e1052b2dbfbfcac76d..59f369f98a04311f5bfa49d01e706d4b12ca97c4 100644 (file)
@@ -42,15 +42,75 @@ static struct alarm_base {
        clockid_t               base_clockid;
 } alarm_bases[ALARM_NUMTYPE];
 
+/* freezer delta & lock used to handle clock_nanosleep triggered wakeups */
+static ktime_t freezer_delta;
+static DEFINE_SPINLOCK(freezer_delta_lock);
+
 #ifdef CONFIG_RTC_CLASS
 /* rtc timer and device for setting alarm wakeups at suspend */
 static struct rtc_timer                rtctimer;
 static struct rtc_device       *rtcdev;
-#endif
+static DEFINE_SPINLOCK(rtcdev_lock);
 
-/* freezer delta & lock used to handle clock_nanosleep triggered wakeups */
-static ktime_t freezer_delta;
-static DEFINE_SPINLOCK(freezer_delta_lock);
+/**
+ * has_wakealarm - check rtc device has wakealarm ability
+ * @dev: current device
+ * @name_ptr: name to be returned
+ *
+ * This helper function checks to see if the rtc device can wake
+ * from suspend.
+ */
+static int has_wakealarm(struct device *dev, void *name_ptr)
+{
+       struct rtc_device *candidate = to_rtc_device(dev);
+
+       if (!candidate->ops->set_alarm)
+               return 0;
+       if (!device_may_wakeup(candidate->dev.parent))
+               return 0;
+
+       *(const char **)name_ptr = dev_name(dev);
+       return 1;
+}
+
+/**
+ * alarmtimer_get_rtcdev - Return selected rtcdevice
+ *
+ * This function returns the rtc device to use for wakealarms.
+ * If one has not already been chosen, it checks to see if a
+ * functional rtc device is available.
+ */
+static struct rtc_device *alarmtimer_get_rtcdev(void)
+{
+       struct device *dev;
+       char *str;
+       unsigned long flags;
+       struct rtc_device *ret;
+
+       spin_lock_irqsave(&rtcdev_lock, flags);
+       if (!rtcdev) {
+               /* Find an rtc device and init the rtc_timer */
+               dev = class_find_device(rtc_class, NULL, &str, has_wakealarm);
+               /* If we have a device then str is valid. See has_wakealarm() */
+               if (dev) {
+                       rtcdev = rtc_class_open(str);
+                       /*
+                        * Drop the reference we got in class_find_device,
+                        * rtc_open takes its own.
+                        */
+                       put_device(dev);
+                       rtc_timer_init(&rtctimer, NULL, NULL);
+               }
+       }
+       ret = rtcdev;
+       spin_unlock_irqrestore(&rtcdev_lock, flags);
+
+       return ret;
+}
+#else
+#define alarmtimer_get_rtcdev() (0)
+#define rtcdev (0)
+#endif
 
 
 /**
@@ -166,6 +226,7 @@ static int alarmtimer_suspend(struct device *dev)
        struct rtc_time tm;
        ktime_t min, now;
        unsigned long flags;
+       struct rtc_device *rtc;
        int i;
 
        spin_lock_irqsave(&freezer_delta_lock, flags);
@@ -173,8 +234,9 @@ static int alarmtimer_suspend(struct device *dev)
        freezer_delta = ktime_set(0, 0);
        spin_unlock_irqrestore(&freezer_delta_lock, flags);
 
+       rtc = rtcdev;
        /* If we have no rtcdev, just return */
-       if (!rtcdev)
+       if (!rtc)
                return 0;
 
        /* Find the soonest timer to expire*/
@@ -199,12 +261,12 @@ static int alarmtimer_suspend(struct device *dev)
        WARN_ON(min.tv64 < NSEC_PER_SEC);
 
        /* Setup an rtc timer to fire that far in the future */
-       rtc_timer_cancel(rtcdev, &rtctimer);
-       rtc_read_time(rtcdev, &tm);
+       rtc_timer_cancel(rtc, &rtctimer);
+       rtc_read_time(rtc, &tm);
        now = rtc_tm_to_ktime(tm);
        now = ktime_add(now, min);
 
-       rtc_timer_start(rtcdev, &rtctimer, now, ktime_set(0, 0));
+       rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0));
 
        return 0;
 }
@@ -322,6 +384,9 @@ static int alarm_clock_getres(const clockid_t which_clock, struct timespec *tp)
 {
        clockid_t baseid = alarm_bases[clock2alarm(which_clock)].base_clockid;
 
+       if (!alarmtimer_get_rtcdev())
+               return -ENOTSUPP;
+
        return hrtimer_get_res(baseid, tp);
 }
 
@@ -336,6 +401,9 @@ static int alarm_clock_get(clockid_t which_clock, struct timespec *tp)
 {
        struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)];
 
+       if (!alarmtimer_get_rtcdev())
+               return -ENOTSUPP;
+
        *tp = ktime_to_timespec(base->gettime());
        return 0;
 }
@@ -351,6 +419,9 @@ static int alarm_timer_create(struct k_itimer *new_timer)
        enum  alarmtimer_type type;
        struct alarm_base *base;
 
+       if (!alarmtimer_get_rtcdev())
+               return -ENOTSUPP;
+
        if (!capable(CAP_WAKE_ALARM))
                return -EPERM;
 
@@ -385,6 +456,9 @@ static void alarm_timer_get(struct k_itimer *timr,
  */
 static int alarm_timer_del(struct k_itimer *timr)
 {
+       if (!rtcdev)
+               return -ENOTSUPP;
+
        alarm_cancel(&timr->it.alarmtimer);
        return 0;
 }
@@ -402,6 +476,9 @@ static int alarm_timer_set(struct k_itimer *timr, int flags,
                                struct itimerspec *new_setting,
                                struct itimerspec *old_setting)
 {
+       if (!rtcdev)
+               return -ENOTSUPP;
+
        /* Save old values */
        old_setting->it_interval =
                        ktime_to_timespec(timr->it.alarmtimer.period);
@@ -541,6 +618,9 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
        int ret = 0;
        struct restart_block *restart;
 
+       if (!alarmtimer_get_rtcdev())
+               return -ENOTSUPP;
+
        if (!capable(CAP_WAKE_ALARM))
                return -EPERM;
 
@@ -638,65 +718,3 @@ static int __init alarmtimer_init(void)
 }
 device_initcall(alarmtimer_init);
 
-#ifdef CONFIG_RTC_CLASS
-/**
- * has_wakealarm - check rtc device has wakealarm ability
- * @dev: current device
- * @name_ptr: name to be returned
- *
- * This helper function checks to see if the rtc device can wake
- * from suspend.
- */
-static int __init has_wakealarm(struct device *dev, void *name_ptr)
-{
-       struct rtc_device *candidate = to_rtc_device(dev);
-
-       if (!candidate->ops->set_alarm)
-               return 0;
-       if (!device_may_wakeup(candidate->dev.parent))
-               return 0;
-
-       *(const char **)name_ptr = dev_name(dev);
-       return 1;
-}
-
-/**
- * alarmtimer_init_late - Late initializing of alarmtimer code
- *
- * This function locates a rtc device to use for wakealarms.
- * Run as late_initcall to make sure rtc devices have been
- * registered.
- */
-static int __init alarmtimer_init_late(void)
-{
-       struct device *dev;
-       char *str;
-
-       /* Find an rtc device and init the rtc_timer */
-       dev = class_find_device(rtc_class, NULL, &str, has_wakealarm);
-       /* If we have a device then str is valid. See has_wakealarm() */
-       if (dev) {
-               rtcdev = rtc_class_open(str);
-               /*
-                * Drop the reference we got in class_find_device,
-                * rtc_open takes its own.
-                */
-               put_device(dev);
-       }
-       if (!rtcdev) {
-               printk(KERN_WARNING "No RTC device found, ALARM timers will"
-                       " not wake from suspend");
-       }
-       rtc_timer_init(&rtctimer, NULL, NULL);
-
-       return 0;
-}
-#else
-static int __init alarmtimer_init_late(void)
-{
-       printk(KERN_WARNING "Kernel not built with RTC support, ALARM timers"
-               " will not wake from suspend");
-       return 0;
-}
-#endif
-late_initcall(alarmtimer_init_late);
index 1c95fd677328e4fe3d0e582fc62284d9ec150a68..e0980f0d9a0ad2d559b98c12f26317b55044cad1 100644 (file)
@@ -185,7 +185,6 @@ static struct clocksource *watchdog;
 static struct timer_list watchdog_timer;
 static DECLARE_WORK(watchdog_work, clocksource_watchdog_work);
 static DEFINE_SPINLOCK(watchdog_lock);
-static cycle_t watchdog_last;
 static int watchdog_running;
 
 static int clocksource_watchdog_kthread(void *data);
@@ -254,11 +253,6 @@ static void clocksource_watchdog(unsigned long data)
        if (!watchdog_running)
                goto out;
 
-       wdnow = watchdog->read(watchdog);
-       wd_nsec = clocksource_cyc2ns((wdnow - watchdog_last) & watchdog->mask,
-                                    watchdog->mult, watchdog->shift);
-       watchdog_last = wdnow;
-
        list_for_each_entry(cs, &watchdog_list, wd_list) {
 
                /* Clocksource already marked unstable? */
@@ -268,19 +262,28 @@ static void clocksource_watchdog(unsigned long data)
                        continue;
                }
 
+               local_irq_disable();
                csnow = cs->read(cs);
+               wdnow = watchdog->read(watchdog);
+               local_irq_enable();
 
                /* Clocksource initialized ? */
                if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) {
                        cs->flags |= CLOCK_SOURCE_WATCHDOG;
-                       cs->wd_last = csnow;
+                       cs->wd_last = wdnow;
+                       cs->cs_last = csnow;
                        continue;
                }
 
-               /* Check the deviation from the watchdog clocksource. */
-               cs_nsec = clocksource_cyc2ns((csnow - cs->wd_last) &
+               wd_nsec = clocksource_cyc2ns((wdnow - cs->wd_last) & watchdog->mask,
+                                            watchdog->mult, watchdog->shift);
+
+               cs_nsec = clocksource_cyc2ns((csnow - cs->cs_last) &
                                             cs->mask, cs->mult, cs->shift);
-               cs->wd_last = csnow;
+               cs->cs_last = csnow;
+               cs->wd_last = wdnow;
+
+               /* Check the deviation from the watchdog clocksource. */
                if (abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD) {
                        clocksource_unstable(cs, cs_nsec - wd_nsec);
                        continue;
@@ -318,7 +321,6 @@ static inline void clocksource_start_watchdog(void)
                return;
        init_timer(&watchdog_timer);
        watchdog_timer.function = clocksource_watchdog;
-       watchdog_last = watchdog->read(watchdog);
        watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL;
        add_timer_on(&watchdog_timer, cpumask_first(cpu_online_mask));
        watchdog_running = 1;
index dff763b7baf172d9d7b90c8f0dddc0427a83a1c4..1f06468a10d7a65ad8c0bffa8e13c0eaf44a8ad4 100644 (file)
@@ -240,13 +240,10 @@ static const char **find_next(void *v, loff_t *pos)
        const char **fmt = v;
        int start_index;
 
-       if (!fmt)
-               fmt = __start___trace_bprintk_fmt + *pos;
-
        start_index = __stop___trace_bprintk_fmt - __start___trace_bprintk_fmt;
 
        if (*pos < start_index)
-               return fmt;
+               return __start___trace_bprintk_fmt + *pos;
 
        return find_next_mod_format(start_index, v, fmt, pos);
 }
index 41baf02924e64cc926ef3b2560a8f02c76c1bbf0..3f3b68199d744bd4fc9b94dcb9ca6e831502b0f2 100644 (file)
@@ -572,7 +572,7 @@ EXPORT_SYMBOL(bitmap_scnlistprintf);
 
 /**
  * __bitmap_parselist - convert list format ASCII string to bitmap
- * @bp: read nul-terminated user string from this buffer
+ * @buf: read nul-terminated user string from this buffer
  * @buflen: buffer size in bytes.  If string is smaller than this
  *    then it must be terminated with a \0.
  * @is_user: location of buffer, 0 indicates kernel space
index 82dc34c095c25ea0e14619d68bda9d3942836bd5..640bd98a4c8aa59fd3f597da6f0706287de5609c 100644 (file)
@@ -948,14 +948,14 @@ const struct kobj_ns_type_operations *kobj_ns_ops(struct kobject *kobj)
 }
 
 
-const void *kobj_ns_current(enum kobj_ns_type type)
+void *kobj_ns_grab_current(enum kobj_ns_type type)
 {
-       const void *ns = NULL;
+       void *ns = NULL;
 
        spin_lock(&kobj_ns_type_lock);
        if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) &&
            kobj_ns_ops_tbl[type])
-               ns = kobj_ns_ops_tbl[type]->current_ns();
+               ns = kobj_ns_ops_tbl[type]->grab_current_ns();
        spin_unlock(&kobj_ns_type_lock);
 
        return ns;
@@ -987,23 +987,15 @@ const void *kobj_ns_initial(enum kobj_ns_type type)
        return ns;
 }
 
-/*
- * kobj_ns_exit - invalidate a namespace tag
- *
- * @type: the namespace type (i.e. KOBJ_NS_TYPE_NET)
- * @ns: the actual namespace being invalidated
- *
- * This is called when a tag is no longer valid.  For instance,
- * when a network namespace exits, it uses this helper to
- * make sure no sb's sysfs_info points to the now-invalidated
- * netns.
- */
-void kobj_ns_exit(enum kobj_ns_type type, const void *ns)
+void kobj_ns_drop(enum kobj_ns_type type, void *ns)
 {
-       sysfs_exit_ns(type, ns);
+       spin_lock(&kobj_ns_type_lock);
+       if ((type > KOBJ_NS_TYPE_NONE) && (type < KOBJ_NS_TYPES) &&
+           kobj_ns_ops_tbl[type] && kobj_ns_ops_tbl[type]->drop_ns)
+               kobj_ns_ops_tbl[type]->drop_ns(ns);
+       spin_unlock(&kobj_ns_type_lock);
 }
 
-
 EXPORT_SYMBOL(kobject_get);
 EXPORT_SYMBOL(kobject_put);
 EXPORT_SYMBOL(kobject_del);
index 021a2960ef9e18d061c972590f7651a35e7652ce..6cc604bd56496e2742e371d63234af08f9f0859b 100644 (file)
@@ -144,9 +144,20 @@ static void isolate_freepages(struct zone *zone,
        int nr_freepages = cc->nr_freepages;
        struct list_head *freelist = &cc->freepages;
 
+       /*
+        * Initialise the free scanner. The starting point is where we last
+        * scanned from (or the end of the zone if starting). The low point
+        * is the end of the pageblock the migration scanner is using.
+        */
        pfn = cc->free_pfn;
        low_pfn = cc->migrate_pfn + pageblock_nr_pages;
-       high_pfn = low_pfn;
+
+       /*
+        * Take care that if the migration scanner is at the end of the zone
+        * that the free scanner does not accidentally move to the next zone
+        * in the next isolation cycle.
+        */
+       high_pfn = min(low_pfn, pfn);
 
        /*
         * Isolate free pages until enough are available to migrate the
@@ -240,11 +251,18 @@ static bool too_many_isolated(struct zone *zone)
        return isolated > (inactive + active) / 2;
 }
 
+/* possible outcome of isolate_migratepages */
+typedef enum {
+       ISOLATE_ABORT,          /* Abort compaction now */
+       ISOLATE_NONE,           /* No pages isolated, continue scanning */
+       ISOLATE_SUCCESS,        /* Pages isolated, migrate */
+} isolate_migrate_t;
+
 /*
  * Isolate all pages that can be migrated from the block pointed to by
  * the migrate scanner within compact_control.
  */
-static unsigned long isolate_migratepages(struct zone *zone,
+static isolate_migrate_t isolate_migratepages(struct zone *zone,
                                        struct compact_control *cc)
 {
        unsigned long low_pfn, end_pfn;
@@ -261,7 +279,7 @@ static unsigned long isolate_migratepages(struct zone *zone,
        /* Do not cross the free scanner or scan within a memory hole */
        if (end_pfn > cc->free_pfn || !pfn_valid(low_pfn)) {
                cc->migrate_pfn = end_pfn;
-               return 0;
+               return ISOLATE_NONE;
        }
 
        /*
@@ -270,10 +288,14 @@ static unsigned long isolate_migratepages(struct zone *zone,
         * delay for some time until fewer pages are isolated
         */
        while (unlikely(too_many_isolated(zone))) {
+               /* async migration should just abort */
+               if (!cc->sync)
+                       return ISOLATE_ABORT;
+
                congestion_wait(BLK_RW_ASYNC, HZ/10);
 
                if (fatal_signal_pending(current))
-                       return 0;
+                       return ISOLATE_ABORT;
        }
 
        /* Time to isolate some pages for migration */
@@ -358,7 +380,7 @@ static unsigned long isolate_migratepages(struct zone *zone,
 
        trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated);
 
-       return cc->nr_migratepages;
+       return ISOLATE_SUCCESS;
 }
 
 /*
@@ -420,13 +442,6 @@ static int compact_finished(struct zone *zone,
        if (cc->free_pfn <= cc->migrate_pfn)
                return COMPACT_COMPLETE;
 
-       /* Compaction run is not finished if the watermark is not met */
-       watermark = low_wmark_pages(zone);
-       watermark += (1 << cc->order);
-
-       if (!zone_watermark_ok(zone, cc->order, watermark, 0, 0))
-               return COMPACT_CONTINUE;
-
        /*
         * order == -1 is expected when compacting via
         * /proc/sys/vm/compact_memory
@@ -434,6 +449,13 @@ static int compact_finished(struct zone *zone,
        if (cc->order == -1)
                return COMPACT_CONTINUE;
 
+       /* Compaction run is not finished if the watermark is not met */
+       watermark = low_wmark_pages(zone);
+       watermark += (1 << cc->order);
+
+       if (!zone_watermark_ok(zone, cc->order, watermark, 0, 0))
+               return COMPACT_CONTINUE;
+
        /* Direct compactor: Is a suitable page free? */
        for (order = cc->order; order < MAX_ORDER; order++) {
                /* Job done if page is free of the right migratetype */
@@ -460,6 +482,13 @@ unsigned long compaction_suitable(struct zone *zone, int order)
        int fragindex;
        unsigned long watermark;
 
+       /*
+        * order == -1 is expected when compacting via
+        * /proc/sys/vm/compact_memory
+        */
+       if (order == -1)
+               return COMPACT_CONTINUE;
+
        /*
         * Watermarks for order-0 must be met for compaction. Note the 2UL.
         * This is because during migration, copies of pages need to be
@@ -469,18 +498,12 @@ unsigned long compaction_suitable(struct zone *zone, int order)
        if (!zone_watermark_ok(zone, 0, watermark, 0, 0))
                return COMPACT_SKIPPED;
 
-       /*
-        * order == -1 is expected when compacting via
-        * /proc/sys/vm/compact_memory
-        */
-       if (order == -1)
-               return COMPACT_CONTINUE;
-
        /*
         * fragmentation index determines if allocation failures are due to
         * low memory or external fragmentation
         *
-        * index of -1 implies allocations might succeed dependingon watermarks
+        * index of -1000 implies allocations might succeed depending on
+        * watermarks
         * index towards 0 implies failure is due to lack of memory
         * index towards 1000 implies failure is due to fragmentation
         *
@@ -490,7 +513,8 @@ unsigned long compaction_suitable(struct zone *zone, int order)
        if (fragindex >= 0 && fragindex <= sysctl_extfrag_threshold)
                return COMPACT_SKIPPED;
 
-       if (fragindex == -1 && zone_watermark_ok(zone, order, watermark, 0, 0))
+       if (fragindex == -1000 && zone_watermark_ok(zone, order, watermark,
+           0, 0))
                return COMPACT_PARTIAL;
 
        return COMPACT_CONTINUE;
@@ -522,8 +546,15 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
                unsigned long nr_migrate, nr_remaining;
                int err;
 
-               if (!isolate_migratepages(zone, cc))
+               switch (isolate_migratepages(zone, cc)) {
+               case ISOLATE_ABORT:
+                       ret = COMPACT_PARTIAL;
+                       goto out;
+               case ISOLATE_NONE:
                        continue;
+               case ISOLATE_SUCCESS:
+                       ;
+               }
 
                nr_migrate = cc->nr_migratepages;
                err = migrate_pages(&cc->migratepages, compaction_alloc,
@@ -547,6 +578,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
 
        }
 
+out:
        /* Release free pages and check accounting */
        cc->nr_freepages -= release_freepages(&cc->freepages);
        VM_BUG_ON(cc->nr_freepages != 0);
index 615d9743a3cbad1ca19d745c45115eecb1c463f4..81532f297fd22cd11e1c7a4161c8e320a7015ec2 100644 (file)
@@ -2234,11 +2234,8 @@ static void khugepaged_loop(void)
        while (likely(khugepaged_enabled())) {
 #ifndef CONFIG_NUMA
                hpage = khugepaged_alloc_hugepage();
-               if (unlikely(!hpage)) {
-                       count_vm_event(THP_COLLAPSE_ALLOC_FAILED);
+               if (unlikely(!hpage))
                        break;
-               }
-               count_vm_event(THP_COLLAPSE_ALLOC);
 #else
                if (IS_ERR(hpage)) {
                        khugepaged_alloc_sleep();
index 6402458fee38ca5ba2109882e92ebbf63e97c787..bfcf153bc82907f31ccc1921256622a82bf20d2f 100644 (file)
@@ -1111,6 +1111,14 @@ static void __init gather_bootmem_prealloc(void)
                WARN_ON(page_count(page) != 1);
                prep_compound_huge_page(page, h->order);
                prep_new_huge_page(h, page, page_to_nid(page));
+               /*
+                * If we had gigantic hugepages allocated at boot time, we need
+                * to restore the 'stolen' pages to totalram_pages in order to
+                * fix confusing memory reports from free(1) and another
+                * side-effects, like CommitLimit going negative.
+                */
+               if (h->order > (MAX_ORDER - 1))
+                       totalram_pages += 1 << h->order;
        }
 }
 
index d708b3ef2260282a3d6e5784a60c1fb003339f8e..9a68b0cf0a1c4c8009ee25d2990530d7e2927132 100644 (file)
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -1302,6 +1302,12 @@ static struct rmap_item *scan_get_next_rmap_item(struct page **page)
                slot = list_entry(slot->mm_list.next, struct mm_slot, mm_list);
                ksm_scan.mm_slot = slot;
                spin_unlock(&ksm_mmlist_lock);
+               /*
+                * Although we tested list_empty() above, a racing __ksm_exit
+                * of the last mm on the list may have removed it since then.
+                */
+               if (slot == &ksm_mm_head)
+                       return NULL;
 next_mm:
                ksm_scan.address = 0;
                ksm_scan.rmap_list = &slot->rmap_list;
index bd9052a5d3ad74aa2db023c953f0b498e5ab7dd0..ddffc74cdebe50f1d83a592a6d905ad0ff011f16 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/limits.h>
 #include <linux/mutex.h>
 #include <linux/rbtree.h>
+#include <linux/shmem_fs.h>
 #include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/swapops.h>
@@ -359,7 +360,7 @@ enum charge_type {
 static void mem_cgroup_get(struct mem_cgroup *mem);
 static void mem_cgroup_put(struct mem_cgroup *mem);
 static struct mem_cgroup *parent_mem_cgroup(struct mem_cgroup *mem);
-static void drain_all_stock_async(void);
+static void drain_all_stock_async(struct mem_cgroup *mem);
 
 static struct mem_cgroup_per_zone *
 mem_cgroup_zoneinfo(struct mem_cgroup *mem, int nid, int zid)
@@ -735,7 +736,7 @@ struct mem_cgroup *mem_cgroup_from_task(struct task_struct *p)
                                struct mem_cgroup, css);
 }
 
-static struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
+struct mem_cgroup *try_get_mem_cgroup_from_mm(struct mm_struct *mm)
 {
        struct mem_cgroup *mem = NULL;
 
@@ -1663,15 +1664,21 @@ static int mem_cgroup_hierarchical_reclaim(struct mem_cgroup *root_mem,
        excess = res_counter_soft_limit_excess(&root_mem->res) >> PAGE_SHIFT;
 
        /* If memsw_is_minimum==1, swap-out is of-no-use. */
-       if (root_mem->memsw_is_minimum)
+       if (!check_soft && root_mem->memsw_is_minimum)
                noswap = true;
 
        while (1) {
                victim = mem_cgroup_select_victim(root_mem);
                if (victim == root_mem) {
                        loop++;
-                       if (loop >= 1)
-                               drain_all_stock_async();
+                       /*
+                        * We are not draining per cpu cached charges during
+                        * soft limit reclaim  because global reclaim doesn't
+                        * care about charges. It tries to free some memory and
+                        * charges will not give any.
+                        */
+                       if (!check_soft && loop >= 1)
+                               drain_all_stock_async(root_mem);
                        if (loop >= 2) {
                                /*
                                 * If we have not been able to reclaim
@@ -1934,9 +1941,11 @@ struct memcg_stock_pcp {
        struct mem_cgroup *cached; /* this never be root cgroup */
        unsigned int nr_pages;
        struct work_struct work;
+       unsigned long flags;
+#define FLUSHING_CACHED_CHARGE (0)
 };
 static DEFINE_PER_CPU(struct memcg_stock_pcp, memcg_stock);
-static atomic_t memcg_drain_count;
+static DEFINE_MUTEX(percpu_charge_mutex);
 
 /*
  * Try to consume stocked charge on this cpu. If success, one page is consumed
@@ -1984,6 +1993,7 @@ static void drain_local_stock(struct work_struct *dummy)
 {
        struct memcg_stock_pcp *stock = &__get_cpu_var(memcg_stock);
        drain_stock(stock);
+       clear_bit(FLUSHING_CACHED_CHARGE, &stock->flags);
 }
 
 /*
@@ -2008,26 +2018,45 @@ static void refill_stock(struct mem_cgroup *mem, unsigned int nr_pages)
  * expects some charges will be back to res_counter later but cannot wait for
  * it.
  */
-static void drain_all_stock_async(void)
+static void drain_all_stock_async(struct mem_cgroup *root_mem)
 {
-       int cpu;
-       /* This function is for scheduling "drain" in asynchronous way.
-        * The result of "drain" is not directly handled by callers. Then,
-        * if someone is calling drain, we don't have to call drain more.
-        * Anyway, WORK_STRUCT_PENDING check in queue_work_on() will catch if
-        * there is a race. We just do loose check here.
+       int cpu, curcpu;
+       /*
+        * If someone calls draining, avoid adding more kworker runs.
         */
-       if (atomic_read(&memcg_drain_count))
+       if (!mutex_trylock(&percpu_charge_mutex))
                return;
        /* Notify other cpus that system-wide "drain" is running */
-       atomic_inc(&memcg_drain_count);
        get_online_cpus();
+       /*
+        * Get a hint for avoiding draining charges on the current cpu,
+        * which must be exhausted by our charging.  It is not required that
+        * this be a precise check, so we use raw_smp_processor_id() instead of
+        * getcpu()/putcpu().
+        */
+       curcpu = raw_smp_processor_id();
        for_each_online_cpu(cpu) {
                struct memcg_stock_pcp *stock = &per_cpu(memcg_stock, cpu);
-               schedule_work_on(cpu, &stock->work);
+               struct mem_cgroup *mem;
+
+               if (cpu == curcpu)
+                       continue;
+
+               mem = stock->cached;
+               if (!mem)
+                       continue;
+               if (mem != root_mem) {
+                       if (!root_mem->use_hierarchy)
+                               continue;
+                       /* check whether "mem" is under tree of "root_mem" */
+                       if (!css_is_ancestor(&mem->css, &root_mem->css))
+                               continue;
+               }
+               if (!test_and_set_bit(FLUSHING_CACHED_CHARGE, &stock->flags))
+                       schedule_work_on(cpu, &stock->work);
        }
        put_online_cpus();
-       atomic_dec(&memcg_drain_count);
+       mutex_unlock(&percpu_charge_mutex);
        /* We don't wait for flush_work */
 }
 
@@ -2035,9 +2064,9 @@ static void drain_all_stock_async(void)
 static void drain_all_stock_sync(void)
 {
        /* called when force_empty is called */
-       atomic_inc(&memcg_drain_count);
+       mutex_lock(&percpu_charge_mutex);
        schedule_on_each_cpu(drain_local_stock);
-       atomic_dec(&memcg_drain_count);
+       mutex_unlock(&percpu_charge_mutex);
 }
 
 /*
@@ -4640,6 +4669,7 @@ static struct cftype mem_cgroup_files[] = {
        {
                .name = "numa_stat",
                .open = mem_control_numa_stat_open,
+               .mode = S_IRUGO,
        },
 #endif
 };
@@ -5414,18 +5444,16 @@ static void mem_cgroup_move_task(struct cgroup_subsys *ss,
                                struct cgroup *old_cont,
                                struct task_struct *p)
 {
-       struct mm_struct *mm;
+       struct mm_struct *mm = get_task_mm(p);
 
-       if (!mc.to)
-               /* no need to move charge */
-               return;
-
-       mm = get_task_mm(p);
        if (mm) {
-               mem_cgroup_move_charge(mm);
+               if (mc.to)
+                       mem_cgroup_move_charge(mm);
+               put_swap_token(mm);
                mmput(mm);
        }
-       mem_cgroup_clear_mc();
+       if (mc.to)
+               mem_cgroup_clear_mc();
 }
 #else  /* !CONFIG_MMU */
 static int mem_cgroup_can_attach(struct cgroup_subsys *ss,
index 5c8f7e08928d5faba209a0392b4b2befe17a67e3..740c4f52059cef1bff55fb4293ec41218967fc02 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/swapops.h>
 #include <linux/hugetlb.h>
 #include <linux/memory_hotplug.h>
+#include <linux/mm_inline.h>
 #include "internal.h"
 
 int sysctl_memory_failure_early_kill __read_mostly = 0;
@@ -390,10 +391,11 @@ static void collect_procs_anon(struct page *page, struct list_head *to_kill,
        struct task_struct *tsk;
        struct anon_vma *av;
 
-       read_lock(&tasklist_lock);
        av = page_lock_anon_vma(page);
        if (av == NULL) /* Not actually mapped anymore */
-               goto out;
+               return;
+
+       read_lock(&tasklist_lock);
        for_each_process (tsk) {
                struct anon_vma_chain *vmac;
 
@@ -407,9 +409,8 @@ static void collect_procs_anon(struct page *page, struct list_head *to_kill,
                                add_to_kill(tsk, page, vma, to_kill, tkc);
                }
        }
-       page_unlock_anon_vma(av);
-out:
        read_unlock(&tasklist_lock);
+       page_unlock_anon_vma(av);
 }
 
 /*
@@ -423,17 +424,8 @@ static void collect_procs_file(struct page *page, struct list_head *to_kill,
        struct prio_tree_iter iter;
        struct address_space *mapping = page->mapping;
 
-       /*
-        * A note on the locking order between the two locks.
-        * We don't rely on this particular order.
-        * If you have some other code that needs a different order
-        * feel free to switch them around. Or add a reverse link
-        * from mm_struct to task_struct, then this could be all
-        * done without taking tasklist_lock and looping over all tasks.
-        */
-
-       read_lock(&tasklist_lock);
        mutex_lock(&mapping->i_mmap_mutex);
+       read_lock(&tasklist_lock);
        for_each_process(tsk) {
                pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
 
@@ -453,8 +445,8 @@ static void collect_procs_file(struct page *page, struct list_head *to_kill,
                                add_to_kill(tsk, page, vma, to_kill, tkc);
                }
        }
-       mutex_unlock(&mapping->i_mmap_mutex);
        read_unlock(&tasklist_lock);
+       mutex_unlock(&mapping->i_mmap_mutex);
 }
 
 /*
@@ -1468,7 +1460,8 @@ int soft_offline_page(struct page *page, int flags)
        put_page(page);
        if (!ret) {
                LIST_HEAD(pagelist);
-
+               inc_zone_page_state(page, NR_ISOLATED_ANON +
+                                           page_is_file_cache(page));
                list_add(&page->lru, &pagelist);
                ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL,
                                                                0, true);
index 6953d3926e01e8ad1370304064ec2a0e94ad1ebb..40b7531ee8badb288823b64715265d0f16be397d 100644 (file)
@@ -1112,11 +1112,13 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
        int force_flush = 0;
        int rss[NR_MM_COUNTERS];
        spinlock_t *ptl;
+       pte_t *start_pte;
        pte_t *pte;
 
 again:
        init_rss_vec(rss);
-       pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+       start_pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+       pte = start_pte;
        arch_enter_lazy_mmu_mode();
        do {
                pte_t ptent = *pte;
@@ -1196,7 +1198,7 @@ again:
 
        add_mm_rss_vec(mm, rss);
        arch_leave_lazy_mmu_mode();
-       pte_unmap_unlock(pte - 1, ptl);
+       pte_unmap_unlock(start_pte, ptl);
 
        /*
         * mmu_gather ran out of room to batch pages, we break out of
@@ -1296,7 +1298,7 @@ static unsigned long unmap_page_range(struct mmu_gather *tlb,
 
 /**
  * unmap_vmas - unmap a range of memory covered by a list of vma's
- * @tlbp: address of the caller's struct mmu_gather
+ * @tlb: address of the caller's struct mmu_gather
  * @vma: the starting vma
  * @start_addr: virtual address at which to start unmapping
  * @end_addr: virtual address at which to end unmapping
@@ -2796,30 +2798,6 @@ void unmap_mapping_range(struct address_space *mapping,
 }
 EXPORT_SYMBOL(unmap_mapping_range);
 
-int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end)
-{
-       struct address_space *mapping = inode->i_mapping;
-
-       /*
-        * If the underlying filesystem is not going to provide
-        * a way to truncate a range of blocks (punch a hole) -
-        * we should return failure right now.
-        */
-       if (!inode->i_op->truncate_range)
-               return -ENOSYS;
-
-       mutex_lock(&inode->i_mutex);
-       down_write(&inode->i_alloc_sem);
-       unmap_mapping_range(mapping, offset, (end - offset), 1);
-       truncate_inode_pages_range(mapping, offset, end);
-       unmap_mapping_range(mapping, offset, (end - offset), 1);
-       inode->i_op->truncate_range(inode, offset, end);
-       up_write(&inode->i_alloc_sem);
-       mutex_unlock(&inode->i_mutex);
-
-       return 0;
-}
-
 /*
  * We enter with non-exclusive mmap_sem (to exclude vma changes,
  * but allow concurrent faults), and pte mapped but not yet locked.
index 9f646374e32f5ec7704b86ad653c2794037b830a..c46887b5a11eaa5bbe48008d16ad71bd37f7302f 100644 (file)
@@ -494,6 +494,14 @@ static pg_data_t __ref *hotadd_new_pgdat(int nid, u64 start)
        /* init node's zones as empty zones, we don't have any present pages.*/
        free_area_init_node(nid, zones_size, start_pfn, zholes_size);
 
+       /*
+        * The node we allocated has no zone fallback lists. For avoiding
+        * to access not-initialized zonelist, build here.
+        */
+       mutex_lock(&zonelists_mutex);
+       build_all_zonelists(NULL);
+       mutex_unlock(&zonelists_mutex);
+
        return pgdat;
 }
 
@@ -515,7 +523,7 @@ int mem_online_node(int nid)
 
        lock_memory_hotplug();
        pgdat = hotadd_new_pgdat(nid, 0);
-       if (pgdat) {
+       if (!pgdat) {
                ret = -ENOMEM;
                goto out;
        }
index e4a5c912983df5352d701bce82fb691160c2e657..666e4e677414e6d790de715761e395116441e6c4 100644 (file)
@@ -288,7 +288,7 @@ static int migrate_page_move_mapping(struct address_space *mapping,
         */
        __dec_zone_page_state(page, NR_FILE_PAGES);
        __inc_zone_page_state(newpage, NR_FILE_PAGES);
-       if (PageSwapBacked(page)) {
+       if (!PageSwapCache(page) && PageSwapBacked(page)) {
                __dec_zone_page_state(page, NR_SHMEM);
                __inc_zone_page_state(newpage, NR_SHMEM);
        }
index bbdc9af5e1177108894d881126761fa71ef9cada..d49736ff8a8dad10420a4f2f76ca89da52c7da89 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -906,14 +906,7 @@ struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *vma)
        if (anon_vma)
                return anon_vma;
 try_prev:
-       /*
-        * It is potentially slow to have to call find_vma_prev here.
-        * But it's only on the first write fault on the vma, not
-        * every time, and we could devise a way to avoid it later
-        * (e.g. stash info in next's anon_vma_node when assigning
-        * an anon_vma, or when trying vma_merge).  Another time.
-        */
-       BUG_ON(find_vma_prev(vma->vm_mm, vma->vm_start, &near) != vma);
+       near = vma->vm_prev;
        if (!near)
                goto none;
 
@@ -2044,9 +2037,10 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
                return -EINVAL;
 
        /* Find the first overlapping VMA */
-       vma = find_vma_prev(mm, start, &prev);
+       vma = find_vma(mm, start);
        if (!vma)
                return 0;
+       prev = vma->vm_prev;
        /* we have  start < vma->vm_end  */
 
        /* if it doesn't overlap, we have nothing.. */
index 74ccff61d1bea8d6e258170280ea5b20523dad23..53bffc6c293eb4fb7aa2a00be5a8712946dab5c9 100644 (file)
@@ -162,13 +162,13 @@ static void free_page_cgroup(void *addr)
 }
 #endif
 
-static int __meminit init_section_page_cgroup(unsigned long pfn)
+static int __meminit init_section_page_cgroup(unsigned long pfn, int nid)
 {
        struct page_cgroup *base, *pc;
        struct mem_section *section;
        unsigned long table_size;
        unsigned long nr;
-       int nid, index;
+       int index;
 
        nr = pfn_to_section_nr(pfn);
        section = __nr_to_section(nr);
@@ -176,7 +176,6 @@ static int __meminit init_section_page_cgroup(unsigned long pfn)
        if (section->page_cgroup)
                return 0;
 
-       nid = page_to_nid(pfn_to_page(pfn));
        table_size = sizeof(struct page_cgroup) * PAGES_PER_SECTION;
        base = alloc_page_cgroup(table_size, nid);
 
@@ -196,7 +195,11 @@ static int __meminit init_section_page_cgroup(unsigned long pfn)
                pc = base + index;
                init_page_cgroup(pc, nr);
        }
-
+       /*
+        * The passed "pfn" may not be aligned to SECTION.  For the calculation
+        * we need to apply a mask.
+        */
+       pfn &= PAGE_SECTION_MASK;
        section->page_cgroup = base - pfn;
        total_usage += table_size;
        return 0;
@@ -225,10 +228,20 @@ int __meminit online_page_cgroup(unsigned long start_pfn,
        start = start_pfn & ~(PAGES_PER_SECTION - 1);
        end = ALIGN(start_pfn + nr_pages, PAGES_PER_SECTION);
 
+       if (nid == -1) {
+               /*
+                * In this case, "nid" already exists and contains valid memory.
+                * "start_pfn" passed to us is a pfn which is an arg for
+                * online__pages(), and start_pfn should exist.
+                */
+               nid = pfn_to_nid(start_pfn);
+               VM_BUG_ON(!node_state(nid, N_ONLINE));
+       }
+
        for (pfn = start; !fail && pfn < end; pfn += PAGES_PER_SECTION) {
                if (!pfn_present(pfn))
                        continue;
-               fail = init_section_page_cgroup(pfn);
+               fail = init_section_page_cgroup(pfn, nid);
        }
        if (!fail)
                return 0;
@@ -284,25 +297,47 @@ static int __meminit page_cgroup_callback(struct notifier_block *self,
 void __init page_cgroup_init(void)
 {
        unsigned long pfn;
-       int fail = 0;
+       int nid;
 
        if (mem_cgroup_disabled())
                return;
 
-       for (pfn = 0; !fail && pfn < max_pfn; pfn += PAGES_PER_SECTION) {
-               if (!pfn_present(pfn))
-                       continue;
-               fail = init_section_page_cgroup(pfn);
-       }
-       if (fail) {
-               printk(KERN_CRIT "try 'cgroup_disable=memory' boot option\n");
-               panic("Out of memory");
-       } else {
-               hotplug_memory_notifier(page_cgroup_callback, 0);
+       for_each_node_state(nid, N_HIGH_MEMORY) {
+               unsigned long start_pfn, end_pfn;
+
+               start_pfn = node_start_pfn(nid);
+               end_pfn = node_end_pfn(nid);
+               /*
+                * start_pfn and end_pfn may not be aligned to SECTION and the
+                * page->flags of out of node pages are not initialized.  So we
+                * scan [start_pfn, the biggest section's pfn < end_pfn) here.
+                */
+               for (pfn = start_pfn;
+                    pfn < end_pfn;
+                     pfn = ALIGN(pfn + 1, PAGES_PER_SECTION)) {
+
+                       if (!pfn_valid(pfn))
+                               continue;
+                       /*
+                        * Nodes's pfns can be overlapping.
+                        * We know some arch can have a nodes layout such as
+                        * -------------pfn-------------->
+                        * N0 | N1 | N2 | N0 | N1 | N2|....
+                        */
+                       if (pfn_to_nid(pfn) != nid)
+                               continue;
+                       if (init_section_page_cgroup(pfn, nid))
+                               goto oom;
+               }
        }
+       hotplug_memory_notifier(page_cgroup_callback, 0);
        printk(KERN_INFO "allocated %ld bytes of page_cgroup\n", total_usage);
-       printk(KERN_INFO "please try 'cgroup_disable=memory' option if you don't"
-       " want memory cgroups\n");
+       printk(KERN_INFO "please try 'cgroup_disable=memory' option if you "
+                        "don't want memory cgroups\n");
+       return;
+oom:
+       printk(KERN_CRIT "try 'cgroup_disable=memory' boot option\n");
+       panic("Out of memory");
 }
 
 void __meminit pgdat_page_cgroup_init(struct pglist_data *pgdat)
index 0eb463ea88dd71326b70342f8492df873a6b5df1..23295f65ae43386574f9058e30e28cdca9a8a708 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -38,9 +38,8 @@
  *                           in arch-dependent flush_dcache_mmap_lock,
  *                           within inode_wb_list_lock in __sync_single_inode)
  *
- * (code doesn't rely on that order so it could be switched around)
- * ->tasklist_lock
- *   anon_vma->mutex      (memory_failure, collect_procs_anon)
+ * anon_vma->mutex,mapping->i_mutex      (memory_failure, collect_procs_anon)
+ *   ->tasklist_lock
  *     pte map lock
  */
 
@@ -112,9 +111,9 @@ static inline void anon_vma_free(struct anon_vma *anon_vma)
        kmem_cache_free(anon_vma_cachep, anon_vma);
 }
 
-static inline struct anon_vma_chain *anon_vma_chain_alloc(void)
+static inline struct anon_vma_chain *anon_vma_chain_alloc(gfp_t gfp)
 {
-       return kmem_cache_alloc(anon_vma_chain_cachep, GFP_KERNEL);
+       return kmem_cache_alloc(anon_vma_chain_cachep, gfp);
 }
 
 static void anon_vma_chain_free(struct anon_vma_chain *anon_vma_chain)
@@ -159,7 +158,7 @@ int anon_vma_prepare(struct vm_area_struct *vma)
                struct mm_struct *mm = vma->vm_mm;
                struct anon_vma *allocated;
 
-               avc = anon_vma_chain_alloc();
+               avc = anon_vma_chain_alloc(GFP_KERNEL);
                if (!avc)
                        goto out_enomem;
 
@@ -200,6 +199,32 @@ int anon_vma_prepare(struct vm_area_struct *vma)
        return -ENOMEM;
 }
 
+/*
+ * This is a useful helper function for locking the anon_vma root as
+ * we traverse the vma->anon_vma_chain, looping over anon_vma's that
+ * have the same vma.
+ *
+ * Such anon_vma's should have the same root, so you'd expect to see
+ * just a single mutex_lock for the whole traversal.
+ */
+static inline struct anon_vma *lock_anon_vma_root(struct anon_vma *root, struct anon_vma *anon_vma)
+{
+       struct anon_vma *new_root = anon_vma->root;
+       if (new_root != root) {
+               if (WARN_ON_ONCE(root))
+                       mutex_unlock(&root->mutex);
+               root = new_root;
+               mutex_lock(&root->mutex);
+       }
+       return root;
+}
+
+static inline void unlock_anon_vma_root(struct anon_vma *root)
+{
+       if (root)
+               mutex_unlock(&root->mutex);
+}
+
 static void anon_vma_chain_link(struct vm_area_struct *vma,
                                struct anon_vma_chain *avc,
                                struct anon_vma *anon_vma)
@@ -208,13 +233,11 @@ static void anon_vma_chain_link(struct vm_area_struct *vma,
        avc->anon_vma = anon_vma;
        list_add(&avc->same_vma, &vma->anon_vma_chain);
 
-       anon_vma_lock(anon_vma);
        /*
         * It's critical to add new vmas to the tail of the anon_vma,
         * see comment in huge_memory.c:__split_huge_page().
         */
        list_add_tail(&avc->same_anon_vma, &anon_vma->head);
-       anon_vma_unlock(anon_vma);
 }
 
 /*
@@ -224,13 +247,24 @@ static void anon_vma_chain_link(struct vm_area_struct *vma,
 int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
 {
        struct anon_vma_chain *avc, *pavc;
+       struct anon_vma *root = NULL;
 
        list_for_each_entry_reverse(pavc, &src->anon_vma_chain, same_vma) {
-               avc = anon_vma_chain_alloc();
-               if (!avc)
-                       goto enomem_failure;
-               anon_vma_chain_link(dst, avc, pavc->anon_vma);
+               struct anon_vma *anon_vma;
+
+               avc = anon_vma_chain_alloc(GFP_NOWAIT | __GFP_NOWARN);
+               if (unlikely(!avc)) {
+                       unlock_anon_vma_root(root);
+                       root = NULL;
+                       avc = anon_vma_chain_alloc(GFP_KERNEL);
+                       if (!avc)
+                               goto enomem_failure;
+               }
+               anon_vma = pavc->anon_vma;
+               root = lock_anon_vma_root(root, anon_vma);
+               anon_vma_chain_link(dst, avc, anon_vma);
        }
+       unlock_anon_vma_root(root);
        return 0;
 
  enomem_failure:
@@ -263,7 +297,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
        anon_vma = anon_vma_alloc();
        if (!anon_vma)
                goto out_error;
-       avc = anon_vma_chain_alloc();
+       avc = anon_vma_chain_alloc(GFP_KERNEL);
        if (!avc)
                goto out_error_free_anon_vma;
 
@@ -280,7 +314,9 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
        get_anon_vma(anon_vma->root);
        /* Mark this anon_vma as the one where our new (COWed) pages go. */
        vma->anon_vma = anon_vma;
+       anon_vma_lock(anon_vma);
        anon_vma_chain_link(vma, avc, anon_vma);
+       anon_vma_unlock(anon_vma);
 
        return 0;
 
@@ -291,36 +327,43 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
        return -ENOMEM;
 }
 
-static void anon_vma_unlink(struct anon_vma_chain *anon_vma_chain)
-{
-       struct anon_vma *anon_vma = anon_vma_chain->anon_vma;
-       int empty;
-
-       /* If anon_vma_fork fails, we can get an empty anon_vma_chain. */
-       if (!anon_vma)
-               return;
-
-       anon_vma_lock(anon_vma);
-       list_del(&anon_vma_chain->same_anon_vma);
-
-       /* We must garbage collect the anon_vma if it's empty */
-       empty = list_empty(&anon_vma->head);
-       anon_vma_unlock(anon_vma);
-
-       if (empty)
-               put_anon_vma(anon_vma);
-}
-
 void unlink_anon_vmas(struct vm_area_struct *vma)
 {
        struct anon_vma_chain *avc, *next;
+       struct anon_vma *root = NULL;
 
        /*
         * Unlink each anon_vma chained to the VMA.  This list is ordered
         * from newest to oldest, ensuring the root anon_vma gets freed last.
         */
        list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) {
-               anon_vma_unlink(avc);
+               struct anon_vma *anon_vma = avc->anon_vma;
+
+               root = lock_anon_vma_root(root, anon_vma);
+               list_del(&avc->same_anon_vma);
+
+               /*
+                * Leave empty anon_vmas on the list - we'll need
+                * to free them outside the lock.
+                */
+               if (list_empty(&anon_vma->head))
+                       continue;
+
+               list_del(&avc->same_vma);
+               anon_vma_chain_free(avc);
+       }
+       unlock_anon_vma_root(root);
+
+       /*
+        * Iterate the list once more, it now only contains empty and unlinked
+        * anon_vmas, destroy them. Could not do before due to __put_anon_vma()
+        * needing to acquire the anon_vma->root->mutex.
+        */
+       list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) {
+               struct anon_vma *anon_vma = avc->anon_vma;
+
+               put_anon_vma(anon_vma);
+
                list_del(&avc->same_vma);
                anon_vma_chain_free(avc);
        }
index 966e2b31fc60d5016cbe3415837d29b81dc8d684..883e98f78ca97a714175be2ad807d08da7ce9d0f 100644 (file)
@@ -539,7 +539,7 @@ static void shmem_free_pages(struct list_head *next)
        } while (next);
 }
 
-static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end)
+void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end)
 {
        struct shmem_inode_info *info = SHMEM_I(inode);
        unsigned long idx;
@@ -562,6 +562,8 @@ static void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end)
        spinlock_t *punch_lock;
        unsigned long upper_limit;
 
+       truncate_inode_pages_range(inode->i_mapping, start, end);
+
        inode->i_ctime = inode->i_mtime = CURRENT_TIME;
        idx = (start + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
        if (idx >= info->next_index)
@@ -738,16 +740,8 @@ done2:
                 * lowered next_index.  Also, though shmem_getpage checks
                 * i_size before adding to cache, no recheck after: so fix the
                 * narrow window there too.
-                *
-                * Recalling truncate_inode_pages_range and unmap_mapping_range
-                * every time for punch_hole (which never got a chance to clear
-                * SHMEM_PAGEIN at the start of vmtruncate_range) is expensive,
-                * yet hardly ever necessary: try to optimize them out later.
                 */
                truncate_inode_pages_range(inode->i_mapping, start, end);
-               if (punch_hole)
-                       unmap_mapping_range(inode->i_mapping, start,
-                                                       end - start, 1);
        }
 
        spin_lock(&info->lock);
@@ -766,22 +760,23 @@ done2:
                shmem_free_pages(pages_to_free.next);
        }
 }
+EXPORT_SYMBOL_GPL(shmem_truncate_range);
 
-static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
+static int shmem_setattr(struct dentry *dentry, struct iattr *attr)
 {
        struct inode *inode = dentry->d_inode;
-       loff_t newsize = attr->ia_size;
        int error;
 
        error = inode_change_ok(inode, attr);
        if (error)
                return error;
 
-       if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)
-                                       && newsize != inode->i_size) {
+       if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
+               loff_t oldsize = inode->i_size;
+               loff_t newsize = attr->ia_size;
                struct page *page = NULL;
 
-               if (newsize < inode->i_size) {
+               if (newsize < oldsize) {
                        /*
                         * If truncating down to a partial page, then
                         * if that page is already allocated, hold it
@@ -810,12 +805,19 @@ static int shmem_notify_change(struct dentry *dentry, struct iattr *attr)
                                spin_unlock(&info->lock);
                        }
                }
-
-               /* XXX(truncate): truncate_setsize should be called last */
-               truncate_setsize(inode, newsize);
+               if (newsize != oldsize) {
+                       i_size_write(inode, newsize);
+                       inode->i_ctime = inode->i_mtime = CURRENT_TIME;
+               }
+               if (newsize < oldsize) {
+                       loff_t holebegin = round_up(newsize, PAGE_SIZE);
+                       unmap_mapping_range(inode->i_mapping, holebegin, 0, 1);
+                       shmem_truncate_range(inode, newsize, (loff_t)-1);
+                       /* unmap again to remove racily COWed private pages */
+                       unmap_mapping_range(inode->i_mapping, holebegin, 0, 1);
+               }
                if (page)
                        page_cache_release(page);
-               shmem_truncate_range(inode, newsize, (loff_t)-1);
        }
 
        setattr_copy(inode, attr);
@@ -832,7 +834,6 @@ static void shmem_evict_inode(struct inode *inode)
        struct shmem_xattr *xattr, *nxattr;
 
        if (inode->i_mapping->a_ops == &shmem_aops) {
-               truncate_inode_pages(inode->i_mapping, 0);
                shmem_unacct_size(info->flags, inode->i_size);
                inode->i_size = 0;
                shmem_truncate_range(inode, 0, (loff_t)-1);
@@ -2706,7 +2707,7 @@ static const struct file_operations shmem_file_operations = {
 };
 
 static const struct inode_operations shmem_inode_operations = {
-       .setattr        = shmem_notify_change,
+       .setattr        = shmem_setattr,
        .truncate_range = shmem_truncate_range,
 #ifdef CONFIG_TMPFS_XATTR
        .setxattr       = shmem_setxattr,
@@ -2739,7 +2740,7 @@ static const struct inode_operations shmem_dir_inode_operations = {
        .removexattr    = shmem_removexattr,
 #endif
 #ifdef CONFIG_TMPFS_POSIX_ACL
-       .setattr        = shmem_notify_change,
+       .setattr        = shmem_setattr,
        .check_acl      = generic_check_acl,
 #endif
 };
@@ -2752,7 +2753,7 @@ static const struct inode_operations shmem_special_inode_operations = {
        .removexattr    = shmem_removexattr,
 #endif
 #ifdef CONFIG_TMPFS_POSIX_ACL
-       .setattr        = shmem_notify_change,
+       .setattr        = shmem_setattr,
        .check_acl      = generic_check_acl,
 #endif
 };
@@ -2908,6 +2909,12 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user)
        return 0;
 }
 
+void shmem_truncate_range(struct inode *inode, loff_t start, loff_t end)
+{
+       truncate_inode_pages_range(inode->i_mapping, start, end);
+}
+EXPORT_SYMBOL_GPL(shmem_truncate_range);
+
 #ifdef CONFIG_CGROUP_MEM_RES_CTLR
 /**
  * mem_cgroup_get_shmem_target - find a page or entry assigned to the shmem file
@@ -3033,3 +3040,26 @@ int shmem_zero_setup(struct vm_area_struct *vma)
        shmem_set_file(vma, file);
        return 0;
 }
+
+/**
+ * shmem_read_mapping_page_gfp - read into page cache, using specified page allocation flags.
+ * @mapping:   the page's address_space
+ * @index:     the page index
+ * @gfp:       the page allocator flags to use if allocating
+ *
+ * This behaves as a tmpfs "read_cache_page_gfp(mapping, index, gfp)",
+ * with any new page allocations done using the specified allocation flags.
+ * But read_cache_page_gfp() uses the ->readpage() method: which does not
+ * suit tmpfs, since it may have pages in swapcache, and needs to find those
+ * for itself; although drivers/gpu/drm i915 and ttm rely upon this support.
+ *
+ * Provide a stub for those callers to start using now, then later
+ * flesh it out to call shmem_getpage() with additional gfp mask, when
+ * shmem_file_splice_read() is added and shmem_readpage() is removed.
+ */
+struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
+                                        pgoff_t index, gfp_t gfp)
+{
+       return read_cache_page_gfp(mapping, index, gfp);
+}
+EXPORT_SYMBOL_GPL(shmem_read_mapping_page_gfp);
index d537d29e9b7bb5d9364b531e17f972618a5cad4b..ff8dc1a18cb4fb6e15dac52b3dff0c491337f9af 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
 #include <linux/namei.h>
-#include <linux/shm.h>
+#include <linux/shmem_fs.h>
 #include <linux/blkdev.h>
 #include <linux/random.h>
 #include <linux/writeback.h>
index 2372d4ed5dd8ff763d3aaed5cb546c8033eca1ff..fabf2d0f51695eddacdb6b013fac0b9cdee3a655 100644 (file)
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/swap.h>
+#include <linux/memcontrol.h>
+
+#include <trace/events/vmscan.h>
+
+#define TOKEN_AGING_INTERVAL   (0xFF)
 
 static DEFINE_SPINLOCK(swap_token_lock);
 struct mm_struct *swap_token_mm;
+struct mem_cgroup *swap_token_memcg;
 static unsigned int global_faults;
+static unsigned int last_aging;
+
+#ifdef CONFIG_CGROUP_MEM_RES_CTLR
+static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm)
+{
+       struct mem_cgroup *memcg;
+
+       memcg = try_get_mem_cgroup_from_mm(mm);
+       if (memcg)
+               css_put(mem_cgroup_css(memcg));
+
+       return memcg;
+}
+#else
+static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm)
+{
+       return NULL;
+}
+#endif
 
 void grab_swap_token(struct mm_struct *mm)
 {
        int current_interval;
+       unsigned int old_prio = mm->token_priority;
 
        global_faults++;
 
@@ -38,40 +64,81 @@ void grab_swap_token(struct mm_struct *mm)
                return;
 
        /* First come first served */
-       if (swap_token_mm == NULL) {
-               mm->token_priority = mm->token_priority + 2;
-               swap_token_mm = mm;
-               goto out;
+       if (!swap_token_mm)
+               goto replace_token;
+
+       if ((global_faults - last_aging) > TOKEN_AGING_INTERVAL) {
+               swap_token_mm->token_priority /= 2;
+               last_aging = global_faults;
        }
 
-       if (mm != swap_token_mm) {
-               if (current_interval < mm->last_interval)
-                       mm->token_priority++;
-               else {
-                       if (likely(mm->token_priority > 0))
-                               mm->token_priority--;
-               }
-               /* Check if we deserve the token */
-               if (mm->token_priority > swap_token_mm->token_priority) {
-                       mm->token_priority += 2;
-                       swap_token_mm = mm;
-               }
-       } else {
-               /* Token holder came in again! */
+       if (mm == swap_token_mm) {
                mm->token_priority += 2;
+               goto update_priority;
+       }
+
+       if (current_interval < mm->last_interval)
+               mm->token_priority++;
+       else {
+               if (likely(mm->token_priority > 0))
+                       mm->token_priority--;
        }
 
+       /* Check if we deserve the token */
+       if (mm->token_priority > swap_token_mm->token_priority)
+               goto replace_token;
+
+update_priority:
+       trace_update_swap_token_priority(mm, old_prio, swap_token_mm);
+
 out:
        mm->faultstamp = global_faults;
        mm->last_interval = current_interval;
        spin_unlock(&swap_token_lock);
+       return;
+
+replace_token:
+       mm->token_priority += 2;
+       trace_replace_swap_token(swap_token_mm, mm);
+       swap_token_mm = mm;
+       swap_token_memcg = swap_token_memcg_from_mm(mm);
+       last_aging = global_faults;
+       goto out;
 }
 
 /* Called on process exit. */
 void __put_swap_token(struct mm_struct *mm)
 {
        spin_lock(&swap_token_lock);
-       if (likely(mm == swap_token_mm))
+       if (likely(mm == swap_token_mm)) {
+               trace_put_swap_token(swap_token_mm);
                swap_token_mm = NULL;
+               swap_token_memcg = NULL;
+       }
        spin_unlock(&swap_token_lock);
 }
+
+static bool match_memcg(struct mem_cgroup *a, struct mem_cgroup *b)
+{
+       if (!a)
+               return true;
+       if (!b)
+               return true;
+       if (a == b)
+               return true;
+       return false;
+}
+
+void disable_swap_token(struct mem_cgroup *memcg)
+{
+       /* memcg reclaim don't disable unrelated mm token. */
+       if (match_memcg(memcg, swap_token_memcg)) {
+               spin_lock(&swap_token_lock);
+               if (match_memcg(memcg, swap_token_memcg)) {
+                       trace_disable_swap_token(swap_token_mm);
+                       swap_token_mm = NULL;
+                       swap_token_memcg = NULL;
+               }
+               spin_unlock(&swap_token_lock);
+       }
+}
index 3a29a6180212d7bcf25ab0d6fd97acdb16fc8f42..e13f22efaad741bfb0268ba577c3d34807769201 100644 (file)
@@ -304,6 +304,11 @@ EXPORT_SYMBOL(truncate_inode_pages_range);
  * @lstart: offset from which to truncate
  *
  * Called under (and serialised by) inode->i_mutex.
+ *
+ * Note: When this function returns, there can be a page in the process of
+ * deletion (inside __delete_from_page_cache()) in the specified range.  Thus
+ * mapping->nrpages can be non-zero when this function returns even after
+ * truncation of the whole mapping.
  */
 void truncate_inode_pages(struct address_space *mapping, loff_t lstart)
 {
@@ -603,3 +608,27 @@ int vmtruncate(struct inode *inode, loff_t offset)
        return 0;
 }
 EXPORT_SYMBOL(vmtruncate);
+
+int vmtruncate_range(struct inode *inode, loff_t offset, loff_t end)
+{
+       struct address_space *mapping = inode->i_mapping;
+
+       /*
+        * If the underlying filesystem is not going to provide
+        * a way to truncate a range of blocks (punch a hole) -
+        * we should return failure right now.
+        */
+       if (!inode->i_op->truncate_range)
+               return -ENOSYS;
+
+       mutex_lock(&inode->i_mutex);
+       down_write(&inode->i_alloc_sem);
+       unmap_mapping_range(mapping, offset, (end - offset), 1);
+       inode->i_op->truncate_range(inode, offset, end);
+       /* unmap again to remove racily COWed private pages */
+       unmap_mapping_range(mapping, offset, (end - offset), 1);
+       up_write(&inode->i_alloc_sem);
+       mutex_unlock(&inode->i_mutex);
+
+       return 0;
+}
index faa0a088f9cc83a5a4cd7d05e40924144c795c19..4f49535d4cd31f998fd58f456eb7ff16ccbf82f9 100644 (file)
@@ -1124,8 +1124,20 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
                                        nr_lumpy_dirty++;
                                scan++;
                        } else {
-                               /* the page is freed already. */
-                               if (!page_count(cursor_page))
+                               /*
+                                * Check if the page is freed already.
+                                *
+                                * We can't use page_count() as that
+                                * requires compound_head and we don't
+                                * have a pin on the page here. If a
+                                * page is tail, we may or may not
+                                * have isolated the head, so assume
+                                * it's not free, it'd be tricky to
+                                * track the head status without a
+                                * page pin.
+                                */
+                               if (!PageTail(cursor_page) &&
+                                   !atomic_read(&cursor_page->_count))
                                        continue;
                                break;
                        }
@@ -1983,14 +1995,13 @@ restart:
  * If a zone is deemed to be full of pinned pages then just give it a light
  * scan then give up on it.
  */
-static unsigned long shrink_zones(int priority, struct zonelist *zonelist,
+static void shrink_zones(int priority, struct zonelist *zonelist,
                                        struct scan_control *sc)
 {
        struct zoneref *z;
        struct zone *zone;
        unsigned long nr_soft_reclaimed;
        unsigned long nr_soft_scanned;
-       unsigned long total_scanned = 0;
 
        for_each_zone_zonelist_nodemask(zone, z, zonelist,
                                        gfp_zone(sc->gfp_mask), sc->nodemask) {
@@ -2005,19 +2016,23 @@ static unsigned long shrink_zones(int priority, struct zonelist *zonelist,
                                continue;
                        if (zone->all_unreclaimable && priority != DEF_PRIORITY)
                                continue;       /* Let kswapd poll it */
+                       /*
+                        * This steals pages from memory cgroups over softlimit
+                        * and returns the number of reclaimed pages and
+                        * scanned pages. This works for global memory pressure
+                        * and balancing, not for a memcg's limit.
+                        */
+                       nr_soft_scanned = 0;
+                       nr_soft_reclaimed = mem_cgroup_soft_limit_reclaim(zone,
+                                               sc->order, sc->gfp_mask,
+                                               &nr_soft_scanned);
+                       sc->nr_reclaimed += nr_soft_reclaimed;
+                       sc->nr_scanned += nr_soft_scanned;
+                       /* need some check for avoid more shrink_zone() */
                }
 
-               nr_soft_scanned = 0;
-               nr_soft_reclaimed = mem_cgroup_soft_limit_reclaim(zone,
-                                                       sc->order, sc->gfp_mask,
-                                                       &nr_soft_scanned);
-               sc->nr_reclaimed += nr_soft_reclaimed;
-               total_scanned += nr_soft_scanned;
-
                shrink_zone(priority, zone, sc);
        }
-
-       return total_scanned;
 }
 
 static bool zone_reclaimable(struct zone *zone)
@@ -2081,8 +2096,8 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist,
        for (priority = DEF_PRIORITY; priority >= 0; priority--) {
                sc->nr_scanned = 0;
                if (!priority)
-                       disable_swap_token();
-               total_scanned += shrink_zones(priority, zonelist, sc);
+                       disable_swap_token(sc->mem_cgroup);
+               shrink_zones(priority, zonelist, sc);
                /*
                 * Don't shrink slabs when reclaiming memory from
                 * over limit cgroups
@@ -2407,7 +2422,7 @@ loop_again:
 
                /* The swap token gets in the way of swapout... */
                if (!priority)
-                       disable_swap_token();
+                       disable_swap_token(NULL);
 
                all_zones_ok = 1;
                balanced = 0;
index c7a581a96894c7193ff75c48573976aad6133255..917ecb93ea28d477d75c729accac39eacbdfa752 100644 (file)
@@ -205,7 +205,7 @@ int register_vlan_dev(struct net_device *dev)
        grp->nr_vlans++;
 
        if (ngrp) {
-               if (ops->ndo_vlan_rx_register)
+               if (ops->ndo_vlan_rx_register && (real_dev->features & NETIF_F_HW_VLAN_RX))
                        ops->ndo_vlan_rx_register(real_dev, ngrp);
                rcu_assign_pointer(real_dev->vlgrp, ngrp);
        }
index b46ab0c481f05432c6eb26312d63d029fb2e62e5..eec5b332ec2dce3082807cd52de3ccef7610b4da 100644 (file)
@@ -477,14 +477,16 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
         * command otherwise */
        u8 events[8] = { 0xff, 0xff, 0xfb, 0xff, 0x00, 0x00, 0x00, 0x00 };
 
-       /* Events for 1.2 and newer controllers */
-       if (hdev->lmp_ver > 1) {
-               events[4] |= 0x01; /* Flow Specification Complete */
-               events[4] |= 0x02; /* Inquiry Result with RSSI */
-               events[4] |= 0x04; /* Read Remote Extended Features Complete */
-               events[5] |= 0x08; /* Synchronous Connection Complete */
-               events[5] |= 0x10; /* Synchronous Connection Changed */
-       }
+       /* CSR 1.1 dongles does not accept any bitfield so don't try to set
+        * any event mask for pre 1.2 devices */
+       if (hdev->lmp_ver <= 1)
+               return;
+
+       events[4] |= 0x01; /* Flow Specification Complete */
+       events[4] |= 0x02; /* Inquiry Result with RSSI */
+       events[4] |= 0x04; /* Read Remote Extended Features Complete */
+       events[5] |= 0x08; /* Synchronous Connection Complete */
+       events[5] |= 0x10; /* Synchronous Connection Changed */
 
        if (hdev->features[3] & LMP_RSSI_INQ)
                events[4] |= 0x04; /* Inquiry Result with RSSI */
index 18dc9888d8c28064f9a32bd129c7a23d6711af04..8248303f44e892f66ba5af8841f094696e88f8cd 100644 (file)
@@ -413,6 +413,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us
                        break;
                }
 
+               memset(&cinfo, 0, sizeof(cinfo));
                cinfo.hci_handle = chan->conn->hcon->handle;
                memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3);
 
index 386cfaffd4b7569e919c933f89192eeb30cf14e2..1b10727ce523e077c1f571910275e085b6ee32f6 100644 (file)
@@ -788,6 +788,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u
 
                l2cap_sk = rfcomm_pi(sk)->dlc->session->sock->sk;
 
+               memset(&cinfo, 0, sizeof(cinfo));
                cinfo.hci_handle = conn->hcon->handle;
                memcpy(cinfo.dev_class, conn->hcon->dev_class, 3);
 
index 3e1c6b1910381dea4973269bd0a9e5fcf2a453cb..aacaa27f20727cbc618b8c43fe50e4472532be0a 100644 (file)
@@ -372,6 +372,15 @@ static void __sco_sock_close(struct sock *sk)
 
        case BT_CONNECTED:
        case BT_CONFIG:
+               if (sco_pi(sk)->conn) {
+                       sk->sk_state = BT_DISCONN;
+                       sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
+                       hci_conn_put(sco_pi(sk)->conn->hcon);
+                       sco_pi(sk)->conn->hcon = NULL;
+               } else
+                       sco_chan_del(sk, ECONNRESET);
+               break;
+
        case BT_CONNECT:
        case BT_DISCONN:
                sco_chan_del(sk, ECONNRESET);
@@ -835,7 +844,9 @@ static void sco_chan_del(struct sock *sk, int err)
                conn->sk = NULL;
                sco_pi(sk)->conn = NULL;
                sco_conn_unlock(conn);
-               hci_conn_put(conn->hcon);
+
+               if (conn->hcon)
+                       hci_conn_put(conn->hcon);
        }
 
        sk->sk_state = BT_CLOSED;
index a6b2f86378c75437bba1300d23acc3b9ca188a58..c188c803c09c5085014b5bb221aeb57c8fba4871 100644 (file)
@@ -243,6 +243,7 @@ int br_netpoll_enable(struct net_bridge_port *p)
                goto out;
 
        np->dev = p->dev;
+       strlcpy(np->dev_name, p->dev->name, IFNAMSIZ);
 
        err = __netpoll_setup(np);
        if (err) {
index 2f14eafdeeabe80d5dd5a5643e55ecf3a2e74f52..29b9812c8da0d38f5ab9461162cdbc74093c25cf 100644 (file)
@@ -1424,7 +1424,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br,
        switch (ih->type) {
        case IGMP_HOST_MEMBERSHIP_REPORT:
        case IGMPV2_HOST_MEMBERSHIP_REPORT:
-               BR_INPUT_SKB_CB(skb2)->mrouters_only = 1;
+               BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
                err = br_ip4_multicast_add_group(br, port, ih->group);
                break;
        case IGMPV3_HOST_MEMBERSHIP_REPORT:
@@ -1543,7 +1543,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br,
                        goto out;
                }
                mld = (struct mld_msg *)skb_transport_header(skb2);
-               BR_INPUT_SKB_CB(skb2)->mrouters_only = 1;
+               BR_INPUT_SKB_CB(skb)->mrouters_only = 1;
                err = br_ip6_multicast_add_group(br, port, &mld->mld_mca);
                break;
            }
index 3a66b8c10e09ab1876e7b678efc65073699342a0..c23979e79dfadce502c5d70927412849b79b868e 100644 (file)
@@ -255,7 +255,7 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
 
                if (cfsrvl_phyid_match(layer, phyid) && layer->ctrlcmd) {
 
-                       if ((ctrl == _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND ||
+                       if ((ctrl == _CAIF_CTRLCMD_PHYIF_DOWN_IND ||
                                ctrl == CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND) &&
                                        layer->id != 0) {
 
index 11b98bc2aa8f4db7805cfe14f2087f5d8ced9824..33d2a1fba131695451de05e191ae9c10fb2cd307 100644 (file)
@@ -1179,9 +1179,14 @@ static void remove_queue_kobjects(struct net_device *net)
 #endif
 }
 
-static const void *net_current_ns(void)
+static void *net_grab_current_ns(void)
 {
-       return current->nsproxy->net_ns;
+       struct net *ns = current->nsproxy->net_ns;
+#ifdef CONFIG_NET_NS
+       if (ns)
+               atomic_inc(&ns->passive);
+#endif
+       return ns;
 }
 
 static const void *net_initial_ns(void)
@@ -1196,22 +1201,13 @@ static const void *net_netlink_ns(struct sock *sk)
 
 struct kobj_ns_type_operations net_ns_type_operations = {
        .type = KOBJ_NS_TYPE_NET,
-       .current_ns = net_current_ns,
+       .grab_current_ns = net_grab_current_ns,
        .netlink_ns = net_netlink_ns,
        .initial_ns = net_initial_ns,
+       .drop_ns = net_drop_ns,
 };
 EXPORT_SYMBOL_GPL(net_ns_type_operations);
 
-static void net_kobj_ns_exit(struct net *net)
-{
-       kobj_ns_exit(KOBJ_NS_TYPE_NET, net);
-}
-
-static struct pernet_operations kobj_net_ops = {
-       .exit = net_kobj_ns_exit,
-};
-
-
 #ifdef CONFIG_HOTPLUG
 static int netdev_uevent(struct device *d, struct kobj_uevent_env *env)
 {
@@ -1339,6 +1335,5 @@ EXPORT_SYMBOL(netdev_class_remove_file);
 int netdev_kobject_init(void)
 {
        kobj_ns_type_register(&net_ns_type_operations);
-       register_pernet_subsys(&kobj_net_ops);
        return class_register(&net_class);
 }
index e41e5110c65ca2aa1ae57ddfd970caee49a6312f..ea489db1bc2361c20001576a5e909aa22cb689d2 100644 (file)
@@ -128,6 +128,7 @@ static __net_init int setup_net(struct net *net)
        LIST_HEAD(net_exit_list);
 
        atomic_set(&net->count, 1);
+       atomic_set(&net->passive, 1);
 
 #ifdef NETNS_REFCNT_DEBUG
        atomic_set(&net->use_count, 0);
@@ -210,6 +211,13 @@ static void net_free(struct net *net)
        kmem_cache_free(net_cachep, net);
 }
 
+void net_drop_ns(void *p)
+{
+       struct net *ns = p;
+       if (ns && atomic_dec_and_test(&ns->passive))
+               net_free(ns);
+}
+
 struct net *copy_net_ns(unsigned long flags, struct net *old_net)
 {
        struct net *net;
@@ -230,7 +238,7 @@ struct net *copy_net_ns(unsigned long flags, struct net *old_net)
        }
        mutex_unlock(&net_mutex);
        if (rv < 0) {
-               net_free(net);
+               net_drop_ns(net);
                return ERR_PTR(rv);
        }
        return net;
@@ -286,7 +294,7 @@ static void cleanup_net(struct work_struct *work)
        /* Finally it is safe to free my network namespace structure */
        list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) {
                list_del_init(&net->exit_list);
-               net_free(net);
+               net_drop_ns(net);
        }
 }
 static DECLARE_WORK(net_cleanup_work, cleanup_net);
index ed0eab39f531f028e96deaa5f61755c46c4e5855..02548b292b53bf416f4e0ced8daeeb9e842666e3 100644 (file)
@@ -44,7 +44,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid,
        pr_debug("%s\n", __func__);
 
        if (!buf)
-               goto out;
+               return -EMSGSIZE;
 
        hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags,
                IEEE802154_LIST_PHY);
@@ -65,6 +65,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 pid,
                                pages * sizeof(uint32_t), buf);
 
        mutex_unlock(&phy->pib_lock);
+       kfree(buf);
        return genlmsg_end(msg, hdr);
 
 nla_put_failure:
index 3af16baac56f52dd9ae0b68610c7f9c810034a6a..d4e5ade7f851af38fe9a41c419d2c924d4bdc199 100644 (file)
@@ -693,6 +693,7 @@ int inet_accept(struct socket *sock, struct socket *newsock, int flags)
 
        lock_sock(sk2);
 
+       sock_rps_record_flow(sk2);
        WARN_ON(!((1 << sk2->sk_state) &
                  (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE)));
 
index 6ffe94ca5bc98bfea2488679ba416ef71295b71a..3267d389843794e0b481f05c22021e905fc6e6d1 100644 (file)
@@ -437,7 +437,7 @@ static int valid_cc(const void *bc, int len, int cc)
                        return 0;
                if (cc == len)
                        return 1;
-               if (op->yes < 4)
+               if (op->yes < 4 || op->yes & 3)
                        return 0;
                len -= op->yes;
                bc  += op->yes;
@@ -447,11 +447,11 @@ static int valid_cc(const void *bc, int len, int cc)
 
 static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
 {
-       const unsigned char *bc = bytecode;
+       const void *bc = bytecode;
        int  len = bytecode_len;
 
        while (len > 0) {
-               struct inet_diag_bc_op *op = (struct inet_diag_bc_op *)bc;
+               const struct inet_diag_bc_op *op = bc;
 
 //printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len);
                switch (op->code) {
@@ -462,22 +462,20 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
                case INET_DIAG_BC_S_LE:
                case INET_DIAG_BC_D_GE:
                case INET_DIAG_BC_D_LE:
-                       if (op->yes < 4 || op->yes > len + 4)
-                               return -EINVAL;
                case INET_DIAG_BC_JMP:
-                       if (op->no < 4 || op->no > len + 4)
+                       if (op->no < 4 || op->no > len + 4 || op->no & 3)
                                return -EINVAL;
                        if (op->no < len &&
                            !valid_cc(bytecode, bytecode_len, len - op->no))
                                return -EINVAL;
                        break;
                case INET_DIAG_BC_NOP:
-                       if (op->yes < 4 || op->yes > len + 4)
-                               return -EINVAL;
                        break;
                default:
                        return -EINVAL;
                }
+               if (op->yes < 4 || op->yes > len + 4 || op->yes & 3)
+                       return -EINVAL;
                bc  += op->yes;
                len -= op->yes;
        }
index f7f9bd7ba12d8b4f6d0f938835efac7e34dfbed5..5c9b9d963918aa538086239d2351afea574324cb 100644 (file)
@@ -203,7 +203,8 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp)
        else
                pmsg->outdev_name[0] = '\0';
 
-       if (entry->indev && entry->skb->dev) {
+       if (entry->indev && entry->skb->dev &&
+           entry->skb->mac_header != entry->skb->network_header) {
                pmsg->hw_type = entry->skb->dev->type;
                pmsg->hw_addrlen = dev_parse_header(entry->skb,
                                                    pmsg->hw_addr);
index 7647438435030a4fa29ba98539ec423921086b16..24e556e83a3ba97fe633525c10e63d4bcb767b34 100644 (file)
@@ -566,7 +566,7 @@ check_entry(const struct ipt_entry *e, const char *name)
        const struct xt_entry_target *t;
 
        if (!ip_checkentry(&e->ip)) {
-               duprintf("ip check failed %p %s.\n", e, par->match->name);
+               duprintf("ip check failed %p %s.\n", e, name);
                return -EINVAL;
        }
 
index af6e9c778345ff802916cc7fa0078cbd79735c81..2b57e52c746c4518b914da30775044692a740396 100644 (file)
@@ -25,7 +25,8 @@ MODULE_LICENSE("GPL");
 static inline bool match_ip(const struct sk_buff *skb,
                            const struct ipt_ecn_info *einfo)
 {
-       return (ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect;
+       return ((ip_hdr(skb)->tos & IPT_ECN_IP_MASK) == einfo->ip_ect) ^
+              !!(einfo->invert & IPT_ECN_OP_MATCH_IP);
 }
 
 static inline bool match_tcp(const struct sk_buff *skb,
@@ -76,8 +77,6 @@ static bool ecn_mt(const struct sk_buff *skb, struct xt_action_param *par)
                        return false;
 
        if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR)) {
-               if (ip_hdr(skb)->protocol != IPPROTO_TCP)
-                       return false;
                if (!match_tcp(skb, info, &par->hotdrop))
                        return false;
        }
@@ -97,7 +96,7 @@ static int ecn_mt_check(const struct xt_mtchk_param *par)
                return -EINVAL;
 
        if (info->operation & (IPT_ECN_OP_MATCH_ECE|IPT_ECN_OP_MATCH_CWR) &&
-           ip->proto != IPPROTO_TCP) {
+           (ip->proto != IPPROTO_TCP || ip->invflags & IPT_INV_PROTO)) {
                pr_info("cannot match TCP bits in rule for non-tcp packets\n");
                return -EINVAL;
        }
index db10075dd88e4720e1ba97bf7365b424e2fb124b..de9da21113a11be6c9f57b15a97b3936a574e512 100644 (file)
@@ -121,7 +121,9 @@ static unsigned int ipv4_confirm(unsigned int hooknum,
                return ret;
        }
 
-       if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status)) {
+       /* adjust seqs for loopback traffic only in outgoing direction */
+       if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) &&
+           !nf_is_loopback_packet(skb)) {
                typeof(nf_nat_seq_adjust_hook) seq_adjust;
 
                seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook);
index 9aaa67165f42453ed0af947cebb53cc49163ab4a..39b403f854c6debeb03437a2a9a0c9746083b399 100644 (file)
@@ -41,7 +41,6 @@
 #include <linux/proc_fs.h>
 #include <net/sock.h>
 #include <net/ping.h>
-#include <net/icmp.h>
 #include <net/udp.h>
 #include <net/route.h>
 #include <net/inet_common.h>
index 045f0ec6a4a02a257cd60760283cdd3fb8cd5fda..aa13ef1051108dac93a9151d0819d9fd7447ec64 100644 (file)
@@ -1902,9 +1902,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 
        hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev)));
        rth = rt_intern_hash(hash, rth, skb, dev->ifindex);
-       err = 0;
-       if (IS_ERR(rth))
-               err = PTR_ERR(rth);
+       return IS_ERR(rth) ? PTR_ERR(rth) : 0;
 
 e_nobufs:
        return -ENOBUFS;
index a7d6671e33b8a6e46aba0b352ad083736d1b421b..708dc203b0348c3365b6ac3cd2e36559a069d0cc 100644 (file)
@@ -1589,6 +1589,7 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
                        goto discard;
 
                if (nsk != sk) {
+                       sock_rps_save_rxhash(nsk, skb->rxhash);
                        if (tcp_child_process(sk, nsk, skb)) {
                                rsk = nsk;
                                goto reset;
index 065fe405fb58486430a1f81209d9d4b6ec31abdf..249394863284bcb2edcb3228183a953393df1a26 100644 (file)
@@ -204,7 +204,8 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp)
        else
                pmsg->outdev_name[0] = '\0';
 
-       if (entry->indev && entry->skb->dev) {
+       if (entry->indev && entry->skb->dev &&
+           entry->skb->mac_header != entry->skb->network_header) {
                pmsg->hw_type = entry->skb->dev->type;
                pmsg->hw_addrlen = dev_parse_header(entry->skb, pmsg->hw_addr);
        }
index d1fd28711ba50e1ad8ac90a0c32df360ec911d70..87551ca568cd80e35671153b80acb5c6f6986fe8 100644 (file)
@@ -1644,6 +1644,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
                 * the new socket..
                 */
                if(nsk != sk) {
+                       sock_rps_save_rxhash(nsk, skb->rxhash);
                        if (tcp_child_process(sk, nsk, skb))
                                goto reset;
                        if (opt_skb)
index bf28ac2fc99b7cf164d82417e6248049787ff923..782db275ac53591eeae96b750f5bbf5cc14b063f 100644 (file)
@@ -776,8 +776,16 @@ static void ip_vs_conn_expire(unsigned long data)
                if (cp->control)
                        ip_vs_control_del(cp);
 
-               if (cp->flags & IP_VS_CONN_F_NFCT)
+               if (cp->flags & IP_VS_CONN_F_NFCT) {
                        ip_vs_conn_drop_conntrack(cp);
+                       /* Do not access conntracks during subsys cleanup
+                        * because nf_conntrack_find_get can not be used after
+                        * conntrack cleanup for the net.
+                        */
+                       smp_rmb();
+                       if (ipvs->enable)
+                               ip_vs_conn_drop_conntrack(cp);
+               }
 
                ip_vs_pe_put(cp->pe);
                kfree(cp->pe_data);
index 55af2242bccd482b8cb762a8f3419cc922724791..24c28d238dcb62f7dc148648a35e8a05b7278fbc 100644 (file)
@@ -1945,6 +1945,7 @@ static void __net_exit __ip_vs_dev_cleanup(struct net *net)
 {
        EnterFunction(2);
        net_ipvs(net)->enable = 0;      /* Disable packet reception */
+       smp_wmb();
        __ip_vs_sync_cleanup(net);
        LeaveFunction(2);
 }
index e0ee010935e7008a8730b2c87a2c9c689226fb8a..2e7ccbb43ddb563b7491eafe197ec0e91d8c4b4b 100644 (file)
@@ -456,7 +456,8 @@ __build_packet_message(struct nfulnl_instance *inst,
        if (skb->mark)
                NLA_PUT_BE32(inst->skb, NFULA_MARK, htonl(skb->mark));
 
-       if (indev && skb->dev) {
+       if (indev && skb->dev &&
+           skb->mac_header != skb->network_header) {
                struct nfulnl_msg_packet_hw phw;
                int len = dev_parse_header(skb, phw.hw_addr);
                if (len > 0) {
index b83123f12b42e30612481796bc6c9a4d3bacab60..fdd2fafe0a14ed8810181aae57168f841d5b3f1e 100644 (file)
@@ -335,7 +335,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
        if (entskb->mark)
                NLA_PUT_BE32(skb, NFQA_MARK, htonl(entskb->mark));
 
-       if (indev && entskb->dev) {
+       if (indev && entskb->dev &&
+           entskb->mac_header != entskb->network_header) {
                struct nfqnl_msg_packet_hw phw;
                int len = dev_parse_header(entskb, phw.hw_addr);
                if (len) {
index 339ba64cce1e2ee7134a2c9d09cd64f5fb9cb85e..5daf6cc4faea19f39081765433f4cf2333280605 100644 (file)
@@ -577,13 +577,13 @@ retry:
        }
        inode = &gss_msg->inode->vfs_inode;
        for (;;) {
-               prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE);
+               prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_KILLABLE);
                spin_lock(&inode->i_lock);
                if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) {
                        break;
                }
                spin_unlock(&inode->i_lock);
-               if (signalled()) {
+               if (fatal_signal_pending(current)) {
                        err = -ERESTARTSYS;
                        goto out_intr;
                }
index 0a9a2ec2e46983f0b73bf20d267721024c11646c..c3b75333b821d2b58da65d16dc099ee6cf2b9da3 100644 (file)
@@ -43,6 +43,7 @@
 #include <linux/sunrpc/gss_krb5.h>
 #include <linux/sunrpc/xdr.h>
 #include <linux/crypto.h>
+#include <linux/sunrpc/gss_krb5_enctypes.h>
 
 #ifdef RPC_DEBUG
 # define RPCDBG_FACILITY       RPCDBG_AUTH
@@ -750,7 +751,7 @@ static struct gss_api_mech gss_kerberos_mech = {
        .gm_ops         = &gss_kerberos_ops,
        .gm_pf_num      = ARRAY_SIZE(gss_kerberos_pfs),
        .gm_pfs         = gss_kerberos_pfs,
-       .gm_upcall_enctypes = "18,17,16,23,3,1,2",
+       .gm_upcall_enctypes = KRB5_SUPPORTED_ENCTYPES,
 };
 
 static int __init init_kerberos_module(void)
index b84d7395535e7aae2d523797134c27d8a9e57c11..8c9141583d6f135714eac27c100e4bc9c3426631 100644 (file)
@@ -1061,7 +1061,7 @@ call_allocate(struct rpc_task *task)
 
        dprintk("RPC: %5u rpc_buffer allocation failed\n", task->tk_pid);
 
-       if (RPC_IS_ASYNC(task) || !signalled()) {
+       if (RPC_IS_ASYNC(task) || !fatal_signal_pending(current)) {
                task->tk_action = call_allocate;
                rpc_delay(task, HZ>>4);
                return;
@@ -1175,6 +1175,9 @@ call_bind_status(struct rpc_task *task)
                        status = -EOPNOTSUPP;
                        break;
                }
+               if (task->tk_rebind_retry == 0)
+                       break;
+               task->tk_rebind_retry--;
                rpc_delay(task, 3*HZ);
                goto retry_timeout;
        case -ETIMEDOUT:
index 6b43ee7221d5a830b8b0acea4375f9341aacfc90..a27406b1654f190f645e9b3c393b46f4b6d939fb 100644 (file)
@@ -792,6 +792,7 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta
        /* Initialize retry counters */
        task->tk_garb_retry = 2;
        task->tk_cred_retry = 2;
+       task->tk_rebind_retry = 2;
 
        task->tk_priority = task_setup_data->priority - RPC_PRIORITY_LOW;
        task->tk_owner = current->tgid;
index 8657f99bfb2b7d171df283d82092cba96731fcbd..b0aa2c680593d0c09857b9447d54ef933861ed3b 100755 (executable)
@@ -1943,6 +1943,11 @@ sub process {
                        WARN("LINUX_VERSION_CODE should be avoided, code should be for the version to which it is merged\n" . $herecurr);
                }
 
+# check for uses of printk_ratelimit
+               if ($line =~ /\bprintk_ratelimit\s*\(/) {
+                       WARN("Prefer printk_ratelimited or pr_<level>_ratelimited to printk_ratelimit\n" . $herecurr);
+               }
+
 # printk should use KERN_* levels.  Note that follow on printk's on the
 # same line do not need a level, so we use the current block context
 # to try and find and validate the current printk.  In summary the current
index cd1f779fa51d38eafc4f75bac0649e592703a7fb..1be68269e1c2a2c55e2db2cc46d206539c5f79f3 100644 (file)
@@ -474,17 +474,11 @@ struct cgroup_subsys devices_subsys = {
        .subsys_id = devices_subsys_id,
 };
 
-int devcgroup_inode_permission(struct inode *inode, int mask)
+int __devcgroup_inode_permission(struct inode *inode, int mask)
 {
        struct dev_cgroup *dev_cgroup;
        struct dev_whitelist_item *wh;
 
-       dev_t device = inode->i_rdev;
-       if (!device)
-               return 0;
-       if (!S_ISBLK(inode->i_mode) && !S_ISCHR(inode->i_mode))
-               return 0;
-
        rcu_read_lock();
 
        dev_cgroup = task_devcgroup(current);
index d31862e0aa1c00f415d447e12e780482e2bdbca5..82465328c39b94b5264fb65ba27399f6cdf4d68f 100644 (file)
@@ -71,9 +71,8 @@ EXPORT_SYMBOL(complete_request_key);
  * This is called in context of freshly forked kthread before kernel_execve(),
  * so we can simply install the desired session_keyring at this point.
  */
-static int umh_keys_init(struct subprocess_info *info)
+static int umh_keys_init(struct subprocess_info *info, struct cred *cred)
 {
-       struct cred *cred = (struct cred*)current_cred();
        struct key *keyring = info->data;
 
        return install_session_keyring_to_cred(cred, keyring);
@@ -470,7 +469,7 @@ static struct key *construct_key_and_link(struct key_type *type,
        } else if (ret == -EINPROGRESS) {
                ret = 0;
        } else {
-               key = ERR_PTR(ret);
+               goto couldnt_alloc_key;
        }
 
        key_put(dest_keyring);
@@ -480,6 +479,7 @@ static struct key *construct_key_and_link(struct key_type *type,
 construction_failed:
        key_negate_and_link(key, key_negative_timeout, NULL, NULL);
        key_put(key);
+couldnt_alloc_key:
        key_put(dest_keyring);
        kleave(" = %d", ret);
        return ERR_PTR(ret);
index 77d44138864fd5862a180c5907a81c2a52f1b6ab..35459340019e44399775c2f96aa9b5871f8d566c 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/audit.h>
 #include <linux/uaccess.h>
 #include <linux/kobject.h>
+#include <linux/ctype.h>
 
 /* selinuxfs pseudo filesystem for exporting the security policy API.
    Based on the proc code and the fs/nfsd/nfsctl.c code. */
@@ -751,6 +752,14 @@ out:
        return length;
 }
 
+static inline int hexcode_to_int(int code) {
+       if (code == '\0' || !isxdigit(code))
+               return -1;
+       if (isdigit(code))
+               return code - '0';
+       return tolower(code) - 'a' + 10;
+}
+
 static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
 {
        char *scon = NULL, *tcon = NULL;
@@ -785,8 +794,34 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
        nargs = sscanf(buf, "%s %s %hu %s", scon, tcon, &tclass, namebuf);
        if (nargs < 3 || nargs > 4)
                goto out;
-       if (nargs == 4)
+       if (nargs == 4) {
+               /*
+                * If and when the name of new object to be queried contains
+                * either whitespace or multibyte characters, they shall be
+                * encoded based on the percentage-encoding rule.
+                * If not encoded, the sscanf logic picks up only left-half
+                * of the supplied name; splitted by a whitespace unexpectedly.
+                */
+               char   *r, *w;
+               int     c1, c2;
+
+               r = w = namebuf;
+               do {
+                       c1 = *r++;
+                       if (c1 == '+')
+                               c1 = ' ';
+                       else if (c1 == '%') {
+                               if ((c1 = hexcode_to_int(*r++)) < 0)
+                                       goto out;
+                               if ((c2 = hexcode_to_int(*r++)) < 0)
+                                       goto out;
+                               c1 = (c1 << 4) | c2;
+                       }
+                       *w++ = c1;
+               } while (c1 != '\0');
+
                objname = namebuf;
+       }
 
        length = security_context_to_sid(scon, strlen(scon) + 1, &ssid);
        if (length)
index 102e9ec1b77a327477592b05a8e60933d348d7c1..d246aca3f4fbd43563bf01d20d78e28feb826ad8 100644 (file)
@@ -3222,6 +3222,9 @@ static int filename_trans_write(struct policydb *p, void *fp)
        __le32 buf[1];
        int rc;
 
+       if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
+               return 0;
+
        nel = 0;
        rc = hashtab_map(p->filename_trans, hashtab_cnt, &nel);
        if (rc)
index 162a864dba24f51c55156d0733fcae3a88df2da6..9fc2e15841c96f54edbefb24a96c40405d06bedd 100644 (file)
@@ -138,7 +138,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
        }
        if (need_dev) {
                /* Get mount point or device file. */
-               if (kern_path(dev_name, LOOKUP_FOLLOW, &path)) {
+               if (!dev_name || kern_path(dev_name, LOOKUP_FOLLOW, &path)) {
                        error = -ENOENT;
                        goto out;
                }
index 86ee16ca365e6fc612a4ad25baf6ecbf9fbc6893..440030818db70c88c582d0047790baed074297c9 100644 (file)
@@ -209,6 +209,7 @@ static void isight_packet(struct fw_iso_context *context, u32 cycle,
                isight->packet_index = -1;
                return;
        }
+       fw_iso_context_queue_flush(isight->context);
 
        if (++index >= QUEUE_LENGTH)
                index = 0;
index 2ca6f4f85b412a18502ac0f6370d19cc604d7d56..e3569bdd3b64e704f82c9e621110abe8e0853f8d 100644 (file)
@@ -27,7 +27,6 @@
 #include "hpioctl.h"
 
 #include <linux/pci.h>
-#include <linux/version.h>
 #include <linux/init.h>
 #include <linux/jiffies.h>
 #include <linux/slab.h>
index 5e619a84da061295fa4758e313935e89aea8009d..15f0161ce4a2342f9eb9b5eca86392a9481eacc2 100644 (file)
@@ -1440,6 +1440,14 @@ static struct snd_emu_chip_details emu_chip_details[] = {
         .ca0102_chip = 1,
         .spk71 = 1,
         .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */
+       /* EMU0404 PCIe */
+       {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40051102,
+        .driver = "Audigy2", .name = "E-mu 0404 PCIe [MAEM8984]",
+        .id = "EMU0404",
+        .emu10k2_chip = 1,
+        .ca0108_chip = 1,
+        .spk71 = 1,
+        .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 PCIe ver_03 */
        /* Note that all E-mu cards require kernel 2.6 or newer. */
        {.vendor = 0x1102, .device = 0x0008,
         .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]",
index f1de1bac042c260e5612a2f55f9ff13e79a30406..55f0647458c70aebb79028d3131e6f520d63eb19 100644 (file)
@@ -50,7 +50,12 @@ int snd_hda_enable_beep_device(struct hda_codec *codec, int enable);
 int snd_hda_attach_beep_device(struct hda_codec *codec, int nid);
 void snd_hda_detach_beep_device(struct hda_codec *codec);
 #else
-#define snd_hda_attach_beep_device(...)                0
-#define snd_hda_detach_beep_device(...)
+static inline int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
+{
+       return 0;
+}
+static inline void snd_hda_detach_beep_device(struct hda_codec *codec)
+{
+}
 #endif
 #endif
index 43fcfbd32847019931bc774bf00ecd20b2887a9b..d21191dcfe8809e27d8fe9da883b796b20d18322 100644 (file)
@@ -4883,7 +4883,6 @@ static const struct snd_pci_quirk alc880_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
        SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
        SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
-       SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST),
        SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
        SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
        SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
@@ -12600,6 +12599,7 @@ static const struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = {
  */
 enum {
        PINFIX_FSC_H270,
+       PINFIX_HP_Z200,
 };
 
 static const struct alc_fixup alc262_fixups[] = {
@@ -12612,9 +12612,17 @@ static const struct alc_fixup alc262_fixups[] = {
                        { }
                }
        },
+       [PINFIX_HP_Z200] = {
+               .type = ALC_FIXUP_PINS,
+               .v.pins = (const struct alc_pincfg[]) {
+                       { 0x16, 0x99130120 }, /* internal speaker */
+                       { }
+               }
+       },
 };
 
 static const struct snd_pci_quirk alc262_fixup_tbl[] = {
+       SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
        SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
        {}
 };
@@ -12731,6 +12739,8 @@ static const struct snd_pci_quirk alc262_cfg_tbl[] = {
                           ALC262_HP_BPC),
        SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1500, "HP z series",
                           ALC262_HP_BPC),
+       SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200",
+                          ALC262_AUTO),
        SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1700, "HP xw series",
                           ALC262_HP_BPC),
        SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
@@ -13316,9 +13326,8 @@ static void alc268_acer_lc_setup(struct hda_codec *codec)
        struct alc_spec *spec = codec->spec;
        spec->autocfg.hp_pins[0] = 0x15;
        spec->autocfg.speaker_pins[0] = 0x14;
-       spec->automute_mixer_nid[0] = 0x0f;
        spec->automute = 1;
-       spec->automute_mode = ALC_AUTOMUTE_MIXER;
+       spec->automute_mode = ALC_AUTOMUTE_AMP;
        spec->ext_mic.pin = 0x18;
        spec->ext_mic.mux_idx = 0;
        spec->int_mic.pin = 0x12;
@@ -13873,7 +13882,6 @@ static const struct snd_pci_quirk alc268_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
        SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
        SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA),
-       SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER),
        SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
        {}
 };
index 605c99e1e520de5d205a76046764d7e5f0f5a852..f43bb0eaed8b8e3c6f75ca08c7179267937c3be1 100644 (file)
@@ -745,12 +745,23 @@ static int via_independent_hp_put(struct snd_kcontrol *kcontrol,
        struct via_spec *spec = codec->spec;
        hda_nid_t nid = kcontrol->private_value;
        unsigned int pinsel = ucontrol->value.enumerated.item[0];
+       unsigned int parm0, parm1;
        /* Get Independent Mode index of headphone pin widget */
        spec->hp_independent_mode = spec->hp_independent_mode_index == pinsel
                ? 1 : 0;
-       if (spec->codec_type == VT1718S)
+       if (spec->codec_type == VT1718S) {
                snd_hda_codec_write(codec, nid, 0,
                                    AC_VERB_SET_CONNECT_SEL, pinsel ? 2 : 0);
+               /* Set correct mute switch for MW3 */
+               parm0 = spec->hp_independent_mode ?
+                              AMP_IN_UNMUTE(0) : AMP_IN_MUTE(0);
+               parm1 = spec->hp_independent_mode ?
+                              AMP_IN_MUTE(1) : AMP_IN_UNMUTE(1);
+               snd_hda_codec_write(codec, 0x1b, 0,
+                                   AC_VERB_SET_AMP_GAIN_MUTE, parm0);
+               snd_hda_codec_write(codec, 0x1b, 0,
+                                   AC_VERB_SET_AMP_GAIN_MUTE, parm1);
+       }
        else
                snd_hda_codec_write(codec, nid, 0,
                                    AC_VERB_SET_CONNECT_SEL, pinsel);
@@ -832,10 +843,13 @@ static int via_hp_build(struct hda_codec *codec)
        knew->subdevice = HDA_SUBDEV_NID_FLAG | nid;
        knew->private_value = nid;
 
-       knew = via_clone_control(spec, &via_hp_mixer[1]);
-       if (knew == NULL)
-               return -ENOMEM;
-       knew->subdevice = side_mute_channel(spec);
+       nid = side_mute_channel(spec);
+       if (nid) {
+               knew = via_clone_control(spec, &via_hp_mixer[1]);
+               if (knew == NULL)
+                       return -ENOMEM;
+               knew->subdevice = nid;
+       }
 
        return 0;
 }
@@ -4280,9 +4294,6 @@ static const struct hda_verb vt1718S_volume_init_verbs[] = {
        {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
        {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
        {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
-
-       /* Setup default input of Front HP to MW9 */
-       {0x28, AC_VERB_SET_CONNECT_SEL, 0x1},
        /* PW9 PW10 Output enable */
        {0x2d, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN},
        {0x2e, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_OUT_EN},
@@ -4291,10 +4302,10 @@ static const struct hda_verb vt1718S_volume_init_verbs[] = {
        /* Enable Boost Volume backdoor */
        {0x1, 0xf88, 0x8},
        /* MW0/1/2/3/4: un-mute index 0 (AOWx), mute index 1 (MW9) */
-       {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
        {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
        {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
+       {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
        {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
        {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
        {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
@@ -4304,8 +4315,6 @@ static const struct hda_verb vt1718S_volume_init_verbs[] = {
        /* set MUX1 = 2 (AOW4), MUX2 = 1 (AOW3) */
        {0x34, AC_VERB_SET_CONNECT_SEL, 0x2},
        {0x35, AC_VERB_SET_CONNECT_SEL, 0x1},
-       /* Unmute MW4's index 0 */
-       {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
        { }
 };
 
@@ -4453,6 +4462,19 @@ static int vt1718S_auto_create_multi_out_ctls(struct via_spec *spec,
                        if (err < 0)
                                return err;
                } else if (i == AUTO_SEQ_FRONT) {
+                       /* add control to mixer index 0 */
+                       err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
+                                             "Master Front Playback Volume",
+                                             HDA_COMPOSE_AMP_VAL(0x21, 3, 5,
+                                                                 HDA_INPUT));
+                       if (err < 0)
+                               return err;
+                       err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
+                                             "Master Front Playback Switch",
+                                             HDA_COMPOSE_AMP_VAL(0x21, 3, 5,
+                                                                 HDA_INPUT));
+                       if (err < 0)
+                               return err;
                        /* Front */
                        sprintf(name, "%s Playback Volume", chname[i]);
                        err = via_add_control(
index 34b24286d279d542e3d24e80a3531e8cf95bc8f5..2692e5ae5f2daa53822242c864a4f1b5ddf6a8ff 100644 (file)
@@ -445,7 +445,7 @@ static void lola_reset_setups(struct lola *chip)
        lola_setup_all_analog_gains(chip, PLAY, false); /* output, update */
 }
 
-static int lola_parse_tree(struct lola *chip)
+static int __devinit lola_parse_tree(struct lola *chip)
 {
        unsigned int val;
        int nid, err;
index 949691a876d3635798c6000da1b651d13684b1a6..3f08afc0f0d382b5b509c924abc2eb8532f4c822 100644 (file)
@@ -521,6 +521,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
 
 /* revisions >= 230 indicate AES32 card */
+#define HDSPM_MADI_OLD_REV     207
 #define HDSPM_MADI_REV         210
 #define HDSPM_RAYDAT_REV       211
 #define HDSPM_AIO_REV          212
@@ -1143,7 +1144,7 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm)
 
                /* if wordclock has synced freq and wordclock is valid */
                if ((status2 & HDSPM_wcLock) != 0 &&
-                               (status & HDSPM_SelSyncRef0) == 0) {
+                               (status2 & HDSPM_SelSyncRef0) == 0) {
 
                        rate_bits = status2 & HDSPM_wcFreqMask;
 
@@ -1639,12 +1640,14 @@ static int snd_hdspm_midi_input_read (struct hdspm_midi *hmidi)
                }
        }
        hmidi->pending = 0;
+       spin_unlock_irqrestore(&hmidi->lock, flags);
 
+       spin_lock_irqsave(&hmidi->hdspm->lock, flags);
        hmidi->hdspm->control_register |= hmidi->ie;
        hdspm_write(hmidi->hdspm, HDSPM_controlRegister,
                    hmidi->hdspm->control_register);
+       spin_unlock_irqrestore(&hmidi->hdspm->lock, flags);
 
-       spin_unlock_irqrestore (&hmidi->lock, flags);
        return snd_hdspm_midi_output_write (hmidi);
 }
 
@@ -6377,6 +6380,7 @@ static int __devinit snd_hdspm_create(struct snd_card *card,
 
        switch (hdspm->firmware_rev) {
        case HDSPM_MADI_REV:
+       case HDSPM_MADI_OLD_REV:
                hdspm->io_type = MADI;
                hdspm->card_name = "RME MADI";
                hdspm->midiPorts = 3;
index 3c2ee1bb73cdb8c85d21372b41d3598cf7b4bcad..6af23d06870f8a03d1a8a1910577d6a13fef67a3 100644 (file)
@@ -13,7 +13,6 @@
 
 #include <linux/module.h>
 #include <linux/moduleparam.h>
-#include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/delay.h>
index d8f130d39dd904c341d539fbe5457fe976b285b1..bb699bb55a502c041b9d47fff2f5c396c8c431c8 100644 (file)
@@ -11,9 +11,6 @@ menuconfig SND_IMX_SOC
 
 if SND_IMX_SOC
 
-config SND_MXC_SOC_SSI
-       tristate
-
 config SND_MXC_SOC_FIQ
        tristate
 
@@ -24,7 +21,6 @@ config SND_MXC_SOC_WM1133_EV1
        tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted"
        depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
        select SND_SOC_WM8350
-       select SND_MXC_SOC_SSI
        select SND_MXC_SOC_FIQ
        help
          Enable support for audio on the i.MX31ADS with the WM1133-EV1
@@ -34,7 +30,6 @@ config SND_SOC_MX27VIS_AIC32X4
        tristate "SoC audio support for Visstrim M10 boards"
        depends on MACH_IMX27_VISSTRIM_M10
        select SND_SOC_TVL320AIC32X4
-       select SND_MXC_SOC_SSI
        select SND_MXC_SOC_MX2
        help
          Say Y if you want to add support for SoC audio on Visstrim SM10
@@ -44,7 +39,6 @@ config SND_SOC_PHYCORE_AC97
        tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards"
        depends on MACH_PCM043 || MACH_PCA100
        select SND_SOC_WM9712
-       select SND_MXC_SOC_SSI
        select SND_MXC_SOC_FIQ
        help
          Say Y if you want to add support for SoC audio on Phytec phyCORE
@@ -57,7 +51,6 @@ config SND_SOC_EUKREA_TLV320
                || MACH_EUKREA_MBIMXSD35_BASEBOARD \
                || MACH_EUKREA_MBIMXSD51_BASEBOARD
        select SND_SOC_TLV320AIC23
-       select SND_MXC_SOC_SSI
        select SND_MXC_SOC_FIQ
        help
          Enable I2S based access to the TLV320AIC23B codec attached
index aab7765f401a0904397c9c22a801fc10670b73f4..4173b3d87f979d2757f1498bd503f15b07195542 100644 (file)
@@ -337,3 +337,5 @@ static void __exit snd_imx_pcm_exit(void)
        platform_driver_unregister(&imx_pcm_driver);
 }
 module_exit(snd_imx_pcm_exit);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:imx-pcm-audio");
index 5b13feca753732a6664969308e0794b161936aa8..61fceb09cdb5bbbf426270696bbf48b058f4d658 100644 (file)
@@ -774,4 +774,4 @@ module_exit(imx_ssi_exit);
 MODULE_AUTHOR("Sascha Hauer, <s.hauer@pengutronix.de>");
 MODULE_DESCRIPTION("i.MX I2S/ac97 SoC Interface");
 MODULE_LICENSE("GPL");
-
+MODULE_ALIAS("platform:imx-ssi");
index 2ce0b2d891d5081df50ed6c677ef835eab845b94..fab20a54e86340f1b5d2536cc9e3002613ef1c7d 100644 (file)
@@ -95,14 +95,14 @@ static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
-       if (dai->driver->playback.channels_min) {
+       if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
                ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_PLAYBACK);
                if (ret)
                        goto out;
        }
 
-       if (dai->driver->capture.channels_min) {
+       if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
                ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
                        SNDRV_PCM_STREAM_CAPTURE);
                if (ret)
index c005ceb70c9d1dfc624ffa11a13eec427e2215b9..039b9532b270cb8c1bb300efd0d1a7f385d95aa4 100644 (file)
@@ -409,9 +409,6 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
        codec->bulk_write_raw = snd_soc_hw_bulk_write_raw;
 
        switch (control) {
-       case SND_SOC_CUSTOM:
-               break;
-
        case SND_SOC_I2C:
 #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
                codec->hw_write = (hw_write_t)i2c_master_send;
index a91719d5918b69c6e76e577364c59f892f5768bd..1e3ae3327dd3a65431b4a517ab5b340dac2ee6f7 100644 (file)
@@ -270,7 +270,6 @@ static int usb6fire_fw_ezusb_upload(
        data = 0x00; /* resume ezusb cpu */
        ret = usb6fire_fw_ezusb_write(device, 0xa0, 0xe600, &data, 1);
        if (ret < 0) {
-               release_firmware(fw);
                snd_printk(KERN_ERR PREFIX "unable to upload ezusb "
                                "firmware %s: end message.\n", fwname);
                return ret;
index b137b25865cc986cc8f6bc8d21ca482e34b987cd..d144cdb2f15909acefec2f0c45ea0cd1ff523030 100644 (file)
@@ -395,12 +395,12 @@ static int usb6fire_pcm_open(struct snd_pcm_substream *alsa_sub)
        alsa_rt->hw = pcm_hw;
 
        if (alsa_sub->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-               if (rt->rate >= 0)
+               if (rt->rate < ARRAY_SIZE(rates))
                        alsa_rt->hw.rates = rates_alsaid[rt->rate];
                alsa_rt->hw.channels_max = OUT_N_CHANNELS;
                sub = &rt->playback;
        } else if (alsa_sub->stream == SNDRV_PCM_STREAM_CAPTURE) {
-               if (rt->rate >= 0)
+               if (rt->rate < ARRAY_SIZE(rates))
                        alsa_rt->hw.rates = rates_alsaid[rt->rate];
                alsa_rt->hw.channels_max = IN_N_CHANNELS;
                sub = &rt->capture;
index 032ba6398a5c696cc46b0957d9452b68aad2d660..940257b5774ec209d09e3b2d4fbee647ff86dd71 100644 (file)
@@ -633,7 +633,7 @@ prefix_SQ = $(subst ','\'',$(prefix))
 
 SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
 
-LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive $(EXTLIBS)
+LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
 
 ALL_CFLAGS += $(BASIC_CFLAGS)
 ALL_CFLAGS += $(ARCH_CFLAGS)
index 9c5fb4d93824e406d534631a39ca96ea48e415a0..ad73300f7bac6d1b11e4db0f1e121e0e26b0fb0c 100755 (executable)
@@ -23,7 +23,7 @@ if test -d ../../.git -o -f ../../.git &&
 then
        VN=$(echo "$VN" | sed -e 's/-/./g');
 else
-       VN=$(make -sC ../.. kernelversion)
+       VN=$(MAKEFLAGS= make -sC ../.. kernelversion)
 fi
 
 VN=$(expr "$VN" : v*'\(.*\)')
index 1e88485c16a04b755e68bb14510c3fd5cf368769..0a7ed5b5e281c88b321de87ced66a3d29ebb003d 100644 (file)
@@ -2187,6 +2187,7 @@ static const struct flag flags[] = {
        { "TASKLET_SOFTIRQ", 6 },
        { "SCHED_SOFTIRQ", 7 },
        { "HRTIMER_SOFTIRQ", 8 },
+       { "RCU_SOFTIRQ", 9 },
 
        { "HRTIMER_NORESTART", 0 },
        { "HRTIMER_RESTART", 1 },