]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 21 Apr 2011 16:57:56 +0000 (09:57 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 21 Apr 2011 16:57:56 +0000 (09:57 -0700)
* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
  agp: fix arbitrary kernel memory writes
  agp: fix OOM and buffer overflow
  drm/radeon/kms: fix IH writeback on r6xx+ on big endian machines

460 files changed:
Documentation/feature-removal-schedule.txt
Documentation/hwmon/max16064 [new file with mode: 0644]
Documentation/hwmon/max34440 [new file with mode: 0644]
Documentation/hwmon/max8688 [new file with mode: 0644]
Documentation/hwmon/pmbus
Documentation/hwmon/smm665
Documentation/hwmon/submitting-patches [new file with mode: 0644]
Documentation/input/event-codes.txt [new file with mode: 0644]
Documentation/md.txt
MAINTAINERS
Makefile
arch/alpha/kernel/Makefile
arch/alpha/kernel/core_mcpcia.c
arch/alpha/kernel/err_titan.c
arch/alpha/kernel/irq_alpha.c
arch/alpha/kernel/setup.c
arch/alpha/kernel/smc37c93x.c
arch/alpha/kernel/sys_wildfire.c
arch/alpha/kernel/time.c
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/common/Makefile
arch/arm/include/asm/cputype.h
arch/arm/include/asm/thread_notify.h
arch/arm/include/asm/unistd.h
arch/arm/kernel/Makefile
arch/arm/kernel/calls.S
arch/arm/kernel/elf.c
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/perf_event.c
arch/arm/kernel/process.c
arch/arm/kernel/traps.c
arch/arm/mach-mmp/include/mach/gpio.h
arch/arm/mach-mmp/include/mach/mfp-pxa168.h
arch/arm/mach-msm/board-qsd8x50.c
arch/arm/mach-msm/timer.c
arch/arm/mach-pxa/include/mach/gpio.h
arch/arm/mach-pxa/include/mach/irqs.h
arch/arm/mach-pxa/pxa25x.c
arch/arm/mach-pxa/pxa27x.c
arch/arm/mach-tegra/gpio.c
arch/arm/mach-tegra/tegra2_clocks.c
arch/arm/mm/mmap.c
arch/arm/mm/proc-arm920.S
arch/arm/mm/proc-arm926.S
arch/arm/mm/proc-sa1100.S
arch/arm/mm/proc-v6.S
arch/arm/mm/proc-v7.S
arch/arm/mm/proc-xsc3.S
arch/arm/mm/proc-xscale.S
arch/arm/plat-s5p/pm.c
arch/arm/plat-samsung/pm-check.c
arch/arm/plat-samsung/pm.c
arch/arm/vfp/vfpmodule.c
arch/avr32/include/asm/setup.h
arch/avr32/kernel/setup.c
arch/avr32/kernel/traps.c
arch/avr32/mach-at32ap/clock.c
arch/avr32/mach-at32ap/extint.c
arch/avr32/mach-at32ap/pio.c
arch/avr32/mach-at32ap/pm-at32ap700x.S
arch/blackfin/include/asm/system.h
arch/blackfin/kernel/gptimers.c
arch/blackfin/kernel/time-ts.c
arch/blackfin/mach-common/smp.c
arch/m68k/include/asm/unistd.h
arch/m68k/kernel/entry_mm.S
arch/m68k/kernel/syscalltable.S
arch/microblaze/Kconfig
arch/powerpc/Kconfig
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/pte-common.h
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/crash.c
arch/powerpc/kernel/ibmebus.c
arch/powerpc/kernel/legacy_serial.c
arch/powerpc/kernel/perf_event.c
arch/powerpc/kernel/time.c
arch/powerpc/platforms/powermac/smp.c
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/fsl_rio.c
arch/um/Kconfig.x86
arch/um/include/asm/bug.h [new file with mode: 0644]
arch/x86/include/asm/gart.h
arch/x86/include/asm/msr-index.h
arch/x86/kernel/aperture_64.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/perf_event_amd.c
arch/x86/kernel/pci-gart_64.c
arch/x86/kernel/smpboot.c
arch/x86/platform/ce4100/falconfalls.dts
arch/x86/platform/mrst/mrst.c
arch/x86/xen/Kconfig
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/x86/xen/setup.c
block/blk-core.c
block/blk-exec.c
block/blk-flush.c
block/blk-sysfs.c
block/cfq-iosched.c
block/elevator.c
drivers/amba/bus.c
drivers/base/platform.c
drivers/base/power/main.c
drivers/connector/connector.c
drivers/dma/fsldma.c
drivers/gpio/ml_ioh_gpio.c
drivers/gpio/pca953x.c
drivers/gpio/pch_gpio.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_tv.c
drivers/hwmon/pmbus_core.c
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/i2c-core.c
drivers/input/evdev.c
drivers/input/input.c
drivers/input/keyboard/twl4030_keypad.c
drivers/input/misc/xen-kbdfront.c
drivers/input/touchscreen/h3600_ts_input.c
drivers/leds/leds-regulator.c
drivers/md/dm-raid.c
drivers/md/md.c
drivers/md/md.h
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/md/raid5.h
drivers/media/video/videobuf-dma-contig.c
drivers/mfd/mfd-core.c
drivers/misc/sgi-gru/grufile.c
drivers/mtd/mtdswap.c
drivers/mtd/nand/atmel_nand.c
drivers/net/benet/be.h
drivers/net/benet/be_main.c
drivers/net/bna/bfa_ioc.c
drivers/net/bna/bfa_ioc.h
drivers/net/bna/bfa_ioc_ct.c
drivers/net/bna/bfi.h
drivers/net/bna/bnad.c
drivers/net/bnx2x/bnx2x_ethtool.c
drivers/net/bonding/bond_alb.c
drivers/net/bonding/bond_alb.h
drivers/net/can/mcp251x.c
drivers/net/can/mscan/mpc5xxx_can.c
drivers/net/loopback.c
drivers/net/mlx4/en_rx.c
drivers/net/mlx4/main.c
drivers/net/mlx4/mlx4.h
drivers/net/mlx4/sense.c
drivers/net/natsemi.c
drivers/net/netxen/netxen_nic.h
drivers/net/netxen/netxen_nic_main.c
drivers/net/pppoe.c
drivers/net/qlcnic/qlcnic.h
drivers/net/qlcnic/qlcnic_main.c
drivers/net/sfc/efx.c
drivers/net/sfc/io.h
drivers/net/sfc/net_driver.h
drivers/net/sfc/nic.c
drivers/net/sfc/nic.h
drivers/net/sfc/selftest.c
drivers/net/sfc/tx.c
drivers/net/sis900.c
drivers/net/smsc911x.c
drivers/net/stmmac/dwmac_lib.c
drivers/net/stmmac/stmmac_main.c
drivers/net/tokenring/3c359.c
drivers/net/tokenring/lanstreamer.c
drivers/net/tokenring/olympic.c
drivers/net/usb/smsc95xx.c
drivers/net/wireless/ath/ath9k/hif_usb.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/mac.c
drivers/net/wireless/ath/ath9k/mac.h
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/ath/regd_common.h
drivers/net/wireless/b43/dma.c
drivers/net/wireless/b43/dma.h
drivers/net/wireless/iwlegacy/Kconfig
drivers/net/wireless/iwlegacy/iwl-3945-hw.h
drivers/net/wireless/iwlegacy/iwl-4965-hw.h
drivers/net/wireless/iwlegacy/iwl-core.c
drivers/net/wireless/iwlegacy/iwl-eeprom.c
drivers/net/wireless/iwlegacy/iwl3945-base.c
drivers/net/wireless/iwlegacy/iwl4965-base.c
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-eeprom.h
drivers/net/wireless/mwl8k.c
drivers/net/wireless/p54/p54usb.c
drivers/net/wireless/p54/txrx.c
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rtlwifi/efuse.c
drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
drivers/net/wireless/rtlwifi/usb.c
drivers/net/wireless/wl12xx/sdio.c
drivers/net/wireless/wl12xx/spi.c
drivers/net/wireless/wl12xx/testmode.c
drivers/net/wireless/zd1211rw/zd_usb.c
drivers/net/wireless/zd1211rw/zd_usb.h
drivers/pci/Kconfig
drivers/pci/Makefile
drivers/pci/intel-iommu.c
drivers/pci/pci-driver.c
drivers/pci/setup-bus.c
drivers/pcmcia/pxa2xx_balloon3.c
drivers/pcmcia/pxa2xx_trizeps4.c
drivers/platform/x86/Kconfig
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/eeepc-wmi.c
drivers/platform/x86/intel_pmic_gpio.c
drivers/platform/x86/samsung-laptop.c
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/rapidio/rio.c
drivers/rapidio/switches/idt_gen2.c
drivers/rtc/class.c
drivers/rtc/interface.c
drivers/rtc/rtc-bfin.c
drivers/rtc/rtc-mc13xxx.c
drivers/rtc/rtc-omap.c
drivers/rtc/rtc-s3c.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_transport_fc.c
drivers/spi/amba-pl022.c
drivers/spi/dw_spi.c
drivers/spi/pxa2xx_spi.c
drivers/spi/spi_bfin5xx.c
drivers/staging/Kconfig
drivers/staging/Makefile
drivers/staging/samsung-laptop/Kconfig [deleted file]
drivers/staging/samsung-laptop/Makefile [deleted file]
drivers/staging/samsung-laptop/TODO [deleted file]
drivers/staging/samsung-laptop/samsung-laptop.c [deleted file]
drivers/usb/Kconfig
drivers/usb/core/devices.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/gadget/f_audio.c
drivers/usb/gadget/f_eem.c
drivers/usb/gadget/fsl_qe_udc.c
drivers/usb/gadget/inode.c
drivers/usb/gadget/pch_udc.c
drivers/usb/gadget/r8a66597-udc.c
drivers/usb/host/ehci-q.c
drivers/usb/host/isp1760-hcd.c
drivers/usb/host/ohci-au1xxx.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/musb/Kconfig
drivers/usb/musb/blackfin.c
drivers/usb/musb/cppi_dma.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_core.h
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/musbhsdma.c
drivers/usb/musb/omap2430.c
drivers/usb/musb/ux500.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/option.c
drivers/usb/serial/qcserial.c
drivers/video/pxafb.c
drivers/xen/events.c
drivers/xen/manage.c
fs/9p/fid.c
fs/9p/v9fs.h
fs/9p/vfs_dentry.c
fs/9p/vfs_inode_dotl.c
fs/9p/vfs_super.c
fs/binfmt_elf.c
fs/btrfs/acl.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/btrfs/xattr.c
fs/cifs/README
fs/cifs/cache.c
fs/cifs/cifs_debug.c
fs/cifs/cifs_spnego.c
fs/cifs/cifs_unicode.c
fs/cifs/cifs_unicode.h
fs/cifs/cifsencrypt.c
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/cifs/file.c
fs/cifs/link.c
fs/cifs/misc.c
fs/cifs/sess.c
fs/dcache.c
fs/ext4/ext4_jbd2.h
fs/ext4/fsync.c
fs/ext4/inode.c
fs/ext4/super.c
fs/fhandle.c
fs/filesystems.c
fs/gfs2/aops.c
fs/gfs2/dir.c
fs/gfs2/file.c
fs/gfs2/glops.c
fs/gfs2/inode.c
fs/gfs2/inode.h
fs/gfs2/ops_fstype.c
fs/gfs2/rgrp.c
fs/gfs2/super.c
fs/jbd2/commit.c
fs/jbd2/journal.c
fs/namei.c
fs/namespace.c
fs/nfs/write.c
fs/nfsd/lockd.c
fs/nfsd/nfs4state.c
fs/nfsd/vfs.c
fs/partitions/ldm.c
fs/proc/base.c
fs/ramfs/file-nommu.c
fs/ubifs/debug.h
fs/ubifs/file.c
fs/xattr.c
fs/xfs/linux-2.6/xfs_buf.c
fs/xfs/linux-2.6/xfs_message.c
fs/xfs/linux-2.6/xfs_message.h
fs/xfs/linux-2.6/xfs_super.c
fs/xfs/linux-2.6/xfs_sync.c
fs/xfs/linux-2.6/xfs_sync.h
fs/xfs/quota/xfs_qm.c
fs/xfs/quota/xfs_qm.h
fs/xfs/quota/xfs_qm_syscalls.c
fs/xfs/xfs_alloc.c
fs/xfs/xfs_inode_item.c
fs/xfs/xfs_itable.c
fs/xfs/xfs_log.c
fs/xfs/xfs_log_priv.h
fs/xfs/xfs_mount.h
fs/xfs/xfs_trans_ail.c
fs/xfs/xfs_trans_priv.h
include/linux/blkdev.h
include/linux/can/platform/mcp251x.h
include/linux/device-mapper.h
include/linux/input.h
include/linux/input/mt.h
include/linux/memcontrol.h
include/linux/mfd/core.h
include/linux/netfilter.h
include/linux/netfilter/ipset/ip_set.h
include/linux/netfilter/ipset/ip_set_ahash.h
include/linux/pid.h
include/linux/platform_device.h
include/linux/posix-clock.h
include/linux/rio.h
include/linux/rio_ids.h
include/linux/rtc.h
include/linux/sched.h
include/linux/suspend.h
include/linux/usb/usbnet.h
include/linux/vmstat.h
include/net/9p/9p.h
include/net/9p/client.h
include/net/ip_vs.h
include/net/mac80211.h
include/net/route.h
include/trace/events/block.h
kernel/futex.c
kernel/perf_event.c
kernel/pid.c
kernel/power/Kconfig
kernel/sched.c
kernel/sched_fair.c
kernel/time/posix-clock.c
kernel/trace/blktrace.c
lib/kstrtox.c
lib/test-kstrtox.c
mm/huge_memory.c
mm/memory.c
mm/memory_hotplug.c
mm/mlock.c
mm/mmap.c
mm/oom_kill.c
mm/page_alloc.c
mm/shmem.c
mm/vmscan.c
mm/vmstat.c
net/9p/client.c
net/9p/protocol.c
net/9p/trans_common.c
net/9p/trans_virtio.c
net/bridge/br_netfilter.c
net/caif/cfdgml.c
net/caif/cfmuxl.c
net/ceph/osd_client.c
net/core/dev.c
net/dsa/mv88e6131.c
net/dsa/mv88e6xxx.h
net/ieee802154/Makefile
net/ipv4/inet_connection_sock.c
net/ipv4/inetpeer.c
net/ipv4/ip_options.c
net/ipv4/netfilter.c
net/ipv4/route.c
net/ipv4/sysctl_net_ipv4.c
net/ipv4/xfrm4_policy.c
net/ipv6/inet6_connection_sock.c
net/ipv6/netfilter.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/irda/af_irda.c
net/llc/llc_input.c
net/mac80211/rx.c
net/netfilter/Kconfig
net/netfilter/ipset/ip_set_bitmap_ip.c
net/netfilter/ipset/ip_set_bitmap_ipmac.c
net/netfilter/ipset/ip_set_bitmap_port.c
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipset/ip_set_list_set.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/nf_conntrack_h323_asn1.c
net/netfilter/nf_conntrack_h323_main.c
net/netfilter/xt_TCPMSS.c
net/netfilter/xt_addrtype.c
net/netfilter/xt_conntrack.c
net/netfilter/xt_set.c
net/sctp/associola.c
sound/arm/pxa2xx-pcm-lib.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/soc/pxa/pxa2xx-pcm.c
sound/soc/pxa/zylonite.c
sound/soc/soc-core.c
sound/usb/midi.c
tools/perf/builtin-record.c
tools/perf/builtin-stat.c
tools/perf/builtin-test.c
tools/perf/builtin-top.c
tools/perf/util/cgroup.c
tools/perf/util/evlist.c
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/python.c
tools/perf/util/ui/browsers/annotate.c
tools/perf/util/ui/browsers/hists.c

index 274b32d12532a2e0e3814e70940b39721dde864a..492e81df296835e04ff6195304b3a32931e466c6 100644 (file)
@@ -387,26 +387,6 @@ Who:       Tejun Heo <tj@kernel.org>
 
 ----------------------------
 
-What:  Support for lcd_switch and display_get in asus-laptop driver
-When:  March 2010
-Why:   These two features use non-standard interfaces. There are the
-       only features that really need multiple path to guess what's
-       the right method name on a specific laptop.
-
-       Removing them will allow to remove a lot of code an significantly
-       clean the drivers.
-
-       This will affect the backlight code which won't be able to know
-       if the backlight is on or off. The platform display file will also be
-       write only (like the one in eeepc-laptop).
-
-       This should'nt affect a lot of user because they usually know
-       when their display is on or off.
-
-Who:   Corentin Chary <corentin.chary@gmail.com>
-
-----------------------------
-
 What:  sysfs-class-rfkill state file
 When:  Feb 2014
 Files: net/rfkill/core.c
diff --git a/Documentation/hwmon/max16064 b/Documentation/hwmon/max16064
new file mode 100644 (file)
index 0000000..4172899
--- /dev/null
@@ -0,0 +1,62 @@
+Kernel driver max16064
+======================
+
+Supported chips:
+  * Maxim MAX16064
+    Prefix: 'max16064'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX16064.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports hardware montoring for Maxim MAX16064 Quad Power-Supply
+Controller with Active-Voltage Output Control and PMBus Interface.
+
+The driver is a client driver to the core PMBus driver.
+Please see Documentation/hwmon/pmbus for details on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices for
+details.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported. Limits are read-write; all other
+attributes are read-only.
+
+in[1-4]_label          "vout[1-4]"
+in[1-4]_input          Measured voltage. From READ_VOUT register.
+in[1-4]_min            Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
+in[1-4]_max            Maximum voltage. From VOUT_OV_WARN_LIMIT register.
+in[1-4]_lcrit          Critical minumum Voltage. VOUT_UV_FAULT_LIMIT register.
+in[1-4]_crit           Critical maximum voltage. From VOUT_OV_FAULT_LIMIT register.
+in[1-4]_min_alarm      Voltage low alarm. From VOLTAGE_UV_WARNING status.
+in[1-4]_max_alarm      Voltage high alarm. From VOLTAGE_OV_WARNING status.
+in[1-4]_lcrit_alarm    Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
+in[1-4]_crit_alarm     Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
+
+temp1_input            Measured temperature. From READ_TEMPERATURE_1 register.
+temp1_max              Maximum temperature. From OT_WARN_LIMIT register.
+temp1_crit             Critical high temperature. From OT_FAULT_LIMIT register.
+temp1_max_alarm                Chip temperature high alarm. Set by comparing
+                       READ_TEMPERATURE_1 with OT_WARN_LIMIT if TEMP_OT_WARNING
+                       status is set.
+temp1_crit_alarm       Chip temperature critical high alarm. Set by comparing
+                       READ_TEMPERATURE_1 with OT_FAULT_LIMIT if TEMP_OT_FAULT
+                       status is set.
diff --git a/Documentation/hwmon/max34440 b/Documentation/hwmon/max34440
new file mode 100644 (file)
index 0000000..6c525dd
--- /dev/null
@@ -0,0 +1,79 @@
+Kernel driver max34440
+======================
+
+Supported chips:
+  * Maxim MAX34440
+    Prefixes: 'max34440'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34440.pdf
+  * Maxim MAX34441
+    PMBus 5-Channel Power-Supply Manager and Intelligent Fan Controller
+    Prefixes: 'max34441'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34441.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports hardware montoring for Maxim MAX34440 PMBus 6-Channel
+Power-Supply Manager and MAX34441 PMBus 5-Channel Power-Supply Manager
+and Intelligent Fan Controller.
+
+The driver is a client driver to the core PMBus driver. Please see
+Documentation/hwmon/pmbus for details on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices for
+details.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported. Limits are read-write; all other
+attributes are read-only.
+
+in[1-6]_label          "vout[1-6]".
+in[1-6]_input          Measured voltage. From READ_VOUT register.
+in[1-6]_min            Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
+in[1-6]_max            Maximum voltage. From VOUT_OV_WARN_LIMIT register.
+in[1-6]_lcrit          Critical minumum Voltage. VOUT_UV_FAULT_LIMIT register.
+in[1-6]_crit           Critical maximum voltage. From VOUT_OV_FAULT_LIMIT register.
+in[1-6]_min_alarm      Voltage low alarm. From VOLTAGE_UV_WARNING status.
+in[1-6]_max_alarm      Voltage high alarm. From VOLTAGE_OV_WARNING status.
+in[1-6]_lcrit_alarm    Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
+in[1-6]_crit_alarm     Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
+
+curr[1-6]_label                "iout[1-6]".
+curr[1-6]_input                Measured current. From READ_IOUT register.
+curr[1-6]_max          Maximum current. From IOUT_OC_WARN_LIMIT register.
+curr[1-6]_crit         Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
+curr[1-6]_max_alarm    Current high alarm. From IOUT_OC_WARNING status.
+curr[1-6]_crit_alarm   Current critical high alarm. From IOUT_OC_FAULT status.
+
+                       in6 and curr6 attributes only exist for MAX34440.
+
+temp[1-8]_input                Measured temperatures. From READ_TEMPERATURE_1 register.
+                       temp1 is the chip's internal temperature. temp2..temp5
+                       are remote I2C temperature sensors. For MAX34441, temp6
+                       is a remote thermal-diode sensor. For MAX34440, temp6..8
+                       are remote I2C temperature sensors.
+temp[1-8]_max          Maximum temperature. From OT_WARN_LIMIT register.
+temp[1-8]_crit         Critical high temperature. From OT_FAULT_LIMIT register.
+temp[1-8]_max_alarm    Temperature high alarm.
+temp[1-8]_crit_alarm   Temperature critical high alarm.
+
+                       temp7 and temp8 attributes only exist for MAX34440.
diff --git a/Documentation/hwmon/max8688 b/Documentation/hwmon/max8688
new file mode 100644 (file)
index 0000000..0ddd3a4
--- /dev/null
@@ -0,0 +1,69 @@
+Kernel driver max8688
+=====================
+
+Supported chips:
+  * Maxim MAX8688
+    Prefix: 'max8688'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX8688.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports hardware montoring for Maxim MAX8688 Digital Power-Supply
+Controller/Monitor with PMBus Interface.
+
+The driver is a client driver to the core PMBus driver. Please see
+Documentation/hwmon/pmbus for details on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices for
+details.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported. Limits are read-write; all other
+attributes are read-only.
+
+in1_label              "vout1"
+in1_input              Measured voltage. From READ_VOUT register.
+in1_min                        Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
+in1_max                        Maximum voltage. From VOUT_OV_WARN_LIMIT register.
+in1_lcrit              Critical minumum Voltage. VOUT_UV_FAULT_LIMIT register.
+in1_crit               Critical maximum voltage. From VOUT_OV_FAULT_LIMIT register.
+in1_min_alarm          Voltage low alarm. From VOLTAGE_UV_WARNING status.
+in1_max_alarm          Voltage high alarm. From VOLTAGE_OV_WARNING status.
+in1_lcrit_alarm                Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
+in1_crit_alarm         Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
+
+curr1_label            "iout1"
+curr1_input            Measured current. From READ_IOUT register.
+curr1_max              Maximum current. From IOUT_OC_WARN_LIMIT register.
+curr1_crit             Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
+curr1_max_alarm                Current high alarm. From IOUT_OC_WARN_LIMIT register.
+curr1_crit_alarm       Current critical high alarm. From IOUT_OC_FAULT status.
+
+temp1_input            Measured temperature. From READ_TEMPERATURE_1 register.
+temp1_max              Maximum temperature. From OT_WARN_LIMIT register.
+temp1_crit             Critical high temperature. From OT_FAULT_LIMIT register.
+temp1_max_alarm                Chip temperature high alarm. Set by comparing
+                       READ_TEMPERATURE_1 with OT_WARN_LIMIT if TEMP_OT_WARNING
+                       status is set.
+temp1_crit_alarm       Chip temperature critical high alarm. Set by comparing
+                       READ_TEMPERATURE_1 with OT_FAULT_LIMIT if TEMP_OT_FAULT
+                       status is set.
index dc4933e96344809ea8bf4f65ba607142426d4e69..5e462fc7f99b5f2e0f42c4edb92ebc1ac6c7571f 100644 (file)
@@ -13,26 +13,6 @@ Supported chips:
     Prefix: 'ltc2978'
     Addresses scanned: -
     Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf
-  * Maxim MAX16064
-    Quad Power-Supply Controller
-    Prefix: 'max16064'
-    Addresses scanned: -
-    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX16064.pdf
-  * Maxim MAX34440
-    PMBus 6-Channel Power-Supply Manager
-    Prefixes: 'max34440'
-    Addresses scanned: -
-    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34440.pdf
-  * Maxim MAX34441
-    PMBus 5-Channel Power-Supply Manager and Intelligent Fan Controller
-    Prefixes: 'max34441'
-    Addresses scanned: -
-    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34441.pdf
-  * Maxim MAX8688
-    Digital Power-Supply Controller/Monitor
-    Prefix: 'max8688'
-    Addresses scanned: -
-    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX8688.pdf
   * Generic PMBus devices
     Prefix: 'pmbus'
     Addresses scanned: -
@@ -175,11 +155,13 @@ currX_crit                Critical maximum current.
                        From IIN_OC_FAULT_LIMIT or IOUT_OC_FAULT_LIMIT register.
 currX_alarm            Current high alarm.
                        From IIN_OC_WARNING or IOUT_OC_WARNING status.
+currX_max_alarm                Current high alarm.
+                       From IIN_OC_WARN_LIMIT or IOUT_OC_WARN_LIMIT status.
 currX_lcrit_alarm      Output current critical low alarm.
                        From IOUT_UC_FAULT status.
 currX_crit_alarm       Current critical high alarm.
                        From IIN_OC_FAULT or IOUT_OC_FAULT status.
-currX_label            "iin" or "vinY"
+currX_label            "iin" or "ioutY"
 
 powerX_input           Measured power. From READ_PIN or READ_POUT register.
 powerX_cap             Output power cap. From POUT_MAX register.
@@ -193,13 +175,13 @@ powerX_crit_alarm Output power critical high alarm.
                        From POUT_OP_FAULT status.
 powerX_label           "pin" or "poutY"
 
-tempX_input            Measured tempererature.
+tempX_input            Measured temperature.
                        From READ_TEMPERATURE_X register.
-tempX_min              Mimimum tempererature. From UT_WARN_LIMIT register.
-tempX_max              Maximum tempererature. From OT_WARN_LIMIT register.
-tempX_lcrit            Critical low tempererature.
+tempX_min              Mimimum temperature. From UT_WARN_LIMIT register.
+tempX_max              Maximum temperature. From OT_WARN_LIMIT register.
+tempX_lcrit            Critical low temperature.
                        From UT_FAULT_LIMIT register.
-tempX_crit             Critical high tempererature.
+tempX_crit             Critical high temperature.
                        From OT_FAULT_LIMIT register.
 tempX_min_alarm                Chip temperature low alarm. Set by comparing
                        READ_TEMPERATURE_X with UT_WARN_LIMIT if
index 3820fc9ca52d25ae4c3ed9a7e6d7f04fcb092bee..59e316140542017517be09171448fc4e6e16d28e 100644 (file)
@@ -150,8 +150,8 @@ in8_crit_alarm              Channel F critical alarm
 in9_crit_alarm         AIN1 critical alarm
 in10_crit_alarm                AIN2 critical alarm
 
-temp1_input            Chip tempererature
-temp1_min              Mimimum chip tempererature
-temp1_max              Maximum chip tempererature
-temp1_crit             Critical chip tempererature
+temp1_input            Chip temperature
+temp1_min              Mimimum chip temperature
+temp1_max              Maximum chip temperature
+temp1_crit             Critical chip temperature
 temp1_crit_alarm       Temperature critical alarm
diff --git a/Documentation/hwmon/submitting-patches b/Documentation/hwmon/submitting-patches
new file mode 100644 (file)
index 0000000..86f42e8
--- /dev/null
@@ -0,0 +1,109 @@
+       How to Get Your Patch Accepted Into the Hwmon Subsystem
+       -------------------------------------------------------
+
+This text is is a collection of suggestions for people writing patches or
+drivers for the hwmon subsystem. Following these suggestions will greatly
+increase the chances of your change being accepted.
+
+
+1. General
+----------
+
+* It should be unnecessary to mention, but please read and follow
+    Documentation/SubmitChecklist
+    Documentation/SubmittingDrivers
+    Documentation/SubmittingPatches
+    Documentation/CodingStyle
+
+* If your patch generates checkpatch warnings, please refrain from explanations
+  such as "I don't like that coding style". Keep in mind that each unnecessary
+  warning helps hiding a real problem. If you don't like the kernel coding
+  style, don't write kernel drivers.
+
+* Please test your patch thoroughly. We are not your test group.
+  Sometimes a patch can not or not completely be tested because of missing
+  hardware. In such cases, you should test-build the code on at least one
+  architecture. If run-time testing was not achieved, it should be written
+  explicitly below the patch header.
+
+* If your patch (or the driver) is affected by configuration options such as
+  CONFIG_SMP or CONFIG_HOTPLUG, make sure it compiles for all configuration
+  variants.
+
+
+2. Adding functionality to existing drivers
+-------------------------------------------
+
+* Make sure the documentation in Documentation/hwmon/<driver_name> is up to
+  date.
+
+* Make sure the information in Kconfig is up to date.
+
+* If the added functionality requires some cleanup or structural changes, split
+  your patch into a cleanup part and the actual addition. This makes it easier
+  to review your changes, and to bisect any resulting problems.
+
+* Never mix bug fixes, cleanup, and functional enhancements in a single patch.
+
+
+3. New drivers
+--------------
+
+* Running your patch or driver file(s) through checkpatch does not mean its
+  formatting is clean. If unsure about formatting in your new driver, run it
+  through Lindent. Lindent is not perfect, and you may have to do some minor
+  cleanup, but it is a good start.
+
+* Consider adding yourself to MAINTAINERS.
+
+* Document the driver in Documentation/hwmon/<driver_name>.
+
+* Add the driver to Kconfig and Makefile in alphabetical order.
+
+* Make sure that all dependencies are listed in Kconfig. For new drivers, it
+  is most likely prudent to add a dependency on EXPERIMENTAL.
+
+* Avoid forward declarations if you can. Rearrange the code if necessary.
+
+* Avoid calculations in macros and macro-generated functions. While such macros
+  may save a line or so in the source, it obfuscates the code and makes code
+  review more difficult. It may also result in code which is more complicated
+  than necessary. Use inline functions or just regular functions instead.
+
+* If the driver has a detect function, make sure it is silent. Debug messages
+  and messages printed after a successful detection are acceptable, but it
+  must not print messages such as "Chip XXX not found/supported".
+
+  Keep in mind that the detect function will run for all drivers supporting an
+  address if a chip is detected on that address. Unnecessary messages will just
+  pollute the kernel log and not provide any value.
+
+* Provide a detect function if and only if a chip can be detected reliably.
+
+* Avoid writing to chip registers in the detect function. If you have to write,
+  only do it after you have already gathered enough data to be certain that the
+  detection is going to be successful.
+
+  Keep in mind that the chip might not be what your driver believes it is, and
+  writing to it might cause a bad misconfiguration.
+
+* Make sure there are no race conditions in the probe function. Specifically,
+  completely initialize your chip first, then create sysfs entries and register
+  with the hwmon subsystem.
+
+* Do not provide support for deprecated sysfs attributes.
+
+* Do not create non-standard attributes unless really needed. If you have to use
+  non-standard attributes, or you believe you do, discuss it on the mailing list
+  first. Either case, provide a detailed explanation why you need the
+  non-standard attribute(s).
+  Standard attributes are specified in Documentation/hwmon/sysfs-interface.
+
+* When deciding which sysfs attributes to support, look at the chip's
+  capabilities. While we do not expect your driver to support everything the
+  chip may offer, it should at least support all limits and alarms.
+
+* Last but not least, please check if a driver for your chip already exists
+  before starting to write a new driver. Especially for temperature sensors,
+  new chips are often variants of previously released chips. In some cases,
+  a presumably new chip may simply have been relabeled.
diff --git a/Documentation/input/event-codes.txt b/Documentation/input/event-codes.txt
new file mode 100644 (file)
index 0000000..23fcb05
--- /dev/null
@@ -0,0 +1,262 @@
+The input protocol uses a map of types and codes to express input device values
+to userspace. This document describes the types and codes and how and when they
+may be used.
+
+A single hardware event generates multiple input events. Each input event
+contains the new value of a single data item. A special event type, EV_SYN, is
+used to separate input events into packets of input data changes occurring at
+the same moment in time. In the following, the term "event" refers to a single
+input event encompassing a type, code, and value.
+
+The input protocol is a stateful protocol. Events are emitted only when values
+of event codes have changed. However, the state is maintained within the Linux
+input subsystem; drivers do not need to maintain the state and may attempt to
+emit unchanged values without harm. Userspace may obtain the current state of
+event code values using the EVIOCG* ioctls defined in linux/input.h. The event
+reports supported by a device are also provided by sysfs in
+class/input/event*/device/capabilities/, and the properties of a device are
+provided in class/input/event*/device/properties.
+
+Types:
+==========
+Types are groupings of codes under a logical input construct. Each type has a
+set of applicable codes to be used in generating events. See the Codes section
+for details on valid codes for each type.
+
+* EV_SYN:
+  - Used as markers to separate events. Events may be separated in time or in
+    space, such as with the multitouch protocol.
+
+* EV_KEY:
+  - Used to describe state changes of keyboards, buttons, or other key-like
+    devices.
+
+* EV_REL:
+  - Used to describe relative axis value changes, e.g. moving the mouse 5 units
+    to the left.
+
+* EV_ABS:
+  - Used to describe absolute axis value changes, e.g. describing the
+    coordinates of a touch on a touchscreen.
+
+* EV_MSC:
+  - Used to describe miscellaneous input data that do not fit into other types.
+
+* EV_SW:
+  - Used to describe binary state input switches.
+
+* EV_LED:
+  - Used to turn LEDs on devices on and off.
+
+* EV_SND:
+  - Used to output sound to devices.
+
+* EV_REP:
+  - Used for autorepeating devices.
+
+* EV_FF:
+  - Used to send force feedback commands to an input device.
+
+* EV_PWR:
+  - A special type for power button and switch input.
+
+* EV_FF_STATUS:
+  - Used to receive force feedback device status.
+
+Codes:
+==========
+Codes define the precise type of event.
+
+EV_SYN:
+----------
+EV_SYN event values are undefined. Their usage is defined only by when they are
+sent in the evdev event stream.
+
+* SYN_REPORT:
+  - Used to synchronize and separate events into packets of input data changes
+    occurring at the same moment in time. For example, motion of a mouse may set
+    the REL_X and REL_Y values for one motion, then emit a SYN_REPORT. The next
+    motion will emit more REL_X and REL_Y values and send another SYN_REPORT.
+
+* SYN_CONFIG:
+  - TBD
+
+* SYN_MT_REPORT:
+  - Used to synchronize and separate touch events. See the
+    multi-touch-protocol.txt document for more information.
+
+* SYN_DROPPED:
+  - Used to indicate buffer overrun in the evdev client's event queue.
+    Client should ignore all events up to and including next SYN_REPORT
+    event and query the device (using EVIOCG* ioctls) to obtain its
+    current state.
+
+EV_KEY:
+----------
+EV_KEY events take the form KEY_<name> or BTN_<name>. For example, KEY_A is used
+to represent the 'A' key on a keyboard. When a key is depressed, an event with
+the key's code is emitted with value 1. When the key is released, an event is
+emitted with value 0. Some hardware send events when a key is repeated. These
+events have a value of 2. In general, KEY_<name> is used for keyboard keys, and
+BTN_<name> is used for other types of momentary switch events.
+
+A few EV_KEY codes have special meanings:
+
+* BTN_TOOL_<name>:
+  - These codes are used in conjunction with input trackpads, tablets, and
+    touchscreens. These devices may be used with fingers, pens, or other tools.
+    When an event occurs and a tool is used, the corresponding BTN_TOOL_<name>
+    code should be set to a value of 1. When the tool is no longer interacting
+    with the input device, the BTN_TOOL_<name> code should be reset to 0. All
+    trackpads, tablets, and touchscreens should use at least one BTN_TOOL_<name>
+    code when events are generated.
+
+* BTN_TOUCH:
+    BTN_TOUCH is used for touch contact. While an input tool is determined to be
+    within meaningful physical contact, the value of this property must be set
+    to 1. Meaningful physical contact may mean any contact, or it may mean
+    contact conditioned by an implementation defined property. For example, a
+    touchpad may set the value to 1 only when the touch pressure rises above a
+    certain value. BTN_TOUCH may be combined with BTN_TOOL_<name> codes. For
+    example, a pen tablet may set BTN_TOOL_PEN to 1 and BTN_TOUCH to 0 while the
+    pen is hovering over but not touching the tablet surface.
+
+Note: For appropriate function of the legacy mousedev emulation driver,
+BTN_TOUCH must be the first evdev code emitted in a synchronization frame.
+
+Note: Historically a touch device with BTN_TOOL_FINGER and BTN_TOUCH was
+interpreted as a touchpad by userspace, while a similar device without
+BTN_TOOL_FINGER was interpreted as a touchscreen. For backwards compatibility
+with current userspace it is recommended to follow this distinction. In the
+future, this distinction will be deprecated and the device properties ioctl
+EVIOCGPROP, defined in linux/input.h, will be used to convey the device type.
+
+* BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP, BTN_TOOL_TRIPLETAP, BTN_TOOL_QUADTAP:
+  - These codes denote one, two, three, and four finger interaction on a
+    trackpad or touchscreen. For example, if the user uses two fingers and moves
+    them on the touchpad in an effort to scroll content on screen,
+    BTN_TOOL_DOUBLETAP should be set to value 1 for the duration of the motion.
+    Note that all BTN_TOOL_<name> codes and the BTN_TOUCH code are orthogonal in
+    purpose. A trackpad event generated by finger touches should generate events
+    for one code from each group. At most only one of these BTN_TOOL_<name>
+    codes should have a value of 1 during any synchronization frame.
+
+Note: Historically some drivers emitted multiple of the finger count codes with
+a value of 1 in the same synchronization frame. This usage is deprecated.
+
+Note: In multitouch drivers, the input_mt_report_finger_count() function should
+be used to emit these codes. Please see multi-touch-protocol.txt for details.
+
+EV_REL:
+----------
+EV_REL events describe relative changes in a property. For example, a mouse may
+move to the left by a certain number of units, but its absolute position in
+space is unknown. If the absolute position is known, EV_ABS codes should be used
+instead of EV_REL codes.
+
+A few EV_REL codes have special meanings:
+
+* REL_WHEEL, REL_HWHEEL:
+  - These codes are used for vertical and horizontal scroll wheels,
+    respectively.
+
+EV_ABS:
+----------
+EV_ABS events describe absolute changes in a property. For example, a touchpad
+may emit coordinates for a touch location.
+
+A few EV_ABS codes have special meanings:
+
+* ABS_DISTANCE:
+  - Used to describe the distance of a tool from an interaction surface. This
+    event should only be emitted while the tool is hovering, meaning in close
+    proximity of the device and while the value of the BTN_TOUCH code is 0. If
+    the input device may be used freely in three dimensions, consider ABS_Z
+    instead.
+
+* ABS_MT_<name>:
+  - Used to describe multitouch input events. Please see
+    multi-touch-protocol.txt for details.
+
+EV_SW:
+----------
+EV_SW events describe stateful binary switches. For example, the SW_LID code is
+used to denote when a laptop lid is closed.
+
+Upon binding to a device or resuming from suspend, a driver must report
+the current switch state. This ensures that the device, kernel, and userspace
+state is in sync.
+
+Upon resume, if the switch state is the same as before suspend, then the input
+subsystem will filter out the duplicate switch state reports. The driver does
+not need to keep the state of the switch at any time.
+
+EV_MSC:
+----------
+EV_MSC events are used for input and output events that do not fall under other
+categories.
+
+EV_LED:
+----------
+EV_LED events are used for input and output to set and query the state of
+various LEDs on devices.
+
+EV_REP:
+----------
+EV_REP events are used for specifying autorepeating events.
+
+EV_SND:
+----------
+EV_SND events are used for sending sound commands to simple sound output
+devices.
+
+EV_FF:
+----------
+EV_FF events are used to initialize a force feedback capable device and to cause
+such device to feedback.
+
+EV_PWR:
+----------
+EV_PWR events are a special type of event used specifically for power
+mangement. Its usage is not well defined. To be addressed later.
+
+Guidelines:
+==========
+The guidelines below ensure proper single-touch and multi-finger functionality.
+For multi-touch functionality, see the multi-touch-protocol.txt document for
+more information.
+
+Mice:
+----------
+REL_{X,Y} must be reported when the mouse moves. BTN_LEFT must be used to report
+the primary button press. BTN_{MIDDLE,RIGHT,4,5,etc.} should be used to report
+further buttons of the device. REL_WHEEL and REL_HWHEEL should be used to report
+scroll wheel events where available.
+
+Touchscreens:
+----------
+ABS_{X,Y} must be reported with the location of the touch. BTN_TOUCH must be
+used to report when a touch is active on the screen.
+BTN_{MOUSE,LEFT,MIDDLE,RIGHT} must not be reported as the result of touch
+contact. BTN_TOOL_<name> events should be reported where possible.
+
+Trackpads:
+----------
+Legacy trackpads that only provide relative position information must report
+events like mice described above.
+
+Trackpads that provide absolute touch position must report ABS_{X,Y} for the
+location of the touch. BTN_TOUCH should be used to report when a touch is active
+on the trackpad. Where multi-finger support is available, BTN_TOOL_<name> should
+be used to report the number of touches active on the trackpad.
+
+Tablets:
+----------
+BTN_TOOL_<name> events must be reported when a stylus or other tool is active on
+the tablet. ABS_{X,Y} must be reported with the location of the tool. BTN_TOUCH
+should be used to report when the tool is in contact with the tablet.
+BTN_{STYLUS,STYLUS2} should be used to report buttons on the tool itself. Any
+button may be used for buttons on the tablet except BTN_{MOUSE,LEFT}.
+BTN_{0,1,2,etc} are good generic codes for unlabeled buttons. Do not use
+meaningful buttons, like BTN_FORWARD, unless the button is labeled for that
+purpose on the device.
index a81c7b4790f2177afb7ad1911dbc20a5128ad7eb..2366b1c8cf19492f52480669449ecd2b0a0d0f34 100644 (file)
@@ -552,6 +552,16 @@ also have
      within the array where IO will be blocked.  This is currently
      only supported for raid4/5/6.
 
+   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
+     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
+     that number to reach sync_max.  Then you can either increase
+     "sync_max", or can write 'idle' to "sync_action".
+
 
 Each active md device may also have attributes specific to the
 personality module that manages it.
index 6b4b9cdec370fef4f83ed5449329dc8339347f71..1e2724e55cf014319b16bcbde917dabefbed23f7 100644 (file)
@@ -151,6 +151,7 @@ S:  Maintained
 F:     drivers/net/hamradio/6pack.c
 
 8169 10/100/1000 GIGABIT ETHERNET DRIVER
+M:     Realtek linux nic maintainers <nic_swsd@realtek.com>
 M:     Francois Romieu <romieu@fr.zoreil.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
@@ -184,10 +185,9 @@ F: Documentation/filesystems/9p.txt
 F:     fs/9p/
 
 A2232 SERIAL BOARD DRIVER
-M:     Enver Haase <A2232@gmx.net>
 L:     linux-m68k@lists.linux-m68k.org
-S:     Maintained
-F:     drivers/char/ser_a2232*
+S:     Orphan
+F:     drivers/staging/generic_serial/ser_a2232*
 
 AACRAID SCSI RAID DRIVER
 M:     Adaptec OEM Raid Solutions <aacraid@adaptec.com>
@@ -877,6 +877,13 @@ F: arch/arm/mach-mv78xx0/
 F:     arch/arm/mach-orion5x/
 F:     arch/arm/plat-orion/
 
+ARM/Orion SoC/Technologic Systems TS-78xx platform support
+M:     Alexander Clouter <alex@digriz.org.uk>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+W:     http://www.digriz.org.uk/ts78xx/kernel
+S:     Maintained
+F:     arch/arm/mach-orion5x/ts78xx-*
+
 ARM/MIOA701 MACHINE SUPPORT
 M:     Robert Jarzmik <robert.jarzmik@free.fr>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1063,7 +1070,7 @@ F:        arch/arm/mach-shmobile/
 F:     drivers/sh/
 
 ARM/TELECHIPS ARM ARCHITECTURE
-M:     "Hans J. Koch" <hjk@linutronix.de>
+M:     "Hans J. Koch" <hjk@hansjkoch.de>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/plat-tcc/
@@ -1823,11 +1830,10 @@ S:      Maintained
 F:     drivers/platform/x86/compal-laptop.c
 
 COMPUTONE INTELLIPORT MULTIPORT CARD
-M:     "Michael H. Warfield" <mhw@wittsend.com>
 W:     http://www.wittsend.com/computone.html
-S:     Maintained
+S:     Orphan
 F:     Documentation/serial/computone.txt
-F:     drivers/char/ip2/
+F:     drivers/staging/tty/ip2/
 
 CONEXANT ACCESSRUNNER USB DRIVER
 M:     Simon Arlott <cxacru@fire.lp0.eu>
@@ -2010,7 +2016,7 @@ F:        drivers/net/wan/cycx*
 CYCLADES ASYNC MUX DRIVER
 W:     http://www.cyclades.com/
 S:     Orphan
-F:     drivers/char/cyclades.c
+F:     drivers/tty/cyclades.c
 F:     include/linux/cyclades.h
 
 CYCLADES PC300 DRIVER
@@ -2124,8 +2130,8 @@ L:        Eng.Linux@digi.com
 W:     http://www.digi.com
 S:     Orphan
 F:     Documentation/serial/digiepca.txt
-F:     drivers/char/epca*
-F:     drivers/char/digi*
+F:     drivers/staging/tty/epca*
+F:     drivers/staging/tty/digi*
 
 DIOLAN U2C-12 I2C DRIVER
 M:     Guenter Roeck <guenter.roeck@ericsson.com>
@@ -4077,7 +4083,7 @@ F:        drivers/video/matrox/matroxfb_*
 F:     include/linux/matroxfb.h
 
 MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
-M:     "Hans J. Koch" <hjk@linutronix.de>
+M:     "Hans J. Koch" <hjk@hansjkoch.de>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/max6650
@@ -4192,7 +4198,7 @@ MOXA SMARTIO/INDUSTIO/INTELLIO SERIAL CARD
 M:     Jiri Slaby <jirislaby@gmail.com>
 S:     Maintained
 F:     Documentation/serial/moxa-smartio
-F:     drivers/char/mxser.*
+F:     drivers/tty/mxser.*
 
 MSI LAPTOP SUPPORT
 M:     "Lee, Chun-Yi" <jlee@novell.com>
@@ -4234,7 +4240,7 @@ F:        sound/oss/msnd*
 
 MULTITECH MULTIPORT CARD (ISICOM)
 S:     Orphan
-F:     drivers/char/isicom.c
+F:     drivers/tty/isicom.c
 F:     include/linux/isicom.h
 
 MUSB MULTIPOINT HIGH SPEED DUAL-ROLE CONTROLLER
@@ -5273,14 +5279,14 @@ F:      drivers/memstick/host/r592.*
 RISCOM8 DRIVER
 S:     Orphan
 F:     Documentation/serial/riscom8.txt
-F:     drivers/char/riscom8*
+F:     drivers/staging/tty/riscom8*
 
 ROCKETPORT DRIVER
 P:     Comtrol Corp.
 W:     http://www.comtrol.com
 S:     Maintained
 F:     Documentation/serial/rocket.txt
-F:     drivers/char/rocket*
+F:     drivers/tty/rocket*
 
 ROSE NETWORK LAYER
 M:     Ralf Baechle <ralf@linux-mips.org>
@@ -5916,10 +5922,9 @@ F:       arch/arm/mach-spear6xx/spear600.c
 F:     arch/arm/mach-spear6xx/spear600_evb.c
 
 SPECIALIX IO8+ MULTIPORT SERIAL CARD DRIVER
-M:     Roger Wolff <R.E.Wolff@BitWizard.nl>
-S:     Supported
+S:     Orphan
 F:     Documentation/serial/specialix.txt
-F:     drivers/char/specialix*
+F:     drivers/staging/tty/specialix*
 
 SPI SUBSYSTEM
 M:     David Brownell <dbrownell@users.sourceforge.net>
@@ -5964,7 +5969,6 @@ F:        arch/alpha/kernel/srm_env.c
 
 STABLE BRANCH
 M:     Greg Kroah-Hartman <greg@kroah.com>
-M:     Chris Wright <chrisw@sous-sol.org>
 L:     stable@kernel.org
 S:     Maintained
 
@@ -6248,7 +6252,8 @@ M:        Greg Ungerer <gerg@uclinux.org>
 W:     http://www.uclinux.org/
 L:     uclinux-dev@uclinux.org  (subscribers-only)
 S:     Maintained
-F:     arch/m68knommu/
+F:     arch/m68k/*/*_no.*
+F:     arch/m68k/include/asm/*_no.*
 
 UCLINUX FOR RENESAS H8/300 (H8300)
 M:     Yoshinori Sato <ysato@users.sourceforge.jp>
@@ -6618,7 +6623,7 @@ F:        fs/hostfs/
 F:     fs/hppfs/
 
 USERSPACE I/O (UIO)
-M:     "Hans J. Koch" <hjk@linutronix.de>
+M:     "Hans J. Koch" <hjk@hansjkoch.de>
 M:     Greg Kroah-Hartman <gregkh@suse.de>
 S:     Maintained
 F:     Documentation/DocBook/uio-howto.tmpl
@@ -6916,6 +6921,13 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.
 S:     Maintained
 F:     drivers/platform/x86
 
+XEN NETWORK BACKEND DRIVER
+M:     Ian Campbell <ian.campbell@citrix.com>
+L:     xen-devel@lists.xensource.com (moderated for non-subscribers)
+L:     netdev@vger.kernel.org
+S:     Supported
+F:     drivers/net/xen-netback/*
+
 XEN PCI SUBSYSTEM
 M:     Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
 L:     xen-devel@lists.xensource.com (moderated for non-subscribers)
index 8392b64079df3c0ef838913e656cfe0ff1a1ae69..b967b967572bb1c3bca2ab1b046add090b0f9248 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 39
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc4
 NAME = Flesh-Eating Bats with Fangs
 
 # *DOCUMENTATION*
index 9bb7b858ed239ef4e590732a75fe250bbf934eaf..7a6d908bb865c2e83a5cc51dcd975830f8cdfc4a 100644 (file)
@@ -4,7 +4,7 @@
 
 extra-y                := head.o vmlinux.lds
 asflags-y      := $(KBUILD_CFLAGS)
-ccflags-y      := -Werror -Wno-sign-compare
+ccflags-y      := -Wno-sign-compare
 
 obj-y    := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
            irq_alpha.o signal.o setup.o ptrace.o time.o \
index 381fec0af52e35a6262586059ccdacbcfd863148..da7bcc372f16c50f6cc3f048b6a6956df748aec4 100644 (file)
@@ -88,7 +88,7 @@ conf_read(unsigned long addr, unsigned char type1,
 {
        unsigned long flags;
        unsigned long mid = MCPCIA_HOSE2MID(hose->index);
-       unsigned int stat0, value, temp, cpu;
+       unsigned int stat0, value, cpu;
 
        cpu = smp_processor_id();
 
@@ -101,7 +101,7 @@ conf_read(unsigned long addr, unsigned char type1,
        stat0 = *(vuip)MCPCIA_CAP_ERR(mid);
        *(vuip)MCPCIA_CAP_ERR(mid) = stat0;
        mb();
-       temp = *(vuip)MCPCIA_CAP_ERR(mid);
+       *(vuip)MCPCIA_CAP_ERR(mid);
        DBG_CFG(("conf_read: MCPCIA_CAP_ERR(%d) was 0x%x\n", mid, stat0));
 
        mb();
@@ -136,7 +136,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1,
 {
        unsigned long flags;
        unsigned long mid = MCPCIA_HOSE2MID(hose->index);
-       unsigned int stat0, temp, cpu;
+       unsigned int stat0, cpu;
 
        cpu = smp_processor_id();
 
@@ -145,7 +145,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1,
        /* Reset status register to avoid losing errors.  */
        stat0 = *(vuip)MCPCIA_CAP_ERR(mid);
        *(vuip)MCPCIA_CAP_ERR(mid) = stat0; mb();
-       temp = *(vuip)MCPCIA_CAP_ERR(mid);
+       *(vuip)MCPCIA_CAP_ERR(mid);
        DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", mid, stat0));
 
        draina();
@@ -157,7 +157,7 @@ conf_write(unsigned long addr, unsigned int value, unsigned char type1,
        *((vuip)addr) = value;
        mb();
        mb();  /* magic */
-       temp = *(vuip)MCPCIA_CAP_ERR(mid); /* read to force the write */
+       *(vuip)MCPCIA_CAP_ERR(mid); /* read to force the write */
        mcheck_expected(cpu) = 0;
        mb();
 
@@ -572,12 +572,10 @@ mcpcia_print_system_area(unsigned long la_ptr)
 void
 mcpcia_machine_check(unsigned long vector, unsigned long la_ptr)
 {
-       struct el_common *mchk_header;
        struct el_MCPCIA_uncorrected_frame_mcheck *mchk_logout;
        unsigned int cpu = smp_processor_id();
        int expected;
 
-       mchk_header = (struct el_common *)la_ptr;
        mchk_logout = (struct el_MCPCIA_uncorrected_frame_mcheck *)la_ptr;
        expected = mcheck_expected(cpu);
 
index c3b3781a03de01045ebd270319173ae2b5d347ee..14b26c466c8996cc1e4f7e03ff4391bcbb2bc3c8 100644 (file)
@@ -533,8 +533,6 @@ static struct el_subpacket_annotation el_titan_annotations[] = {
 static struct el_subpacket *
 el_process_regatta_subpacket(struct el_subpacket *header)
 {
-       int status;
-
        if (header->class != EL_CLASS__REGATTA_FAMILY) {
                printk("%s  ** Unexpected header CLASS %d TYPE %d, aborting\n",
                       err_print_prefix,
@@ -551,7 +549,7 @@ el_process_regatta_subpacket(struct el_subpacket *header)
                printk("%s  ** Occurred on CPU %d:\n", 
                       err_print_prefix,
                       (int)header->by_type.regatta_frame.cpuid);
-               status = privateer_process_logout_frame((struct el_common *)
+               privateer_process_logout_frame((struct el_common *)
                        header->by_type.regatta_frame.data_start, 1);
                break;
        default:
index 1479dc6ebd97a4288ee6d0dd0334ea17dbf02049..51b7fbd9e4c11406ce8950f6cecc64f1ebd7556a 100644 (file)
@@ -228,7 +228,7 @@ struct irqaction timer_irqaction = {
 void __init
 init_rtc_irq(void)
 {
-       irq_set_chip_and_handler_name(RTC_IRQ, &no_irq_chip,
+       irq_set_chip_and_handler_name(RTC_IRQ, &dummy_irq_chip,
                                      handle_simple_irq, "RTC");
        setup_irq(RTC_IRQ, &timer_irqaction);
 }
index d2634e4476b4589f03831f575ec00751b0434ca9..edbddcbd5bc654692fbfc98572ed8277303d49db 100644 (file)
@@ -1404,8 +1404,6 @@ determine_cpu_caches (unsigned int cpu_type)
        case PCA56_CPU:
        case PCA57_CPU:
          {
-               unsigned long cbox_config, size;
-
                if (cpu_type == PCA56_CPU) {
                        L1I = CSHAPE(16*1024, 6, 1);
                        L1D = CSHAPE(8*1024, 5, 1);
@@ -1415,10 +1413,12 @@ determine_cpu_caches (unsigned int cpu_type)
                }
                L3 = -1;
 
+#if 0
+               unsigned long cbox_config, size;
+
                cbox_config = *(vulp) phys_to_virt (0xfffff00008UL);
                size = 512*1024 * (1 << ((cbox_config >> 12) & 3));
 
-#if 0
                L2 = ((cbox_config >> 31) & 1 ? CSHAPE (size, 6, 1) : -1);
 #else
                L2 = external_cache_probe(512*1024, 6);
index 3e6a2893af9f6e87122ca0e872ec95282cdf3fde..6886b834f4871f54c6eb6fd7a232a20ca12d0d0b 100644 (file)
@@ -79,7 +79,6 @@
 static unsigned long __init SMCConfigState(unsigned long baseAddr)
 {
        unsigned char devId;
-       unsigned char devRev;
 
        unsigned long configPort;
        unsigned long indexPort;
@@ -100,7 +99,7 @@ static unsigned long __init SMCConfigState(unsigned long baseAddr)
                devId = inb(dataPort);
                if (devId == VALID_DEVICE_ID) {
                        outb(DEVICE_REV, indexPort);
-                       devRev = inb(dataPort);
+                       /* unsigned char devRev = */ inb(dataPort);
                        break;
                }
                else
index d3cb28bb8eb0e450fcd4298698b944264d7b1fc0..d92cdc715c6530150563259e6fbc4c859f3e1d9f 100644 (file)
@@ -156,7 +156,6 @@ static void __init
 wildfire_init_irq_per_pca(int qbbno, int pcano)
 {
        int i, irq_bias;
-       unsigned long io_bias;
        static struct irqaction isa_enable = {
                .handler        = no_action,
                .name           = "isa_enable",
@@ -165,10 +164,12 @@ wildfire_init_irq_per_pca(int qbbno, int pcano)
        irq_bias = qbbno * (WILDFIRE_PCA_PER_QBB * WILDFIRE_IRQ_PER_PCA)
                 + pcano * WILDFIRE_IRQ_PER_PCA;
 
+#if 0
+       unsigned long io_bias;
+
        /* Only need the following for first PCI bus per PCA. */
        io_bias = WILDFIRE_IO(qbbno, pcano<<1) - WILDFIRE_IO_BIAS;
 
-#if 0
        outb(0, DMA1_RESET_REG + io_bias);
        outb(0, DMA2_RESET_REG + io_bias);
        outb(DMA_MODE_CASCADE, DMA2_MODE_REG + io_bias);
index a58e84f1a63b76cc3e96856d10736a1c03ba6872..918e8e0b72ff1e3220845ea410277a83ff326517 100644 (file)
@@ -153,6 +153,7 @@ void read_persistent_clock(struct timespec *ts)
                year += 100;
 
        ts->tv_sec = mktime(year, mon, day, hour, min, sec);
+       ts->tv_nsec = 0;
 }
 
 
index fdc9d4dbf85b528fb70614f5ff1a199504a3df75..377a7a595b08041fdacb1dfd43d8be206578bda8 100644 (file)
@@ -1540,7 +1540,6 @@ config HIGHMEM
 config HIGHPTE
        bool "Allocate 2nd-level pagetables from highmem"
        depends on HIGHMEM
-       depends on !OUTER_CACHE
 
 config HW_PERF_EVENTS
        bool "Enable hardware performance counter support for perf events"
@@ -2012,6 +2011,8 @@ source "kernel/power/Kconfig"
 
 config ARCH_SUSPEND_POSSIBLE
        depends on !ARCH_S5P64X0 && !ARCH_S5P6442
+       depends on CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || \
+               CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE
        def_bool y
 
 endmenu
index 494224a9b459060f94f39aafeeae8389111d50a0..03d01d783e3bf95c72f28259aad1550b97c5cc68 100644 (file)
@@ -63,17 +63,6 @@ config DEBUG_USER
              8 - SIGSEGV faults
             16 - SIGBUS faults
 
-config DEBUG_ERRORS
-       bool "Verbose kernel error messages"
-       depends on DEBUG_KERNEL
-       help
-         This option controls verbose debugging information which can be
-         printed when the kernel detects an internal error. This debugging
-         information is useful to kernel hackers when tracking down problems,
-         but mostly meaningless to other people. It's safe to say Y unless
-         you are concerned with the code size or don't want to see these
-         messages.
-
 config DEBUG_STACK_USAGE
        bool "Enable stack utilization instrumentation"
        depends on DEBUG_KERNEL
index e7521bca2c3564eaf3d21663fbf4ae3721e43461..6ea9b6f3607af35121e2e117e1580b1d841b520d 100644 (file)
@@ -16,5 +16,4 @@ obj-$(CONFIG_SHARP_SCOOP)     += scoop.o
 obj-$(CONFIG_ARCH_IXP2000)     += uengine.o
 obj-$(CONFIG_ARCH_IXP23XX)     += uengine.o
 obj-$(CONFIG_PCI_HOST_ITE8152)  += it8152.o
-obj-$(CONFIG_COMMON_CLKDEV)    += clkdev.o
 obj-$(CONFIG_ARM_TIMER_SP804)  += timer-sp.o
index ed5bc9e05a4e176e0c86c89762afeb770efc998c..cd4458f64171e5e40720b991e8df5ad72099b0c5 100644 (file)
@@ -2,6 +2,7 @@
 #define __ASM_ARM_CPUTYPE_H
 
 #include <linux/stringify.h>
+#include <linux/kernel.h>
 
 #define CPUID_ID       0
 #define CPUID_CACHETYPE        1
index c4391ba203507a2b1c34a9634ad6fb9c4ff7eb64..1dc98067589412a8ecc42e72e5b21a5f161b4f2a 100644 (file)
@@ -43,6 +43,7 @@ static inline void thread_notify(unsigned long rc, struct thread_info *thread)
 #define THREAD_NOTIFY_FLUSH    0
 #define THREAD_NOTIFY_EXIT     1
 #define THREAD_NOTIFY_SWITCH   2
+#define THREAD_NOTIFY_COPY     3
 
 #endif
 #endif
index c891eb76c0e313406847e7b9fbe968bb1b8fa459..87dbe3e21970c224391e4f2e29e08c34157821f7 100644 (file)
 #define __NR_fanotify_init             (__NR_SYSCALL_BASE+367)
 #define __NR_fanotify_mark             (__NR_SYSCALL_BASE+368)
 #define __NR_prlimit64                 (__NR_SYSCALL_BASE+369)
+#define __NR_name_to_handle_at         (__NR_SYSCALL_BASE+370)
+#define __NR_open_by_handle_at         (__NR_SYSCALL_BASE+371)
+#define __NR_clock_adjtime             (__NR_SYSCALL_BASE+372)
+#define __NR_syncfs                    (__NR_SYSCALL_BASE+373)
 
 /*
  * The following SWIs are ARM private.
index 74554f1742d72efd2c01a639e5fd0e3460221f94..8d95446150a3e7ed0ad8fd5782f7f918529bc3d7 100644 (file)
@@ -29,7 +29,7 @@ obj-$(CONFIG_MODULES)         += armksyms.o module.o
 obj-$(CONFIG_ARTHUR)           += arthur.o
 obj-$(CONFIG_ISA_DMA)          += dma-isa.o
 obj-$(CONFIG_PCI)              += bios32.o isa.o
-obj-$(CONFIG_PM)               += sleep.o
+obj-$(CONFIG_PM_SLEEP)         += sleep.o
 obj-$(CONFIG_HAVE_SCHED_CLOCK) += sched_clock.o
 obj-$(CONFIG_SMP)              += smp.o smp_tlb.o
 obj-$(CONFIG_HAVE_ARM_SCU)     += smp_scu.o
index 5c26eccef9982665b1e1672416b9bc996f3b2dae..7fbf28c35bb2b438469894bb6bc80797fd8a3cf6 100644 (file)
                CALL(sys_fanotify_init)
                CALL(sys_fanotify_mark)
                CALL(sys_prlimit64)
+/* 370 */      CALL(sys_name_to_handle_at)
+               CALL(sys_open_by_handle_at)
+               CALL(sys_clock_adjtime)
+               CALL(sys_syncfs)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
index d4a0da1e48f40988bb7f92ce34664d86adb74a32..9b05c6a0dceac54615e1dfa472bf28ca946616ac 100644 (file)
@@ -40,15 +40,22 @@ EXPORT_SYMBOL(elf_check_arch);
 void elf_set_personality(const struct elf32_hdr *x)
 {
        unsigned int eflags = x->e_flags;
-       unsigned int personality = PER_LINUX_32BIT;
+       unsigned int personality = current->personality & ~PER_MASK;
+
+       /*
+        * We only support Linux ELF executables, so always set the
+        * personality to LINUX.
+        */
+       personality |= PER_LINUX;
 
        /*
         * APCS-26 is only valid for OABI executables
         */
-       if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN) {
-               if (eflags & EF_ARM_APCS_26)
-                       personality = PER_LINUX;
-       }
+       if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN &&
+           (eflags & EF_ARM_APCS_26))
+               personality &= ~ADDR_LIMIT_32BIT;
+       else
+               personality |= ADDR_LIMIT_32BIT;
 
        set_personality(personality);
 
index 8dbc126f7152d992472898a639801239d49a40ac..87acc25d7a3e203646f2ee71f1d7c711304d52f2 100644 (file)
@@ -868,6 +868,13 @@ static void reset_ctrl_regs(void *info)
                 */
                asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));
                isb();
+
+               /*
+                * Clear any configured vector-catch events before
+                * enabling monitor mode.
+                */
+               asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0));
+               isb();
        }
 
        if (enable_monitor_mode())
index 69cfee0fe00f1cbc38eb7f789ef23aae51688dd6..979da3947f4272c933739064d576f991c412eeac 100644 (file)
@@ -221,7 +221,7 @@ again:
        prev_raw_count &= armpmu->max_period;
 
        if (overflow)
-               delta = armpmu->max_period - prev_raw_count + new_raw_count;
+               delta = armpmu->max_period - prev_raw_count + new_raw_count + 1;
        else
                delta = new_raw_count - prev_raw_count;
 
index 94bbedbed6394cf147e2b73bce3b6629d0dbbd9f..5e1e541972277f38a123d7964fca081629584d50 100644 (file)
@@ -372,6 +372,8 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
        if (clone_flags & CLONE_SETTLS)
                thread->tp_value = regs->ARM_r3;
 
+       thread_notify(THREAD_NOTIFY_COPY, thread);
+
        return 0;
 }
 
index f0000e188c8c8c5a14be6f21c37b961739ecfad6..3b54ad19d4890c40752905af84a345b21ba56b62 100644 (file)
@@ -410,8 +410,7 @@ static int bad_syscall(int n, struct pt_regs *regs)
        struct thread_info *thread = current_thread_info();
        siginfo_t info;
 
-       if (current->personality != PER_LINUX &&
-           current->personality != PER_LINUX_32BIT &&
+       if ((current->personality & PER_MASK) != PER_LINUX &&
            thread->exec_domain->handler) {
                thread->exec_domain->handler(n, regs);
                return regs->ARM_r0;
index ee8b02ed8011dfa615603045a22c5a98956635e4..7bfb827f3fe36a8d71fc874b1a45e446be1d3bac 100644 (file)
@@ -10,7 +10,7 @@
 #define BANK_OFF(n)    (((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
 #define GPIO_REG(x)    (*((volatile u32 *)(GPIO_REGS_VIRT + (x))))
 
-#define NR_BUILTIN_GPIO        (192)
+#define NR_BUILTIN_GPIO                IRQ_GPIO_NUM
 
 #define gpio_to_bank(gpio)     ((gpio) >> 5)
 #define gpio_to_irq(gpio)      (IRQ_GPIO_START + (gpio))
index 4621067c7720f457b311faff80e19dddc87ecd3e..713be155a44d716df91aeb74c2d043630f543564 100644 (file)
@@ -8,6 +8,15 @@
 #define MFP_DRIVE_MEDIUM       (0x2 << 13)
 #define MFP_DRIVE_FAST         (0x3 << 13)
 
+#undef MFP_CFG
+#undef MFP_CFG_DRV
+
+#define MFP_CFG(pin, af)               \
+       (MFP_LPM_INPUT | MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_DRIVE_MEDIUM)
+
+#define MFP_CFG_DRV(pin, af, drv)      \
+       (MFP_LPM_INPUT | MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_DRIVE_##drv)
+
 /* GPIO */
 #define GPIO0_GPIO             MFP_CFG(GPIO0, AF5)
 #define GPIO1_GPIO             MFP_CFG(GPIO1, AF5)
index 7f568611547e94d5343db7d174712dc732ea0f2c..6a96911b0ad508cdde70e79359a8e3480ce10c16 100644 (file)
@@ -160,10 +160,7 @@ static struct msm_mmc_platform_data qsd8x50_sdc1_data = {
 
 static void __init qsd8x50_init_mmc(void)
 {
-       if (machine_is_qsd8x50_ffa() || machine_is_qsd8x50a_ffa())
-               vreg_mmc = vreg_get(NULL, "gp6");
-       else
-               vreg_mmc = vreg_get(NULL, "gp5");
+       vreg_mmc = vreg_get(NULL, "gp5");
 
        if (IS_ERR(vreg_mmc)) {
                pr_err("vreg get for vreg_mmc failed (%ld)\n",
index 56f920c55b6aaaaa45737aeeddffadfa1b1a12d2..38b95e949d13b0a87d83a3274b0369e98c8321ed 100644 (file)
@@ -269,7 +269,7 @@ int __cpuinit local_timer_setup(struct clock_event_device *evt)
 
        /* Use existing clock_event for cpu 0 */
        if (!smp_processor_id())
-               return;
+               return 0;
 
        writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
 
index b024a8b374394ac2731596ba39bba462309f04a6..c4639502efcac4d236f5752172bfe2f29f7af27f 100644 (file)
 #define GAFR(x)                GPIO_REG(0x54 + (((x) & 0x70) >> 2))
 
 
-#define NR_BUILTIN_GPIO 128
+#define NR_BUILTIN_GPIO                PXA_GPIO_IRQ_NUM
 
 #define gpio_to_bank(gpio)     ((gpio) >> 5)
 #define gpio_to_irq(gpio)      IRQ_GPIO(gpio)
-#define irq_to_gpio(irq)       IRQ_TO_GPIO(irq)
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+       int gpio;
+
+       if (irq == IRQ_GPIO0 || irq == IRQ_GPIO1)
+               return irq - IRQ_GPIO0;
+
+       gpio = irq - PXA_GPIO_IRQ_BASE;
+       if (gpio >= 2 && gpio < NR_BUILTIN_GPIO)
+               return gpio;
+
+       return -1;
+}
 
 #ifdef CONFIG_CPU_PXA26x
 /* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
index a4285fc0087841ad0c48902a2ae5d664f1205745..038402404e3932e78c702181c6d62cd4e4d145a7 100644 (file)
@@ -93,9 +93,6 @@
 #define GPIO_2_x_TO_IRQ(x)     (PXA_GPIO_IRQ_BASE + (x))
 #define IRQ_GPIO(x)    (((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_x_TO_IRQ(x))
 
-#define IRQ_TO_GPIO_2_x(i)     ((i) - PXA_GPIO_IRQ_BASE)
-#define IRQ_TO_GPIO(i) (((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i))
-
 /*
  * The following interrupts are for board specific purposes. Since
  * the kernel can only run on one machine at a time, we can re-use
index 6bde5956358d88ceef7c23641bb92c77e3a44154..a4af8c52d7ee297b49246be5246aa0e055e1c970 100644 (file)
@@ -285,7 +285,7 @@ static inline void pxa25x_init_pm(void) {}
 
 static int pxa25x_set_wake(struct irq_data *d, unsigned int on)
 {
-       int gpio = IRQ_TO_GPIO(d->irq);
+       int gpio = irq_to_gpio(d->irq);
        uint32_t mask = 0;
 
        if (gpio >= 0 && gpio < 85)
index 1cb5d0f9723fb28ea9c5c1dabe441646c3dfcf25..909756eaf4b72a3b32a36f444517d1748604767a 100644 (file)
@@ -345,7 +345,7 @@ static inline void pxa27x_init_pm(void) {}
  */
 static int pxa27x_set_wake(struct irq_data *d, unsigned int on)
 {
-       int gpio = IRQ_TO_GPIO(d->irq);
+       int gpio = irq_to_gpio(d->irq);
        uint32_t mask;
 
        if (gpio >= 0 && gpio < 128)
index 76a3f654220f2f012b842b9e2794811fba2a4710..65a1aba6823db6be97b9b87115be7caab4e8f2f9 100644 (file)
@@ -257,7 +257,8 @@ static void tegra_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 void tegra_gpio_resume(void)
 {
        unsigned long flags;
-       int b, p, i;
+       int b;
+       int p;
 
        local_irq_save(flags);
 
@@ -280,7 +281,8 @@ void tegra_gpio_resume(void)
 void tegra_gpio_suspend(void)
 {
        unsigned long flags;
-       int b, p, i;
+       int b;
+       int p;
 
        local_irq_save(flags);
        for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
index 6d7c4eea4dcbcd95a567635667d2ccf557878808..4459470c052de3f97ea29ec138c0a2006787328b 100644 (file)
@@ -1362,14 +1362,15 @@ static int tegra_clk_shared_bus_set_rate(struct clk *c, unsigned long rate)
 {
        unsigned long flags;
        int ret;
+       long new_rate = rate;
 
-       rate = clk_round_rate(c->parent, rate);
-       if (rate < 0)
-               return rate;
+       new_rate = clk_round_rate(c->parent, new_rate);
+       if (new_rate < 0)
+               return new_rate;
 
        spin_lock_irqsave(&c->parent->spinlock, flags);
 
-       c->u.shared_bus_user.rate = rate;
+       c->u.shared_bus_user.rate = new_rate;
        ret = tegra_clk_shared_bus_update(c->parent);
 
        spin_unlock_irqrestore(&c->parent->spinlock, flags);
index afe209e1e1f85fb299e9822ea07a49b13cc29ecf..74be05f3e03ac58be921aff208c6f6aa460ab683 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/shm.h>
 #include <linux/sched.h>
 #include <linux/io.h>
+#include <linux/personality.h>
 #include <linux/random.h>
 #include <asm/cputype.h>
 #include <asm/system.h>
@@ -82,7 +83,8 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
                mm->cached_hole_size = 0;
        }
        /* 8 bits of randomness in 20 address space bits */
-       if (current->flags & PF_RANDOMIZE)
+       if ((current->flags & PF_RANDOMIZE) &&
+           !(current->personality & ADDR_NO_RANDOMIZE))
                addr += (get_random_int() % (1 << 8)) << PAGE_SHIFT;
 
 full_search:
index b46eb21f05c7edf8d53c474a54791ea8ea8a922b..bf8a1d1cccb6c33b26412264a2f05228657e49aa 100644 (file)
@@ -390,7 +390,7 @@ ENTRY(cpu_arm920_set_pte_ext)
 /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
 .globl cpu_arm920_suspend_size
 .equ   cpu_arm920_suspend_size, 4 * 3
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_arm920_do_suspend)
        stmfd   sp!, {r4 - r7, lr}
        mrc     p15, 0, r4, c13, c0, 0  @ PID
index 6a4bdb2c94a7ba0f856bf06c00f95049ab638dc1..0ed85d930c095e3280f7f029973e1530a7fcd4aa 100644 (file)
@@ -404,7 +404,7 @@ ENTRY(cpu_arm926_set_pte_ext)
 /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
 .globl cpu_arm926_suspend_size
 .equ   cpu_arm926_suspend_size, 4 * 3
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_arm926_do_suspend)
        stmfd   sp!, {r4 - r7, lr}
        mrc     p15, 0, r4, c13, c0, 0  @ PID
index 74483d1977fe788ac2b4b8d42e32952da9e7ed0e..184a9c997e36616dcc6819418d380f9d9e439291 100644 (file)
@@ -171,7 +171,7 @@ ENTRY(cpu_sa1100_set_pte_ext)
 
 .globl cpu_sa1100_suspend_size
 .equ   cpu_sa1100_suspend_size, 4*4
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_sa1100_do_suspend)
        stmfd   sp!, {r4 - r7, lr}
        mrc     p15, 0, r4, c3, c0, 0           @ domain ID
index bfa0c9f611c537c85db433da446f791e2f8ba851..7c99cb4c8e4fb8663158caf9832d6df6e9e27ef4 100644 (file)
@@ -124,7 +124,7 @@ ENTRY(cpu_v6_set_pte_ext)
 /* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
 .globl cpu_v6_suspend_size
 .equ   cpu_v6_suspend_size, 4 * 8
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_v6_do_suspend)
        stmfd   sp!, {r4 - r11, lr}
        mrc     p15, 0, r4, c13, c0, 0  @ FCSE/PID
index c35618e42f6fcbd7808f36474518aed226dba7e1..babfba09c89ff390deb7ddfd0496e813f442e047 100644 (file)
@@ -211,7 +211,7 @@ 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
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_v7_do_suspend)
        stmfd   sp!, {r4 - r11, lr}
        mrc     p15, 0, r4, c13, c0, 0  @ FCSE/PID
index 63d8b2044e84114c4401c7851e14b659a39821f2..596213699f37ac8a52d580ae70df8303bc344c94 100644 (file)
@@ -417,7 +417,7 @@ ENTRY(cpu_xsc3_set_pte_ext)
 
 .globl cpu_xsc3_suspend_size
 .equ   cpu_xsc3_suspend_size, 4 * 8
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_xsc3_do_suspend)
        stmfd   sp!, {r4 - r10, lr}
        mrc     p14, 0, r4, c6, c0, 0   @ clock configuration, for turbo mode
index 086038cd86abc1e32ffb0c6552d8fdc85c5a3bd2..ce233bcbf5060c14bfe89c0093020a9c17005904 100644 (file)
@@ -518,7 +518,7 @@ ENTRY(cpu_xscale_set_pte_ext)
 
 .globl cpu_xscale_suspend_size
 .equ   cpu_xscale_suspend_size, 4 * 7
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 ENTRY(cpu_xscale_do_suspend)
        stmfd   sp!, {r4 - r10, lr}
        mrc     p14, 0, r4, c6, c0, 0   @ clock configuration, for turbo mode
index d592b6304b48cf5825b22fe0298d8a2db21b4d52..d15dc47b0e3db50c2c87535aca5f5ff153e4c6b0 100644 (file)
 
 #define PFX "s5p pm: "
 
-/* s3c_pm_check_resume_pin
- *
- * check to see if the pin is configured correctly for sleep mode, and
- * make any necessary adjustments if it is not
-*/
-
-static void s3c_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
-{
-       /* nothing here yet */
-}
-
 /* s3c_pm_configure_extint
  *
  * configure all external interrupt pins
index e4baf76f374ada34260e37dc88916207ad75abf2..6b733fafe7cda41815d88115fa866d1a6976a71b 100644 (file)
@@ -164,7 +164,6 @@ static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
  */
 static u32 *s3c_pm_runcheck(struct resource *res, u32 *val)
 {
-       void *save_at = phys_to_virt(s3c_sleep_save_phys);
        unsigned long addr;
        unsigned long left;
        void *stkpage;
@@ -192,11 +191,6 @@ static u32 *s3c_pm_runcheck(struct resource *res, u32 *val)
                        goto skip_check;
                }
 
-               if (in_region(ptr, left, save_at, 32*4 )) {
-                       S3C_PMDBG("skipping %08lx, has save block in\n", addr);
-                       goto skip_check;
-               }
-
                /* calculate and check the checksum */
 
                calc = crc32_le(~0, ptr, left);
index d5b58d31903c740d2a0328a67e3d536adcc832d8..5c0a440d6e16741f34f547b7aa6583a16997b5c4 100644 (file)
@@ -214,8 +214,9 @@ void s3c_pm_do_restore_core(struct sleep_save *ptr, int count)
  *
  * print any IRQs asserted at resume time (ie, we woke from)
 */
-static void s3c_pm_show_resume_irqs(int start, unsigned long which,
-                                   unsigned long mask)
+static void __maybe_unused s3c_pm_show_resume_irqs(int start,
+                                                  unsigned long which,
+                                                  unsigned long mask)
 {
        int i;
 
index bbf3da012afdf6ab1233f7b6e0bf9eaa7c96194a..f74695075e641ec72562e1c8194a8220327e8bc8 100644 (file)
@@ -78,6 +78,14 @@ static void vfp_thread_exit(struct thread_info *thread)
        put_cpu();
 }
 
+static void vfp_thread_copy(struct thread_info *thread)
+{
+       struct thread_info *parent = current_thread_info();
+
+       vfp_sync_hwstate(parent);
+       thread->vfpstate = parent->vfpstate;
+}
+
 /*
  * When this function is called with the following 'cmd's, the following
  * is true while this function is being run:
@@ -104,12 +112,17 @@ static void vfp_thread_exit(struct thread_info *thread)
 static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
 {
        struct thread_info *thread = v;
+       u32 fpexc;
+#ifdef CONFIG_SMP
+       unsigned int cpu;
+#endif
 
-       if (likely(cmd == THREAD_NOTIFY_SWITCH)) {
-               u32 fpexc = fmrx(FPEXC);
+       switch (cmd) {
+       case THREAD_NOTIFY_SWITCH:
+               fpexc = fmrx(FPEXC);
 
 #ifdef CONFIG_SMP
-               unsigned int cpu = thread->cpu;
+               cpu = thread->cpu;
 
                /*
                 * On SMP, if VFP is enabled, save the old state in
@@ -134,13 +147,20 @@ static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
                 * old state.
                 */
                fmxr(FPEXC, fpexc & ~FPEXC_EN);
-               return NOTIFY_DONE;
-       }
+               break;
 
-       if (cmd == THREAD_NOTIFY_FLUSH)
+       case THREAD_NOTIFY_FLUSH:
                vfp_thread_flush(thread);
-       else
+               break;
+
+       case THREAD_NOTIFY_EXIT:
                vfp_thread_exit(thread);
+               break;
+
+       case THREAD_NOTIFY_COPY:
+               vfp_thread_copy(thread);
+               break;
+       }
 
        return NOTIFY_DONE;
 }
index ff5b7cf6be4dd8065bffb566065de245a3f4020e..160543dbec7eb1c9725c6edf3ba9259e5fd9bd9d 100644 (file)
@@ -94,6 +94,13 @@ struct tag_ethernet {
 
 #define ETH_INVALID_PHY        0xff
 
+/* board information */
+#define ATAG_BOARDINFO 0x54410008
+
+struct tag_boardinfo {
+       u32     board_number;
+};
+
 struct tag {
        struct tag_header hdr;
        union {
@@ -102,6 +109,7 @@ struct tag {
                struct tag_cmdline cmdline;
                struct tag_clock clock;
                struct tag_ethernet ethernet;
+               struct tag_boardinfo boardinfo;
        } u;
 };
 
@@ -128,6 +136,7 @@ extern struct tag *bootloader_tags;
 
 extern resource_size_t fbmem_start;
 extern resource_size_t fbmem_size;
+extern u32 board_number;
 
 void setup_processor(void);
 
index 5c7083916c33c14792728da5a08295476daebc17..bb0974cce4accf3c0a0d01cdfce08d7533d86ab7 100644 (file)
@@ -390,6 +390,21 @@ static int __init parse_tag_clock(struct tag *tag)
 }
 __tagtable(ATAG_CLOCK, parse_tag_clock);
 
+/*
+ * The board_number correspond to the bd->bi_board_number in U-Boot. This
+ * parameter is only available during initialisation and can be used in some
+ * kind of board identification.
+ */
+u32 __initdata board_number;
+
+static int __init parse_tag_boardinfo(struct tag *tag)
+{
+       board_number = tag->u.boardinfo.board_number;
+
+       return 0;
+}
+__tagtable(ATAG_BOARDINFO, parse_tag_boardinfo);
+
 /*
  * Scan the tag table for this tag, and call its parse function. The
  * tag table is built by the linker from all the __tagtable
index b91b2044af9c9660210bb9efd5f11ab60a08dcbc..7aa25756412f16299b69cccfcd1d1c9851aaaec7 100644 (file)
@@ -95,28 +95,6 @@ void _exception(long signr, struct pt_regs *regs, int code,
        info.si_code = code;
        info.si_addr = (void __user *)addr;
        force_sig_info(signr, &info, current);
-
-       /*
-        * Init gets no signals that it doesn't have a handler for.
-        * That's all very well, but if it has caused a synchronous
-        * exception and we ignore the resulting signal, it will just
-        * generate the same exception over and over again and we get
-        * nowhere.  Better to kill it and let the kernel panic.
-        */
-       if (is_global_init(current)) {
-               __sighandler_t handler;
-
-               spin_lock_irq(&current->sighand->siglock);
-               handler = current->sighand->action[signr-1].sa.sa_handler;
-               spin_unlock_irq(&current->sighand->siglock);
-               if (handler == SIG_DFL) {
-                       /* init has generated a synchronous exception
-                          and it doesn't have a handler for the signal */
-                       printk(KERN_CRIT "init has generated signal %ld "
-                              "but has no handler for it\n", signr);
-                       do_exit(signr);
-               }
-       }
 }
 
 asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs)
index 442f08c5e6415f198df5c7843b69d144fa336ed6..86925fd6ea5bb3daf34eb039858ff69f2bb02ec6 100644 (file)
@@ -35,22 +35,30 @@ void at32_clk_register(struct clk *clk)
        spin_unlock(&clk_list_lock);
 }
 
-struct clk *clk_get(struct device *dev, const char *id)
+static struct clk *__clk_get(struct device *dev, const char *id)
 {
        struct clk *clk;
 
-       spin_lock(&clk_list_lock);
-
        list_for_each_entry(clk, &at32_clock_list, list) {
                if (clk->dev == dev && strcmp(id, clk->name) == 0) {
-                       spin_unlock(&clk_list_lock);
                        return clk;
                }
        }
 
-       spin_unlock(&clk_list_lock);
        return ERR_PTR(-ENOENT);
 }
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+       struct clk *clk;
+
+       spin_lock(&clk_list_lock);
+       clk = __clk_get(dev, id);
+       spin_unlock(&clk_list_lock);
+
+       return clk;
+}
+
 EXPORT_SYMBOL(clk_get);
 
 void clk_put(struct clk *clk)
@@ -257,15 +265,15 @@ static int clk_show(struct seq_file *s, void *unused)
        spin_lock(&clk_list_lock);
 
        /* show clock tree as derived from the three oscillators */
-       clk = clk_get(NULL, "osc32k");
+       clk = __clk_get(NULL, "osc32k");
        dump_clock(clk, &r);
        clk_put(clk);
 
-       clk = clk_get(NULL, "osc0");
+       clk = __clk_get(NULL, "osc0");
        dump_clock(clk, &r);
        clk_put(clk);
 
-       clk = clk_get(NULL, "osc1");
+       clk = __clk_get(NULL, "osc1");
        dump_clock(clk, &r);
        clk_put(clk);
 
index 47ba4b9b6db16b5852a0f857236e3d73e5349e75..fbc2aeaebddbde6023bb4853814f2e598436a1bd 100644 (file)
@@ -61,34 +61,34 @@ struct eic {
 static struct eic *nmi_eic;
 static bool nmi_enabled;
 
-static void eic_ack_irq(struct irq_chip *d)
+static void eic_ack_irq(struct irq_data *d)
 {
-       struct eic *eic = irq_data_get_irq_chip_data(data);
+       struct eic *eic = irq_data_get_irq_chip_data(d);
        eic_writel(eic, ICR, 1 << (d->irq - eic->first_irq));
 }
 
-static void eic_mask_irq(struct irq_chip *d)
+static void eic_mask_irq(struct irq_data *d)
 {
-       struct eic *eic = irq_data_get_irq_chip_data(data);
+       struct eic *eic = irq_data_get_irq_chip_data(d);
        eic_writel(eic, IDR, 1 << (d->irq - eic->first_irq));
 }
 
-static void eic_mask_ack_irq(struct irq_chip *d)
+static void eic_mask_ack_irq(struct irq_data *d)
 {
-       struct eic *eic = irq_data_get_irq_chip_data(data);
+       struct eic *eic = irq_data_get_irq_chip_data(d);
        eic_writel(eic, ICR, 1 << (d->irq - eic->first_irq));
        eic_writel(eic, IDR, 1 << (d->irq - eic->first_irq));
 }
 
-static void eic_unmask_irq(struct irq_chip *d)
+static void eic_unmask_irq(struct irq_data *d)
 {
-       struct eic *eic = irq_data_get_irq_chip_data(data);
+       struct eic *eic = irq_data_get_irq_chip_data(d);
        eic_writel(eic, IER, 1 << (d->irq - eic->first_irq));
 }
 
-static int eic_set_irq_type(struct irq_chip *d, unsigned int flow_type)
+static int eic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-       struct eic *eic = irq_data_get_irq_chip_data(data);
+       struct eic *eic = irq_data_get_irq_chip_data(d);
        unsigned int irq = d->irq;
        unsigned int i = irq - eic->first_irq;
        u32 mode, edge, level;
@@ -191,7 +191,7 @@ static int __init eic_probe(struct platform_device *pdev)
 
        regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        int_irq = platform_get_irq(pdev, 0);
-       if (!regs || !int_irq) {
+       if (!regs || (int)int_irq <= 0) {
                dev_dbg(&pdev->dev, "missing regs and/or irq resource\n");
                return -ENXIO;
        }
index f308e1ddc629310ef882c04361b92ae4cef51622..2e0aa853a4bcecec88339d30b22d112114edc5be 100644 (file)
@@ -257,7 +257,7 @@ static void gpio_irq_mask(struct irq_data *d)
        pio_writel(pio, IDR, 1 << (gpio & 0x1f));
 }
 
-static void gpio_irq_unmask(struct irq_data *d))
+static void gpio_irq_unmask(struct irq_data *d)
 {
        unsigned                gpio = irq_to_gpio(d->irq);
        struct pio_device       *pio = &pio_dev[gpio >> 5];
index 17503b0ed6c9b3f5865406fb0d5f44241ce6bab7..f868f4ce761ba6f37a7b63617fba356410263ff1 100644 (file)
@@ -53,7 +53,7 @@ cpu_enter_idle:
        st.w    r8[TI_flags], r9
        unmask_interrupts
        sleep   CPU_SLEEP_IDLE
-       .size   cpu_idle_sleep, . - cpu_idle_sleep
+       .size   cpu_enter_idle, . - cpu_enter_idle
 
        /*
         * Common return path for PM functions that don't run from
index 19e2c7c3e63ac41bf62f2e55a4db10d6bf97a13f..44bd0cced7256dc1a04eb78242b8ad5fb8ca882c 100644 (file)
  * Force strict CPU ordering.
  */
 #define nop()  __asm__ __volatile__ ("nop;\n\t" : : )
-#define mb()   __asm__ __volatile__ (""   : : : "memory")
-#define rmb()  __asm__ __volatile__ (""   : : : "memory")
-#define wmb()  __asm__ __volatile__ (""   : : : "memory")
-#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
-#define read_barrier_depends()                 do { } while(0)
+#define smp_mb()  mb()
+#define smp_rmb() rmb()
+#define smp_wmb() wmb()
+#define set_mb(var, value) do { var = value; mb(); } while (0)
+#define smp_read_barrier_depends()     read_barrier_depends()
 
 #ifdef CONFIG_SMP
 asmlinkage unsigned long __raw_xchg_1_asm(volatile void *ptr, unsigned long value);
@@ -37,16 +37,16 @@ asmlinkage unsigned long __raw_cmpxchg_4_asm(volatile void *ptr,
                                        unsigned long new, unsigned long old);
 
 #ifdef __ARCH_SYNC_CORE_DCACHE
-# define smp_mb()      do { barrier(); smp_check_barrier(); smp_mark_barrier(); } while (0)
-# define smp_rmb()     do { barrier(); smp_check_barrier(); } while (0)
-# define smp_wmb()     do { barrier(); smp_mark_barrier(); } while (0)
-#define smp_read_barrier_depends()     do { barrier(); smp_check_barrier(); } while (0)
-
+/* Force Core data cache coherence */
+# define mb()  do { barrier(); smp_check_barrier(); smp_mark_barrier(); } while (0)
+# define rmb() do { barrier(); smp_check_barrier(); } while (0)
+# define wmb() do { barrier(); smp_mark_barrier(); } while (0)
+# define read_barrier_depends()        do { barrier(); smp_check_barrier(); } while (0)
 #else
-# define smp_mb()      barrier()
-# define smp_rmb()     barrier()
-# define smp_wmb()     barrier()
-#define smp_read_barrier_depends()     barrier()
+# define mb()  barrier()
+# define rmb() barrier()
+# define wmb() barrier()
+# define read_barrier_depends()        do { } while (0)
 #endif
 
 static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
@@ -99,10 +99,10 @@ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
 
 #else /* !CONFIG_SMP */
 
-#define smp_mb()       barrier()
-#define smp_rmb()      barrier()
-#define smp_wmb()      barrier()
-#define smp_read_barrier_depends()     do { } while(0)
+#define mb()   barrier()
+#define rmb()  barrier()
+#define wmb()  barrier()
+#define read_barrier_depends() do { } while (0)
 
 struct __xchg_dummy {
        unsigned long a[100];
index cdbe075de1dc6841411310ef481ed26a4210c2f2..8b81dc04488aa6864aeb23236cadb65cc1cda676 100644 (file)
@@ -268,7 +268,7 @@ void disable_gptimers(uint16_t mask)
        _disable_gptimers(mask);
        for (i = 0; i < MAX_BLACKFIN_GPTIMERS; ++i)
                if (mask & (1 << i))
-                       group_regs[BFIN_TIMER_OCTET(i)]->status |= trun_mask[i];
+                       group_regs[BFIN_TIMER_OCTET(i)]->status = trun_mask[i];
        SSYNC();
 }
 EXPORT_SYMBOL(disable_gptimers);
index 8c9a43daf80fad1f4ecaec62f25ea0778cc2be94..cdb4beb6bc8fc9507bf0531317b8b834eca9d4c8 100644 (file)
@@ -206,8 +206,14 @@ irqreturn_t bfin_gptmr0_interrupt(int irq, void *dev_id)
 {
        struct clock_event_device *evt = dev_id;
        smp_mb();
-       evt->event_handler(evt);
+       /*
+        * We want to ACK before we handle so that we can handle smaller timer
+        * intervals.  This way if the timer expires again while we're handling
+        * things, we're more likely to see that 2nd int rather than swallowing
+        * it by ACKing the int at the end of this handler.
+        */
        bfin_gptmr0_ack();
+       evt->event_handler(evt);
        return IRQ_HANDLED;
 }
 
index 6e17a265c4d3158761450463b3c5a66e63a39bab..8bce5ed031e448ed0a51d9e77c947864eed2e2bf 100644 (file)
@@ -109,10 +109,23 @@ static void ipi_flush_icache(void *info)
        struct blackfin_flush_data *fdata = info;
 
        /* Invalidate the memory holding the bounds of the flushed region. */
-       invalidate_dcache_range((unsigned long)fdata,
-               (unsigned long)fdata + sizeof(*fdata));
+       blackfin_dcache_invalidate_range((unsigned long)fdata,
+                                        (unsigned long)fdata + sizeof(*fdata));
+
+       /* Make sure all write buffers in the data side of the core
+        * are flushed before trying to invalidate the icache.  This
+        * needs to be after the data flush and before the icache
+        * flush so that the SSYNC does the right thing in preventing
+        * the instruction prefetcher from hitting things in cached
+        * memory at the wrong time -- it runs much further ahead than
+        * the pipeline.
+        */
+       SSYNC();
 
-       flush_icache_range(fdata->start, fdata->end);
+       /* ipi_flaush_icache is invoked by generic flush_icache_range,
+        * so call blackfin arch icache flush directly here.
+        */
+       blackfin_icache_flush_range(fdata->start, fdata->end);
 }
 
 static void ipi_call_function(unsigned int cpu, struct ipi_message *msg)
index 26d851d385bb190a81f271f49fe89c74778e3c06..29e17907d9f2c2af079df6e5b8e0b032de792562 100644 (file)
 #define __NR_fanotify_init     337
 #define __NR_fanotify_mark     338
 #define __NR_prlimit64         339
+#define __NR_name_to_handle_at 340
+#define __NR_open_by_handle_at 341
+#define __NR_clock_adjtime     342
+#define __NR_syncfs            343
 
 #ifdef __KERNEL__
 
-#define NR_syscalls            340
+#define NR_syscalls            344
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
index 1559dea36e5581f62bf2d8b4b1fe6c6da37308f4..1359ee659574135d440deea4495728c1cbb872d2 100644 (file)
@@ -750,4 +750,8 @@ sys_call_table:
        .long sys_fanotify_init
        .long sys_fanotify_mark
        .long sys_prlimit64
+       .long sys_name_to_handle_at     /* 340 */
+       .long sys_open_by_handle_at
+       .long sys_clock_adjtime
+       .long sys_syncfs
 
index 79b1ed198c070dd40dbb3cf4f03dd6f24b79cb71..9b8393d8adb89dae4ada43f66c6d63c8670589f6 100644 (file)
@@ -358,6 +358,10 @@ ENTRY(sys_call_table)
        .long sys_fanotify_init
        .long sys_fanotify_mark
        .long sys_prlimit64
+       .long sys_name_to_handle_at     /* 340 */
+       .long sys_open_by_handle_at
+       .long sys_clock_adjtime
+       .long sys_syncfs
 
        .rept NR_syscalls-(.-sys_call_table)/4
                .long sys_ni_syscall
index 851b3bf6e962eb3b6e95d5459645f5dfc4ea80b6..eccdefe70d4e4ba1b4874df00228faff583e948b 100644 (file)
@@ -6,7 +6,6 @@ config MICROBLAZE
        select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_DYNAMIC_FTRACE
        select HAVE_FTRACE_MCOUNT_RECORD
-       select USB_ARCH_HAS_EHCI
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select HAVE_OPROFILE
        select HAVE_ARCH_KGDB
index b6ff882f695bbac53e95b2f6b1a1a00a9bf97ac6..8f4d50b0adfa9ce21bf8dd68158df455ef242af3 100644 (file)
@@ -209,7 +209,7 @@ config ARCH_HIBERNATION_POSSIBLE
 config ARCH_SUSPEND_POSSIBLE
        def_bool y
        depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \
-                  PPC_85xx || PPC_86xx || PPC_PSERIES || 44x || 40x
+                  (PPC_85xx && !SMP) || PPC_86xx || PPC_PSERIES || 44x || 40x
 
 config PPC_DCR_NATIVE
        bool
index be3cdf9134ce8727b9a7787250fb6ba3dfdb8e44..1833d1a07e797eab6c9f174585b42e456d19f559 100644 (file)
@@ -382,10 +382,12 @@ extern const char *powerpc_base_platform;
 #define CPU_FTRS_E500_2        (CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
            CPU_FTR_SPE_COMP | CPU_FTR_MAYBE_CAN_NAP | \
            CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE)
-#define CPU_FTRS_E500MC        (CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
-           CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN | \
+#define CPU_FTRS_E500MC        (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \
            CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
            CPU_FTR_DBELL)
+#define CPU_FTRS_E5500 (CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \
+           CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
+           CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD)
 #define CPU_FTRS_GENERIC_32    (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
 
 /* 64-bit CPUs */
@@ -435,11 +437,15 @@ extern const char *powerpc_base_platform;
 #define CPU_FTRS_COMPATIBLE    (CPU_FTR_USE_TB | CPU_FTR_PPCAS_ARCH_V2)
 
 #ifdef __powerpc64__
+#ifdef CONFIG_PPC_BOOK3E
+#define CPU_FTRS_POSSIBLE      (CPU_FTRS_E5500)
+#else
 #define CPU_FTRS_POSSIBLE      \
            (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 |        \
            CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_POWER6 |       \
            CPU_FTRS_POWER7 | CPU_FTRS_CELL | CPU_FTRS_PA6T |           \
            CPU_FTR_1T_SEGMENT | CPU_FTR_VSX)
+#endif
 #else
 enum {
        CPU_FTRS_POSSIBLE =
@@ -473,16 +479,21 @@ enum {
 #endif
 #ifdef CONFIG_E500
            CPU_FTRS_E500 | CPU_FTRS_E500_2 | CPU_FTRS_E500MC |
+           CPU_FTRS_E5500 |
 #endif
            0,
 };
 #endif /* __powerpc64__ */
 
 #ifdef __powerpc64__
+#ifdef CONFIG_PPC_BOOK3E
+#define CPU_FTRS_ALWAYS                (CPU_FTRS_E5500)
+#else
 #define CPU_FTRS_ALWAYS                \
            (CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 &        \
            CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_POWER6 &       \
            CPU_FTRS_POWER7 & CPU_FTRS_CELL & CPU_FTRS_PA6T & CPU_FTRS_POSSIBLE)
+#endif
 #else
 enum {
        CPU_FTRS_ALWAYS =
@@ -513,6 +524,7 @@ enum {
 #endif
 #ifdef CONFIG_E500
            CPU_FTRS_E500 & CPU_FTRS_E500_2 & CPU_FTRS_E500MC &
+           CPU_FTRS_E5500 &
 #endif
            CPU_FTRS_POSSIBLE,
 };
index 811f04ac3660842baf72973b3786c3d8f9b92c6c..8d1569c290428e82db7d03cec9bca66c66dcf35b 100644 (file)
@@ -162,7 +162,7 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void);
  * on platforms where such control is possible.
  */
 #if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) ||\
-       defined(CONFIG_KPROBES)
+       defined(CONFIG_KPROBES) || defined(CONFIG_DYNAMIC_FTRACE)
 #define PAGE_KERNEL_TEXT       PAGE_KERNEL_X
 #else
 #define PAGE_KERNEL_TEXT       PAGE_KERNEL_ROX
index c9b68d07ac4fca3cdd8996e8a43d850034efb407..b9602ee06deb11ee4c80c8eeeb63a2757f587841 100644 (file)
@@ -1973,7 +1973,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .pvr_mask               = 0xffff0000,
                .pvr_value              = 0x80240000,
                .cpu_name               = "e5500",
-               .cpu_features           = CPU_FTRS_E500MC,
+               .cpu_features           = CPU_FTRS_E5500,
                .cpu_user_features      = COMMON_USER_BOOKE,
                .mmu_features           = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS |
                        MMU_FTR_USE_TLBILX,
index 3d3d416339dd1294ae31380ce0c8474c6eaa3b52..5b5e1f002a8ea2ef2053bb16ba20e1e110edd348 100644 (file)
@@ -163,7 +163,7 @@ static void crash_kexec_prepare_cpus(int cpu)
 }
 
 /* wait for all the CPUs to hit real mode but timeout if they don't come in */
-#if defined(CONFIG_PPC_STD_MMU_64) && defined(CONFIG_SMP)
+#ifdef CONFIG_PPC_STD_MMU_64
 static void crash_kexec_wait_realmode(int cpu)
 {
        unsigned int msecs;
@@ -188,9 +188,7 @@ static void crash_kexec_wait_realmode(int cpu)
        }
        mb();
 }
-#else
-static inline void crash_kexec_wait_realmode(int cpu) {}
-#endif
+#endif /* CONFIG_PPC_STD_MMU_64 */
 
 /*
  * This function will be called by secondary cpus or by kexec cpu
@@ -235,7 +233,9 @@ void crash_kexec_secondary(struct pt_regs *regs)
        crash_ipi_callback(regs);
 }
 
-#else
+#else  /* ! CONFIG_SMP */
+static inline void crash_kexec_wait_realmode(int cpu) {}
+
 static void crash_kexec_prepare_cpus(int cpu)
 {
        /*
@@ -255,7 +255,7 @@ void crash_kexec_secondary(struct pt_regs *regs)
 {
        cpus_in_sr = CPU_MASK_NONE;
 }
-#endif
+#endif /* CONFIG_SMP */
 
 /*
  * Register a function to be called on shutdown.  Only use this if you
index c00d4ca1ee157fc995629825b95af4b8b232a5bb..28581f1ad2c08a8494502e2335cfeef2a295577e 100644 (file)
@@ -527,7 +527,7 @@ static int ibmebus_bus_pm_resume_noirq(struct device *dev)
 
 #endif /* !CONFIG_SUSPEND */
 
-#ifdef CONFIG_HIBERNATION
+#ifdef CONFIG_HIBERNATE_CALLBACKS
 
 static int ibmebus_bus_pm_freeze(struct device *dev)
 {
@@ -665,7 +665,7 @@ static int ibmebus_bus_pm_restore_noirq(struct device *dev)
        return ret;
 }
 
-#else /* !CONFIG_HIBERNATION */
+#else /* !CONFIG_HIBERNATE_CALLBACKS */
 
 #define ibmebus_bus_pm_freeze          NULL
 #define ibmebus_bus_pm_thaw            NULL
@@ -676,7 +676,7 @@ static int ibmebus_bus_pm_restore_noirq(struct device *dev)
 #define ibmebus_bus_pm_poweroff_noirq  NULL
 #define ibmebus_bus_pm_restore_noirq   NULL
 
-#endif /* !CONFIG_HIBERNATION */
+#endif /* !CONFIG_HIBERNATE_CALLBACKS */
 
 static struct dev_pm_ops ibmebus_bus_dev_pm_ops = {
        .prepare = ibmebus_bus_pm_prepare,
index c834757bebc07663ba44f2c779f210a4f308637d..2b97b80d6d7d65911f951276eec81029cda748e6 100644 (file)
@@ -330,9 +330,11 @@ void __init find_legacy_serial_ports(void)
                if (!parent)
                        continue;
                if (of_match_node(legacy_serial_parents, parent) != NULL) {
-                       index = add_legacy_soc_port(np, np);
-                       if (index >= 0 && np == stdout)
-                               legacy_serial_console = index;
+                       if (of_device_is_available(np)) {
+                               index = add_legacy_soc_port(np, np);
+                               if (index >= 0 && np == stdout)
+                                       legacy_serial_console = index;
+                       }
                }
                of_node_put(parent);
        }
index c4063b7f49a0e5536ac441834a755cbe5840a7dd..822f63008ae11642b570986c7faf8ca61478ae10 100644 (file)
@@ -398,6 +398,25 @@ static int check_excludes(struct perf_event **ctrs, unsigned int cflags[],
        return 0;
 }
 
+static u64 check_and_compute_delta(u64 prev, u64 val)
+{
+       u64 delta = (val - prev) & 0xfffffffful;
+
+       /*
+        * POWER7 can roll back counter values, if the new value is smaller
+        * than the previous value it will cause the delta and the counter to
+        * have bogus values unless we rolled a counter over.  If a coutner is
+        * rolled back, it will be smaller, but within 256, which is the maximum
+        * number of events to rollback at once.  If we dectect a rollback
+        * return 0.  This can lead to a small lack of precision in the
+        * counters.
+        */
+       if (prev > val && (prev - val) < 256)
+               delta = 0;
+
+       return delta;
+}
+
 static void power_pmu_read(struct perf_event *event)
 {
        s64 val, delta, prev;
@@ -416,10 +435,11 @@ static void power_pmu_read(struct perf_event *event)
                prev = local64_read(&event->hw.prev_count);
                barrier();
                val = read_pmc(event->hw.idx);
+               delta = check_and_compute_delta(prev, val);
+               if (!delta)
+                       return;
        } while (local64_cmpxchg(&event->hw.prev_count, prev, val) != prev);
 
-       /* The counters are only 32 bits wide */
-       delta = (val - prev) & 0xfffffffful;
        local64_add(delta, &event->count);
        local64_sub(delta, &event->hw.period_left);
 }
@@ -449,8 +469,9 @@ static void freeze_limited_counters(struct cpu_hw_events *cpuhw,
                val = (event->hw.idx == 5) ? pmc5 : pmc6;
                prev = local64_read(&event->hw.prev_count);
                event->hw.idx = 0;
-               delta = (val - prev) & 0xfffffffful;
-               local64_add(delta, &event->count);
+               delta = check_and_compute_delta(prev, val);
+               if (delta)
+                       local64_add(delta, &event->count);
        }
 }
 
@@ -458,14 +479,16 @@ static void thaw_limited_counters(struct cpu_hw_events *cpuhw,
                                  unsigned long pmc5, unsigned long pmc6)
 {
        struct perf_event *event;
-       u64 val;
+       u64 val, prev;
        int i;
 
        for (i = 0; i < cpuhw->n_limited; ++i) {
                event = cpuhw->limited_counter[i];
                event->hw.idx = cpuhw->limited_hwidx[i];
                val = (event->hw.idx == 5) ? pmc5 : pmc6;
-               local64_set(&event->hw.prev_count, val);
+               prev = local64_read(&event->hw.prev_count);
+               if (check_and_compute_delta(prev, val))
+                       local64_set(&event->hw.prev_count, val);
                perf_event_update_userpage(event);
        }
 }
@@ -1197,7 +1220,7 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
 
        /* we don't have to worry about interrupts here */
        prev = local64_read(&event->hw.prev_count);
-       delta = (val - prev) & 0xfffffffful;
+       delta = check_and_compute_delta(prev, val);
        local64_add(delta, &event->count);
 
        /*
index 375480c56eb9fd6699c90e385dd1877affb3d052..f33acfd872ad31ef73df610b07a507d2e6bb78a1 100644 (file)
@@ -229,6 +229,9 @@ static u64 scan_dispatch_log(u64 stop_tb)
        u64 stolen = 0;
        u64 dtb;
 
+       if (!dtl)
+               return 0;
+
        if (i == vpa->dtl_idx)
                return 0;
        while (i < vpa->dtl_idx) {
index a830c5e806577b4c3f443e6617b3964dbf8ae62f..bc5f0dc6ae1e7686f7dd7a10823025d0e138fa13 100644 (file)
@@ -842,6 +842,7 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr)
        mpic_setup_this_cpu();
 }
 
+#ifdef CONFIG_PPC64
 #ifdef CONFIG_HOTPLUG_CPU
 static int smp_core99_cpu_notify(struct notifier_block *self,
                                 unsigned long action, void *hcpu)
@@ -879,7 +880,6 @@ static struct notifier_block __cpuinitdata smp_core99_cpu_nb = {
 
 static void __init smp_core99_bringup_done(void)
 {
-#ifdef CONFIG_PPC64
        extern void g5_phy_disable_cpu1(void);
 
        /* Close i2c bus if it was used for tb sync */
@@ -894,14 +894,14 @@ static void __init smp_core99_bringup_done(void)
                set_cpu_present(1, false);
                g5_phy_disable_cpu1();
        }
-#endif /* CONFIG_PPC64 */
-
 #ifdef CONFIG_HOTPLUG_CPU
        register_cpu_notifier(&smp_core99_cpu_nb);
 #endif
+
        if (ppc_md.progress)
                ppc_md.progress("smp_core99_bringup_done", 0x349);
 }
+#endif /* CONFIG_PPC64 */
 
 #ifdef CONFIG_HOTPLUG_CPU
 
@@ -975,7 +975,9 @@ static void pmac_cpu_die(void)
 struct smp_ops_t core99_smp_ops = {
        .message_pass   = smp_mpic_message_pass,
        .probe          = smp_core99_probe,
+#ifdef CONFIG_PPC64
        .bringup_done   = smp_core99_bringup_done,
+#endif
        .kick_cpu       = smp_core99_kick_cpu,
        .setup_cpu      = smp_core99_setup_cpu,
        .give_timebase  = smp_core99_give_timebase,
index 000724149089c032c45e375b30a0128e449d6e41..6c42cfde8415f31dacd0a981cee09535da581667 100644 (file)
@@ -287,14 +287,22 @@ static int alloc_dispatch_logs(void)
        int cpu, ret;
        struct paca_struct *pp;
        struct dtl_entry *dtl;
+       struct kmem_cache *dtl_cache;
 
        if (!firmware_has_feature(FW_FEATURE_SPLPAR))
                return 0;
 
+       dtl_cache = kmem_cache_create("dtl", DISPATCH_LOG_BYTES,
+                                               DISPATCH_LOG_BYTES, 0, NULL);
+       if (!dtl_cache) {
+               pr_warn("Failed to create dispatch trace log buffer cache\n");
+               pr_warn("Stolen time statistics will be unreliable\n");
+               return 0;
+       }
+
        for_each_possible_cpu(cpu) {
                pp = &paca[cpu];
-               dtl = kmalloc_node(DISPATCH_LOG_BYTES, GFP_KERNEL,
-                                  cpu_to_node(cpu));
+               dtl = kmem_cache_alloc(dtl_cache, GFP_KERNEL);
                if (!dtl) {
                        pr_warn("Failed to allocate dispatch trace log for cpu %d\n",
                                cpu);
index f8f7f28c6343682bc9b00ac7f4a754fe1d00cc47..68ca9290df9451886e74d24fa4834c15780979f5 100644 (file)
@@ -324,6 +324,11 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
        struct resource rsrc;
        const int *bus_range;
 
+       if (!of_device_is_available(dev)) {
+               pr_warning("%s: disabled\n", dev->full_name);
+               return -ENODEV;
+       }
+
        pr_debug("Adding PCI host bridge %s\n", dev->full_name);
 
        /* Fetch host bridge registers address */
index 14232d57369c4de4f373f76e095ec95bb559345e..49798532b477b8630c77a203dfb76c62ad3caf46 100644 (file)
@@ -1457,7 +1457,6 @@ int fsl_rio_setup(struct platform_device *dev)
        port->ops = ops;
        port->priv = priv;
        port->phys_efptr = 0x100;
-       rio_register_mport(port);
 
        priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1);
        rio_regs_win = priv->regs_win;
@@ -1504,6 +1503,9 @@ int fsl_rio_setup(struct platform_device *dev)
        dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n",
                        port->sys_size ? 65536 : 256);
 
+       if (rio_register_mport(port))
+               goto err;
+
        if (port->host_deviceid >= 0)
                out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST |
                        RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED);
index 02fb017fed472ed96d66aa1a4252b17b2f5bd677..a9da516a527416e12cfdc887939e2eb8cbd5020f 100644 (file)
@@ -4,6 +4,10 @@ menu "UML-specific options"
 
 menu "Host processor type and features"
 
+config CMPXCHG_LOCAL
+       bool
+       default n
+
 source "arch/x86/Kconfig.cpu"
 
 endmenu
diff --git a/arch/um/include/asm/bug.h b/arch/um/include/asm/bug.h
new file mode 100644 (file)
index 0000000..9e33b86
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __UM_BUG_H
+#define __UM_BUG_H
+
+#include <asm-generic/bug.h>
+
+#endif
index 43085bfc99c30f963b929a9c7afdcff932ad9236..156cd5d18d2abeabb26a0587cfffd15c52aa6f13 100644 (file)
@@ -66,7 +66,7 @@ static inline void gart_set_size_and_enable(struct pci_dev *dev, u32 order)
         * Don't enable translation but enable GART IO and CPU accesses.
         * Also, set DISTLBWALKPRB since GART tables memory is UC.
         */
-       ctl = DISTLBWALKPRB | order << 1;
+       ctl = order << 1;
 
        pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl);
 }
@@ -75,17 +75,17 @@ static inline void enable_gart_translation(struct pci_dev *dev, u64 addr)
 {
        u32 tmp, ctl;
 
-        /* address of the mappings table */
-        addr >>= 12;
-        tmp = (u32) addr<<4;
-        tmp &= ~0xf;
-        pci_write_config_dword(dev, AMD64_GARTTABLEBASE, tmp);
-
-        /* Enable GART translation for this hammer. */
-        pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl);
-        ctl |= GARTEN;
-        ctl &= ~(DISGARTCPU | DISGARTIO);
-        pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl);
+       /* address of the mappings table */
+       addr >>= 12;
+       tmp = (u32) addr<<4;
+       tmp &= ~0xf;
+       pci_write_config_dword(dev, AMD64_GARTTABLEBASE, tmp);
+
+       /* Enable GART translation for this hammer. */
+       pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl);
+       ctl |= GARTEN | DISTLBWALKPRB;
+       ctl &= ~(DISGARTCPU | DISGARTIO);
+       pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl);
 }
 
 static inline int aperture_valid(u64 aper_base, u32 aper_size, u32 min_size)
index fd5a1f365c95105ebe095c33df1dfbf91e1715a1..3cce71413d0be86278a7037eccc692d3d205b4e8 100644 (file)
 #define MSR_IA32_MC0_ADDR              0x00000402
 #define MSR_IA32_MC0_MISC              0x00000403
 
+#define MSR_AMD64_MC0_MASK             0xc0010044
+
 #define MSR_IA32_MCx_CTL(x)            (MSR_IA32_MC0_CTL + 4*(x))
 #define MSR_IA32_MCx_STATUS(x)         (MSR_IA32_MC0_STATUS + 4*(x))
 #define MSR_IA32_MCx_ADDR(x)           (MSR_IA32_MC0_ADDR + 4*(x))
 #define MSR_IA32_MCx_MISC(x)           (MSR_IA32_MC0_MISC + 4*(x))
 
+#define MSR_AMD64_MCx_MASK(x)          (MSR_AMD64_MC0_MASK + (x))
+
 /* These are consecutive and not in the normal 4er MCE bank block */
 #define MSR_IA32_MC0_CTL2              0x00000280
 #define MSR_IA32_MCx_CTL2(x)           (MSR_IA32_MC0_CTL2 + (x))
index 86d1ad4962a73a352ec22625658bec7deca21d7c..73fb469908c6852476c10a75a05aa49329f386b8 100644 (file)
@@ -499,7 +499,7 @@ out:
                 * Don't enable translation yet but enable GART IO and CPU
                 * accesses and set DISTLBWALKPRB since GART table memory is UC.
                 */
-               u32 ctl = DISTLBWALKPRB | aper_order << 1;
+               u32 ctl = aper_order << 1;
 
                bus = amd_nb_bus_dev_ranges[i].bus;
                dev_base = amd_nb_bus_dev_ranges[i].dev_base;
index 3ecece0217ef1c10e4bcab2a9cd64b9d10f94833..3532d3bf81050ef145a861b09c294980bf1674c3 100644 (file)
@@ -615,6 +615,25 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
        /* As a rule processors have APIC timer running in deep C states */
        if (c->x86 >= 0xf && !cpu_has_amd_erratum(amd_erratum_400))
                set_cpu_cap(c, X86_FEATURE_ARAT);
+
+       /*
+        * Disable GART TLB Walk Errors on Fam10h. We do this here
+        * because this is always needed when GART is enabled, even in a
+        * kernel which has no MCE support built in.
+        */
+       if (c->x86 == 0x10) {
+               /*
+                * BIOS should disable GartTlbWlk Errors themself. If
+                * it doesn't do it here as suggested by the BKDG.
+                *
+                * Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33012
+                */
+               u64 mask;
+
+               rdmsrl(MSR_AMD64_MCx_MASK(4), mask);
+               mask |= (1 << 10);
+               wrmsrl(MSR_AMD64_MCx_MASK(4), mask);
+       }
 }
 
 #ifdef CONFIG_X86_32
index 461f62bbd774a0adec028334f8c723e5a33bea1d..cf4e369cea6793ab3b4eac82fcdcd594547cd019 100644 (file)
@@ -8,7 +8,7 @@ static __initconst const u64 amd_hw_cache_event_ids
  [ C(L1D) ] = {
        [ C(OP_READ) ] = {
                [ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses        */
-               [ C(RESULT_MISS)   ] = 0x0041, /* Data Cache Misses          */
+               [ C(RESULT_MISS)   ] = 0x0141, /* Data Cache Misses          */
        },
        [ C(OP_WRITE) ] = {
                [ C(RESULT_ACCESS) ] = 0x0142, /* Data Cache Refills :system */
@@ -427,7 +427,9 @@ static __initconst const struct x86_pmu amd_pmu = {
  *
  * Exceptions:
  *
+ * 0x000       FP      PERF_CTL[3], PERF_CTL[5:3] (*)
  * 0x003       FP      PERF_CTL[3]
+ * 0x004       FP      PERF_CTL[3], PERF_CTL[5:3] (*)
  * 0x00B       FP      PERF_CTL[3]
  * 0x00D       FP      PERF_CTL[3]
  * 0x023       DE      PERF_CTL[2:0]
@@ -448,6 +450,8 @@ static __initconst const struct x86_pmu amd_pmu = {
  * 0x0DF       LS      PERF_CTL[5:0]
  * 0x1D6       EX      PERF_CTL[5:0]
  * 0x1D8       EX      PERF_CTL[5:0]
+ *
+ * (*) depending on the umask all FPU counters may be used
  */
 
 static struct event_constraint amd_f15_PMC0  = EVENT_CONSTRAINT(0, 0x01, 0);
@@ -460,18 +464,28 @@ static struct event_constraint amd_f15_PMC53 = EVENT_CONSTRAINT(0, 0x38, 0);
 static struct event_constraint *
 amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *event)
 {
-       unsigned int event_code = amd_get_event_code(&event->hw);
+       struct hw_perf_event *hwc = &event->hw;
+       unsigned int event_code = amd_get_event_code(hwc);
 
        switch (event_code & AMD_EVENT_TYPE_MASK) {
        case AMD_EVENT_FP:
                switch (event_code) {
+               case 0x000:
+                       if (!(hwc->config & 0x0000F000ULL))
+                               break;
+                       if (!(hwc->config & 0x00000F00ULL))
+                               break;
+                       return &amd_f15_PMC3;
+               case 0x004:
+                       if (hweight_long(hwc->config & ARCH_PERFMON_EVENTSEL_UMASK) <= 1)
+                               break;
+                       return &amd_f15_PMC3;
                case 0x003:
                case 0x00B:
                case 0x00D:
                        return &amd_f15_PMC3;
-               default:
-                       return &amd_f15_PMC53;
                }
+               return &amd_f15_PMC53;
        case AMD_EVENT_LS:
        case AMD_EVENT_DC:
        case AMD_EVENT_EX_LS:
index 82ada01625b98c111a41fbecf72fdd026c08e5f1..b117efd24f71f589286aac56e0b50fb235dac0cc 100644 (file)
@@ -81,6 +81,9 @@ static u32 gart_unmapped_entry;
 #define AGPEXTERN
 #endif
 
+/* GART can only remap to physical addresses < 1TB */
+#define GART_MAX_PHYS_ADDR     (1ULL << 40)
+
 /* backdoor interface to AGP driver */
 AGPEXTERN int agp_memory_reserved;
 AGPEXTERN __u32 *agp_gatt_table;
@@ -212,9 +215,13 @@ static dma_addr_t dma_map_area(struct device *dev, dma_addr_t phys_mem,
                                size_t size, int dir, unsigned long align_mask)
 {
        unsigned long npages = iommu_num_pages(phys_mem, size, PAGE_SIZE);
-       unsigned long iommu_page = alloc_iommu(dev, npages, align_mask);
+       unsigned long iommu_page;
        int i;
 
+       if (unlikely(phys_mem + size > GART_MAX_PHYS_ADDR))
+               return bad_dma_addr;
+
+       iommu_page = alloc_iommu(dev, npages, align_mask);
        if (iommu_page == -1) {
                if (!nonforced_iommu(dev, phys_mem, size))
                        return phys_mem;
index c2871d3c71b64a62c2902a8e5b48178264c4e788..8ed8908cc9f79ab06d828d181555255fa9f65c82 100644 (file)
@@ -312,6 +312,26 @@ void __cpuinit smp_store_cpu_info(int id)
                identify_secondary_cpu(c);
 }
 
+static void __cpuinit check_cpu_siblings_on_same_node(int cpu1, int cpu2)
+{
+       int node1 = early_cpu_to_node(cpu1);
+       int node2 = early_cpu_to_node(cpu2);
+
+       /*
+        * Our CPU scheduler assumes all logical cpus in the same physical cpu
+        * share the same node. But, buggy ACPI or NUMA emulation might assign
+        * them to different node. Fix it.
+        */
+       if (node1 != node2) {
+               pr_warning("CPU %d in node %d and CPU %d in node %d are in the same physical CPU. forcing same node %d\n",
+                          cpu1, node1, cpu2, node2, node2);
+
+               numa_remove_cpu(cpu1);
+               numa_set_node(cpu1, node2);
+               numa_add_cpu(cpu1);
+       }
+}
+
 static void __cpuinit link_thread_siblings(int cpu1, int cpu2)
 {
        cpumask_set_cpu(cpu1, cpu_sibling_mask(cpu2));
@@ -320,6 +340,7 @@ static void __cpuinit link_thread_siblings(int cpu1, int cpu2)
        cpumask_set_cpu(cpu2, cpu_core_mask(cpu1));
        cpumask_set_cpu(cpu1, cpu_llc_shared_mask(cpu2));
        cpumask_set_cpu(cpu2, cpu_llc_shared_mask(cpu1));
+       check_cpu_siblings_on_same_node(cpu1, cpu2);
 }
 
 
@@ -361,10 +382,12 @@ void __cpuinit set_cpu_sibling_map(int cpu)
                    per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
                        cpumask_set_cpu(i, cpu_llc_shared_mask(cpu));
                        cpumask_set_cpu(cpu, cpu_llc_shared_mask(i));
+                       check_cpu_siblings_on_same_node(cpu, i);
                }
                if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
                        cpumask_set_cpu(i, cpu_core_mask(cpu));
                        cpumask_set_cpu(cpu, cpu_core_mask(i));
+                       check_cpu_siblings_on_same_node(cpu, i);
                        /*
                         *  Does this new cpu bringup a new core?
                         */
index dc701ea585461a3735085447b8e13af6f77b178b..2d6d226f2b10fc511897bd484d25f15c6eef22c1 100644 (file)
@@ -74,6 +74,7 @@
                                compatible = "intel,ce4100-pci", "pci";
                                device_type = "pci";
                                bus-range = <1 1>;
+                               reg = <0x0800 0x0 0x0 0x0 0x0>;
                                ranges = <0x2000000 0 0xdffe0000 0x2000000 0 0xdffe0000 0 0x1000>;
 
                                interrupt-parent = <&ioapic2>;
                                #address-cells = <2>;
                                #size-cells = <1>;
                                compatible = "isa";
+                               reg = <0xf800 0x0 0x0 0x0 0x0>;
                                ranges = <1 0 0 0 0 0x100>;
 
                                rtc@70 {
index 5c0207bf959bc4a8490347d775eba452c13f2684..275dbc19e2cf55f2e7cb55f1c3ad861cb976c8a6 100644 (file)
@@ -97,11 +97,11 @@ static int __init sfi_parse_mtmr(struct sfi_table_header *table)
                        pentry->freq_hz, pentry->irq);
                        if (!pentry->irq)
                                continue;
-                       mp_irq.type = MP_IOAPIC;
+                       mp_irq.type = MP_INTSRC;
                        mp_irq.irqtype = mp_INT;
 /* triggering mode edge bit 2-3, active high polarity bit 0-1 */
                        mp_irq.irqflag = 5;
-                       mp_irq.srcbus = 0;
+                       mp_irq.srcbus = MP_BUS_ISA;
                        mp_irq.srcbusirq = pentry->irq; /* IRQ */
                        mp_irq.dstapic = MP_APIC_ALL;
                        mp_irq.dstirq = pentry->irq;
@@ -168,10 +168,10 @@ int __init sfi_parse_mrtc(struct sfi_table_header *table)
        for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) {
                pr_debug("RTC[%d]: paddr = 0x%08x, irq = %d\n",
                        totallen, (u32)pentry->phys_addr, pentry->irq);
-               mp_irq.type = MP_IOAPIC;
+               mp_irq.type = MP_INTSRC;
                mp_irq.irqtype = mp_INT;
                mp_irq.irqflag = 0xf;   /* level trigger and active low */
-               mp_irq.srcbus = 0;
+               mp_irq.srcbus = MP_BUS_ISA;
                mp_irq.srcbusirq = pentry->irq; /* IRQ */
                mp_irq.dstapic = MP_APIC_ALL;
                mp_irq.dstirq = pentry->irq;
@@ -282,7 +282,7 @@ void __init x86_mrst_early_setup(void)
        /* Avoid searching for BIOS MP tables */
        x86_init.mpparse.find_smp_config = x86_init_noop;
        x86_init.mpparse.get_smp_config = x86_init_uint_noop;
-
+       set_bit(MP_BUS_ISA, mp_bus_not_pci);
 }
 
 /*
index 1c7121ba18ffdc902740c396427e448ae62250d4..5cc821cb2e0968090501e8c6e5af36353d5e2f87 100644 (file)
@@ -39,6 +39,7 @@ config XEN_MAX_DOMAIN_MEMORY
 config XEN_SAVE_RESTORE
        bool
        depends on XEN
+       select HIBERNATE_CALLBACKS
        default y
 
 config XEN_DEBUG_FS
index 49dbd78ec3cb0d4481e72e96cdb041507b5ae686..e3c6a06cf725ef08b87a5961b33043bbf493acf3 100644 (file)
@@ -238,6 +238,7 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx,
 static __init void xen_init_cpuid_mask(void)
 {
        unsigned int ax, bx, cx, dx;
+       unsigned int xsave_mask;
 
        cpuid_leaf1_edx_mask =
                ~((1 << X86_FEATURE_MCE)  |  /* disable MCE */
@@ -249,24 +250,16 @@ static __init void xen_init_cpuid_mask(void)
                cpuid_leaf1_edx_mask &=
                        ~((1 << X86_FEATURE_APIC) |  /* disable local APIC */
                          (1 << X86_FEATURE_ACPI));  /* disable ACPI */
-
        ax = 1;
-       cx = 0;
        xen_cpuid(&ax, &bx, &cx, &dx);
 
-       /* cpuid claims we support xsave; try enabling it to see what happens */
-       if (cx & (1 << (X86_FEATURE_XSAVE % 32))) {
-               unsigned long cr4;
-
-               set_in_cr4(X86_CR4_OSXSAVE);
-               
-               cr4 = read_cr4();
+       xsave_mask =
+               (1 << (X86_FEATURE_XSAVE % 32)) |
+               (1 << (X86_FEATURE_OSXSAVE % 32));
 
-               if ((cr4 & X86_CR4_OSXSAVE) == 0)
-                       cpuid_leaf1_ecx_mask &= ~(1 << (X86_FEATURE_XSAVE % 32));
-
-               clear_in_cr4(X86_CR4_OSXSAVE);
-       }
+       /* Xen will set CR4.OSXSAVE if supported and not disabled by force */
+       if ((cx & xsave_mask) != xsave_mask)
+               cpuid_leaf1_ecx_mask &= ~xsave_mask; /* disable XSAVE & OSXSAVE */
 }
 
 static void xen_set_debugreg(int reg, unsigned long val)
index c82df6c9c0f0a4a1bbc61f1ea881ebdd37fecdef..aef7af92b28b620003a7fa102983324bf9041e09 100644 (file)
@@ -565,13 +565,13 @@ pte_t xen_make_pte_debug(pteval_t pte)
        if (io_page &&
            (xen_initial_domain() || addr >= ISA_END_ADDRESS)) {
                other_addr = pfn_to_mfn(addr >> PAGE_SHIFT) << PAGE_SHIFT;
-               WARN(addr != other_addr,
+               WARN_ONCE(addr != other_addr,
                        "0x%lx is using VM_IO, but it is 0x%lx!\n",
                        (unsigned long)addr, (unsigned long)other_addr);
        } else {
                pteval_t iomap_set = (_pte.pte & PTE_FLAGS_MASK) & _PAGE_IOMAP;
                other_addr = (_pte.pte & PTE_PFN_MASK);
-               WARN((addr == other_addr) && (!io_page) && (!iomap_set),
+               WARN_ONCE((addr == other_addr) && (!io_page) && (!iomap_set),
                        "0x%lx is missing VM_IO (and wasn't fixed)!\n",
                        (unsigned long)addr);
        }
@@ -1473,16 +1473,20 @@ static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd)
 #endif
 }
 
+#ifdef CONFIG_X86_32
 static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
 {
-       unsigned long pfn = pte_pfn(pte);
-
-#ifdef CONFIG_X86_32
        /* If there's an existing pte, then don't allow _PAGE_RW to be set */
        if (pte_val_ma(*ptep) & _PAGE_PRESENT)
                pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) &
                               pte_val_ma(pte));
-#endif
+
+       return pte;
+}
+#else /* CONFIG_X86_64 */
+static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
+{
+       unsigned long pfn = pte_pfn(pte);
 
        /*
         * If the new pfn is within the range of the newly allocated
@@ -1497,6 +1501,7 @@ static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
 
        return pte;
 }
+#endif /* CONFIG_X86_64 */
 
 /* Init-time set_pte while constructing initial pagetables, which
    doesn't allow RO pagetable pages to be remapped RW */
index fa0269a993773f8488f765c3a1e255ba59fd4e3f..90bac0aac3a5d42f3c45b48c3980e0fb432eee03 100644 (file)
@@ -227,7 +227,7 @@ char * __init xen_memory_setup(void)
 
        memcpy(map_raw, map, sizeof(map));
        e820.nr_map = 0;
-       xen_extra_mem_start = mem_end;
+       xen_extra_mem_start = max((1ULL << 32), mem_end);
        for (i = 0; i < memmap.nr_entries; i++) {
                unsigned long long end;
 
index 90f22cc30799cf8bf71e25c4cf68718c3fbf0cf3..a2e58eeb35499d5f44502a650c822ec000007d4e 100644 (file)
@@ -198,26 +198,13 @@ void blk_dump_rq_flags(struct request *rq, char *msg)
 }
 EXPORT_SYMBOL(blk_dump_rq_flags);
 
-/*
- * Make sure that plugs that were pending when this function was entered,
- * are now complete and requests pushed to the queue.
-*/
-static inline void queue_sync_plugs(struct request_queue *q)
-{
-       /*
-        * If the current process is plugged and has barriers submitted,
-        * we will livelock if we don't unplug first.
-        */
-       blk_flush_plug(current);
-}
-
 static void blk_delay_work(struct work_struct *work)
 {
        struct request_queue *q;
 
        q = container_of(work, struct request_queue, delay_work.work);
        spin_lock_irq(q->queue_lock);
-       __blk_run_queue(q, false);
+       __blk_run_queue(q);
        spin_unlock_irq(q->queue_lock);
 }
 
@@ -233,7 +220,8 @@ static void blk_delay_work(struct work_struct *work)
  */
 void blk_delay_queue(struct request_queue *q, unsigned long msecs)
 {
-       schedule_delayed_work(&q->delay_work, msecs_to_jiffies(msecs));
+       queue_delayed_work(kblockd_workqueue, &q->delay_work,
+                               msecs_to_jiffies(msecs));
 }
 EXPORT_SYMBOL(blk_delay_queue);
 
@@ -251,7 +239,7 @@ void blk_start_queue(struct request_queue *q)
        WARN_ON(!irqs_disabled());
 
        queue_flag_clear(QUEUE_FLAG_STOPPED, q);
-       __blk_run_queue(q, false);
+       __blk_run_queue(q);
 }
 EXPORT_SYMBOL(blk_start_queue);
 
@@ -298,37 +286,41 @@ void blk_sync_queue(struct request_queue *q)
 {
        del_timer_sync(&q->timeout);
        cancel_delayed_work_sync(&q->delay_work);
-       queue_sync_plugs(q);
 }
 EXPORT_SYMBOL(blk_sync_queue);
 
 /**
  * __blk_run_queue - run a single device queue
  * @q: The queue to run
- * @force_kblockd: Don't run @q->request_fn directly.  Use kblockd.
  *
  * Description:
  *    See @blk_run_queue. This variant must be called with the queue lock
  *    held and interrupts disabled.
- *
  */
-void __blk_run_queue(struct request_queue *q, bool force_kblockd)
+void __blk_run_queue(struct request_queue *q)
 {
        if (unlikely(blk_queue_stopped(q)))
                return;
 
-       /*
-        * Only recurse once to avoid overrunning the stack, let the unplug
-        * handling reinvoke the handler shortly if we already got there.
-        */
-       if (!force_kblockd && !queue_flag_test_and_set(QUEUE_FLAG_REENTER, q)) {
-               q->request_fn(q);
-               queue_flag_clear(QUEUE_FLAG_REENTER, q);
-       } else
-               queue_delayed_work(kblockd_workqueue, &q->delay_work, 0);
+       q->request_fn(q);
 }
 EXPORT_SYMBOL(__blk_run_queue);
 
+/**
+ * blk_run_queue_async - run a single device queue in workqueue context
+ * @q: The queue to run
+ *
+ * Description:
+ *    Tells kblockd to perform the equivalent of @blk_run_queue on behalf
+ *    of us.
+ */
+void blk_run_queue_async(struct request_queue *q)
+{
+       if (likely(!blk_queue_stopped(q)))
+               queue_delayed_work(kblockd_workqueue, &q->delay_work, 0);
+}
+EXPORT_SYMBOL(blk_run_queue_async);
+
 /**
  * blk_run_queue - run a single device queue
  * @q: The queue to run
@@ -342,7 +334,7 @@ void blk_run_queue(struct request_queue *q)
        unsigned long flags;
 
        spin_lock_irqsave(q->queue_lock, flags);
-       __blk_run_queue(q, false);
+       __blk_run_queue(q);
        spin_unlock_irqrestore(q->queue_lock, flags);
 }
 EXPORT_SYMBOL(blk_run_queue);
@@ -991,7 +983,7 @@ void blk_insert_request(struct request_queue *q, struct request *rq,
                blk_queue_end_tag(q, rq);
 
        add_acct_request(q, rq, where);
-       __blk_run_queue(q, false);
+       __blk_run_queue(q);
        spin_unlock_irqrestore(q->queue_lock, flags);
 }
 EXPORT_SYMBOL(blk_insert_request);
@@ -1311,7 +1303,15 @@ get_rq:
 
        plug = current->plug;
        if (plug) {
-               if (!plug->should_sort && !list_empty(&plug->list)) {
+               /*
+                * If this is the first request added after a plug, fire
+                * of a plug trace. If others have been added before, check
+                * if we have multiple devices in this plug. If so, make a
+                * note to sort the list before dispatch.
+                */
+               if (list_empty(&plug->list))
+                       trace_block_plug(q);
+               else if (!plug->should_sort) {
                        struct request *__rq;
 
                        __rq = list_entry_rq(plug->list.prev);
@@ -1327,7 +1327,7 @@ get_rq:
        } else {
                spin_lock_irq(q->queue_lock);
                add_acct_request(q, req, where);
-               __blk_run_queue(q, false);
+               __blk_run_queue(q);
 out_unlock:
                spin_unlock_irq(q->queue_lock);
        }
@@ -2644,6 +2644,7 @@ void blk_start_plug(struct blk_plug *plug)
 
        plug->magic = PLUG_MAGIC;
        INIT_LIST_HEAD(&plug->list);
+       INIT_LIST_HEAD(&plug->cb_list);
        plug->should_sort = 0;
 
        /*
@@ -2668,33 +2669,93 @@ static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b)
        return !(rqa->q <= rqb->q);
 }
 
-static void flush_plug_list(struct blk_plug *plug)
+/*
+ * If 'from_schedule' is true, then postpone the dispatch of requests
+ * until a safe kblockd context. We due this to avoid accidental big
+ * additional stack usage in driver dispatch, in places where the originally
+ * plugger did not intend it.
+ */
+static void queue_unplugged(struct request_queue *q, unsigned int depth,
+                           bool from_schedule)
+       __releases(q->queue_lock)
+{
+       trace_block_unplug(q, depth, !from_schedule);
+
+       /*
+        * If we are punting this to kblockd, then we can safely drop
+        * the queue_lock before waking kblockd (which needs to take
+        * this lock).
+        */
+       if (from_schedule) {
+               spin_unlock(q->queue_lock);
+               blk_run_queue_async(q);
+       } else {
+               __blk_run_queue(q);
+               spin_unlock(q->queue_lock);
+       }
+
+}
+
+static void flush_plug_callbacks(struct blk_plug *plug)
+{
+       LIST_HEAD(callbacks);
+
+       if (list_empty(&plug->cb_list))
+               return;
+
+       list_splice_init(&plug->cb_list, &callbacks);
+
+       while (!list_empty(&callbacks)) {
+               struct blk_plug_cb *cb = list_first_entry(&callbacks,
+                                                         struct blk_plug_cb,
+                                                         list);
+               list_del(&cb->list);
+               cb->callback(cb);
+       }
+}
+
+void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule)
 {
        struct request_queue *q;
        unsigned long flags;
        struct request *rq;
+       LIST_HEAD(list);
+       unsigned int depth;
 
        BUG_ON(plug->magic != PLUG_MAGIC);
 
+       flush_plug_callbacks(plug);
        if (list_empty(&plug->list))
                return;
 
-       if (plug->should_sort)
-               list_sort(NULL, &plug->list, plug_rq_cmp);
+       list_splice_init(&plug->list, &list);
+
+       if (plug->should_sort) {
+               list_sort(NULL, &list, plug_rq_cmp);
+               plug->should_sort = 0;
+       }
 
        q = NULL;
+       depth = 0;
+
+       /*
+        * Save and disable interrupts here, to avoid doing it for every
+        * queue lock we have to take.
+        */
        local_irq_save(flags);
-       while (!list_empty(&plug->list)) {
-               rq = list_entry_rq(plug->list.next);
+       while (!list_empty(&list)) {
+               rq = list_entry_rq(list.next);
                list_del_init(&rq->queuelist);
                BUG_ON(!(rq->cmd_flags & REQ_ON_PLUG));
                BUG_ON(!rq->q);
                if (rq->q != q) {
-                       if (q) {
-                               __blk_run_queue(q, false);
-                               spin_unlock(q->queue_lock);
-                       }
+                       /*
+                        * This drops the queue lock
+                        */
+                       if (q)
+                               queue_unplugged(q, depth, from_schedule);
                        q = rq->q;
+                       depth = 0;
                        spin_lock(q->queue_lock);
                }
                rq->cmd_flags &= ~REQ_ON_PLUG;
@@ -2706,38 +2767,27 @@ static void flush_plug_list(struct blk_plug *plug)
                        __elv_add_request(q, rq, ELEVATOR_INSERT_FLUSH);
                else
                        __elv_add_request(q, rq, ELEVATOR_INSERT_SORT_MERGE);
-       }
 
-       if (q) {
-               __blk_run_queue(q, false);
-               spin_unlock(q->queue_lock);
+               depth++;
        }
 
-       BUG_ON(!list_empty(&plug->list));
-       local_irq_restore(flags);
-}
-
-static void __blk_finish_plug(struct task_struct *tsk, struct blk_plug *plug)
-{
-       flush_plug_list(plug);
+       /*
+        * This drops the queue lock
+        */
+       if (q)
+               queue_unplugged(q, depth, from_schedule);
 
-       if (plug == tsk->plug)
-               tsk->plug = NULL;
+       local_irq_restore(flags);
 }
 
 void blk_finish_plug(struct blk_plug *plug)
 {
-       if (plug)
-               __blk_finish_plug(current, plug);
-}
-EXPORT_SYMBOL(blk_finish_plug);
+       blk_flush_plug_list(plug, false);
 
-void __blk_flush_plug(struct task_struct *tsk, struct blk_plug *plug)
-{
-       __blk_finish_plug(tsk, plug);
-       tsk->plug = plug;
+       if (plug == current->plug)
+               current->plug = NULL;
 }
-EXPORT_SYMBOL(__blk_flush_plug);
+EXPORT_SYMBOL(blk_finish_plug);
 
 int __init blk_dev_init(void)
 {
index 7482b7fa863ba10b337d7547fb7040767e02b2da..81e31819a597bb0c6ed6dd4f781eb037c986a243 100644 (file)
@@ -55,7 +55,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
        WARN_ON(irqs_disabled());
        spin_lock_irq(q->queue_lock);
        __elv_add_request(q, rq, where);
-       __blk_run_queue(q, false);
+       __blk_run_queue(q);
        /* the queue is stopped so it won't be plugged+unplugged */
        if (rq->cmd_type == REQ_TYPE_PM_RESUME)
                q->request_fn(q);
index eba4a2790c6c4ba2e0467ca58300050e190d6804..6c9b5e189e624888860e5185d1d9b3479b3e49a4 100644 (file)
@@ -218,7 +218,7 @@ static void flush_end_io(struct request *flush_rq, int error)
         * request_fn may confuse the driver.  Always use kblockd.
         */
        if (queued)
-               __blk_run_queue(q, true);
+               blk_run_queue_async(q);
 }
 
 /**
@@ -274,7 +274,7 @@ static void flush_data_end_io(struct request *rq, int error)
         * the comment in flush_end_io().
         */
        if (blk_flush_complete_seq(rq, REQ_FSEQ_DATA, error))
-               __blk_run_queue(q, true);
+               blk_run_queue_async(q);
 }
 
 /**
index 261c75c665ae381a4c12dd444f7ed3b847c155a0..bd236313f35d59bd08da5a3d375cc29eed6fd86f 100644 (file)
@@ -66,14 +66,14 @@ queue_requests_store(struct request_queue *q, const char *page, size_t count)
 
        if (rl->count[BLK_RW_SYNC] >= q->nr_requests) {
                blk_set_queue_full(q, BLK_RW_SYNC);
-       } else if (rl->count[BLK_RW_SYNC]+1 <= q->nr_requests) {
+       } else {
                blk_clear_queue_full(q, BLK_RW_SYNC);
                wake_up(&rl->wait[BLK_RW_SYNC]);
        }
 
        if (rl->count[BLK_RW_ASYNC] >= q->nr_requests) {
                blk_set_queue_full(q, BLK_RW_ASYNC);
-       } else if (rl->count[BLK_RW_ASYNC]+1 <= q->nr_requests) {
+       } else {
                blk_clear_queue_full(q, BLK_RW_ASYNC);
                wake_up(&rl->wait[BLK_RW_ASYNC]);
        }
@@ -498,7 +498,6 @@ int blk_register_queue(struct gendisk *disk)
 {
        int ret;
        struct device *dev = disk_to_dev(disk);
-
        struct request_queue *q = disk->queue;
 
        if (WARN_ON(!q))
@@ -509,8 +508,10 @@ int blk_register_queue(struct gendisk *disk)
                return ret;
 
        ret = kobject_add(&q->kobj, kobject_get(&dev->kobj), "%s", "queue");
-       if (ret < 0)
+       if (ret < 0) {
+               blk_trace_remove_sysfs(dev);
                return ret;
+       }
 
        kobject_uevent(&q->kobj, KOBJ_ADD);
 
@@ -521,7 +522,7 @@ int blk_register_queue(struct gendisk *disk)
        if (ret) {
                kobject_uevent(&q->kobj, KOBJ_REMOVE);
                kobject_del(&q->kobj);
-               blk_trace_remove_sysfs(disk_to_dev(disk));
+               blk_trace_remove_sysfs(dev);
                kobject_put(&dev->kobj);
                return ret;
        }
index 3be881ec95ad06fa95ce0710dddb81f0cbef1c50..5b52011e3a40a38c1235e1729554abfbb9f99c7d 100644 (file)
@@ -2582,28 +2582,20 @@ static void cfq_put_queue(struct cfq_queue *cfqq)
 }
 
 /*
- * Must always be called with the rcu_read_lock() held
+ * Call func for each cic attached to this ioc.
  */
 static void
-__call_for_each_cic(struct io_context *ioc,
-                   void (*func)(struct io_context *, struct cfq_io_context *))
+call_for_each_cic(struct io_context *ioc,
+                 void (*func)(struct io_context *, struct cfq_io_context *))
 {
        struct cfq_io_context *cic;
        struct hlist_node *n;
 
+       rcu_read_lock();
+
        hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list)
                func(ioc, cic);
-}
 
-/*
- * Call func for each cic attached to this ioc.
- */
-static void
-call_for_each_cic(struct io_context *ioc,
-                 void (*func)(struct io_context *, struct cfq_io_context *))
-{
-       rcu_read_lock();
-       __call_for_each_cic(ioc, func);
        rcu_read_unlock();
 }
 
@@ -2664,7 +2656,7 @@ static void cfq_free_io_context(struct io_context *ioc)
         * should be ok to iterate over the known list, we will see all cic's
         * since no new ones are added.
         */
-       __call_for_each_cic(ioc, cic_free_func);
+       call_for_each_cic(ioc, cic_free_func);
 }
 
 static void cfq_put_cooperator(struct cfq_queue *cfqq)
@@ -3368,7 +3360,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                            cfqd->busy_queues > 1) {
                                cfq_del_timer(cfqd, cfqq);
                                cfq_clear_cfqq_wait_request(cfqq);
-                               __blk_run_queue(cfqd->queue, false);
+                               __blk_run_queue(cfqd->queue);
                        } else {
                                cfq_blkiocg_update_idle_time_stats(
                                                &cfqq->cfqg->blkg);
@@ -3383,7 +3375,7 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq,
                 * this new queue is RT and the current one is BE
                 */
                cfq_preempt_queue(cfqd, cfqq);
-               __blk_run_queue(cfqd->queue, false);
+               __blk_run_queue(cfqd->queue);
        }
 }
 
@@ -3743,7 +3735,7 @@ static void cfq_kick_queue(struct work_struct *work)
        struct request_queue *q = cfqd->queue;
 
        spin_lock_irq(q->queue_lock);
-       __blk_run_queue(cfqd->queue, false);
+       __blk_run_queue(cfqd->queue);
        spin_unlock_irq(q->queue_lock);
 }
 
index 0cdb4e7ebab4e8eba1e7ca1514525c1120948e5b..6f6abc08bb565e61d63294e1a14f66ac6cda6a3d 100644 (file)
@@ -642,7 +642,7 @@ void elv_quiesce_start(struct request_queue *q)
         */
        elv_drain_elevator(q);
        while (q->rq.elvpriv) {
-               __blk_run_queue(q, false);
+               __blk_run_queue(q);
                spin_unlock_irq(q->queue_lock);
                msleep(10);
                spin_lock_irq(q->queue_lock);
@@ -695,7 +695,7 @@ void __elv_add_request(struct request_queue *q, struct request *rq, int where)
                 *   with anything.  There's no point in delaying queue
                 *   processing.
                 */
-               __blk_run_queue(q, false);
+               __blk_run_queue(q);
                break;
 
        case ELEVATOR_INSERT_SORT_MERGE:
index 8210405031544e900bcc97f6a7d21c43a02923fb..7025593a58c89d39cb3ff260801b242730d8fdf2 100644 (file)
@@ -214,7 +214,7 @@ static int amba_pm_resume_noirq(struct device *dev)
 
 #endif /* !CONFIG_SUSPEND */
 
-#ifdef CONFIG_HIBERNATION
+#ifdef CONFIG_HIBERNATE_CALLBACKS
 
 static int amba_pm_freeze(struct device *dev)
 {
@@ -352,7 +352,7 @@ static int amba_pm_restore_noirq(struct device *dev)
        return ret;
 }
 
-#else /* !CONFIG_HIBERNATION */
+#else /* !CONFIG_HIBERNATE_CALLBACKS */
 
 #define amba_pm_freeze         NULL
 #define amba_pm_thaw           NULL
@@ -363,7 +363,7 @@ static int amba_pm_restore_noirq(struct device *dev)
 #define amba_pm_poweroff_noirq NULL
 #define amba_pm_restore_noirq  NULL
 
-#endif /* !CONFIG_HIBERNATION */
+#endif /* !CONFIG_HIBERNATE_CALLBACKS */
 
 #ifdef CONFIG_PM
 
index f051cfff18afe2e703bc6383d8b6277cdc652401..9e0e4fc24c46506e4adcfd6f4e429ad6ddced5f7 100644 (file)
@@ -149,6 +149,7 @@ static void platform_device_release(struct device *dev)
 
        of_device_node_put(&pa->pdev.dev);
        kfree(pa->pdev.dev.platform_data);
+       kfree(pa->pdev.mfd_cell);
        kfree(pa->pdev.resource);
        kfree(pa);
 }
@@ -771,7 +772,7 @@ int __weak platform_pm_resume_noirq(struct device *dev)
 
 #endif /* !CONFIG_SUSPEND */
 
-#ifdef CONFIG_HIBERNATION
+#ifdef CONFIG_HIBERNATE_CALLBACKS
 
 static int platform_pm_freeze(struct device *dev)
 {
@@ -909,7 +910,7 @@ static int platform_pm_restore_noirq(struct device *dev)
        return ret;
 }
 
-#else /* !CONFIG_HIBERNATION */
+#else /* !CONFIG_HIBERNATE_CALLBACKS */
 
 #define platform_pm_freeze             NULL
 #define platform_pm_thaw               NULL
@@ -920,7 +921,7 @@ static int platform_pm_restore_noirq(struct device *dev)
 #define platform_pm_poweroff_noirq     NULL
 #define platform_pm_restore_noirq      NULL
 
-#endif /* !CONFIG_HIBERNATION */
+#endif /* !CONFIG_HIBERNATE_CALLBACKS */
 
 #ifdef CONFIG_PM_RUNTIME
 
index 052dc53eef388db918f2a0f6ce961be366691577..fbc5b6e7c59156556cf4d02b0970411e0844dd80 100644 (file)
@@ -233,7 +233,7 @@ static int pm_op(struct device *dev,
                }
                break;
 #endif /* CONFIG_SUSPEND */
-#ifdef CONFIG_HIBERNATION
+#ifdef CONFIG_HIBERNATE_CALLBACKS
        case PM_EVENT_FREEZE:
        case PM_EVENT_QUIESCE:
                if (ops->freeze) {
@@ -260,7 +260,7 @@ static int pm_op(struct device *dev,
                        suspend_report_result(ops->restore, error);
                }
                break;
-#endif /* CONFIG_HIBERNATION */
+#endif /* CONFIG_HIBERNATE_CALLBACKS */
        default:
                error = -EINVAL;
        }
@@ -308,7 +308,7 @@ static int pm_noirq_op(struct device *dev,
                }
                break;
 #endif /* CONFIG_SUSPEND */
-#ifdef CONFIG_HIBERNATION
+#ifdef CONFIG_HIBERNATE_CALLBACKS
        case PM_EVENT_FREEZE:
        case PM_EVENT_QUIESCE:
                if (ops->freeze_noirq) {
@@ -335,7 +335,7 @@ static int pm_noirq_op(struct device *dev,
                        suspend_report_result(ops->restore_noirq, error);
                }
                break;
-#endif /* CONFIG_HIBERNATION */
+#endif /* CONFIG_HIBERNATE_CALLBACKS */
        default:
                error = -EINVAL;
        }
index d77005849af857935fe270725f2ee0d08561d265..219d88a0eeae07c1e963c4997f6894fe79046d2a 100644 (file)
@@ -142,6 +142,7 @@ static int cn_call_callback(struct sk_buff *skb)
                cbq->callback(msg, nsp);
                kfree_skb(skb);
                cn_queue_release_callback(cbq);
+               err = 0;
        }
 
        return err;
index 6b396759e7f596f54eab9d9bd28c06ae13fe6887..8a781540590cdf1e76e79c74d137a647c02642f6 100644 (file)
@@ -1448,7 +1448,7 @@ static const struct of_device_id fsldma_of_ids[] = {
        {}
 };
 
-static struct of_platform_driver fsldma_of_driver = {
+static struct platform_driver fsldma_of_driver = {
        .driver = {
                .name = "fsl-elo-dma",
                .owner = THIS_MODULE,
index 7f6f01a4b145ad00bc9c2b1fac7c704d67e145a4..0a775f7987c257237943879a1d08e5ac20f3cd14 100644 (file)
@@ -116,6 +116,7 @@ static int ioh_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
                reg_val |= (1 << nr);
        else
                reg_val &= ~(1 << nr);
+       iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
 
        mutex_unlock(&chip->lock);
 
index 583e92592073647481d52acf81cd1a520d0e9d85..7630ab7b9bec30cdad9628908d74813075413b65 100644 (file)
@@ -558,7 +558,7 @@ static int __devinit pca953x_probe(struct i2c_client *client,
 
        ret = gpiochip_add(&chip->gpio_chip);
        if (ret)
-               goto out_failed;
+               goto out_failed_irq;
 
        if (pdata->setup) {
                ret = pdata->setup(client, chip->gpio_chip.base,
@@ -570,8 +570,9 @@ static int __devinit pca953x_probe(struct i2c_client *client,
        i2c_set_clientdata(client, chip);
        return 0;
 
-out_failed:
+out_failed_irq:
        pca953x_irq_teardown(chip);
+out_failed:
        kfree(chip->dyn_pdata);
        kfree(chip);
        return ret;
index 2c6af87051030b1017cc5670fcbfd2bfddad61fa..f970a5f3585e03b5395b74f32f6103d21a67128d 100644 (file)
@@ -105,6 +105,7 @@ static int pch_gpio_direction_output(struct gpio_chip *gpio, unsigned nr,
                reg_val |= (1 << nr);
        else
                reg_val &= ~(1 << nr);
+       iowrite32(reg_val, &chip->reg->po);
 
        mutex_unlock(&chip->lock);
 
index 432fc04c6bffc1b58d8da1645a8a5687049a9bc2..e522c702b04e6387a07ae07f5917fb81835705ac 100644 (file)
@@ -3771,8 +3771,11 @@ static bool g4x_compute_wm0(struct drm_device *dev,
        int entries, tlb_miss;
 
        crtc = intel_get_crtc_for_plane(dev, plane);
-       if (crtc->fb == NULL || !crtc->enabled)
+       if (crtc->fb == NULL || !crtc->enabled) {
+               *cursor_wm = cursor->guard_size;
+               *plane_wm = display->guard_size;
                return false;
+       }
 
        htotal = crtc->mode.htotal;
        hdisplay = crtc->mode.hdisplay;
@@ -6215,36 +6218,6 @@ cleanup_work:
        return ret;
 }
 
-static void intel_crtc_reset(struct drm_crtc *crtc)
-{
-       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-       /* Reset flags back to the 'unknown' status so that they
-        * will be correctly set on the initial modeset.
-        */
-       intel_crtc->dpms_mode = -1;
-}
-
-static struct drm_crtc_helper_funcs intel_helper_funcs = {
-       .dpms = intel_crtc_dpms,
-       .mode_fixup = intel_crtc_mode_fixup,
-       .mode_set = intel_crtc_mode_set,
-       .mode_set_base = intel_pipe_set_base,
-       .mode_set_base_atomic = intel_pipe_set_base_atomic,
-       .load_lut = intel_crtc_load_lut,
-       .disable = intel_crtc_disable,
-};
-
-static const struct drm_crtc_funcs intel_crtc_funcs = {
-       .reset = intel_crtc_reset,
-       .cursor_set = intel_crtc_cursor_set,
-       .cursor_move = intel_crtc_cursor_move,
-       .gamma_set = intel_crtc_gamma_set,
-       .set_config = drm_crtc_helper_set_config,
-       .destroy = intel_crtc_destroy,
-       .page_flip = intel_crtc_page_flip,
-};
-
 static void intel_sanitize_modesetting(struct drm_device *dev,
                                       int pipe, int plane)
 {
@@ -6281,6 +6254,42 @@ static void intel_sanitize_modesetting(struct drm_device *dev,
        intel_disable_pipe(dev_priv, pipe);
 }
 
+static void intel_crtc_reset(struct drm_crtc *crtc)
+{
+       struct drm_device *dev = crtc->dev;
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+       /* Reset flags back to the 'unknown' status so that they
+        * will be correctly set on the initial modeset.
+        */
+       intel_crtc->dpms_mode = -1;
+
+       /* We need to fix up any BIOS configuration that conflicts with
+        * our expectations.
+        */
+       intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
+}
+
+static struct drm_crtc_helper_funcs intel_helper_funcs = {
+       .dpms = intel_crtc_dpms,
+       .mode_fixup = intel_crtc_mode_fixup,
+       .mode_set = intel_crtc_mode_set,
+       .mode_set_base = intel_pipe_set_base,
+       .mode_set_base_atomic = intel_pipe_set_base_atomic,
+       .load_lut = intel_crtc_load_lut,
+       .disable = intel_crtc_disable,
+};
+
+static const struct drm_crtc_funcs intel_crtc_funcs = {
+       .reset = intel_crtc_reset,
+       .cursor_set = intel_crtc_cursor_set,
+       .cursor_move = intel_crtc_cursor_move,
+       .gamma_set = intel_crtc_gamma_set,
+       .set_config = drm_crtc_helper_set_config,
+       .destroy = intel_crtc_destroy,
+       .page_flip = intel_crtc_page_flip,
+};
+
 static void intel_crtc_init(struct drm_device *dev, int pipe)
 {
        drm_i915_private_t *dev_priv = dev->dev_private;
@@ -6330,8 +6339,6 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
 
        setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
                    (unsigned long)intel_crtc);
-
-       intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
 }
 
 int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
index 4256b8ef3947454048d2d432c3375776983c3e06..6b22c1dcc015f406bf2fcdbc866511bc92f3d882 100644 (file)
@@ -1151,10 +1151,10 @@ intel_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
                            (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
        {
                int pipeconf_reg = PIPECONF(pipe);
-               int dspcntr_reg = DSPCNTR(pipe);
+               int dspcntr_reg = DSPCNTR(intel_crtc->plane);
                int pipeconf = I915_READ(pipeconf_reg);
                int dspcntr = I915_READ(dspcntr_reg);
-               int dspbase_reg = DSPADDR(pipe);
+               int dspbase_reg = DSPADDR(intel_crtc->plane);
                int xpos = 0x0, ypos = 0x0;
                unsigned int xsize, ysize;
                /* Pipe must be off here */
@@ -1378,7 +1378,9 @@ intel_tv_detect(struct drm_connector *connector, bool force)
        if (type < 0)
                return connector_status_disconnected;
 
+       intel_tv->type = type;
        intel_tv_find_better_format(connector);
+
        return connector_status_connected;
 }
 
@@ -1670,8 +1672,7 @@ intel_tv_init(struct drm_device *dev)
         *
         * More recent chipsets favour HDMI rather than integrated S-Video.
         */
-       connector->polled =
-               DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
+       connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 
        drm_connector_init(dev, connector, &intel_tv_connector_funcs,
                           DRM_MODE_CONNECTOR_SVIDEO);
index edfb92e41735df7f713a2283a12a299e764423ca..196ffafafd88ff3cebf37de7bae8d37494d2dc34 100644 (file)
@@ -139,7 +139,6 @@ struct pmbus_data {
         * A single status register covers multiple attributes,
         * so we keep them all together.
         */
-       u8 status_bits;
        u8 status[PB_NUM_STATUS_REG];
 
        u8 currpage;
index 38319a69bd0a9de978fc688bded38fa3dea90def..d6d58684712bc8b68cafb662316fe123e53b270d 100644 (file)
@@ -232,9 +232,17 @@ static int i2c_inb(struct i2c_adapter *i2c_adap)
  * Sanity check for the adapter hardware - check the reaction of
  * the bus lines only if it seems to be idle.
  */
-static int test_bus(struct i2c_algo_bit_data *adap, char *name)
+static int test_bus(struct i2c_adapter *i2c_adap)
 {
-       int scl, sda;
+       struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+       const char *name = i2c_adap->name;
+       int scl, sda, ret;
+
+       if (adap->pre_xfer) {
+               ret = adap->pre_xfer(i2c_adap);
+               if (ret < 0)
+                       return -ENODEV;
+       }
 
        if (adap->getscl == NULL)
                pr_info("%s: Testing SDA only, SCL is not readable\n", name);
@@ -297,11 +305,19 @@ static int test_bus(struct i2c_algo_bit_data *adap, char *name)
                       "while pulling SCL high!\n", name);
                goto bailout;
        }
+
+       if (adap->post_xfer)
+               adap->post_xfer(i2c_adap);
+
        pr_info("%s: Test OK\n", name);
        return 0;
 bailout:
        sdahi(adap);
        sclhi(adap);
+
+       if (adap->post_xfer)
+               adap->post_xfer(i2c_adap);
+
        return -ENODEV;
 }
 
@@ -607,7 +623,7 @@ static int __i2c_bit_add_bus(struct i2c_adapter *adap,
        int ret;
 
        if (bit_test) {
-               ret = test_bus(bit_adap, adap->name);
+               ret = test_bus(adap);
                if (ret < 0)
                        return -ENODEV;
        }
index 70c30e6bce0b2efcfbdee8f90bfd620d62319bd9..9a58994ff7ea54bd46cf6b576e9e43b10e736b79 100644 (file)
@@ -797,7 +797,8 @@ static int i2c_do_add_adapter(struct i2c_driver *driver,
 
        /* Let legacy drivers scan this bus for matching devices */
        if (driver->attach_adapter) {
-               dev_warn(&adap->dev, "attach_adapter method is deprecated\n");
+               dev_warn(&adap->dev, "%s: attach_adapter method is deprecated\n",
+                        driver->driver.name);
                dev_warn(&adap->dev, "Please use another way to instantiate "
                         "your i2c_client\n");
                /* We ignore the return code; if it fails, too bad */
@@ -984,7 +985,8 @@ static int i2c_do_del_adapter(struct i2c_driver *driver,
 
        if (!driver->detach_adapter)
                return 0;
-       dev_warn(&adapter->dev, "detach_adapter method is deprecated\n");
+       dev_warn(&adapter->dev, "%s: detach_adapter method is deprecated\n",
+                driver->driver.name);
        res = driver->detach_adapter(adapter);
        if (res)
                dev_err(&adapter->dev, "detach_adapter failed (%d) "
index 7f42d3a454d2d6aaebdc41e0e5a8c6700d6a00df..88d8e4cb419a1d0d6cc17828894dc4d3b67e0201 100644 (file)
@@ -39,13 +39,13 @@ struct evdev {
 };
 
 struct evdev_client {
-       int head;
-       int tail;
+       unsigned int head;
+       unsigned int tail;
        spinlock_t buffer_lock; /* protects access to buffer, head and tail */
        struct fasync_struct *fasync;
        struct evdev *evdev;
        struct list_head node;
-       int bufsize;
+       unsigned int bufsize;
        struct input_event buffer[];
 };
 
@@ -55,16 +55,25 @@ static DEFINE_MUTEX(evdev_table_mutex);
 static void evdev_pass_event(struct evdev_client *client,
                             struct input_event *event)
 {
-       /*
-        * Interrupts are disabled, just acquire the lock.
-        * Make sure we don't leave with the client buffer
-        * "empty" by having client->head == client->tail.
-        */
+       /* Interrupts are disabled, just acquire the lock. */
        spin_lock(&client->buffer_lock);
-       do {
-               client->buffer[client->head++] = *event;
-               client->head &= client->bufsize - 1;
-       } while (client->head == client->tail);
+
+       client->buffer[client->head++] = *event;
+       client->head &= client->bufsize - 1;
+
+       if (unlikely(client->head == client->tail)) {
+               /*
+                * This effectively "drops" all unconsumed events, leaving
+                * EV_SYN/SYN_DROPPED plus the newest event in the queue.
+                */
+               client->tail = (client->head - 2) & (client->bufsize - 1);
+
+               client->buffer[client->tail].time = event->time;
+               client->buffer[client->tail].type = EV_SYN;
+               client->buffer[client->tail].code = SYN_DROPPED;
+               client->buffer[client->tail].value = 0;
+       }
+
        spin_unlock(&client->buffer_lock);
 
        if (event->type == EV_SYN)
index d6e8bd8a851c26d0e4718d10d30977451bb28009..ebbceedc92f4fb8a9f8bc959734be4b442586d01 100644 (file)
@@ -1746,6 +1746,42 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int
 }
 EXPORT_SYMBOL(input_set_capability);
 
+static unsigned int input_estimate_events_per_packet(struct input_dev *dev)
+{
+       int mt_slots;
+       int i;
+       unsigned int events;
+
+       if (dev->mtsize) {
+               mt_slots = dev->mtsize;
+       } 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);
+       } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
+               mt_slots = 2;
+       } else {
+               mt_slots = 0;
+       }
+
+       events = mt_slots + 1; /* count SYN_MT_REPORT and SYN_REPORT */
+
+       for (i = 0; i < ABS_CNT; i++) {
+               if (test_bit(i, dev->absbit)) {
+                       if (input_is_mt_axis(i))
+                               events += mt_slots;
+                       else
+                               events++;
+               }
+       }
+
+       for (i = 0; i < REL_CNT; i++)
+               if (test_bit(i, dev->relbit))
+                       events++;
+
+       return events;
+}
+
 #define INPUT_CLEANSE_BITMASK(dev, type, bits)                         \
        do {                                                            \
                if (!test_bit(EV_##type, dev->evbit))                   \
@@ -1793,6 +1829,10 @@ int input_register_device(struct input_dev *dev)
        /* Make sure that bitmasks not mentioned in dev->evbit are clean. */
        input_cleanse_bitmasks(dev);
 
+       if (!dev->hint_events_per_packet)
+               dev->hint_events_per_packet =
+                               input_estimate_events_per_packet(dev);
+
        /*
         * If delay and period are pre-set by the driver, then autorepeating
         * is handled by the driver itself and we don't do it in input.c.
index 09bef79d9da1c6e3aecd6efe40c0d4c4c900ba0b..a26922cf0e84d3049d972b7dc0d79b986b3645fb 100644 (file)
@@ -332,18 +332,20 @@ static int __devinit twl4030_kp_program(struct twl4030_keypad *kp)
 static int __devinit twl4030_kp_probe(struct platform_device *pdev)
 {
        struct twl4030_keypad_data *pdata = pdev->dev.platform_data;
-       const struct matrix_keymap_data *keymap_data = pdata->keymap_data;
+       const struct matrix_keymap_data *keymap_data;
        struct twl4030_keypad *kp;
        struct input_dev *input;
        u8 reg;
        int error;
 
-       if (!pdata || !pdata->rows || !pdata->cols ||
+       if (!pdata || !pdata->rows || !pdata->cols || !pdata->keymap_data ||
            pdata->rows > TWL4030_MAX_ROWS || pdata->cols > TWL4030_MAX_COLS) {
                dev_err(&pdev->dev, "Invalid platform_data\n");
                return -EINVAL;
        }
 
+       keymap_data = pdata->keymap_data;
+
        kp = kzalloc(sizeof(*kp), GFP_KERNEL);
        input = input_allocate_device();
        if (!kp || !input) {
index 7077f9bf5ead88a15eb65699e71d00e49715fc84..62bae99424e6e436defda3723654816c44be2609 100644 (file)
@@ -303,7 +303,7 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,
                                   enum xenbus_state backend_state)
 {
        struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
-       int val;
+       int ret, val;
 
        switch (backend_state) {
        case XenbusStateInitialising:
@@ -316,6 +316,17 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,
 
        case XenbusStateInitWait:
 InitWait:
+               ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+                                  "feature-abs-pointer", "%d", &val);
+               if (ret < 0)
+                       val = 0;
+               if (val) {
+                       ret = xenbus_printf(XBT_NIL, info->xbdev->nodename,
+                                           "request-abs-pointer", "1");
+                       if (ret)
+                               pr_warning("xenkbd: can't request abs-pointer");
+               }
+
                xenbus_switch_state(dev, XenbusStateConnected);
                break;
 
index efa06882de00cb855d992f868079338067813d8c..45f93d0f5592e2c3adcdcfdad32ce83696312647 100644 (file)
@@ -399,31 +399,34 @@ static int h3600ts_connect(struct serio *serio, struct serio_driver *drv)
                        IRQF_SHARED | IRQF_DISABLED, "h3600_action", &ts->dev)) {
                printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
                err = -EBUSY;
-               goto fail2;
+               goto fail1;
        }
 
        if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
                        IRQF_SHARED | IRQF_DISABLED, "h3600_suspend", &ts->dev)) {
                printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
                err = -EBUSY;
-               goto fail3;
+               goto fail2;
        }
 
        serio_set_drvdata(serio, ts);
 
        err = serio_open(serio, drv);
        if (err)
-               return err;
+               goto fail3;
 
        //h3600_flite_control(1, 25);     /* default brightness */
-       input_register_device(ts->dev);
+       err = input_register_device(ts->dev);
+       if (err)
+               goto fail4;
 
        return 0;
 
-fail3: free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev);
+fail4: serio_close(serio);
+fail3: serio_set_drvdata(serio, NULL);
+       free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev);
 fail2: free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev);
-fail1: serio_set_drvdata(serio, NULL);
-       input_free_device(input_dev);
+fail1: input_free_device(input_dev);
        kfree(ts);
        return err;
 }
index 3790816643bef85bee2dd1824bcb29818a693f86..8497f56f8e461cf70d8d1b8692e04b11e353323c 100644 (file)
@@ -178,6 +178,10 @@ static int __devinit regulator_led_probe(struct platform_device *pdev)
        led->cdev.flags |= LED_CORE_SUSPENDRESUME;
        led->vcc = vcc;
 
+       /* to handle correctly an already enabled regulator */
+       if (regulator_is_enabled(led->vcc))
+               led->enabled = 1;
+
        mutex_init(&led->mutex);
        INIT_WORK(&led->work, led_work);
 
index 5ef136cdba91dd4a891f00920029962a54185d63..e5d8904fc8f647162d4a7d79150491797cfda6d2 100644 (file)
@@ -390,13 +390,6 @@ static int raid_is_congested(struct dm_target_callbacks *cb, int bits)
        return md_raid5_congested(&rs->md, bits);
 }
 
-static void raid_unplug(struct dm_target_callbacks *cb)
-{
-       struct raid_set *rs = container_of(cb, struct raid_set, callbacks);
-
-       md_raid5_kick_device(rs->md.private);
-}
-
 /*
  * Construct a RAID4/5/6 mapping:
  * Args:
@@ -487,7 +480,6 @@ static int raid_ctr(struct dm_target *ti, unsigned argc, char **argv)
        }
 
        rs->callbacks.congested_fn = raid_is_congested;
-       rs->callbacks.unplug_fn = raid_unplug;
        dm_table_add_target_callbacks(ti->table, &rs->callbacks);
 
        return 0;
index b12b3776c0c0c8ca46b998cac6df78845363f7ee..7d6f7f18a92052e3258ffeae719c377b2df4fb78 100644 (file)
@@ -447,48 +447,59 @@ EXPORT_SYMBOL(md_flush_request);
 
 /* Support for plugging.
  * This mirrors the plugging support in request_queue, but does not
- * require having a whole queue
+ * require having a whole queue or request structures.
+ * We allocate an md_plug_cb for each md device and each thread it gets
+ * plugged on.  This links tot the private plug_handle structure in the
+ * personality data where we keep a count of the number of outstanding
+ * plugs so other code can see if a plug is active.
  */
-static void plugger_work(struct work_struct *work)
-{
-       struct plug_handle *plug =
-               container_of(work, struct plug_handle, unplug_work);
-       plug->unplug_fn(plug);
-}
-static void plugger_timeout(unsigned long data)
-{
-       struct plug_handle *plug = (void *)data;
-       kblockd_schedule_work(NULL, &plug->unplug_work);
-}
-void plugger_init(struct plug_handle *plug,
-                 void (*unplug_fn)(struct plug_handle *))
-{
-       plug->unplug_flag = 0;
-       plug->unplug_fn = unplug_fn;
-       init_timer(&plug->unplug_timer);
-       plug->unplug_timer.function = plugger_timeout;
-       plug->unplug_timer.data = (unsigned long)plug;
-       INIT_WORK(&plug->unplug_work, plugger_work);
-}
-EXPORT_SYMBOL_GPL(plugger_init);
+struct md_plug_cb {
+       struct blk_plug_cb cb;
+       mddev_t *mddev;
+};
 
-void plugger_set_plug(struct plug_handle *plug)
+static void plugger_unplug(struct blk_plug_cb *cb)
 {
-       if (!test_and_set_bit(PLUGGED_FLAG, &plug->unplug_flag))
-               mod_timer(&plug->unplug_timer, jiffies + msecs_to_jiffies(3)+1);
+       struct md_plug_cb *mdcb = container_of(cb, struct md_plug_cb, cb);
+       if (atomic_dec_and_test(&mdcb->mddev->plug_cnt))
+               md_wakeup_thread(mdcb->mddev->thread);
+       kfree(mdcb);
 }
-EXPORT_SYMBOL_GPL(plugger_set_plug);
 
-int plugger_remove_plug(struct plug_handle *plug)
+/* Check that an unplug wakeup will come shortly.
+ * If not, wakeup the md thread immediately
+ */
+int mddev_check_plugged(mddev_t *mddev)
 {
-       if (test_and_clear_bit(PLUGGED_FLAG, &plug->unplug_flag)) {
-               del_timer(&plug->unplug_timer);
-               return 1;
-       } else
+       struct blk_plug *plug = current->plug;
+       struct md_plug_cb *mdcb;
+
+       if (!plug)
                return 0;
-}
-EXPORT_SYMBOL_GPL(plugger_remove_plug);
 
+       list_for_each_entry(mdcb, &plug->cb_list, cb.list) {
+               if (mdcb->cb.callback == plugger_unplug &&
+                   mdcb->mddev == mddev) {
+                       /* Already on the list, move to top */
+                       if (mdcb != list_first_entry(&plug->cb_list,
+                                                   struct md_plug_cb,
+                                                   cb.list))
+                               list_move(&mdcb->cb.list, &plug->cb_list);
+                       return 1;
+               }
+       }
+       /* Not currently on the callback list */
+       mdcb = kmalloc(sizeof(*mdcb), GFP_ATOMIC);
+       if (!mdcb)
+               return 0;
+
+       mdcb->mddev = mddev;
+       mdcb->cb.callback = plugger_unplug;
+       atomic_inc(&mddev->plug_cnt);
+       list_add(&mdcb->cb.list, &plug->cb_list);
+       return 1;
+}
+EXPORT_SYMBOL_GPL(mddev_check_plugged);
 
 static inline mddev_t *mddev_get(mddev_t *mddev)
 {
@@ -538,6 +549,7 @@ void mddev_init(mddev_t *mddev)
        atomic_set(&mddev->active, 1);
        atomic_set(&mddev->openers, 0);
        atomic_set(&mddev->active_io, 0);
+       atomic_set(&mddev->plug_cnt, 0);
        spin_lock_init(&mddev->write_lock);
        atomic_set(&mddev->flush_pending, 0);
        init_waitqueue_head(&mddev->sb_wait);
@@ -3158,6 +3170,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
        mddev->layout = mddev->new_layout;
        mddev->chunk_sectors = mddev->new_chunk_sectors;
        mddev->delta_disks = 0;
+       mddev->degraded = 0;
        if (mddev->pers->sync_request == NULL) {
                /* this is now an array without redundancy, so
                 * it must always be in_sync
@@ -4723,7 +4736,6 @@ static void md_clean(mddev_t *mddev)
        mddev->bitmap_info.chunksize = 0;
        mddev->bitmap_info.daemon_sleep = 0;
        mddev->bitmap_info.max_write_behind = 0;
-       mddev->plug = NULL;
 }
 
 static void __md_stop_writes(mddev_t *mddev)
@@ -6688,12 +6700,6 @@ int md_allow_write(mddev_t *mddev)
 }
 EXPORT_SYMBOL_GPL(md_allow_write);
 
-void md_unplug(mddev_t *mddev)
-{
-       if (mddev->plug)
-               mddev->plug->unplug_fn(mddev->plug);
-}
-
 #define SYNC_MARKS     10
 #define        SYNC_MARK_STEP  (3*HZ)
 void md_do_sync(mddev_t *mddev)
index 52b407369e13f0c82b7fa23f3ee2ca7d41483bbb..0b1fd3f1d85b5decfaaba4ab8b70595fffbaba1f 100644 (file)
 typedef struct mddev_s mddev_t;
 typedef struct mdk_rdev_s mdk_rdev_t;
 
-/* generic plugging support - like that provided with request_queue,
- * but does not require a request_queue
- */
-struct plug_handle {
-       void                    (*unplug_fn)(struct plug_handle *);
-       struct timer_list       unplug_timer;
-       struct work_struct      unplug_work;
-       unsigned long           unplug_flag;
-};
-#define        PLUGGED_FLAG 1
-void plugger_init(struct plug_handle *plug,
-                 void (*unplug_fn)(struct plug_handle *));
-void plugger_set_plug(struct plug_handle *plug);
-int plugger_remove_plug(struct plug_handle *plug);
-static inline void plugger_flush(struct plug_handle *plug)
-{
-       del_timer_sync(&plug->unplug_timer);
-       cancel_work_sync(&plug->unplug_work);
-}
-
 /*
  * MD's 'extended' device
  */
@@ -199,6 +179,9 @@ struct mddev_s
        int                             delta_disks, new_level, new_layout;
        int                             new_chunk_sectors;
 
+       atomic_t                        plug_cnt;       /* If device is expecting
+                                                        * more bios soon.
+                                                        */
        struct mdk_thread_s             *thread;        /* management thread */
        struct mdk_thread_s             *sync_thread;   /* doing resync or reconstruct */
        sector_t                        curr_resync;    /* last block scheduled */
@@ -336,7 +319,6 @@ struct mddev_s
        struct list_head                all_mddevs;
 
        struct attribute_group          *to_remove;
-       struct plug_handle              *plug; /* if used by personality */
 
        struct bio_set                  *bio_set;
 
@@ -516,7 +498,6 @@ extern int md_integrity_register(mddev_t *mddev);
 extern void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
 extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale);
 extern void restore_bitmap_write_access(struct file *file);
-extern void md_unplug(mddev_t *mddev);
 
 extern void mddev_init(mddev_t *mddev);
 extern int md_run(mddev_t *mddev);
@@ -530,4 +511,5 @@ extern struct bio *bio_clone_mddev(struct bio *bio, gfp_t gfp_mask,
                                   mddev_t *mddev);
 extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
                                   mddev_t *mddev);
+extern int mddev_check_plugged(mddev_t *mddev);
 #endif /* _MD_MD_H */
index c2a21ae56d977d6249f9c8501f124e50c48f15dd..2b7a7ff401dc6fba50047bbc3f0fb1980055da13 100644 (file)
@@ -565,12 +565,6 @@ static void flush_pending_writes(conf_t *conf)
                spin_unlock_irq(&conf->device_lock);
 }
 
-static void md_kick_device(mddev_t *mddev)
-{
-       blk_flush_plug(current);
-       md_wakeup_thread(mddev->thread);
-}
-
 /* Barriers....
  * Sometimes we need to suspend IO while we do something else,
  * either some resync/recovery, or reconfigure the array.
@@ -600,7 +594,7 @@ static void raise_barrier(conf_t *conf)
 
        /* Wait until no block IO is waiting */
        wait_event_lock_irq(conf->wait_barrier, !conf->nr_waiting,
-                           conf->resync_lock, md_kick_device(conf->mddev));
+                           conf->resync_lock, );
 
        /* block any new IO from starting */
        conf->barrier++;
@@ -608,7 +602,7 @@ static void raise_barrier(conf_t *conf)
        /* Now wait for all pending IO to complete */
        wait_event_lock_irq(conf->wait_barrier,
                            !conf->nr_pending && conf->barrier < RESYNC_DEPTH,
-                           conf->resync_lock, md_kick_device(conf->mddev));
+                           conf->resync_lock, );
 
        spin_unlock_irq(&conf->resync_lock);
 }
@@ -630,7 +624,7 @@ static void wait_barrier(conf_t *conf)
                conf->nr_waiting++;
                wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
                                    conf->resync_lock,
-                                   md_kick_device(conf->mddev));
+                                   );
                conf->nr_waiting--;
        }
        conf->nr_pending++;
@@ -666,8 +660,7 @@ static void freeze_array(conf_t *conf)
        wait_event_lock_irq(conf->wait_barrier,
                            conf->nr_pending == conf->nr_queued+1,
                            conf->resync_lock,
-                           ({ flush_pending_writes(conf);
-                              md_kick_device(conf->mddev); }));
+                           flush_pending_writes(conf));
        spin_unlock_irq(&conf->resync_lock);
 }
 static void unfreeze_array(conf_t *conf)
@@ -729,6 +722,7 @@ static int make_request(mddev_t *mddev, struct bio * bio)
        const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
        const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA));
        mdk_rdev_t *blocked_rdev;
+       int plugged;
 
        /*
         * Register the new request and wait if the reconstruction
@@ -820,6 +814,8 @@ static int make_request(mddev_t *mddev, struct bio * bio)
         * inc refcount on their rdev.  Record them by setting
         * bios[x] to bio
         */
+       plugged = mddev_check_plugged(mddev);
+
        disks = conf->raid_disks;
  retry_write:
        blocked_rdev = NULL;
@@ -925,7 +921,7 @@ static int make_request(mddev_t *mddev, struct bio * bio)
        /* In case raid1d snuck in to freeze_array */
        wake_up(&conf->wait_barrier);
 
-       if (do_sync || !bitmap)
+       if (do_sync || !bitmap || !plugged)
                md_wakeup_thread(mddev->thread);
 
        return 0;
@@ -1516,13 +1512,16 @@ static void raid1d(mddev_t *mddev)
        conf_t *conf = mddev->private;
        struct list_head *head = &conf->retry_list;
        mdk_rdev_t *rdev;
+       struct blk_plug plug;
 
        md_check_recovery(mddev);
-       
+
+       blk_start_plug(&plug);
        for (;;) {
                char b[BDEVNAME_SIZE];
 
-               flush_pending_writes(conf);
+               if (atomic_read(&mddev->plug_cnt) == 0)
+                       flush_pending_writes(conf);
 
                spin_lock_irqsave(&conf->device_lock, flags);
                if (list_empty(head)) {
@@ -1593,6 +1592,7 @@ static void raid1d(mddev_t *mddev)
                }
                cond_resched();
        }
+       blk_finish_plug(&plug);
 }
 
 
@@ -2039,7 +2039,6 @@ static int stop(mddev_t *mddev)
 
        md_unregister_thread(mddev->thread);
        mddev->thread = NULL;
-       blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
        if (conf->r1bio_pool)
                mempool_destroy(conf->r1bio_pool);
        kfree(conf->mirrors);
index 2da83d5665925eea27b441e954ca145569278055..8e9462626ec5cb8d7441b46ddae9a848772153fe 100644 (file)
@@ -634,12 +634,6 @@ static void flush_pending_writes(conf_t *conf)
                spin_unlock_irq(&conf->device_lock);
 }
 
-static void md_kick_device(mddev_t *mddev)
-{
-       blk_flush_plug(current);
-       md_wakeup_thread(mddev->thread);
-}
-
 /* Barriers....
  * Sometimes we need to suspend IO while we do something else,
  * either some resync/recovery, or reconfigure the array.
@@ -669,15 +663,15 @@ static void raise_barrier(conf_t *conf, int force)
 
        /* Wait until no block IO is waiting (unless 'force') */
        wait_event_lock_irq(conf->wait_barrier, force || !conf->nr_waiting,
-                           conf->resync_lock, md_kick_device(conf->mddev));
+                           conf->resync_lock, );
 
        /* block any new IO from starting */
        conf->barrier++;
 
-       /* No wait for all pending IO to complete */
+       /* Now wait for all pending IO to complete */
        wait_event_lock_irq(conf->wait_barrier,
                            !conf->nr_pending && conf->barrier < RESYNC_DEPTH,
-                           conf->resync_lock, md_kick_device(conf->mddev));
+                           conf->resync_lock, );
 
        spin_unlock_irq(&conf->resync_lock);
 }
@@ -698,7 +692,7 @@ static void wait_barrier(conf_t *conf)
                conf->nr_waiting++;
                wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
                                    conf->resync_lock,
-                                   md_kick_device(conf->mddev));
+                                   );
                conf->nr_waiting--;
        }
        conf->nr_pending++;
@@ -734,8 +728,8 @@ static void freeze_array(conf_t *conf)
        wait_event_lock_irq(conf->wait_barrier,
                            conf->nr_pending == conf->nr_queued+1,
                            conf->resync_lock,
-                           ({ flush_pending_writes(conf);
-                              md_kick_device(conf->mddev); }));
+                           flush_pending_writes(conf));
+
        spin_unlock_irq(&conf->resync_lock);
 }
 
@@ -762,6 +756,7 @@ static int make_request(mddev_t *mddev, struct bio * bio)
        const unsigned long do_fua = (bio->bi_rw & REQ_FUA);
        unsigned long flags;
        mdk_rdev_t *blocked_rdev;
+       int plugged;
 
        if (unlikely(bio->bi_rw & REQ_FLUSH)) {
                md_flush_request(mddev, bio);
@@ -870,6 +865,8 @@ static int make_request(mddev_t *mddev, struct bio * bio)
         * inc refcount on their rdev.  Record them by setting
         * bios[x] to bio
         */
+       plugged = mddev_check_plugged(mddev);
+
        raid10_find_phys(conf, r10_bio);
  retry_write:
        blocked_rdev = NULL;
@@ -946,9 +943,8 @@ static int make_request(mddev_t *mddev, struct bio * bio)
        /* In case raid10d snuck in to freeze_array */
        wake_up(&conf->wait_barrier);
 
-       if (do_sync || !mddev->bitmap)
+       if (do_sync || !mddev->bitmap || !plugged)
                md_wakeup_thread(mddev->thread);
-
        return 0;
 }
 
@@ -1640,9 +1636,11 @@ static void raid10d(mddev_t *mddev)
        conf_t *conf = mddev->private;
        struct list_head *head = &conf->retry_list;
        mdk_rdev_t *rdev;
+       struct blk_plug plug;
 
        md_check_recovery(mddev);
 
+       blk_start_plug(&plug);
        for (;;) {
                char b[BDEVNAME_SIZE];
 
@@ -1716,6 +1714,7 @@ static void raid10d(mddev_t *mddev)
                }
                cond_resched();
        }
+       blk_finish_plug(&plug);
 }
 
 
index e867ee42b15239707c0dfede4be71d2bc9a72e20..fd500112f13e760797820cb59de32691b9f626ba 100644 (file)
  *
  * We group bitmap updates into batches.  Each batch has a number.
  * We may write out several batches at once, but that isn't very important.
- * conf->bm_write is the number of the last batch successfully written.
- * conf->bm_flush is the number of the last batch that was closed to
+ * conf->seq_write is the number of the last batch successfully written.
+ * conf->seq_flush is the number of the last batch that was closed to
  *    new additions.
  * When we discover that we will need to write to any block in a stripe
  * (in add_stripe_bio) we update the in-memory bitmap and record in sh->bm_seq
- * the number of the batch it will be in. This is bm_flush+1.
+ * the number of the batch it will be in. This is seq_flush+1.
  * When we are ready to do a write, if that batch hasn't been written yet,
  *   we plug the array and queue the stripe for later.
  * When an unplug happens, we increment bm_flush, thus closing the current
@@ -199,14 +199,12 @@ static void __release_stripe(raid5_conf_t *conf, struct stripe_head *sh)
                BUG_ON(!list_empty(&sh->lru));
                BUG_ON(atomic_read(&conf->active_stripes)==0);
                if (test_bit(STRIPE_HANDLE, &sh->state)) {
-                       if (test_bit(STRIPE_DELAYED, &sh->state)) {
+                       if (test_bit(STRIPE_DELAYED, &sh->state))
                                list_add_tail(&sh->lru, &conf->delayed_list);
-                               plugger_set_plug(&conf->plug);
-                       } else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
-                                  sh->bm_seq - conf->seq_write > 0) {
+                       else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
+                                  sh->bm_seq - conf->seq_write > 0)
                                list_add_tail(&sh->lru, &conf->bitmap_list);
-                               plugger_set_plug(&conf->plug);
-                       } else {
+                       else {
                                clear_bit(STRIPE_BIT_DELAY, &sh->state);
                                list_add_tail(&sh->lru, &conf->handle_list);
                        }
@@ -461,7 +459,7 @@ get_active_stripe(raid5_conf_t *conf, sector_t sector,
                                                     < (conf->max_nr_stripes *3/4)
                                                     || !conf->inactive_blocked),
                                                    conf->device_lock,
-                                                   md_raid5_kick_device(conf));
+                                                   );
                                conf->inactive_blocked = 0;
                        } else
                                init_stripe(sh, sector, previous);
@@ -1470,7 +1468,7 @@ static int resize_stripes(raid5_conf_t *conf, int newsize)
                wait_event_lock_irq(conf->wait_for_stripe,
                                    !list_empty(&conf->inactive_list),
                                    conf->device_lock,
-                                   blk_flush_plug(current));
+                                   );
                osh = get_free_stripe(conf);
                spin_unlock_irq(&conf->device_lock);
                atomic_set(&nsh->count, 1);
@@ -3623,8 +3621,7 @@ static void raid5_activate_delayed(raid5_conf_t *conf)
                                atomic_inc(&conf->preread_active_stripes);
                        list_add_tail(&sh->lru, &conf->hold_list);
                }
-       } else
-               plugger_set_plug(&conf->plug);
+       }
 }
 
 static void activate_bit_delay(raid5_conf_t *conf)
@@ -3641,21 +3638,6 @@ static void activate_bit_delay(raid5_conf_t *conf)
        }
 }
 
-void md_raid5_kick_device(raid5_conf_t *conf)
-{
-       blk_flush_plug(current);
-       raid5_activate_delayed(conf);
-       md_wakeup_thread(conf->mddev->thread);
-}
-EXPORT_SYMBOL_GPL(md_raid5_kick_device);
-
-static void raid5_unplug(struct plug_handle *plug)
-{
-       raid5_conf_t *conf = container_of(plug, raid5_conf_t, plug);
-
-       md_raid5_kick_device(conf);
-}
-
 int md_raid5_congested(mddev_t *mddev, int bits)
 {
        raid5_conf_t *conf = mddev->private;
@@ -3945,6 +3927,7 @@ static int make_request(mddev_t *mddev, struct bio * bi)
        struct stripe_head *sh;
        const int rw = bio_data_dir(bi);
        int remaining;
+       int plugged;
 
        if (unlikely(bi->bi_rw & REQ_FLUSH)) {
                md_flush_request(mddev, bi);
@@ -3963,6 +3946,7 @@ static int make_request(mddev_t *mddev, struct bio * bi)
        bi->bi_next = NULL;
        bi->bi_phys_segments = 1;       /* over-loaded to count active stripes */
 
+       plugged = mddev_check_plugged(mddev);
        for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
                DEFINE_WAIT(w);
                int disks, data_disks;
@@ -4057,7 +4041,7 @@ static int make_request(mddev_t *mddev, struct bio * bi)
                                 * add failed due to overlap.  Flush everything
                                 * and wait a while
                                 */
-                               md_raid5_kick_device(conf);
+                               md_wakeup_thread(mddev->thread);
                                release_stripe(sh);
                                schedule();
                                goto retry;
@@ -4077,6 +4061,9 @@ static int make_request(mddev_t *mddev, struct bio * bi)
                }
                        
        }
+       if (!plugged)
+               md_wakeup_thread(mddev->thread);
+
        spin_lock_irq(&conf->device_lock);
        remaining = raid5_dec_bi_phys_segments(bi);
        spin_unlock_irq(&conf->device_lock);
@@ -4478,24 +4465,30 @@ static void raid5d(mddev_t *mddev)
        struct stripe_head *sh;
        raid5_conf_t *conf = mddev->private;
        int handled;
+       struct blk_plug plug;
 
        pr_debug("+++ raid5d active\n");
 
        md_check_recovery(mddev);
 
+       blk_start_plug(&plug);
        handled = 0;
        spin_lock_irq(&conf->device_lock);
        while (1) {
                struct bio *bio;
 
-               if (conf->seq_flush != conf->seq_write) {
-                       int seq = conf->seq_flush;
+               if (atomic_read(&mddev->plug_cnt) == 0 &&
+                   !list_empty(&conf->bitmap_list)) {
+                       /* Now is a good time to flush some bitmap updates */
+                       conf->seq_flush++;
                        spin_unlock_irq(&conf->device_lock);
                        bitmap_unplug(mddev->bitmap);
                        spin_lock_irq(&conf->device_lock);
-                       conf->seq_write = seq;
+                       conf->seq_write = conf->seq_flush;
                        activate_bit_delay(conf);
                }
+               if (atomic_read(&mddev->plug_cnt) == 0)
+                       raid5_activate_delayed(conf);
 
                while ((bio = remove_bio_from_retry(conf))) {
                        int ok;
@@ -4525,6 +4518,7 @@ static void raid5d(mddev_t *mddev)
        spin_unlock_irq(&conf->device_lock);
 
        async_tx_issue_pending_all();
+       blk_finish_plug(&plug);
 
        pr_debug("--- raid5d inactive\n");
 }
@@ -5141,8 +5135,6 @@ static int run(mddev_t *mddev)
                       mdname(mddev));
        md_set_array_sectors(mddev, raid5_size(mddev, 0, 0));
 
-       plugger_init(&conf->plug, raid5_unplug);
-       mddev->plug = &conf->plug;
        if (mddev->queue) {
                int chunk_size;
                /* read-ahead size must cover two whole stripes, which
@@ -5159,7 +5151,6 @@ static int run(mddev_t *mddev)
 
                mddev->queue->backing_dev_info.congested_data = mddev;
                mddev->queue->backing_dev_info.congested_fn = raid5_congested;
-               mddev->queue->queue_lock = &conf->device_lock;
 
                chunk_size = mddev->chunk_sectors << 9;
                blk_queue_io_min(mddev->queue, chunk_size);
@@ -5192,7 +5183,6 @@ static int stop(mddev_t *mddev)
        mddev->thread = NULL;
        if (mddev->queue)
                mddev->queue->backing_dev_info.congested_fn = NULL;
-       plugger_flush(&conf->plug); /* the unplug fn references 'conf'*/
        free_conf(conf);
        mddev->private = NULL;
        mddev->to_remove = &raid5_attrs_group;
@@ -5688,6 +5678,7 @@ static void raid5_quiesce(mddev_t *mddev, int state)
 static void *raid45_takeover_raid0(mddev_t *mddev, int level)
 {
        struct raid0_private_data *raid0_priv = mddev->private;
+       unsigned long long sectors;
 
        /* for raid0 takeover only one zone is supported */
        if (raid0_priv->nr_strip_zones > 1) {
@@ -5696,6 +5687,9 @@ static void *raid45_takeover_raid0(mddev_t *mddev, int level)
                return ERR_PTR(-EINVAL);
        }
 
+       sectors = raid0_priv->strip_zone[0].zone_end;
+       sector_div(sectors, raid0_priv->strip_zone[0].nb_dev);
+       mddev->dev_sectors = sectors;
        mddev->new_level = level;
        mddev->new_layout = ALGORITHM_PARITY_N;
        mddev->new_chunk_sectors = mddev->chunk_sectors;
index 8d563a4f022a778a6d9354a3c1bf514c6f5e10b6..3ca77a2613ba0a544ffa9c4aca4e12122d77cc96 100644 (file)
@@ -400,8 +400,6 @@ struct raid5_private_data {
                                            * Cleared when a sync completes.
                                            */
 
-       struct plug_handle      plug;
-
        /* per cpu variables */
        struct raid5_percpu {
                struct page     *spare_page; /* Used when checking P/Q in raid6 */
index c4742fc15529a97cf4472dde06717f9ef7d31233..c9691115f2d26787fa9d85ae98382539d78a8a98 100644 (file)
@@ -300,7 +300,7 @@ static int __videobuf_mmap_mapper(struct videobuf_queue *q,
 
        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
        retval = remap_pfn_range(vma, vma->vm_start,
-                                PFN_DOWN(virt_to_phys(mem->vaddr)),
+                                mem->dma_handle >> PAGE_SHIFT,
                                 size, vma->vm_page_prot);
        if (retval) {
                dev_err(q->dev, "mmap: remap failed with error %d. ", retval);
index d01574d98870a0473b56be995cd0341786b9b767..f4c8c844b913060c6e0bb12f35db8cba983a81dc 100644 (file)
@@ -55,6 +55,19 @@ int mfd_cell_disable(struct platform_device *pdev)
 }
 EXPORT_SYMBOL(mfd_cell_disable);
 
+static int mfd_platform_add_cell(struct platform_device *pdev,
+                                const struct mfd_cell *cell)
+{
+       if (!cell)
+               return 0;
+
+       pdev->mfd_cell = kmemdup(cell, sizeof(*cell), GFP_KERNEL);
+       if (!pdev->mfd_cell)
+               return -ENOMEM;
+
+       return 0;
+}
+
 static int mfd_add_device(struct device *parent, int id,
                          const struct mfd_cell *cell,
                          struct resource *mem_base,
@@ -75,7 +88,7 @@ static int mfd_add_device(struct device *parent, int id,
 
        pdev->dev.parent = parent;
 
-       ret = platform_device_add_data(pdev, cell, sizeof(*cell));
+       ret = mfd_platform_add_cell(pdev, cell);
        if (ret)
                goto fail_res;
 
@@ -123,7 +136,6 @@ static int mfd_add_device(struct device *parent, int id,
 
        return 0;
 
-/*     platform_device_del(pdev); */
 fail_res:
        kfree(res);
 fail_device:
index 20e4e9395b61ca1c6d85b09511b88f535a8ec120..ecafa4ba238b3ca4991a20dc5e6bb88458aee8de 100644 (file)
@@ -348,15 +348,15 @@ static unsigned long gru_chiplet_cpu_to_mmr(int chiplet, int cpu, int *corep)
 
 static int gru_irq_count[GRU_CHIPLETS_PER_BLADE];
 
-static void gru_noop(unsigned int irq)
+static void gru_noop(struct irq_data *d)
 {
 }
 
 static struct irq_chip gru_chip[GRU_CHIPLETS_PER_BLADE] = {
        [0 ... GRU_CHIPLETS_PER_BLADE - 1] {
-               .mask           = gru_noop,
-               .unmask         = gru_noop,
-               .ack            = gru_noop
+               .irq_mask       = gru_noop,
+               .irq_unmask     = gru_noop,
+               .irq_ack        = gru_noop
        }
 };
 
index 237913c5c92c348f70d9d4f160188402fbb48acf..fed215c4cfa19a3676666dbef17c1e4ce8b8d8bc 100644 (file)
@@ -1452,7 +1452,7 @@ static void mtdswap_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
        oinfo = mtd->ecclayout;
        if (!mtd->oobsize || !oinfo || oinfo->oobavail < MTDSWAP_OOBSIZE) {
                printk(KERN_ERR "%s: Not enough free bytes in OOB, "
-                       "%d available, %lu needed.\n",
+                       "%d available, %zu needed.\n",
                        MTDSWAP_PREFIX, oinfo->oobavail, MTDSWAP_OOBSIZE);
                return;
        }
index 6fae04b3fc6da19a1adad5c261157b62e89fe4b2..950646aa4c4b004a174c1951f08397ab808956c0 100644 (file)
@@ -209,22 +209,8 @@ static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len,
        int err = -EIO;
        enum dma_data_direction dir = is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
 
-       if (buf >= high_memory) {
-               struct page *pg;
-
-               if (((size_t)buf & PAGE_MASK) !=
-                   ((size_t)(buf + len - 1) & PAGE_MASK)) {
-                       dev_warn(host->dev, "Buffer not fit in one page\n");
-                       goto err_buf;
-               }
-
-               pg = vmalloc_to_page(buf);
-               if (pg == 0) {
-                       dev_err(host->dev, "Failed to vmalloc_to_page\n");
-                       goto err_buf;
-               }
-               p = page_address(pg) + ((size_t)buf & ~PAGE_MASK);
-       }
+       if (buf >= high_memory)
+               goto err_buf;
 
        dma_dev = host->dma_chan->device;
 
@@ -280,7 +266,8 @@ static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
        struct nand_chip *chip = mtd->priv;
        struct atmel_nand_host *host = chip->priv;
 
-       if (use_dma && len >= mtd->oobsize)
+       if (use_dma && len > mtd->oobsize)
+               /* only use DMA for bigger than oob size: better performances */
                if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)
                        return;
 
@@ -295,7 +282,8 @@ static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
        struct nand_chip *chip = mtd->priv;
        struct atmel_nand_host *host = chip->priv;
 
-       if (use_dma && len >= mtd->oobsize)
+       if (use_dma && len > mtd->oobsize)
+               /* only use DMA for bigger than oob size: better performances */
                if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0)
                        return;
 
@@ -599,7 +587,10 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
                nand_chip->options |= NAND_USE_FLASH_BBT;
        }
 
-       if (cpu_has_dma() && use_dma) {
+       if (!cpu_has_dma())
+               use_dma = 0;
+
+       if (use_dma) {
                dma_cap_mask_t mask;
 
                dma_cap_zero(mask);
@@ -611,7 +602,8 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
                }
        }
        if (use_dma)
-               dev_info(host->dev, "Using DMA for NAND access.\n");
+               dev_info(host->dev, "Using %s for DMA transfers.\n",
+                                       dma_chan_name(host->dma_chan));
        else
                dev_info(host->dev, "No DMA support for NAND access.\n");
 
index f803c58b941d7196f4ce53d62cf6c5a0a63d33d1..66823eded7a3b7d4ffa7525728d8c587f1628275 100644 (file)
@@ -154,7 +154,7 @@ struct be_eq_obj {
        u16 min_eqd;            /* in usecs */
        u16 max_eqd;            /* in usecs */
        u16 cur_eqd;            /* in usecs */
-       u8  msix_vec_idx;
+       u8  eq_idx;
 
        struct napi_struct napi;
 };
@@ -291,7 +291,7 @@ struct be_adapter {
        u32 num_rx_qs;
        u32 big_page_size;      /* Compounded page size shared by rx wrbs */
 
-       u8 msix_vec_next_idx;
+       u8 eq_next_idx;
        struct be_drv_stats drv_stats;
 
        struct vlan_group *vlan_grp;
index 9a54c8b24ff9d09ed336f70459115d0d2a2e21db..7cb5a114c7338af0c584607c7bcd1e33dba4c0e2 100644 (file)
@@ -1497,7 +1497,7 @@ static int be_tx_queues_create(struct be_adapter *adapter)
        if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd))
                goto tx_eq_free;
 
-       adapter->tx_eq.msix_vec_idx = adapter->msix_vec_next_idx++;
+       adapter->tx_eq.eq_idx = adapter->eq_next_idx++;
 
 
        /* Alloc TX eth compl queue */
@@ -1590,7 +1590,7 @@ static int be_rx_queues_create(struct be_adapter *adapter)
                if (rc)
                        goto err;
 
-               rxo->rx_eq.msix_vec_idx = adapter->msix_vec_next_idx++;
+               rxo->rx_eq.eq_idx = adapter->eq_next_idx++;
 
                /* CQ */
                cq = &rxo->cq;
@@ -1666,11 +1666,11 @@ static irqreturn_t be_intx(int irq, void *dev)
                if (!isr)
                        return IRQ_NONE;
 
-               if ((1 << adapter->tx_eq.msix_vec_idx & isr))
+               if ((1 << adapter->tx_eq.eq_idx & isr))
                        event_handle(adapter, &adapter->tx_eq);
 
                for_all_rx_queues(adapter, rxo, i) {
-                       if ((1 << rxo->rx_eq.msix_vec_idx & isr))
+                       if ((1 << rxo->rx_eq.eq_idx & isr))
                                event_handle(adapter, &rxo->rx_eq);
                }
        }
@@ -1951,7 +1951,7 @@ static void be_sriov_disable(struct be_adapter *adapter)
 static inline int be_msix_vec_get(struct be_adapter *adapter,
                                        struct be_eq_obj *eq_obj)
 {
-       return adapter->msix_entries[eq_obj->msix_vec_idx].vector;
+       return adapter->msix_entries[eq_obj->eq_idx].vector;
 }
 
 static int be_request_irq(struct be_adapter *adapter,
@@ -2345,6 +2345,7 @@ static int be_clear(struct be_adapter *adapter)
        be_mcc_queues_destroy(adapter);
        be_rx_queues_destroy(adapter);
        be_tx_queues_destroy(adapter);
+       adapter->eq_next_idx = 0;
 
        if (be_physfn(adapter) && adapter->sriov_enabled)
                for (vf = 0; vf < num_vfs; vf++)
@@ -3141,12 +3142,14 @@ static int be_resume(struct pci_dev *pdev)
 static void be_shutdown(struct pci_dev *pdev)
 {
        struct be_adapter *adapter = pci_get_drvdata(pdev);
-       struct net_device *netdev =  adapter->netdev;
 
-       if (netif_running(netdev))
+       if (!adapter)
+               return;
+
+       if (netif_running(adapter->netdev))
                cancel_delayed_work_sync(&adapter->work);
 
-       netif_device_detach(netdev);
+       netif_device_detach(adapter->netdev);
 
        be_cmd_reset_function(adapter);
 
index 34933cb9569ffc070692d8031a8c50eb32b07111..7581518ecfa2eade4c4bb4cba60601e5f39b7be2 100644 (file)
@@ -38,6 +38,8 @@
 #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
 #define bfa_ioc_notify_fail(__ioc)                     \
                        ((__ioc)->ioc_hwif->ioc_notify_fail(__ioc))
+#define bfa_ioc_sync_start(__ioc)               \
+                       ((__ioc)->ioc_hwif->ioc_sync_start(__ioc))
 #define bfa_ioc_sync_join(__ioc)                       \
                        ((__ioc)->ioc_hwif->ioc_sync_join(__ioc))
 #define bfa_ioc_sync_leave(__ioc)                      \
@@ -602,7 +604,7 @@ bfa_iocpf_sm_fwcheck(struct bfa_iocpf *iocpf, enum iocpf_event event)
        switch (event) {
        case IOCPF_E_SEMLOCKED:
                if (bfa_ioc_firmware_lock(ioc)) {
-                       if (bfa_ioc_sync_complete(ioc)) {
+                       if (bfa_ioc_sync_start(ioc)) {
                                iocpf->retry_count = 0;
                                bfa_ioc_sync_join(ioc);
                                bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
@@ -1314,7 +1316,7 @@ bfa_nw_ioc_fwver_cmp(struct bfa_ioc *ioc, struct bfi_ioc_image_hdr *fwhdr)
  * execution context (driver/bios) must match.
  */
 static bool
-bfa_ioc_fwver_valid(struct bfa_ioc *ioc)
+bfa_ioc_fwver_valid(struct bfa_ioc *ioc, u32 boot_env)
 {
        struct bfi_ioc_image_hdr fwhdr, *drv_fwhdr;
 
@@ -1325,7 +1327,7 @@ bfa_ioc_fwver_valid(struct bfa_ioc *ioc)
        if (fwhdr.signature != drv_fwhdr->signature)
                return false;
 
-       if (fwhdr.exec != drv_fwhdr->exec)
+       if (swab32(fwhdr.param) != boot_env)
                return false;
 
        return bfa_nw_ioc_fwver_cmp(ioc, &fwhdr);
@@ -1352,9 +1354,12 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
 {
        enum bfi_ioc_state ioc_fwstate;
        bool fwvalid;
+       u32 boot_env;
 
        ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
 
+       boot_env = BFI_BOOT_LOADER_OS;
+
        if (force)
                ioc_fwstate = BFI_IOC_UNINIT;
 
@@ -1362,10 +1367,10 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
         * check if firmware is valid
         */
        fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
-               false : bfa_ioc_fwver_valid(ioc);
+               false : bfa_ioc_fwver_valid(ioc, boot_env);
 
        if (!fwvalid) {
-               bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+               bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, boot_env);
                return;
        }
 
@@ -1396,7 +1401,7 @@ bfa_ioc_hwinit(struct bfa_ioc *ioc, bool force)
        /**
         * Initialize the h/w for any other states.
         */
-       bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+       bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, boot_env);
 }
 
 void
@@ -1506,7 +1511,7 @@ bfa_ioc_hb_stop(struct bfa_ioc *ioc)
  */
 static void
 bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
-                   u32 boot_param)
+                   u32 boot_env)
 {
        u32 *fwimg;
        u32 pgnum, pgoff;
@@ -1558,10 +1563,10 @@ bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
        /*
         * Set boot type and boot param at the end.
        */
-       writel((swab32(swab32(boot_type))), ((ioc->ioc_regs.smem_page_start)
+       writel(boot_type, ((ioc->ioc_regs.smem_page_start)
                        + (BFI_BOOT_TYPE_OFF)));
-       writel((swab32(swab32(boot_param))), ((ioc->ioc_regs.smem_page_start)
-                       + (BFI_BOOT_PARAM_OFF)));
+       writel(boot_env, ((ioc->ioc_regs.smem_page_start)
+                       + (BFI_BOOT_LOADER_OFF)));
 }
 
 static void
@@ -1721,7 +1726,7 @@ bfa_ioc_pll_init(struct bfa_ioc *ioc)
  * as the entry vector.
  */
 static void
-bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_param)
+bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_env)
 {
        void __iomem *rb;
 
@@ -1734,7 +1739,7 @@ bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_param)
         * Initialize IOC state of all functions on a chip reset.
         */
        rb = ioc->pcidev.pci_bar_kva;
-       if (boot_param == BFI_BOOT_TYPE_MEMTEST) {
+       if (boot_type == BFI_BOOT_TYPE_MEMTEST) {
                writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG));
                writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG));
        } else {
@@ -1743,7 +1748,7 @@ bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_param)
        }
 
        bfa_ioc_msgflush(ioc);
-       bfa_ioc_download_fw(ioc, boot_type, boot_param);
+       bfa_ioc_download_fw(ioc, boot_type, boot_env);
 
        /**
         * Enable interrupts just before starting LPU
@@ -2219,13 +2224,9 @@ bfa_nw_ioc_get_mac(struct bfa_ioc *ioc)
 static void
 bfa_ioc_recover(struct bfa_ioc *ioc)
 {
-       u16 bdf;
-
-       bdf = (ioc->pcidev.pci_slot << 8 | ioc->pcidev.pci_func << 3 |
-                                       ioc->pcidev.device_id);
-
-       pr_crit("Firmware heartbeat failure at %d", bdf);
-       BUG_ON(1);
+       pr_crit("Heart Beat of IOC has failed\n");
+       bfa_ioc_stats(ioc, ioc_hbfails);
+       bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
 }
 
 static void
index e4974bc24ef69b3d05229398cc15b4977997226e..bd48abee781f17ed340d18317e07374d2000b8bb 100644 (file)
@@ -194,6 +194,7 @@ struct bfa_ioc_hwif {
                                        bool msix);
        void            (*ioc_notify_fail)      (struct bfa_ioc *ioc);
        void            (*ioc_ownership_reset)  (struct bfa_ioc *ioc);
+       bool            (*ioc_sync_start)       (struct bfa_ioc *ioc);
        void            (*ioc_sync_join)        (struct bfa_ioc *ioc);
        void            (*ioc_sync_leave)       (struct bfa_ioc *ioc);
        void            (*ioc_sync_ack)         (struct bfa_ioc *ioc);
index 469997c4ffd196a4609c58daf83c6112d4fc4995..87aecdf22cf9c29adf4379685d9813bbbebd2cd5 100644 (file)
@@ -41,6 +41,7 @@ static void bfa_ioc_ct_map_port(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix);
 static void bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc);
+static bool bfa_ioc_ct_sync_start(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_sync_join(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc);
@@ -63,6 +64,7 @@ bfa_nw_ioc_set_ct_hwif(struct bfa_ioc *ioc)
        nw_hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
        nw_hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail;
        nw_hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
+       nw_hwif_ct.ioc_sync_start = bfa_ioc_ct_sync_start;
        nw_hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join;
        nw_hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave;
        nw_hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack;
@@ -342,6 +344,32 @@ bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc)
        bfa_nw_ioc_hw_sem_release(ioc);
 }
 
+/**
+ * Synchronized IOC failure processing routines
+ */
+static bool
+bfa_ioc_ct_sync_start(struct bfa_ioc *ioc)
+{
+       u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+       u32 sync_reqd = bfa_ioc_ct_get_sync_reqd(r32);
+
+       /*
+        * Driver load time.  If the sync required bit for this PCI fn
+        * is set, it is due to an unclean exit by the driver for this
+        * PCI fn in the previous incarnation. Whoever comes here first
+        * should clean it up, no matter which PCI fn.
+        */
+
+       if (sync_reqd & bfa_ioc_ct_sync_pos(ioc)) {
+               writel(0, ioc->ioc_regs.ioc_fail_sync);
+               writel(1, ioc->ioc_regs.ioc_usage_reg);
+               writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
+               writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
+               return true;
+       }
+
+       return bfa_ioc_ct_sync_complete(ioc);
+}
 /**
  * Synchronized IOC failure processing routines
  */
index a97396811050eaccc1bcd31064c0088c29479413..6050379526f74f737ed2ef8a12c8f44ece1241d5 100644 (file)
@@ -184,12 +184,14 @@ enum bfi_mclass {
 #define BFI_IOC_MSGLEN_MAX     32      /* 32 bytes */
 
 #define BFI_BOOT_TYPE_OFF              8
-#define BFI_BOOT_PARAM_OFF             12
+#define BFI_BOOT_LOADER_OFF            12
 
-#define BFI_BOOT_TYPE_NORMAL           0       /* param is device id */
+#define BFI_BOOT_TYPE_NORMAL           0
 #define        BFI_BOOT_TYPE_FLASH             1
 #define        BFI_BOOT_TYPE_MEMTEST           2
 
+#define BFI_BOOT_LOADER_OS             0
+
 #define BFI_BOOT_MEMTEST_RES_ADDR   0x900
 #define BFI_BOOT_MEMTEST_RES_SIG    0xA0A1A2A3
 
index 9f356d5d0f3318c42630cd0ce2b479e73a28b75b..8e6ceab9f4d800e4cbfee2cac22a297d0d987396 100644 (file)
@@ -1837,7 +1837,6 @@ bnad_setup_rx(struct bnad *bnad, uint rx_id)
        /* Initialize the Rx event handlers */
        rx_cbfn.rcb_setup_cbfn = bnad_cb_rcb_setup;
        rx_cbfn.rcb_destroy_cbfn = bnad_cb_rcb_destroy;
-       rx_cbfn.rcb_destroy_cbfn = NULL;
        rx_cbfn.ccb_setup_cbfn = bnad_cb_ccb_setup;
        rx_cbfn.ccb_destroy_cbfn = bnad_cb_ccb_destroy;
        rx_cbfn.rx_cleanup_cbfn = bnad_cb_rx_cleanup;
index f5050155c6b5e04d87a62be1f8f22a78dc953d9e..89cb977898cb5cfbce98bd53422c9d27128761e5 100644 (file)
@@ -2114,19 +2114,18 @@ static int bnx2x_phys_id(struct net_device *dev, u32 data)
        for (i = 0; i < (data * 2); i++) {
                if ((i % 2) == 0)
                        bnx2x_set_led(&bp->link_params, &bp->link_vars,
-                                     LED_MODE_OPER, SPEED_1000);
+                                     LED_MODE_ON, SPEED_1000);
                else
                        bnx2x_set_led(&bp->link_params, &bp->link_vars,
-                                     LED_MODE_OFF, 0);
+                                     LED_MODE_FRONT_PANEL_OFF, 0);
 
                msleep_interruptible(500);
                if (signal_pending(current))
                        break;
        }
 
-       if (bp->link_vars.link_up)
-               bnx2x_set_led(&bp->link_params, &bp->link_vars, LED_MODE_OPER,
-                             bp->link_vars.line_speed);
+       bnx2x_set_led(&bp->link_params, &bp->link_vars,
+                     LED_MODE_OPER, bp->link_vars.line_speed);
 
        return 0;
 }
index 9bc5de3e04a8375894e040cd3cb794a0fff5f90c..ba715826e2a8f1c7cf66213f777527d5db053d4c 100644 (file)
@@ -176,7 +176,7 @@ static int tlb_initialize(struct bonding *bond)
        bond_info->tx_hashtbl = new_hashtbl;
 
        for (i = 0; i < TLB_HASH_TABLE_SIZE; i++) {
-               tlb_init_table_entry(&bond_info->tx_hashtbl[i], 1);
+               tlb_init_table_entry(&bond_info->tx_hashtbl[i], 0);
        }
 
        _unlock_tx_hashtbl(bond);
@@ -701,7 +701,7 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond)
                 */
                rlb_choose_channel(skb, bond);
 
-               /* The ARP relpy packets must be delayed so that
+               /* The ARP reply packets must be delayed so that
                 * they can cancel out the influence of the ARP request.
                 */
                bond->alb_info.rlb_update_delay_counter = RLB_UPDATE_DELAY;
@@ -1042,7 +1042,7 @@ static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *sla
  *
  * If the permanent hw address of @slave is @bond's hw address, we need to
  * find a different hw address to give @slave, that isn't in use by any other
- * slave in the bond. This address must be, of course, one of the premanent
+ * slave in the bond. This address must be, of course, one of the permanent
  * addresses of the other slaves.
  *
  * We go over the slave list, and for each slave there we compare its
index 86861f08b24d1ec91f3b80e8efe4f83999b404a7..8ca7158b2dda412f158ae790050c380e2abd2971 100644 (file)
@@ -75,7 +75,7 @@ struct tlb_client_info {
                                 * gave this entry index.
                                 */
        u32 tx_bytes;           /* Each Client accumulates the BytesTx that
-                                * were tranmitted to it, and after each
+                                * were transmitted to it, and after each
                                 * CallBack the LoadHistory is divided
                                 * by the balance interval
                                 */
@@ -122,7 +122,6 @@ struct tlb_slave_info {
 };
 
 struct alb_bond_info {
-       struct timer_list       alb_timer;
        struct tlb_client_info  *tx_hashtbl; /* Dynamically allocated */
        spinlock_t              tx_hashtbl_lock;
        u32                     unbalanced_load;
@@ -140,7 +139,6 @@ struct alb_bond_info {
        struct slave            *next_rx_slave;/* next slave to be assigned
                                                * to a new rx client for
                                                */
-       u32                     rlb_interval_counter;
        u8                      primary_is_promisc;        /* boolean */
        u32                     rlb_promisc_timeout_counter;/* counts primary
                                                             * promiscuity time
index 7513c4523ac4833d05e7e6efe3c4e07268704175..330140ee266dfe7d19e9ba4be07dd3a384b6605e 100644 (file)
@@ -931,7 +931,8 @@ static int mcp251x_open(struct net_device *net)
        priv->tx_len = 0;
 
        ret = request_threaded_irq(spi->irq, NULL, mcp251x_can_ist,
-                         IRQF_TRIGGER_FALLING, DEVICE_NAME, priv);
+                 pdata->irq_flags ? pdata->irq_flags : IRQF_TRIGGER_FALLING,
+                 DEVICE_NAME, priv);
        if (ret) {
                dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
                if (pdata->transceiver_enable)
index c0a1bc5b14352288d5c73238031547e4afd9ee98..bd1d811c204f276cbf2aa74f07035cd8ae0875ef 100644 (file)
@@ -260,7 +260,7 @@ static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev)
 
        if (!ofdev->dev.of_match)
                return -EINVAL;
-       data = (struct mpc5xxx_can_data *)of_dev->dev.of_match->data;
+       data = (struct mpc5xxx_can_data *)ofdev->dev.of_match->data;
 
        base = of_iomap(np, 0);
        if (!base) {
index ea0dc451da9c874716c689a051cb967082c8bf6b..d70fb76edb7717062544a3c87d27e5799d0348c9 100644 (file)
@@ -173,7 +173,8 @@ static void loopback_setup(struct net_device *dev)
                | NETIF_F_RXCSUM
                | NETIF_F_HIGHDMA
                | NETIF_F_LLTX
-               | NETIF_F_NETNS_LOCAL;
+               | NETIF_F_NETNS_LOCAL
+               | NETIF_F_VLAN_CHALLENGED;
        dev->ethtool_ops        = &loopback_ethtool_ops;
        dev->header_ops         = &eth_header_ops;
        dev->netdev_ops         = &loopback_ops;
index cfd50bc49169844cb17a5e2e48c83f262ef18c7d..62dd21b06df4f8faabe1522f78476ecd02c33b33 100644 (file)
@@ -345,6 +345,8 @@ int mlx4_en_activate_rx_rings(struct mlx4_en_priv *priv)
                err = mlx4_en_init_allocator(priv, ring);
                if (err) {
                        en_err(priv, "Failed initializing ring allocator\n");
+                       if (ring->stride <= TXBB_SIZE)
+                               ring->buf -= TXBB_SIZE;
                        ring_ind--;
                        goto err_allocator;
                }
@@ -369,6 +371,8 @@ err_buffers:
        ring_ind = priv->rx_ring_num - 1;
 err_allocator:
        while (ring_ind >= 0) {
+               if (priv->rx_ring[ring_ind].stride <= TXBB_SIZE)
+                       priv->rx_ring[ring_ind].buf -= TXBB_SIZE;
                mlx4_en_destroy_allocator(priv, &priv->rx_ring[ring_ind]);
                ring_ind--;
        }
index 62fa7eec5f0c448be487ed78bc4da11eaaa4a751..3814fc9b1145d50fc6fe25426436f895d9010b63 100644 (file)
@@ -944,6 +944,10 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
        }
 
        for (port = 1; port <= dev->caps.num_ports; port++) {
+               enum mlx4_port_type port_type = 0;
+               mlx4_SENSE_PORT(dev, port, &port_type);
+               if (port_type)
+                       dev->caps.port_type[port] = port_type;
                ib_port_default_caps = 0;
                err = mlx4_get_port_ib_caps(dev, port, &ib_port_default_caps);
                if (err)
@@ -958,6 +962,7 @@ static int mlx4_setup_hca(struct mlx4_dev *dev)
                        goto err_mcg_table_free;
                }
        }
+       mlx4_set_port_mask(dev);
 
        return 0;
 
index c1e0e5f1bcdbb0c85891b678798e6c59e7aafbe2..dd7d745fbab49e2b730f556fd4aef4c1e738862c 100644 (file)
@@ -431,6 +431,8 @@ void mlx4_srq_event(struct mlx4_dev *dev, u32 srqn, int event_type);
 
 void mlx4_handle_catas_err(struct mlx4_dev *dev);
 
+int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
+                   enum mlx4_port_type *type);
 void mlx4_do_sense_ports(struct mlx4_dev *dev,
                         enum mlx4_port_type *stype,
                         enum mlx4_port_type *defaults);
index 015fbe785c13304aab333759a4629250b531b8d9..e2337a7411d943409fc881d911b21d2c907bcc18 100644 (file)
@@ -38,8 +38,8 @@
 
 #include "mlx4.h"
 
-static int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
-                          enum mlx4_port_type *type)
+int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
+                   enum mlx4_port_type *type)
 {
        u64 out_param;
        int err = 0;
index aa2813e06d0033ebcc48f07967c884d9b20735d8..1074231f0a0d722a803bcc968372d9705b582a53 100644 (file)
@@ -860,6 +860,9 @@ static int __devinit natsemi_probe1 (struct pci_dev *pdev,
                prev_eedata = eedata;
        }
 
+       /* Store MAC Address in perm_addr */
+       memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN);
+
        dev->base_addr = (unsigned long __force) ioaddr;
        dev->irq = irq;
 
index d7299f1a49401dc57d84610696008e63b90efe98..679dc8519c5b6db3c5916f81197b7413b66c44cc 100644 (file)
 
 #define        MAX_NUM_CARDS           4
 
-#define MAX_BUFFERS_PER_CMD    32
+#define NETXEN_MAX_FRAGS_PER_TX        14
 #define MAX_TSO_HEADER_DESC    2
 #define MGMT_CMD_DESC_RESV     4
 #define TX_STOP_THRESH         ((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \
@@ -558,7 +558,7 @@ struct netxen_recv_crb {
  */
 struct netxen_cmd_buffer {
        struct sk_buff *skb;
-       struct netxen_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1];
+       struct netxen_skb_frag frag_array[MAX_SKB_FRAGS + 1];
        u32 frag_count;
 };
 
index 83348dc4b184c5f8afbafc892b0c91dccd0dce13..e8a4b66559999b2fef6e375fb568abfa8f663786 100644 (file)
@@ -1844,6 +1844,8 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        struct cmd_desc_type0 *hwdesc, *first_desc;
        struct pci_dev *pdev;
        int i, k;
+       int delta = 0;
+       struct skb_frag_struct *frag;
 
        u32 producer;
        int frag_count, no_of_desc;
@@ -1851,6 +1853,21 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
 
        frag_count = skb_shinfo(skb)->nr_frags + 1;
 
+       /* 14 frags supported for normal packet and
+        * 32 frags supported for TSO packet
+        */
+       if (!skb_is_gso(skb) && frag_count > NETXEN_MAX_FRAGS_PER_TX) {
+
+               for (i = 0; i < (frag_count - NETXEN_MAX_FRAGS_PER_TX); i++) {
+                       frag = &skb_shinfo(skb)->frags[i];
+                       delta += frag->size;
+               }
+
+               if (!__pskb_pull_tail(skb, delta))
+                       goto drop_packet;
+
+               frag_count = 1 + skb_shinfo(skb)->nr_frags;
+       }
        /* 4 fragments per cmd des */
        no_of_desc = (frag_count + 3) >> 2;
 
index 693aaef4e3ced74366a964142d48c073c0ed4a88..718879b35b7d2ac2ea5415dcd70b63e64da94255 100644 (file)
@@ -317,7 +317,7 @@ static void pppoe_flush_dev(struct net_device *dev)
                        lock_sock(sk);
 
                        if (po->pppoe_dev == dev &&
-                           sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+                           sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
                                pppox_unbind_sock(sk);
                                sk->sk_state = PPPOX_ZOMBIE;
                                sk->sk_state_change(sk);
index dc44564ef6f9984fdc9a214491d9bdced015eb80..b0dead00b2d1d6b7809bd2b01906b5bff5a786b5 100644 (file)
@@ -99,6 +99,7 @@
 #define TX_UDPV6_PKT   0x0c
 
 /* Tx defines */
+#define QLCNIC_MAX_FRAGS_PER_TX        14
 #define MAX_TSO_HEADER_DESC    2
 #define MGMT_CMD_DESC_RESV     4
 #define TX_STOP_THRESH         ((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \
index cd88c7e1bfa9c76c3ae156da021a020f27346be5..cb1a1ef36c0ade56ddb5dfb98c2ef2ce8813b100 100644 (file)
@@ -2099,6 +2099,7 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        struct cmd_desc_type0 *hwdesc, *first_desc;
        struct pci_dev *pdev;
        struct ethhdr *phdr;
+       int delta = 0;
        int i, k;
 
        u32 producer;
@@ -2118,6 +2119,19 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
        }
 
        frag_count = skb_shinfo(skb)->nr_frags + 1;
+       /* 14 frags supported for normal packet and
+        * 32 frags supported for TSO packet
+        */
+       if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) {
+
+               for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++)
+                       delta += skb_shinfo(skb)->frags[i].size;
+
+               if (!__pskb_pull_tail(skb, delta))
+                       goto drop_packet;
+
+               frag_count = 1 + skb_shinfo(skb)->nr_frags;
+       }
 
        /* 4 fragments per cmd des */
        no_of_desc = (frag_count + 3) >> 2;
index d890679e4c4d293538b0e8d98cb1f34466e23947..a3c2aab53de8d29407e11386e51c7fefcd00c402 100644 (file)
@@ -328,7 +328,8 @@ static int efx_poll(struct napi_struct *napi, int budget)
  * processing to finish, then directly poll (and ack ) the eventq.
  * Finally reenable NAPI and interrupts.
  *
- * Since we are touching interrupts the caller should hold the suspend lock
+ * This is for use only during a loopback self-test.  It must not
+ * deliver any packets up the stack as this can result in deadlock.
  */
 void efx_process_channel_now(struct efx_channel *channel)
 {
@@ -336,6 +337,7 @@ void efx_process_channel_now(struct efx_channel *channel)
 
        BUG_ON(channel->channel >= efx->n_channels);
        BUG_ON(!channel->enabled);
+       BUG_ON(!efx->loopback_selftest);
 
        /* Disable interrupts and wait for ISRs to complete */
        efx_nic_disable_interrupts(efx);
@@ -1436,7 +1438,7 @@ static void efx_start_all(struct efx_nic *efx)
         * restart the transmit interface early so the watchdog timer stops */
        efx_start_port(efx);
 
-       if (efx_dev_registered(efx))
+       if (efx_dev_registered(efx) && !efx->port_inhibited)
                netif_tx_wake_all_queues(efx->net_dev);
 
        efx_for_each_channel(channel, efx)
index d9d8c2ef1074a3de6278eff70d7894cc8cc65991..cc978803d484bf84510ca5beb24ca41dd83a93ba 100644 (file)
@@ -152,6 +152,7 @@ static inline void efx_reado(struct efx_nic *efx, efx_oword_t *value,
 
        spin_lock_irqsave(&efx->biu_lock, flags);
        value->u32[0] = _efx_readd(efx, reg + 0);
+       rmb();
        value->u32[1] = _efx_readd(efx, reg + 4);
        value->u32[2] = _efx_readd(efx, reg + 8);
        value->u32[3] = _efx_readd(efx, reg + 12);
@@ -174,6 +175,7 @@ static inline void efx_sram_readq(struct efx_nic *efx, void __iomem *membase,
        value->u64[0] = (__force __le64)__raw_readq(membase + addr);
 #else
        value->u32[0] = (__force __le32)__raw_readl(membase + addr);
+       rmb();
        value->u32[1] = (__force __le32)__raw_readl(membase + addr + 4);
 #endif
        spin_unlock_irqrestore(&efx->biu_lock, flags);
index 9ffa9a6b55a0b3cf76009bf146b7eee0c74a3750..191a311da2dc77b4bfa65bcb927148cf791a54a0 100644 (file)
@@ -330,7 +330,6 @@ enum efx_rx_alloc_method {
  * @eventq_mask: Event queue pointer mask
  * @eventq_read_ptr: Event queue read pointer
  * @last_eventq_read_ptr: Last event queue read pointer value.
- * @magic_count: Event queue test event count
  * @irq_count: Number of IRQs since last adaptive moderation decision
  * @irq_mod_score: IRQ moderation score
  * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors
@@ -360,7 +359,6 @@ struct efx_channel {
        unsigned int eventq_mask;
        unsigned int eventq_read_ptr;
        unsigned int last_eventq_read_ptr;
-       unsigned int magic_count;
 
        unsigned int irq_count;
        unsigned int irq_mod_score;
index e8396614daf38b4e7d7c923a65d2bb109f066d98..10f1cb79c1472cfb91f9a50f16f827248bd00c96 100644 (file)
@@ -84,7 +84,8 @@ static inline void efx_write_buf_tbl(struct efx_nic *efx, efx_qword_t *value,
 static inline efx_qword_t *efx_event(struct efx_channel *channel,
                                     unsigned int index)
 {
-       return ((efx_qword_t *) (channel->eventq.addr)) + index;
+       return ((efx_qword_t *) (channel->eventq.addr)) +
+               (index & channel->eventq_mask);
 }
 
 /* See if an event is present
@@ -673,7 +674,8 @@ void efx_nic_eventq_read_ack(struct efx_channel *channel)
        efx_dword_t reg;
        struct efx_nic *efx = channel->efx;
 
-       EFX_POPULATE_DWORD_1(reg, FRF_AZ_EVQ_RPTR, channel->eventq_read_ptr);
+       EFX_POPULATE_DWORD_1(reg, FRF_AZ_EVQ_RPTR,
+                            channel->eventq_read_ptr & channel->eventq_mask);
        efx_writed_table(efx, &reg, efx->type->evq_rptr_tbl_base,
                         channel->channel);
 }
@@ -908,7 +910,7 @@ efx_handle_generated_event(struct efx_channel *channel, efx_qword_t *event)
 
        code = EFX_QWORD_FIELD(*event, FSF_AZ_DRV_GEN_EV_MAGIC);
        if (code == EFX_CHANNEL_MAGIC_TEST(channel))
-               ++channel->magic_count;
+               ; /* ignore */
        else if (code == EFX_CHANNEL_MAGIC_FILL(channel))
                /* The queue must be empty, so we won't receive any rx
                 * events, so efx_process_channel() won't refill the
@@ -1015,8 +1017,7 @@ int efx_nic_process_eventq(struct efx_channel *channel, int budget)
                /* Clear this event by marking it all ones */
                EFX_SET_QWORD(*p_event);
 
-               /* Increment read pointer */
-               read_ptr = (read_ptr + 1) & channel->eventq_mask;
+               ++read_ptr;
 
                ev_code = EFX_QWORD_FIELD(event, FSF_AZ_EV_CODE);
 
@@ -1060,6 +1061,13 @@ out:
        return spent;
 }
 
+/* Check whether an event is present in the eventq at the current
+ * read pointer.  Only useful for self-test.
+ */
+bool efx_nic_event_present(struct efx_channel *channel)
+{
+       return efx_event_present(efx_event(channel, channel->eventq_read_ptr));
+}
 
 /* Allocate buffer table entries for event queue */
 int efx_nic_probe_eventq(struct efx_channel *channel)
@@ -1165,7 +1173,7 @@ static void efx_poll_flush_events(struct efx_nic *efx)
        struct efx_tx_queue *tx_queue;
        struct efx_rx_queue *rx_queue;
        unsigned int read_ptr = channel->eventq_read_ptr;
-       unsigned int end_ptr = (read_ptr - 1) & channel->eventq_mask;
+       unsigned int end_ptr = read_ptr + channel->eventq_mask - 1;
 
        do {
                efx_qword_t *event = efx_event(channel, read_ptr);
@@ -1205,7 +1213,7 @@ static void efx_poll_flush_events(struct efx_nic *efx)
                 * it's ok to throw away every non-flush event */
                EFX_SET_QWORD(*event);
 
-               read_ptr = (read_ptr + 1) & channel->eventq_mask;
+               ++read_ptr;
        } while (read_ptr != end_ptr);
 
        channel->eventq_read_ptr = read_ptr;
index d9de1b647d416b601f62cb1e6a1a6f56f09a4830..a42db6e35be39166d86f72887def5619c581dc58 100644 (file)
@@ -184,6 +184,7 @@ extern void efx_nic_fini_eventq(struct efx_channel *channel);
 extern void efx_nic_remove_eventq(struct efx_channel *channel);
 extern int efx_nic_process_eventq(struct efx_channel *channel, int rx_quota);
 extern void efx_nic_eventq_read_ack(struct efx_channel *channel);
+extern bool efx_nic_event_present(struct efx_channel *channel);
 
 /* MAC/PHY */
 extern void falcon_drain_tx_fifo(struct efx_nic *efx);
index a0f49b348d62872be7512019083badfc50ab9db8..50ad3bcaf68a243ec41d78d72e1cd358c0455e59 100644 (file)
@@ -131,8 +131,6 @@ static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests)
 static int efx_test_interrupts(struct efx_nic *efx,
                               struct efx_self_tests *tests)
 {
-       struct efx_channel *channel;
-
        netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n");
        tests->interrupt = -1;
 
@@ -140,15 +138,6 @@ static int efx_test_interrupts(struct efx_nic *efx,
        efx->last_irq_cpu = -1;
        smp_wmb();
 
-       /* ACK each interrupting event queue. Receiving an interrupt due to
-        * traffic before a test event is raised is considered a pass */
-       efx_for_each_channel(channel, efx) {
-               if (channel->work_pending)
-                       efx_process_channel_now(channel);
-               if (efx->last_irq_cpu >= 0)
-                       goto success;
-       }
-
        efx_nic_generate_interrupt(efx);
 
        /* Wait for arrival of test interrupt. */
@@ -173,13 +162,13 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
                               struct efx_self_tests *tests)
 {
        struct efx_nic *efx = channel->efx;
-       unsigned int magic_count, count;
+       unsigned int read_ptr, count;
 
        tests->eventq_dma[channel->channel] = -1;
        tests->eventq_int[channel->channel] = -1;
        tests->eventq_poll[channel->channel] = -1;
 
-       magic_count = channel->magic_count;
+       read_ptr = channel->eventq_read_ptr;
        channel->efx->last_irq_cpu = -1;
        smp_wmb();
 
@@ -190,10 +179,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
        do {
                schedule_timeout_uninterruptible(HZ / 100);
 
-               if (channel->work_pending)
-                       efx_process_channel_now(channel);
-
-               if (channel->magic_count != magic_count)
+               if (ACCESS_ONCE(channel->eventq_read_ptr) != read_ptr)
                        goto eventq_ok;
        } while (++count < 2);
 
@@ -211,8 +197,7 @@ static int efx_test_eventq_irq(struct efx_channel *channel,
        }
 
        /* Check to see if event was received even if interrupt wasn't */
-       efx_process_channel_now(channel);
-       if (channel->magic_count != magic_count) {
+       if (efx_nic_event_present(channel)) {
                netif_err(efx, drv, efx->net_dev,
                          "channel %d event was generated, but "
                          "failed to trigger an interrupt\n", channel->channel);
@@ -770,6 +755,8 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests,
        __efx_reconfigure_port(efx);
        mutex_unlock(&efx->mac_lock);
 
+       netif_tx_wake_all_queues(efx->net_dev);
+
        return rc_test;
 }
 
index 13980190821762aa47a31729b688e5b36001ef77..d2c85dfdf3bf3a338349dbe21a5547d99cd6c98a 100644 (file)
@@ -435,7 +435,8 @@ void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
         * queue state. */
        smp_mb();
        if (unlikely(netif_tx_queue_stopped(tx_queue->core_txq)) &&
-           likely(efx->port_enabled)) {
+           likely(efx->port_enabled) &&
+           likely(!efx->port_inhibited)) {
                fill_level = tx_queue->insert_count - tx_queue->read_count;
                if (fill_level < EFX_TXQ_THRESHOLD(efx)) {
                        EFX_BUG_ON_PARANOID(!efx_dev_registered(efx));
index cb317cd069ffcb5d13fa2fe5a5d920049b23ffeb..484f795a779dbca9b20e4f089d06cf1b9e253a50 100644 (file)
@@ -240,7 +240,8 @@ static const struct ethtool_ops sis900_ethtool_ops;
  *     @net_dev: the net device to get address for
  *
  *     Older SiS900 and friends, use EEPROM to store MAC address.
- *     MAC address is read from read_eeprom() into @net_dev->dev_addr.
+ *     MAC address is read from read_eeprom() into @net_dev->dev_addr and
+ *     @net_dev->perm_addr.
  */
 
 static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
@@ -261,6 +262,9 @@ static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_de
        for (i = 0; i < 3; i++)
                ((u16 *)(net_dev->dev_addr))[i] = read_eeprom(ioaddr, i+EEPROMMACAddr);
 
+       /* Store MAC Address in perm_addr */
+       memcpy(net_dev->perm_addr, net_dev->dev_addr, ETH_ALEN);
+
        return 1;
 }
 
@@ -271,7 +275,8 @@ static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_de
  *
  *     SiS630E model, use APC CMOS RAM to store MAC address.
  *     APC CMOS RAM is accessed through ISA bridge.
- *     MAC address is read into @net_dev->dev_addr.
+ *     MAC address is read into @net_dev->dev_addr and
+ *     @net_dev->perm_addr.
  */
 
 static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
@@ -296,6 +301,10 @@ static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
                outb(0x09 + i, 0x70);
                ((u8 *)(net_dev->dev_addr))[i] = inb(0x71);
        }
+
+       /* Store MAC Address in perm_addr */
+       memcpy(net_dev->perm_addr, net_dev->dev_addr, ETH_ALEN);
+
        pci_write_config_byte(isa_bridge, 0x48, reg & ~0x40);
        pci_dev_put(isa_bridge);
 
@@ -310,7 +319,7 @@ static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
  *
  *     SiS635 model, set MAC Reload Bit to load Mac address from APC
  *     to rfdr. rfdr is accessed through rfcr. MAC address is read into
- *     @net_dev->dev_addr.
+ *     @net_dev->dev_addr and @net_dev->perm_addr.
  */
 
 static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
@@ -334,6 +343,9 @@ static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
                *( ((u16 *)net_dev->dev_addr) + i) = inw(ioaddr + rfdr);
        }
 
+       /* Store MAC Address in perm_addr */
+       memcpy(net_dev->perm_addr, net_dev->dev_addr, ETH_ALEN);
+
        /* enable packet filtering */
        outl(rfcrSave | RFEN, rfcr + ioaddr);
 
@@ -353,7 +365,7 @@ static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
  *     EEDONE signal to refuse EEPROM access by LAN.
  *     The EEPROM map of SiS962 or SiS963 is different to SiS900.
  *     The signature field in SiS962 or SiS963 spec is meaningless.
- *     MAC address is read into @net_dev->dev_addr.
+ *     MAC address is read into @net_dev->dev_addr and @net_dev->perm_addr.
  */
 
 static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev,
@@ -372,6 +384,9 @@ static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev,
                        for (i = 0; i < 3; i++)
                                ((u16 *)(net_dev->dev_addr))[i] = read_eeprom(ioaddr, i+EEPROMMACAddr);
 
+                       /* Store MAC Address in perm_addr */
+                       memcpy(net_dev->perm_addr, net_dev->dev_addr, ETH_ALEN);
+
                        outl(EEDONE, ee_addr);
                        return 1;
                } else {
index c498b720b532cd49c88444c41a1ddea4ebdbdc83..4b42ecc63dcfd582203141b5e8f92ddfb42a25ba 100644 (file)
@@ -1818,6 +1818,7 @@ static int __devinit smsc911x_init(struct net_device *dev)
        SMSC_TRACE(PROBE, "PHY will be autodetected.");
 
        spin_lock_init(&pdata->dev_lock);
+       spin_lock_init(&pdata->mac_lock);
 
        if (pdata->ioaddr == 0) {
                SMSC_WARNING(PROBE, "pdata->ioaddr: 0x00000000");
@@ -1895,8 +1896,11 @@ static int __devinit smsc911x_init(struct net_device *dev)
        /* workaround for platforms without an eeprom, where the mac address
         * is stored elsewhere and set by the bootloader.  This saves the
         * mac address before resetting the device */
-       if (pdata->config.flags & SMSC911X_SAVE_MAC_ADDRESS)
+       if (pdata->config.flags & SMSC911X_SAVE_MAC_ADDRESS) {
+               spin_lock_irq(&pdata->mac_lock);
                smsc911x_read_mac_address(dev);
+               spin_unlock_irq(&pdata->mac_lock);
+       }
 
        /* Reset the LAN911x */
        if (smsc911x_soft_reset(pdata))
@@ -2059,8 +2063,6 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
                SMSC_TRACE(PROBE, "Network interface: \"%s\"", dev->name);
        }
 
-       spin_lock_init(&pdata->mac_lock);
-
        retval = smsc911x_mii_init(pdev, dev);
        if (retval) {
                SMSC_WARNING(PROBE,
index d65fab1ba790dfd0dba7af94bbf2506fc5566d7f..e25093510b0cd462af521f45aa5b3f43c98c0213 100644 (file)
@@ -26,9 +26,9 @@
 
 #undef DWMAC_DMA_DEBUG
 #ifdef DWMAC_DMA_DEBUG
-#define DBG(fmt, args...)  printk(fmt, ## args)
+#define DWMAC_LIB_DBG(fmt, args...)  printk(fmt, ## args)
 #else
-#define DBG(fmt, args...)  do { } while (0)
+#define DWMAC_LIB_DBG(fmt, args...)  do { } while (0)
 #endif
 
 /* CSR1 enables the transmit DMA to check for new descriptor */
@@ -152,7 +152,7 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
        /* read the status register (CSR5) */
        u32 intr_status = readl(ioaddr + DMA_STATUS);
 
-       DBG(INFO, "%s: [CSR5: 0x%08x]\n", __func__, intr_status);
+       DWMAC_LIB_DBG(KERN_INFO "%s: [CSR5: 0x%08x]\n", __func__, intr_status);
 #ifdef DWMAC_DMA_DEBUG
        /* It displays the DMA process states (CSR5 register) */
        show_tx_process_state(intr_status);
@@ -160,43 +160,43 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
 #endif
        /* ABNORMAL interrupts */
        if (unlikely(intr_status & DMA_STATUS_AIS)) {
-               DBG(INFO, "CSR5[15] DMA ABNORMAL IRQ: ");
+               DWMAC_LIB_DBG(KERN_INFO "CSR5[15] DMA ABNORMAL IRQ: ");
                if (unlikely(intr_status & DMA_STATUS_UNF)) {
-                       DBG(INFO, "transmit underflow\n");
+                       DWMAC_LIB_DBG(KERN_INFO "transmit underflow\n");
                        ret = tx_hard_error_bump_tc;
                        x->tx_undeflow_irq++;
                }
                if (unlikely(intr_status & DMA_STATUS_TJT)) {
-                       DBG(INFO, "transmit jabber\n");
+                       DWMAC_LIB_DBG(KERN_INFO "transmit jabber\n");
                        x->tx_jabber_irq++;
                }
                if (unlikely(intr_status & DMA_STATUS_OVF)) {
-                       DBG(INFO, "recv overflow\n");
+                       DWMAC_LIB_DBG(KERN_INFO "recv overflow\n");
                        x->rx_overflow_irq++;
                }
                if (unlikely(intr_status & DMA_STATUS_RU)) {
-                       DBG(INFO, "receive buffer unavailable\n");
+                       DWMAC_LIB_DBG(KERN_INFO "receive buffer unavailable\n");
                        x->rx_buf_unav_irq++;
                }
                if (unlikely(intr_status & DMA_STATUS_RPS)) {
-                       DBG(INFO, "receive process stopped\n");
+                       DWMAC_LIB_DBG(KERN_INFO "receive process stopped\n");
                        x->rx_process_stopped_irq++;
                }
                if (unlikely(intr_status & DMA_STATUS_RWT)) {
-                       DBG(INFO, "receive watchdog\n");
+                       DWMAC_LIB_DBG(KERN_INFO "receive watchdog\n");
                        x->rx_watchdog_irq++;
                }
                if (unlikely(intr_status & DMA_STATUS_ETI)) {
-                       DBG(INFO, "transmit early interrupt\n");
+                       DWMAC_LIB_DBG(KERN_INFO "transmit early interrupt\n");
                        x->tx_early_irq++;
                }
                if (unlikely(intr_status & DMA_STATUS_TPS)) {
-                       DBG(INFO, "transmit process stopped\n");
+                       DWMAC_LIB_DBG(KERN_INFO "transmit process stopped\n");
                        x->tx_process_stopped_irq++;
                        ret = tx_hard_error;
                }
                if (unlikely(intr_status & DMA_STATUS_FBI)) {
-                       DBG(INFO, "fatal bus error\n");
+                       DWMAC_LIB_DBG(KERN_INFO "fatal bus error\n");
                        x->fatal_bus_error_irq++;
                        ret = tx_hard_error;
                }
@@ -215,7 +215,7 @@ int dwmac_dma_interrupt(void __iomem *ioaddr,
        /* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
        writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
 
-       DBG(INFO, "\n\n");
+       DWMAC_LIB_DBG(KERN_INFO "\n\n");
        return ret;
 }
 
index 0e5f03135b50abd053712ca6ddaf1e14df76a241..cc973fc384052bc2a5315aa982237b5bbc31015f 100644 (file)
@@ -750,7 +750,6 @@ static void stmmac_dma_interrupt(struct stmmac_priv *priv)
                        priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
                        priv->xstats.threshold = tc;
                }
-               stmmac_tx_err(priv);
        } else if (unlikely(status == tx_hard_error))
                stmmac_tx_err(priv);
 }
@@ -781,21 +780,6 @@ static int stmmac_open(struct net_device *dev)
 
        stmmac_verify_args();
 
-       ret = stmmac_init_phy(dev);
-       if (unlikely(ret)) {
-               pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret);
-               return ret;
-       }
-
-       /* Request the IRQ lines */
-       ret = request_irq(dev->irq, stmmac_interrupt,
-                         IRQF_SHARED, dev->name, dev);
-       if (unlikely(ret < 0)) {
-               pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
-                      __func__, dev->irq, ret);
-               return ret;
-       }
-
 #ifdef CONFIG_STMMAC_TIMER
        priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
        if (unlikely(priv->tm == NULL)) {
@@ -814,6 +798,11 @@ static int stmmac_open(struct net_device *dev)
        } else
                priv->tm->enable = 1;
 #endif
+       ret = stmmac_init_phy(dev);
+       if (unlikely(ret)) {
+               pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret);
+               goto open_error;
+       }
 
        /* Create and initialize the TX/RX descriptors chains. */
        priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
@@ -822,12 +811,11 @@ static int stmmac_open(struct net_device *dev)
        init_dma_desc_rings(dev);
 
        /* DMA initialization and SW reset */
-       if (unlikely(priv->hw->dma->init(priv->ioaddr, priv->plat->pbl,
-                                        priv->dma_tx_phy,
-                                        priv->dma_rx_phy) < 0)) {
-
+       ret = priv->hw->dma->init(priv->ioaddr, priv->plat->pbl,
+                                 priv->dma_tx_phy, priv->dma_rx_phy);
+       if (ret < 0) {
                pr_err("%s: DMA initialization failed\n", __func__);
-               return -1;
+               goto open_error;
        }
 
        /* Copy the MAC addr into the HW  */
@@ -848,6 +836,15 @@ static int stmmac_open(struct net_device *dev)
        writel(0xffffffff, priv->ioaddr + MMC_HIGH_INTR_MASK);
        writel(0xffffffff, priv->ioaddr + MMC_LOW_INTR_MASK);
 
+       /* Request the IRQ lines */
+       ret = request_irq(dev->irq, stmmac_interrupt,
+                        IRQF_SHARED, dev->name, dev);
+       if (unlikely(ret < 0)) {
+               pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
+                      __func__, dev->irq, ret);
+               goto open_error;
+       }
+
        /* Enable the MAC Rx/Tx */
        stmmac_enable_mac(priv->ioaddr);
 
@@ -878,7 +875,17 @@ static int stmmac_open(struct net_device *dev)
        napi_enable(&priv->napi);
        skb_queue_head_init(&priv->rx_recycle);
        netif_start_queue(dev);
+
        return 0;
+
+open_error:
+#ifdef CONFIG_STMMAC_TIMER
+       kfree(priv->tm);
+#endif
+       if (priv->phydev)
+               phy_disconnect(priv->phydev);
+
+       return ret;
 }
 
 /**
index 8a3b191b195b8bc015694b5042fd67a340ecd421..ff32befd84433c98867a6b7a9d8824978e9e8557 100644 (file)
@@ -1251,7 +1251,7 @@ static netdev_tx_t xl_xmit(struct sk_buff *skb, struct net_device *dev)
 /* 
  * The NIC has told us that a packet has been downloaded onto the card, we must
  * find out which packet it has done, clear the skb and information for the packet
- * then advance around the ring for all tranmitted packets
+ * then advance around the ring for all transmitted packets
  */
 
 static void xl_dn_comp(struct net_device *dev) 
@@ -1568,7 +1568,7 @@ static void xl_arb_cmd(struct net_device *dev)
                        if (lan_status_diff & LSC_SOFT_ERR)
                                        printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame\n",dev->name);
                        if (lan_status_diff & LSC_TRAN_BCN) 
-                                       printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n",dev->name);
+                                       printk(KERN_INFO "%s: We are transmitting the beacon, aaah\n",dev->name);
                        if (lan_status_diff & LSC_SS) 
                                        printk(KERN_INFO "%s: Single Station on the ring\n", dev->name);
                        if (lan_status_diff & LSC_RING_REC)
index 5bd140704533f353fa6b7ee05a6cbd9445aec7ad..9354ca9da576c97f7ff54ed014480d29e877ec48 100644 (file)
@@ -1675,7 +1675,7 @@ drop_frame:
                        if (lan_status_diff & LSC_SOFT_ERR)
                                printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame\n", dev->name);
                        if (lan_status_diff & LSC_TRAN_BCN)
-                               printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n", dev->name);
+                               printk(KERN_INFO "%s: We are transmitting the beacon, aaah\n", dev->name);
                        if (lan_status_diff & LSC_SS)
                                printk(KERN_INFO "%s: Single Station on the ring\n", dev->name);
                        if (lan_status_diff & LSC_RING_REC)
index 3d2fbe60b46e07f57e97f418ad62a903e908b26f..2684003b8ab6478037d1047328c61be4f02a8837 100644 (file)
@@ -1500,7 +1500,7 @@ drop_frame:
                        if (lan_status_diff & LSC_SOFT_ERR)
                                        printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame\n",dev->name);
                        if (lan_status_diff & LSC_TRAN_BCN) 
-                                       printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n",dev->name);
+                                       printk(KERN_INFO "%s: We are transmitting the beacon, aaah\n",dev->name);
                        if (lan_status_diff & LSC_SS) 
                                        printk(KERN_INFO "%s: Single Station on the ring\n", dev->name);
                        if (lan_status_diff & LSC_RING_REC)
index 727874d9deb6d886fd9d357484c57d3ee899d079..47a6c870b51fae361b39de950ee4a523ced52475 100644 (file)
@@ -1313,6 +1313,21 @@ static const struct usb_device_id products[] = {
                USB_DEVICE(0x0424, 0x9909),
                .driver_info = (unsigned long) &smsc95xx_info,
        },
+       {
+               /* SMSC LAN9530 USB Ethernet Device */
+               USB_DEVICE(0x0424, 0x9530),
+               .driver_info = (unsigned long) &smsc95xx_info,
+       },
+       {
+               /* SMSC LAN9730 USB Ethernet Device */
+               USB_DEVICE(0x0424, 0x9730),
+               .driver_info = (unsigned long) &smsc95xx_info,
+       },
+       {
+               /* SMSC LAN89530 USB Ethernet Device */
+               USB_DEVICE(0x0424, 0x9E08),
+               .driver_info = (unsigned long) &smsc95xx_info,
+       },
        { },            /* END */
 };
 MODULE_DEVICE_TABLE(usb, products);
index f1b8af64569cbdeea7d80316d071aea329eab494..2d10239ce8295e2633699c6680a9f1b7072703e1 100644 (file)
@@ -1040,7 +1040,7 @@ static int ath9k_hif_usb_probe(struct usb_interface *interface,
        }
 
        ret = ath9k_htc_hw_init(hif_dev->htc_handle,
-                               &hif_dev->udev->dev, hif_dev->device_id,
+                               &interface->dev, hif_dev->device_id,
                                hif_dev->udev->product, id->driver_info);
        if (ret) {
                ret = -EINVAL;
@@ -1158,7 +1158,7 @@ fail_resume:
 #endif
 
 static struct usb_driver ath9k_hif_usb_driver = {
-       .name = "ath9k_hif_usb",
+       .name = KBUILD_MODNAME,
        .probe = ath9k_hif_usb_probe,
        .disconnect = ath9k_hif_usb_disconnect,
 #ifdef CONFIG_PM
index 338b07502f1adc5621c60815a8f5ce8c0e0345e6..c95bc5cc1a1fbb4bad3d2e816477c5cfbe96fb97 100644 (file)
@@ -1254,15 +1254,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
        ah->txchainmask = common->tx_chainmask;
        ah->rxchainmask = common->rx_chainmask;
 
-       if ((common->bus_ops->ath_bus_type != ATH_USB) && !ah->chip_fullsleep) {
-               ath9k_hw_abortpcurecv(ah);
-               if (!ath9k_hw_stopdmarecv(ah)) {
-                       ath_dbg(common, ATH_DBG_XMIT,
-                               "Failed to stop receive dma\n");
-                       bChannelChange = false;
-               }
-       }
-
        if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
                return -EIO;
 
@@ -2546,6 +2537,7 @@ static struct {
        { AR_SREV_VERSION_9287,         "9287" },
        { AR_SREV_VERSION_9271,         "9271" },
        { AR_SREV_VERSION_9300,         "9300" },
+       { AR_SREV_VERSION_9485,         "9485" },
 };
 
 /* For devices with external radios */
index 562257ac52cfecf77ee58cd7f1318507f14d9b75..edc1cbbfecaf6fbd153ce00237f1101f49096edc 100644 (file)
@@ -751,28 +751,47 @@ void ath9k_hw_abortpcurecv(struct ath_hw *ah)
 }
 EXPORT_SYMBOL(ath9k_hw_abortpcurecv);
 
-bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
+bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset)
 {
 #define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
 #define AH_RX_TIME_QUANTUM     100     /* usec */
        struct ath_common *common = ath9k_hw_common(ah);
+       u32 mac_status, last_mac_status = 0;
        int i;
 
+       /* Enable access to the DMA observation bus */
+       REG_WRITE(ah, AR_MACMISC,
+                 ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
+                  (AR_MACMISC_MISC_OBS_BUS_1 <<
+                   AR_MACMISC_MISC_OBS_BUS_MSB_S)));
+
        REG_WRITE(ah, AR_CR, AR_CR_RXD);
 
        /* Wait for rx enable bit to go low */
        for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) {
                if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0)
                        break;
+
+               if (!AR_SREV_9300_20_OR_LATER(ah)) {
+                       mac_status = REG_READ(ah, AR_DMADBG_7) & 0x7f0;
+                       if (mac_status == 0x1c0 && mac_status == last_mac_status) {
+                               *reset = true;
+                               break;
+                       }
+
+                       last_mac_status = mac_status;
+               }
+
                udelay(AH_TIME_QUANTUM);
        }
 
        if (i == 0) {
                ath_err(common,
-                       "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
+                       "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n",
                        AH_RX_STOP_DMA_TIMEOUT / 1000,
                        REG_READ(ah, AR_CR),
-                       REG_READ(ah, AR_DIAG_SW));
+                       REG_READ(ah, AR_DIAG_SW),
+                       REG_READ(ah, AR_DMADBG_7));
                return false;
        } else {
                return true;
index b2b2ff852c328142a55396801010c46e32c72432..c2a59386fb9cf05a7eabb12214e613103e0c08b0 100644 (file)
@@ -695,7 +695,7 @@ bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set);
 void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp);
 void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning);
 void ath9k_hw_abortpcurecv(struct ath_hw *ah);
-bool ath9k_hw_stopdmarecv(struct ath_hw *ah);
+bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset);
 int ath9k_hw_beaconq_setup(struct ath_hw *ah);
 
 /* Interrupt Handling */
index dddb85de622d2ea253152032ec8edf86df475754..17d04ff8d678021aaf0f52f2da55794e017272b5 100644 (file)
@@ -1376,7 +1376,6 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
 
        ath9k_calculate_iter_data(hw, vif, &iter_data);
 
-       ath9k_ps_wakeup(sc);
        /* Set BSSID mask. */
        memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
        ath_hw_setbssidmask(common);
@@ -1411,7 +1410,6 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
        }
 
        ath9k_hw_set_interrupts(ah, ah->imask);
-       ath9k_ps_restore(sc);
 
        /* Set up ANI */
        if ((iter_data.naps + iter_data.nadhocs) > 0) {
@@ -1457,6 +1455,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
        struct ath_vif *avp = (void *)vif->drv_priv;
        int ret = 0;
 
+       ath9k_ps_wakeup(sc);
        mutex_lock(&sc->mutex);
 
        switch (vif->type) {
@@ -1503,6 +1502,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,
        ath9k_do_vif_add_setup(hw, vif);
 out:
        mutex_unlock(&sc->mutex);
+       ath9k_ps_restore(sc);
        return ret;
 }
 
@@ -1517,6 +1517,7 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
 
        ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n");
        mutex_lock(&sc->mutex);
+       ath9k_ps_wakeup(sc);
 
        /* See if new interface type is valid. */
        if ((new_type == NL80211_IFTYPE_ADHOC) &&
@@ -1546,6 +1547,7 @@ static int ath9k_change_interface(struct ieee80211_hw *hw,
 
        ath9k_do_vif_add_setup(hw, vif);
 out:
+       ath9k_ps_restore(sc);
        mutex_unlock(&sc->mutex);
        return ret;
 }
@@ -1558,6 +1560,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
 
        ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n");
 
+       ath9k_ps_wakeup(sc);
        mutex_lock(&sc->mutex);
 
        sc->nvifs--;
@@ -1569,6 +1572,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw,
        ath9k_calculate_summary_state(hw, NULL);
 
        mutex_unlock(&sc->mutex);
+       ath9k_ps_restore(sc);
 }
 
 static void ath9k_enable_ps(struct ath_softc *sc)
@@ -1809,6 +1813,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
 
        txq = sc->tx.txq_map[queue];
 
+       ath9k_ps_wakeup(sc);
        mutex_lock(&sc->mutex);
 
        memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
@@ -1832,6 +1837,7 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
                        ath_beaconq_config(sc);
 
        mutex_unlock(&sc->mutex);
+       ath9k_ps_restore(sc);
 
        return ret;
 }
@@ -1894,6 +1900,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
        int slottime;
        int error;
 
+       ath9k_ps_wakeup(sc);
        mutex_lock(&sc->mutex);
 
        if (changed & BSS_CHANGED_BSSID) {
@@ -1994,6 +2001,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
        }
 
        mutex_unlock(&sc->mutex);
+       ath9k_ps_restore(sc);
 }
 
 static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
index a9c3f4672aa0e12736a24c8ddb4e4c280d635d29..dcd19bc337d1ddf96890432f085ee6ee83c9658d 100644 (file)
@@ -486,12 +486,12 @@ start_recv:
 bool ath_stoprecv(struct ath_softc *sc)
 {
        struct ath_hw *ah = sc->sc_ah;
-       bool stopped;
+       bool stopped, reset = false;
 
        spin_lock_bh(&sc->rx.rxbuflock);
        ath9k_hw_abortpcurecv(ah);
        ath9k_hw_setrxfilter(ah, 0);
-       stopped = ath9k_hw_stopdmarecv(ah);
+       stopped = ath9k_hw_stopdmarecv(ah, &reset);
 
        if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
                ath_edma_stop_recv(sc);
@@ -506,7 +506,7 @@ bool ath_stoprecv(struct ath_softc *sc)
                        "confusing the DMA engine when we start RX up\n");
                ATH_DBG_WARN_ON_ONCE(!stopped);
        }
-       return stopped;
+       return stopped || reset;
 }
 
 void ath_flushrecv(struct ath_softc *sc)
index 248c670fdfbefe0bf06e3ace4e33b2e4bd43da05..5c2cfe6941524ccd7b05525a147b5ce6854c3133 100644 (file)
@@ -195,6 +195,7 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = {
        {APL9_WORLD, CTL_ETSI, CTL_ETSI},
 
        {APL3_FCCA, CTL_FCC, CTL_FCC},
+       {APL7_FCCA, CTL_FCC, CTL_FCC},
        {APL1_ETSIC, CTL_FCC, CTL_ETSI},
        {APL2_ETSIC, CTL_FCC, CTL_ETSI},
        {APL2_APLD, CTL_FCC, NO_CTL},
index 3d5566e7af0ad51ea08088c8adaa03f1c2a1e02b..ff0f5ba14b2cfb60223a19455772fddca719951b 100644 (file)
@@ -1536,7 +1536,7 @@ static void dma_rx(struct b43_dmaring *ring, int *slot)
                dmaaddr = meta->dmaaddr;
                goto drop_recycle_buffer;
        }
-       if (unlikely(len > ring->rx_buffersize)) {
+       if (unlikely(len + ring->frameoffset > ring->rx_buffersize)) {
                /* The data did not fit into one descriptor buffer
                 * and is split over multiple buffers.
                 * This should never happen, as we try to allocate buffers
index a01c2100f166455d055fa1717574fbb85dfdd3f6..e8a80a1251bf602ba89c726d8019188914f73c78 100644 (file)
@@ -163,7 +163,7 @@ struct b43_dmadesc_generic {
 /* DMA engine tuning knobs */
 #define B43_TXRING_SLOTS               256
 #define B43_RXRING_SLOTS               64
-#define B43_DMA0_RX_BUFFERSIZE         IEEE80211_MAX_FRAME_LEN
+#define B43_DMA0_RX_BUFFERSIZE         (B43_DMA0_RX_FRAMEOFFSET + IEEE80211_MAX_FRAME_LEN)
 
 /* Pointer poison */
 #define B43_DMA_PTR_POISON             ((void *)ERR_PTR(-ENOMEM))
index 2a45dd44cc127ba7abf3400012059ab90addcb73..aef65cd47661e39a62106b232eccb8054b382411 100644 (file)
@@ -1,6 +1,5 @@
 config IWLWIFI_LEGACY
-       tristate "Intel Wireless Wifi legacy devices"
-       depends on PCI && MAC80211
+       tristate
        select FW_LOADER
        select NEW_LEDS
        select LEDS_CLASS
@@ -65,7 +64,8 @@ endmenu
 
 config IWL4965
        tristate "Intel Wireless WiFi 4965AGN (iwl4965)"
-       depends on IWLWIFI_LEGACY
+       depends on PCI && MAC80211
+       select IWLWIFI_LEGACY
        ---help---
          This option enables support for
 
@@ -92,7 +92,8 @@ config IWL4965
 
 config IWL3945
        tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)"
-       depends on IWLWIFI_LEGACY
+       depends on PCI && MAC80211
+       select IWLWIFI_LEGACY
        ---help---
          Select to build the driver supporting the:
 
index 779d3cb86e2c86ad9c15f207288032064bca9dcf..5c3a68d3af12e3e7c7fe137a536d2759416f2443 100644 (file)
@@ -74,8 +74,6 @@
 /* RSSI to dBm */
 #define IWL39_RSSI_OFFSET      95
 
-#define IWL_DEFAULT_TX_POWER   0x0F
-
 /*
  * EEPROM related constants, enums, and structures.
  */
index 08b189c8472d214d20ed132a3f0849e693136a29..fc6fa2886d9c38f05099516147dacc3088afb748 100644 (file)
@@ -804,9 +804,6 @@ struct iwl4965_scd_bc_tbl {
 
 #define IWL4965_DEFAULT_TX_RETRY  15
 
-/* Limit range of txpower output target to be between these values */
-#define IWL4965_TX_POWER_TARGET_POWER_MIN      (0)     /* 0 dBm: 1 milliwatt */
-
 /* EEPROM */
 #define IWL4965_FIRST_AMPDU_QUEUE      10
 
index 7007d61bb6b5c904aa62af13183bc67b24eb635f..c1511b14b239c69884292e5e8e33296debbdebc4 100644 (file)
@@ -160,6 +160,7 @@ int iwl_legacy_init_geos(struct iwl_priv *priv)
        struct ieee80211_channel *geo_ch;
        struct ieee80211_rate *rates;
        int i = 0;
+       s8 max_tx_power = 0;
 
        if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
            priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
@@ -235,8 +236,8 @@ int iwl_legacy_init_geos(struct iwl_priv *priv)
 
                        geo_ch->flags |= ch->ht40_extension_channel;
 
-                       if (ch->max_power_avg > priv->tx_power_device_lmt)
-                               priv->tx_power_device_lmt = ch->max_power_avg;
+                       if (ch->max_power_avg > max_tx_power)
+                               max_tx_power = ch->max_power_avg;
                } else {
                        geo_ch->flags |= IEEE80211_CHAN_DISABLED;
                }
@@ -249,6 +250,10 @@ int iwl_legacy_init_geos(struct iwl_priv *priv)
                                 geo_ch->flags);
        }
 
+       priv->tx_power_device_lmt = max_tx_power;
+       priv->tx_power_user_lmt = max_tx_power;
+       priv->tx_power_next = max_tx_power;
+
        if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
             priv->cfg->sku & IWL_SKU_A) {
                IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
@@ -1124,11 +1129,11 @@ int iwl_legacy_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
        if (!priv->cfg->ops->lib->send_tx_power)
                return -EOPNOTSUPP;
 
-       if (tx_power < IWL4965_TX_POWER_TARGET_POWER_MIN) {
+       /* 0 dBm mean 1 milliwatt */
+       if (tx_power < 0) {
                IWL_WARN(priv,
-                        "Requested user TXPOWER %d below lower limit %d.\n",
-                        tx_power,
-                        IWL4965_TX_POWER_TARGET_POWER_MIN);
+                        "Requested user TXPOWER %d below 1 mW.\n",
+                        tx_power);
                return -EINVAL;
        }
 
index 04c5648027df8db645aa57d4f5535267c5a15d3b..cb346d1a9ffa6e5f581b5b9c9c0a52f6ffafed3a 100644 (file)
@@ -471,13 +471,6 @@ int iwl_legacy_init_channel_map(struct iwl_priv *priv)
                                             flags & EEPROM_CHANNEL_RADAR))
                                       ? "" : "not ");
 
-                       /* Set the tx_power_user_lmt to the highest power
-                        * supported by any channel */
-                       if (eeprom_ch_info[ch].max_power_avg >
-                                               priv->tx_power_user_lmt)
-                               priv->tx_power_user_lmt =
-                                   eeprom_ch_info[ch].max_power_avg;
-
                        ch_info++;
                }
        }
index 28eb3d885ba176874a0896bcfa03c5c4953f9af3..cc7ebcee60e5bd6e9d49f2a1ae8c17dee1c31f21 100644 (file)
@@ -3825,10 +3825,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
        priv->force_reset[IWL_FW_RESET].reset_duration =
                IWL_DELAY_NEXT_FORCE_FW_RELOAD;
 
-
-       priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
-       priv->tx_power_next = IWL_DEFAULT_TX_POWER;
-
        if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
                IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
                         eeprom->version);
index 91b3d8b9d7a5aceb2ecc0fbdc5d657dbe19a2cc8..d484c3678163f9191570f59dade85c9d642e018e 100644 (file)
@@ -3140,12 +3140,6 @@ static int iwl4965_init_drv(struct iwl_priv *priv)
 
        iwl_legacy_init_scan_params(priv);
 
-       /* Set the tx_power_user_lmt to the lowest power level
-        * this value will get overwritten by channel max power avg
-        * from eeprom */
-       priv->tx_power_user_lmt = IWL4965_TX_POWER_TARGET_POWER_MIN;
-       priv->tx_power_next = IWL4965_TX_POWER_TARGET_POWER_MIN;
-
        ret = iwl_legacy_init_channel_map(priv);
        if (ret) {
                IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
index 3ea31b659d1a5b620318d731c4036648e9ebd2b6..22e045b5bcee0a335baac193c8becdc8300314a1 100644 (file)
@@ -530,6 +530,9 @@ static struct iwl_ht_params iwl5000_ht_params = {
 struct iwl_cfg iwl5300_agn_cfg = {
        .name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
        IWL_DEVICE_5000,
+       /* at least EEPROM 0x11A has wrong info */
+       .valid_tx_ant = ANT_ABC,        /* .cfg overwrite */
+       .valid_rx_ant = ANT_ABC,        /* .cfg overwrite */
        .ht_params = &iwl5000_ht_params,
 };
 
index 98aa8af01192bbe561b1bbf97d208dd3bdd5a54f..20b66469d68f2784e67e423546a60025e6da44a1 100644 (file)
@@ -241,7 +241,7 @@ struct iwl_eeprom_enhanced_txpwr {
 
 /* 6x00 Specific */
 #define EEPROM_6000_TX_POWER_VERSION    (4)
-#define EEPROM_6000_EEPROM_VERSION     (0x434)
+#define EEPROM_6000_EEPROM_VERSION     (0x423)
 
 /* 6x50 Specific */
 #define EEPROM_6050_TX_POWER_VERSION    (4)
index 36952274950e3cf7537834a132d5374f7b2b7322..c1ceb4b23971ea884577bb876432e4a764301446 100644 (file)
@@ -137,6 +137,7 @@ struct mwl8k_tx_queue {
 struct mwl8k_priv {
        struct ieee80211_hw *hw;
        struct pci_dev *pdev;
+       int irq;
 
        struct mwl8k_device_info *device_info;
 
@@ -3761,9 +3762,11 @@ static int mwl8k_start(struct ieee80211_hw *hw)
        rc = request_irq(priv->pdev->irq, mwl8k_interrupt,
                         IRQF_SHARED, MWL8K_NAME, hw);
        if (rc) {
+               priv->irq = -1;
                wiphy_err(hw->wiphy, "failed to register IRQ handler\n");
                return -EIO;
        }
+       priv->irq = priv->pdev->irq;
 
        /* Enable TX reclaim and RX tasklets.  */
        tasklet_enable(&priv->poll_tx_task);
@@ -3800,6 +3803,7 @@ static int mwl8k_start(struct ieee80211_hw *hw)
        if (rc) {
                iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
                free_irq(priv->pdev->irq, hw);
+               priv->irq = -1;
                tasklet_disable(&priv->poll_tx_task);
                tasklet_disable(&priv->poll_rx_task);
        }
@@ -3818,7 +3822,10 @@ static void mwl8k_stop(struct ieee80211_hw *hw)
 
        /* Disable interrupts */
        iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
-       free_irq(priv->pdev->irq, hw);
+       if (priv->irq != -1) {
+               free_irq(priv->pdev->irq, hw);
+               priv->irq = -1;
+       }
 
        /* Stop finalize join worker */
        cancel_work_sync(&priv->finalize_join_worker);
index 9b344a921e742e29ce483450ea9313186f2d0e23..e18358725b69813077de8d9e55f8a98d5fa7a021 100644 (file)
@@ -56,6 +56,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
        {USB_DEVICE(0x0846, 0x4210)},   /* Netgear WG121 the second ? */
        {USB_DEVICE(0x0846, 0x4220)},   /* Netgear WG111 */
        {USB_DEVICE(0x09aa, 0x1000)},   /* Spinnaker Proto board */
+       {USB_DEVICE(0x0bf8, 0x1007)},   /* Fujitsu E-5400 USB */
        {USB_DEVICE(0x0cde, 0x0006)},   /* Medion 40900, Roper Europe */
        {USB_DEVICE(0x0db0, 0x6826)},   /* MSI UB54G (MS-6826) */
        {USB_DEVICE(0x107b, 0x55f2)},   /* Gateway WGU-210 (Gemtek) */
@@ -68,6 +69,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
        {USB_DEVICE(0x1915, 0x2235)},   /* Linksys WUSB54G Portable OEM */
        {USB_DEVICE(0x2001, 0x3701)},   /* DLink DWL-G120 Spinnaker */
        {USB_DEVICE(0x2001, 0x3703)},   /* DLink DWL-G122 */
+       {USB_DEVICE(0x2001, 0x3762)},   /* Conceptronic C54U */
        {USB_DEVICE(0x5041, 0x2234)},   /* Linksys WUSB54G */
        {USB_DEVICE(0x5041, 0x2235)},   /* Linksys WUSB54G Portable */
 
index 7834c26c295438e39ab1c63d3e1b0444ca81ef2f..042842e704de17945d7f61b9c6069072ad5230fe 100644 (file)
@@ -703,7 +703,7 @@ void p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb)
        struct p54_tx_info *p54info;
        struct p54_hdr *hdr;
        struct p54_tx_data *txhdr;
-       unsigned int padding, len, extra_len;
+       unsigned int padding, len, extra_len = 0;
        int i, j, ridx;
        u16 hdr_flags = 0, aid = 0;
        u8 rate, queue = 0, crypt_offset = 0;
index 9de9dbe943998e1790a8d514157eea8028410238..84eb6ad3637752c686a9cd8d1be0e058cacda162 100644 (file)
@@ -1062,8 +1062,10 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
         * Stop all work.
         */
        cancel_work_sync(&rt2x00dev->intf_work);
-       cancel_work_sync(&rt2x00dev->rxdone_work);
-       cancel_work_sync(&rt2x00dev->txdone_work);
+       if (rt2x00_is_usb(rt2x00dev)) {
+               cancel_work_sync(&rt2x00dev->rxdone_work);
+               cancel_work_sync(&rt2x00dev->txdone_work);
+       }
        destroy_workqueue(rt2x00dev->workqueue);
 
        /*
index f74a8701c67ddfc5fcb28724b673b97c9a29d64d..590f14f45a8900cf2c7eba2c1c4a1885fe570a48 100644 (file)
@@ -685,7 +685,7 @@ static int efuse_pg_packet_read(struct ieee80211_hw *hw, u8 offset, u8 *data)
 
        u8 efuse_data, word_cnts = 0;
        u16 efuse_addr = 0;
-       u8 hworden;
+       u8 hworden = 0;
        u8 tmpdata[8];
 
        if (data == NULL)
index 5ef91374b230924dbd52be91d3be9d09ff963ea0..28a6ce3bc239612ef7834115f05b0688766438f4 100644 (file)
@@ -303,7 +303,7 @@ static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,
        u16 box_reg, box_extreg;
        u8 u1b_tmp;
        bool isfw_read = false;
-       u8 buf_index;
+       u8 buf_index = 0;
        bool bwrite_sucess = false;
        u8 wait_h2c_limmit = 100;
        u8 wait_writeh2c_limmit = 100;
index a4b2613d6a8c205deee0af697b00f6882cd57213..f5d85735d6420d350b1e3376b506bbdad5b95a75 100644 (file)
@@ -246,7 +246,7 @@ static void _rtl_usb_io_handler_init(struct device *dev,
 
 static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw)
 {
-       struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct rtl_priv __maybe_unused *rtlpriv = rtl_priv(hw);
 
        mutex_destroy(&rtlpriv->io.bb_mutex);
 }
index 5b9dbeafec06a812bde9ecb54ea8cf91027fe3de..b1c7d031c39163686050d624246190e22ee2e348 100644 (file)
@@ -340,7 +340,7 @@ module_init(wl1271_init);
 module_exit(wl1271_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
+MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
 MODULE_FIRMWARE(WL1271_FW_NAME);
 MODULE_FIRMWARE(WL1271_AP_FW_NAME);
index 18cf01719ae0d0def752f9a039bb4f82f0bf699a..ffc745b17f4d631f88a98d3531e2f69b6776e6a4 100644 (file)
@@ -487,7 +487,7 @@ module_init(wl1271_init);
 module_exit(wl1271_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
+MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
 MODULE_FIRMWARE(WL1271_FW_NAME);
 MODULE_FIRMWARE(WL1271_AP_FW_NAME);
index e64403b6896d7f135af9f2743345dcfeb8de28f2..6ec06a4a4c6dfdbe220f39bc4f910445901fbb22 100644 (file)
@@ -204,7 +204,10 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
 
        kfree(wl->nvs);
 
-       wl->nvs = kzalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
+       if (len != sizeof(struct wl1271_nvs_file))
+               return -EINVAL;
+
+       wl->nvs = kzalloc(len, GFP_KERNEL);
        if (!wl->nvs) {
                wl1271_error("could not allocate memory for the nvs file");
                ret = -ENOMEM;
index 58236e6d0921308f72e55accc7676bca0c64f42d..ab607bbd6291f716c246d5215b117e08247fe484 100644 (file)
@@ -643,7 +643,7 @@ static void rx_urb_complete(struct urb *urb)
        usb = urb->context;
        rx = &usb->rx;
 
-       zd_usb_reset_rx_idle_timer(usb);
+       tasklet_schedule(&rx->reset_timer_tasklet);
 
        if (length%rx->usb_packet_size > rx->usb_packet_size-4) {
                /* If there is an old first fragment, we don't care. */
@@ -812,6 +812,7 @@ void zd_usb_disable_rx(struct zd_usb *usb)
        __zd_usb_disable_rx(usb);
        mutex_unlock(&rx->setup_mutex);
 
+       tasklet_kill(&rx->reset_timer_tasklet);
        cancel_delayed_work_sync(&rx->idle_work);
 }
 
@@ -1106,6 +1107,13 @@ static void zd_rx_idle_timer_handler(struct work_struct *work)
        zd_usb_reset_rx(usb);
 }
 
+static void zd_usb_reset_rx_idle_timer_tasklet(unsigned long param)
+{
+       struct zd_usb *usb = (struct zd_usb *)param;
+
+       zd_usb_reset_rx_idle_timer(usb);
+}
+
 void zd_usb_reset_rx_idle_timer(struct zd_usb *usb)
 {
        struct zd_usb_rx *rx = &usb->rx;
@@ -1127,6 +1135,7 @@ static inline void init_usb_interrupt(struct zd_usb *usb)
 static inline void init_usb_rx(struct zd_usb *usb)
 {
        struct zd_usb_rx *rx = &usb->rx;
+
        spin_lock_init(&rx->lock);
        mutex_init(&rx->setup_mutex);
        if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) {
@@ -1136,11 +1145,14 @@ static inline void init_usb_rx(struct zd_usb *usb)
        }
        ZD_ASSERT(rx->fragment_length == 0);
        INIT_DELAYED_WORK(&rx->idle_work, zd_rx_idle_timer_handler);
+       rx->reset_timer_tasklet.func = zd_usb_reset_rx_idle_timer_tasklet;
+       rx->reset_timer_tasklet.data = (unsigned long)usb;
 }
 
 static inline void init_usb_tx(struct zd_usb *usb)
 {
        struct zd_usb_tx *tx = &usb->tx;
+
        spin_lock_init(&tx->lock);
        atomic_set(&tx->enabled, 0);
        tx->stopped = 0;
@@ -1671,6 +1683,10 @@ static void iowrite16v_urb_complete(struct urb *urb)
 
        if (urb->status && !usb->cmd_error)
                usb->cmd_error = urb->status;
+
+       if (!usb->cmd_error &&
+                       urb->actual_length != urb->transfer_buffer_length)
+               usb->cmd_error = -EIO;
 }
 
 static int zd_submit_waiting_urb(struct zd_usb *usb, bool last)
@@ -1805,7 +1821,7 @@ int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
        usb_fill_int_urb(urb, udev, usb_sndintpipe(udev, EP_REGS_OUT),
                         req, req_len, iowrite16v_urb_complete, usb,
                         ep->desc.bInterval);
-       urb->transfer_flags |= URB_FREE_BUFFER | URB_SHORT_NOT_OK;
+       urb->transfer_flags |= URB_FREE_BUFFER;
 
        /* Submit previous URB */
        r = zd_submit_waiting_urb(usb, false);
index b3df2c8116cc6ef2d22234318ceacb4866a2481a..325d0f9892571a6724d993c0ab8c28fe7a752f6c 100644 (file)
@@ -183,6 +183,7 @@ struct zd_usb_rx {
        spinlock_t lock;
        struct mutex setup_mutex;
        struct delayed_work idle_work;
+       struct tasklet_struct reset_timer_tasklet;
        u8 fragment[2 * USB_MAX_RX_SIZE];
        unsigned int fragment_length;
        unsigned int usb_packet_size;
index c8ff646c0b056e9fc8c81f3110fe53bb4b12df39..0fa466a91bf413995169f1751823e25784d70891 100644 (file)
@@ -88,4 +88,6 @@ config PCI_IOAPIC
        depends on HOTPLUG
        default y
 
-select NLS if (DMI || ACPI)
+config PCI_LABEL
+       def_bool y if (DMI || ACPI)
+       select NLS
index 98d61c8e984bc218c823fcaeecb02fdcf18183a3..c85f744270a56664cb91a720624cfc97dc29c6ee 100644 (file)
@@ -56,10 +56,10 @@ obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
 # ACPI Related PCI FW Functions
 # ACPI _DSM provided firmware instance and string name
 #
-obj-$(CONFIG_ACPI)    += pci-acpi.o pci-label.o
+obj-$(CONFIG_ACPI)    += pci-acpi.o
 
 # SMBIOS provided firmware instance and labels
-obj-$(CONFIG_DMI)    += pci-label.o
+obj-$(CONFIG_PCI_LABEL) += pci-label.o
 
 # Cardbus & CompactPCI use setup-bus
 obj-$(CONFIG_HOTPLUG) += setup-bus.o
index 505c1c7075f011df2e94755b2fb88f632a4c148c..d552d2c77844327010074ee71550e58ccb0a3280 100644 (file)
@@ -1299,7 +1299,7 @@ static void iommu_detach_domain(struct dmar_domain *domain,
 static struct iova_domain reserved_iova_list;
 static struct lock_class_key reserved_rbtree_key;
 
-static void dmar_init_reserved_ranges(void)
+static int dmar_init_reserved_ranges(void)
 {
        struct pci_dev *pdev = NULL;
        struct iova *iova;
@@ -1313,8 +1313,10 @@ static void dmar_init_reserved_ranges(void)
        /* IOAPIC ranges shouldn't be accessed by DMA */
        iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
                IOVA_PFN(IOAPIC_RANGE_END));
-       if (!iova)
+       if (!iova) {
                printk(KERN_ERR "Reserve IOAPIC range failed\n");
+               return -ENODEV;
+       }
 
        /* Reserve all PCI MMIO to avoid peer-to-peer access */
        for_each_pci_dev(pdev) {
@@ -1327,11 +1329,13 @@ static void dmar_init_reserved_ranges(void)
                        iova = reserve_iova(&reserved_iova_list,
                                            IOVA_PFN(r->start),
                                            IOVA_PFN(r->end));
-                       if (!iova)
+                       if (!iova) {
                                printk(KERN_ERR "Reserve iova failed\n");
+                               return -ENODEV;
+                       }
                }
        }
-
+       return 0;
 }
 
 static void domain_reserve_special_ranges(struct dmar_domain *domain)
@@ -1835,7 +1839,7 @@ static struct dmar_domain *get_domain_for_dev(struct pci_dev *pdev, int gaw)
 
        ret = iommu_attach_domain(domain, iommu);
        if (ret) {
-               domain_exit(domain);
+               free_domain_mem(domain);
                goto error;
        }
 
@@ -2213,7 +2217,7 @@ static int __init iommu_prepare_static_identity_mapping(int hw)
        return 0;
 }
 
-int __init init_dmars(void)
+static int __init init_dmars(int force_on)
 {
        struct dmar_drhd_unit *drhd;
        struct dmar_rmrr_unit *rmrr;
@@ -2393,8 +2397,15 @@ int __init init_dmars(void)
         *   enable translation
         */
        for_each_drhd_unit(drhd) {
-               if (drhd->ignored)
+               if (drhd->ignored) {
+                       /*
+                        * we always have to disable PMRs or DMA may fail on
+                        * this device
+                        */
+                       if (force_on)
+                               iommu_disable_protect_mem_regions(drhd->iommu);
                        continue;
+               }
                iommu = drhd->iommu;
 
                iommu_flush_write_buffer(iommu);
@@ -3240,9 +3251,15 @@ static int device_notifier(struct notifier_block *nb,
        if (!domain)
                return 0;
 
-       if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through)
+       if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) {
                domain_remove_one_dev_info(domain, pdev);
 
+               if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
+                   !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
+                   list_empty(&domain->devices))
+                       domain_exit(domain);
+       }
+
        return 0;
 }
 
@@ -3277,12 +3294,21 @@ int __init intel_iommu_init(void)
        if (no_iommu || dmar_disabled)
                return -ENODEV;
 
-       iommu_init_mempool();
-       dmar_init_reserved_ranges();
+       if (iommu_init_mempool()) {
+               if (force_on)
+                       panic("tboot: Failed to initialize iommu memory\n");
+               return  -ENODEV;
+       }
+
+       if (dmar_init_reserved_ranges()) {
+               if (force_on)
+                       panic("tboot: Failed to reserve iommu ranges\n");
+               return  -ENODEV;
+       }
 
        init_no_remapping_devices();
 
-       ret = init_dmars();
+       ret = init_dmars(force_on);
        if (ret) {
                if (force_on)
                        panic("tboot: Failed to initialize DMARs\n");
@@ -3391,6 +3417,11 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
                domain->iommu_count--;
                domain_update_iommu_cap(domain);
                spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
+
+               spin_lock_irqsave(&iommu->lock, tmp_flags);
+               clear_bit(domain->id, iommu->domain_ids);
+               iommu->domains[domain->id] = NULL;
+               spin_unlock_irqrestore(&iommu->lock, tmp_flags);
        }
 
        spin_unlock_irqrestore(&device_domain_lock, flags);
@@ -3607,9 +3638,9 @@ static int intel_iommu_attach_device(struct iommu_domain *domain,
 
                pte = dmar_domain->pgd;
                if (dma_pte_present(pte)) {
-                       free_pgtable_page(dmar_domain->pgd);
                        dmar_domain->pgd = (struct dma_pte *)
                                phys_to_virt(dma_pte_addr(pte));
+                       free_pgtable_page(pte);
                }
                dmar_domain->agaw--;
        }
index d86ea8b0113701ecbbcb26de06c20f6d60089510..135df164a4c1e897e4d36a7d5a49336518669480 100644 (file)
@@ -781,7 +781,7 @@ static int pci_pm_resume(struct device *dev)
 
 #endif /* !CONFIG_SUSPEND */
 
-#ifdef CONFIG_HIBERNATION
+#ifdef CONFIG_HIBERNATE_CALLBACKS
 
 static int pci_pm_freeze(struct device *dev)
 {
@@ -970,7 +970,7 @@ static int pci_pm_restore(struct device *dev)
        return error;
 }
 
-#else /* !CONFIG_HIBERNATION */
+#else /* !CONFIG_HIBERNATE_CALLBACKS */
 
 #define pci_pm_freeze          NULL
 #define pci_pm_freeze_noirq    NULL
@@ -981,7 +981,7 @@ static int pci_pm_restore(struct device *dev)
 #define pci_pm_restore         NULL
 #define pci_pm_restore_noirq   NULL
 
-#endif /* !CONFIG_HIBERNATION */
+#endif /* !CONFIG_HIBERNATE_CALLBACKS */
 
 #ifdef CONFIG_PM_RUNTIME
 
index 89d0a6a88df7b4ea5479630e4657cee8d912b475..ebf51ad1b71478f08532edcdda8b3acf9d711bb7 100644 (file)
@@ -676,10 +676,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
                        min_align = align1 >> 1;
                align += aligns[order];
        }
-       size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), align);
+       size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
        size1 = !add_size ? size :
                calculate_memsize(size, min_size+add_size, 0,
-                               resource_size(b_res), align);
+                               resource_size(b_res), min_align);
        if (!size0 && !size1) {
                if (b_res->start || b_res->end)
                        dev_info(&bus->self->dev, "disabling bridge window "
index 453c54c97612833b341a1e9787d9a8d51c7ec223..4c3e94c0ae85336a9fcee6511d570e1ab4b058e5 100644 (file)
@@ -25,6 +25,8 @@
 
 #include <mach/balloon3.h>
 
+#include <asm/mach-types.h>
+
 #include "soc_common.h"
 
 /*
@@ -127,6 +129,9 @@ static int __init balloon3_pcmcia_init(void)
 {
        int ret;
 
+       if (!machine_is_balloon3())
+               return -ENODEV;
+
        balloon3_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
        if (!balloon3_pcmcia_device)
                return -ENOMEM;
index b7e596620db16c594a7ba3cc73c2bbd9643b0e43..b829e655457b7df517175dae74099d7275d0c1e3 100644 (file)
@@ -69,15 +69,15 @@ static int trizeps_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
        for (i = 0; i < ARRAY_SIZE(irqs); i++) {
                if (irqs[i].sock != skt->nr)
                        continue;
-               if (gpio_request(IRQ_TO_GPIO(irqs[i].irq), irqs[i].str) < 0) {
+               if (gpio_request(irq_to_gpio(irqs[i].irq), irqs[i].str) < 0) {
                        pr_err("%s: sock %d unable to request gpio %d\n",
-                               __func__, skt->nr, IRQ_TO_GPIO(irqs[i].irq));
+                               __func__, skt->nr, irq_to_gpio(irqs[i].irq));
                        ret = -EBUSY;
                        goto error;
                }
-               if (gpio_direction_input(IRQ_TO_GPIO(irqs[i].irq)) < 0) {
+               if (gpio_direction_input(irq_to_gpio(irqs[i].irq)) < 0) {
                        pr_err("%s: sock %d unable to set input gpio %d\n",
-                               __func__, skt->nr, IRQ_TO_GPIO(irqs[i].irq));
+                               __func__, skt->nr, irq_to_gpio(irqs[i].irq));
                        ret = -EINVAL;
                        goto error;
                }
@@ -86,7 +86,7 @@ static int trizeps_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 
 error:
        for (; i >= 0; i--) {
-               gpio_free(IRQ_TO_GPIO(irqs[i].irq));
+               gpio_free(irq_to_gpio(irqs[i].irq));
        }
        return (ret);
 }
@@ -97,7 +97,7 @@ static void trizeps_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
        /* free allocated gpio's */
        gpio_free(GPIO_PRDY);
        for (i = 0; i < ARRAY_SIZE(irqs); i++)
-               gpio_free(IRQ_TO_GPIO(irqs[i].irq));
+               gpio_free(irq_to_gpio(irqs[i].irq));
 }
 
 static unsigned long trizeps_pcmcia_status[2];
@@ -226,6 +226,9 @@ static int __init trizeps_pcmcia_init(void)
 {
        int ret;
 
+       if (!machine_is_trizeps4() && !machine_is_trizeps4wl())
+               return -ENODEV;
+
        trizeps_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
        if (!trizeps_pcmcia_device)
                return -ENOMEM;
index 2ee442c2a5db094df620a50bcbdf03072fc64336..0485e394712aa4645cc695230f2dcaaca1664af3 100644 (file)
@@ -187,7 +187,8 @@ config MSI_LAPTOP
        depends on ACPI
        depends on BACKLIGHT_CLASS_DEVICE
        depends on RFKILL
-       depends on SERIO_I8042
+       depends on INPUT && SERIO_I8042
+       select INPUT_SPARSEKMAP
        ---help---
          This is a driver for laptops built by MSI (MICRO-STAR
          INTERNATIONAL):
index 5ea6c3477d17da4f17f3f07059329fdff1212da3..ac4e7f83ce6c8a4914af0e2df7080bd956b26f6f 100644 (file)
@@ -89,7 +89,7 @@ MODULE_LICENSE("GPL");
 #define ACERWMID_EVENT_GUID "676AA15E-6A47-4D9F-A2CC-1E6D18D14026"
 
 MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB");
-MODULE_ALIAS("wmi:6AF4F258-B401-42Fd-BE91-3D4AC2D7C0D3");
+MODULE_ALIAS("wmi:6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3");
 MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026");
 
 enum acer_wmi_event_ids {
index efc776cb0c664e0c8bf19c092c0a48367d4e1043..832a3fd7c1c8538ef77fd26c628e0ddd2c1644d6 100644 (file)
@@ -201,8 +201,8 @@ static int asus_wmi_input_init(struct asus_wmi *asus)
        if (!asus->inputdev)
                return -ENOMEM;
 
-       asus->inputdev->name = asus->driver->input_phys;
-       asus->inputdev->phys = asus->driver->input_name;
+       asus->inputdev->name = asus->driver->input_name;
+       asus->inputdev->phys = asus->driver->input_phys;
        asus->inputdev->id.bustype = BUS_HOST;
        asus->inputdev->dev.parent = &asus->platform_device->dev;
 
index 0ddc434fb93ba2bdb8144f5937ba66707d3c72f5..649dcadd8ea372973cd45db1b5b8274847baff36 100644 (file)
@@ -67,9 +67,11 @@ static const struct key_entry eeepc_wmi_keymap[] = {
        { KE_KEY, 0x82, { KEY_CAMERA } },
        { KE_KEY, 0x83, { KEY_CAMERA_ZOOMIN } },
        { KE_KEY, 0x88, { KEY_WLAN } },
+       { KE_KEY, 0xbd, { KEY_CAMERA } },
        { KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
        { KE_KEY, 0xe0, { KEY_PROG1 } }, /* Task Manager */
        { KE_KEY, 0xe1, { KEY_F14 } }, /* Change Resolution */
+       { KE_KEY, 0xe8, { KEY_SCREENLOCK } },
        { KE_KEY, 0xe9, { KEY_BRIGHTNESS_ZERO } },
        { KE_KEY, 0xeb, { KEY_CAMERA_ZOOMOUT } },
        { KE_KEY, 0xec, { KEY_CAMERA_UP } },
index d653104b59cb25540d17a85d78f298eea75fd48a..464bb3fc4d88b1c7d8fc9583b48fee3fec610a4f 100644 (file)
@@ -74,6 +74,19 @@ struct pmic_gpio {
        u32                     trigger_type;
 };
 
+static void pmic_program_irqtype(int gpio, int type)
+{
+       if (type & IRQ_TYPE_EDGE_RISING)
+               intel_scu_ipc_update_register(GPIO0 + gpio, 0x20, 0x20);
+       else
+               intel_scu_ipc_update_register(GPIO0 + gpio, 0x00, 0x20);
+
+       if (type & IRQ_TYPE_EDGE_FALLING)
+               intel_scu_ipc_update_register(GPIO0 + gpio, 0x10, 0x10);
+       else
+               intel_scu_ipc_update_register(GPIO0 + gpio, 0x00, 0x10);
+};
+
 static int pmic_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 {
        if (offset > 8) {
@@ -166,16 +179,38 @@ static int pmic_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
        return pg->irq_base + offset;
 }
 
+static void pmic_bus_lock(struct irq_data *data)
+{
+       struct pmic_gpio *pg = irq_data_get_irq_chip_data(data);
+
+       mutex_lock(&pg->buslock);
+}
+
+static void pmic_bus_sync_unlock(struct irq_data *data)
+{
+       struct pmic_gpio *pg = irq_data_get_irq_chip_data(data);
+
+       if (pg->update_type) {
+               unsigned int gpio = pg->update_type & ~GPIO_UPDATE_TYPE;
+
+               pmic_program_irqtype(gpio, pg->trigger_type);
+               pg->update_type = 0;
+       }
+       mutex_unlock(&pg->buslock);
+}
+
 /* the gpiointr register is read-clear, so just do nothing. */
 static void pmic_irq_unmask(struct irq_data *data) { }
 
 static void pmic_irq_mask(struct irq_data *data) { }
 
 static struct irq_chip pmic_irqchip = {
-       .name           = "PMIC-GPIO",
-       .irq_mask       = pmic_irq_mask,
-       .irq_unmask     = pmic_irq_unmask,
-       .irq_set_type   = pmic_irq_type,
+       .name                   = "PMIC-GPIO",
+       .irq_mask               = pmic_irq_mask,
+       .irq_unmask             = pmic_irq_unmask,
+       .irq_set_type           = pmic_irq_type,
+       .irq_bus_lock           = pmic_bus_lock,
+       .irq_bus_sync_unlock    = pmic_bus_sync_unlock,
 };
 
 static irqreturn_t pmic_irq_handler(int irq, void *data)
index de434c6dc2d661133175ddf11464b4dac48f118e..d347116d150e38146eedf6e817e51afc84898169 100644 (file)
@@ -570,6 +570,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
                },
                .callback = dmi_check_cb,
        },
+       {
+               .ident = "R410 Plus",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR,
+                                       "SAMSUNG ELECTRONICS CO., LTD."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "R410P"),
+                       DMI_MATCH(DMI_BOARD_NAME, "R460"),
+               },
+               .callback = dmi_check_cb,
+       },
        {
                .ident = "R518",
                .matches = {
@@ -591,12 +601,12 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = {
                .callback = dmi_check_cb,
        },
        {
-               .ident = "N150/N210/N220",
+               .ident = "N150/N210/N220/N230",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR,
                                        "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220/N230"),
+                       DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220/N230"),
                },
                .callback = dmi_check_cb,
        },
@@ -771,6 +781,7 @@ static int __init samsung_init(void)
 
        /* create a backlight device to talk to this one */
        memset(&props, 0, sizeof(struct backlight_properties));
+       props.type = BACKLIGHT_PLATFORM;
        props.max_brightness = sabi_config->max_brightness;
        backlight_device = backlight_device_register("samsung", &sdev->dev,
                                                     NULL, &backlight_ops,
index e642f5f295046edf07f9d16aed5bc26f5dde8731..8f709aec4da0ac2ebb81d09e19baea9932506f26 100644 (file)
@@ -138,6 +138,8 @@ MODULE_PARM_DESC(kbd_backlight_timeout,
                 "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout "
                 "(default: 0)");
 
+static void sony_nc_kbd_backlight_resume(void);
+
 enum sony_nc_rfkill {
        SONY_WIFI,
        SONY_BLUETOOTH,
@@ -771,11 +773,6 @@ static int sony_nc_handles_setup(struct platform_device *pd)
        if (!handles)
                return -ENOMEM;
 
-       sysfs_attr_init(&handles->devattr.attr);
-       handles->devattr.attr.name = "handles";
-       handles->devattr.attr.mode = S_IRUGO;
-       handles->devattr.show = sony_nc_handles_show;
-
        for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
                if (!acpi_callsetfunc(sony_nc_acpi_handle,
                                        "SN00", i + 0x20, &result)) {
@@ -785,11 +782,18 @@ static int sony_nc_handles_setup(struct platform_device *pd)
                }
        }
 
-       /* allow reading capabilities via sysfs */
-       if (device_create_file(&pd->dev, &handles->devattr)) {
-               kfree(handles);
-               handles = NULL;
-               return -1;
+       if (debug) {
+               sysfs_attr_init(&handles->devattr.attr);
+               handles->devattr.attr.name = "handles";
+               handles->devattr.attr.mode = S_IRUGO;
+               handles->devattr.show = sony_nc_handles_show;
+
+               /* allow reading capabilities via sysfs */
+               if (device_create_file(&pd->dev, &handles->devattr)) {
+                       kfree(handles);
+                       handles = NULL;
+                       return -1;
+               }
        }
 
        return 0;
@@ -798,7 +802,8 @@ static int sony_nc_handles_setup(struct platform_device *pd)
 static int sony_nc_handles_cleanup(struct platform_device *pd)
 {
        if (handles) {
-               device_remove_file(&pd->dev, &handles->devattr);
+               if (debug)
+                       device_remove_file(&pd->dev, &handles->devattr);
                kfree(handles);
                handles = NULL;
        }
@@ -808,6 +813,11 @@ static int sony_nc_handles_cleanup(struct platform_device *pd)
 static int sony_find_snc_handle(int handle)
 {
        int i;
+
+       /* not initialized yet, return early */
+       if (!handles)
+               return -1;
+
        for (i = 0; i < 0x10; i++) {
                if (handles->cap[i] == handle) {
                        dprintk("found handle 0x%.4x (offset: 0x%.2x)\n",
@@ -1168,6 +1178,9 @@ static int sony_nc_resume(struct acpi_device *device)
        /* re-read rfkill state */
        sony_nc_rfkill_update();
 
+       /* restore kbd backlight states */
+       sony_nc_kbd_backlight_resume();
+
        return 0;
 }
 
@@ -1355,6 +1368,7 @@ out_no_enum:
 #define KBDBL_HANDLER  0x137
 #define KBDBL_PRESENT  0xB00
 #define        SET_MODE        0xC00
+#define SET_STATE      0xD00
 #define SET_TIMEOUT    0xE00
 
 struct kbd_backlight {
@@ -1377,6 +1391,10 @@ static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value)
                                (value << 0x10) | SET_MODE, &result))
                return -EIO;
 
+       /* Try to turn the light on/off immediately */
+       sony_call_snc_handle(KBDBL_HANDLER, (value << 0x10) | SET_STATE,
+                       &result);
+
        kbdbl_handle->mode = value;
 
        return 0;
@@ -1458,7 +1476,7 @@ static int sony_nc_kbd_backlight_setup(struct platform_device *pd)
 {
        int result;
 
-       if (sony_call_snc_handle(0x137, KBDBL_PRESENT, &result))
+       if (sony_call_snc_handle(KBDBL_HANDLER, KBDBL_PRESENT, &result))
                return 0;
        if (!(result & 0x02))
                return 0;
@@ -1501,13 +1519,36 @@ outkzalloc:
 static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd)
 {
        if (kbdbl_handle) {
+               int result;
+
                device_remove_file(&pd->dev, &kbdbl_handle->mode_attr);
                device_remove_file(&pd->dev, &kbdbl_handle->timeout_attr);
+
+               /* restore the default hw behaviour */
+               sony_call_snc_handle(KBDBL_HANDLER, 0x1000 | SET_MODE, &result);
+               sony_call_snc_handle(KBDBL_HANDLER, SET_TIMEOUT, &result);
+
                kfree(kbdbl_handle);
        }
        return 0;
 }
 
+static void sony_nc_kbd_backlight_resume(void)
+{
+       int ignore = 0;
+
+       if (!kbdbl_handle)
+               return;
+
+       if (kbdbl_handle->mode == 0)
+               sony_call_snc_handle(KBDBL_HANDLER, SET_MODE, &ignore);
+
+       if (kbdbl_handle->timeout != 0)
+               sony_call_snc_handle(KBDBL_HANDLER,
+                               (kbdbl_handle->timeout << 0x10) | SET_TIMEOUT,
+                               &ignore);
+}
+
 static void sony_nc_backlight_setup(void)
 {
        acpi_handle unused;
index a08561f5349ef038decaf8edcd73528f30f056a9..efb3b6b9bcdbe0746011c5762ec875218ac669ce 100644 (file)
@@ -8618,8 +8618,7 @@ static bool __pure __init tpacpi_is_valid_fw_id(const char* const s,
                tpacpi_is_fw_digit(s[1]) &&
                s[2] == t && s[3] == 'T' &&
                tpacpi_is_fw_digit(s[4]) &&
-               tpacpi_is_fw_digit(s[5]) &&
-               s[6] == 'W' && s[7] == 'W';
+               tpacpi_is_fw_digit(s[5]);
 }
 
 /* returns 0 - probe ok, or < 0 - probe error.
index c29719cacbca00e108203361a25ee70cb5c8017f..86c9a091a2ffdbfb3cac0868f17824ee9f4e5b6d 100644 (file)
@@ -1171,16 +1171,17 @@ static int rio_hdid_setup(char *str)
 
 __setup("riohdid=", rio_hdid_setup);
 
-void rio_register_mport(struct rio_mport *port)
+int rio_register_mport(struct rio_mport *port)
 {
        if (next_portid >= RIO_MAX_MPORTS) {
                pr_err("RIO: reached specified max number of mports\n");
-               return;
+               return 1;
        }
 
        port->id = next_portid++;
        port->host_deviceid = rio_get_hdid(port->id);
        list_add_tail(&port->node, &rio_mports);
+       return 0;
 }
 
 EXPORT_SYMBOL_GPL(rio_local_get_device_id);
index 095016a9dec16930f7ed0947c0e607717678b16a..ac2701b22e7133f8239a3136b18a5f85799f8578 100644 (file)
@@ -418,3 +418,4 @@ DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1848, idtg2_switch_init);
 DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1616, idtg2_switch_init);
 DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTVPS1616, idtg2_switch_init);
 DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTSPS1616, idtg2_switch_init);
+DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1432, idtg2_switch_init);
index 09b4437b3e616aa57cdfec861b2b2ddf0ff9dd59..39013867cbd6cf0deeffcd59cb4c43280cac4618 100644 (file)
@@ -171,7 +171,7 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
        err = __rtc_read_alarm(rtc, &alrm);
 
        if (!err && !rtc_valid_tm(&alrm.time))
-               rtc_set_alarm(rtc, &alrm);
+               rtc_initialize_alarm(rtc, &alrm);
 
        strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE);
        dev_set_name(&rtc->dev, "rtc%d", id);
index 23719f0acbf64b6cc240b75a72f0c274be4078cf..ef6316acec43a3312c00c6d8ca27b5ec8314f526 100644 (file)
@@ -375,6 +375,32 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
 }
 EXPORT_SYMBOL_GPL(rtc_set_alarm);
 
+/* Called once per device from rtc_device_register */
+int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
+{
+       int err;
+
+       err = rtc_valid_tm(&alarm->time);
+       if (err != 0)
+               return err;
+
+       err = mutex_lock_interruptible(&rtc->ops_lock);
+       if (err)
+               return err;
+
+       rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time);
+       rtc->aie_timer.period = ktime_set(0, 0);
+       if (alarm->enabled) {
+               rtc->aie_timer.enabled = 1;
+               timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node);
+       }
+       mutex_unlock(&rtc->ops_lock);
+       return err;
+}
+EXPORT_SYMBOL_GPL(rtc_initialize_alarm);
+
+
+
 int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
 {
        int err = mutex_lock_interruptible(&rtc->ops_lock);
index a0fc4cf42abf36b8c54a5e9a9d082648f87a4244..90d866272c8ea5095981afaa62396f03d92343b6 100644 (file)
@@ -250,6 +250,8 @@ static int bfin_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
                bfin_rtc_int_set_alarm(rtc);
        else
                bfin_rtc_int_clear(~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY));
+
+       return 0;
 }
 
 static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm)
index c420064695598edbe9cdc42c5767d35cc21d2811..c5ac03793e7910fec863f70130496cd3a3d60e9c 100644 (file)
@@ -401,6 +401,7 @@ const struct platform_device_id mc13xxx_rtc_idtable[] = {
        }, {
                .name = "mc13892-rtc",
        },
+       { }
 };
 
 static struct platform_driver mc13xxx_rtc_driver = {
index de0dd7b1f146e0e7fff07bd30487b1da9add0ca1..bcae8dd41496ab089d43e6639fedfd4272dca035 100644 (file)
@@ -394,7 +394,7 @@ static int __init omap_rtc_probe(struct platform_device *pdev)
        return 0;
 
 fail2:
-       free_irq(omap_rtc_timer, NULL);
+       free_irq(omap_rtc_timer, rtc);
 fail1:
        rtc_device_unregister(rtc);
 fail0:
index 714964913e5eb37d9c9dff9f0f346bbe6d41d5e7..b3466c491cd35cbbd93a64df0f1dbcf070c84e6c 100644 (file)
@@ -336,7 +336,6 @@ static void s3c_rtc_release(struct device *dev)
 
        /* do not clear AIE here, it may be needed for wake */
 
-       s3c_rtc_setpie(dev, 0);
        free_irq(s3c_rtc_alarmno, rtc_dev);
        free_irq(s3c_rtc_tickno, rtc_dev);
 }
@@ -408,7 +407,6 @@ static int __devexit s3c_rtc_remove(struct platform_device *dev)
        platform_set_drvdata(dev, NULL);
        rtc_device_unregister(rtc);
 
-       s3c_rtc_setpie(&dev->dev, 0);
        s3c_rtc_setaie(&dev->dev, 0);
 
        clk_disable(rtc_clk);
index 6d5c7ff43f5bdaf1984a62696e8acb03cdead3c5..e9901b8f8443ec3cf6b75487cf36d57584bccd17 100644 (file)
@@ -411,8 +411,6 @@ static void scsi_run_queue(struct request_queue *q)
        list_splice_init(&shost->starved_list, &starved_list);
 
        while (!list_empty(&starved_list)) {
-               int flagset;
-
                /*
                 * As long as shost is accepting commands and we have
                 * starved queues, call blk_run_queue. scsi_request_fn
@@ -435,20 +433,7 @@ static void scsi_run_queue(struct request_queue *q)
                        continue;
                }
 
-               spin_unlock(shost->host_lock);
-
-               spin_lock(sdev->request_queue->queue_lock);
-               flagset = test_bit(QUEUE_FLAG_REENTER, &q->queue_flags) &&
-                               !test_bit(QUEUE_FLAG_REENTER,
-                                       &sdev->request_queue->queue_flags);
-               if (flagset)
-                       queue_flag_set(QUEUE_FLAG_REENTER, sdev->request_queue);
-               __blk_run_queue(sdev->request_queue, false);
-               if (flagset)
-                       queue_flag_clear(QUEUE_FLAG_REENTER, sdev->request_queue);
-               spin_unlock(sdev->request_queue->queue_lock);
-
-               spin_lock(shost->host_lock);
+               blk_run_queue_async(sdev->request_queue);
        }
        /* put any unprocessed entries back */
        list_splice(&starved_list, &shost->starved_list);
index fdf3fa639056c42a61a099d2d6a69cc68c6caaa2..815069d13f9b57edc5ddaf22dbb223c452d74811 100644 (file)
@@ -3816,28 +3816,17 @@ fail_host_msg:
 static void
 fc_bsg_goose_queue(struct fc_rport *rport)
 {
-       int flagset;
-       unsigned long flags;
-
        if (!rport->rqst_q)
                return;
 
+       /*
+        * This get/put dance makes no sense
+        */
        get_device(&rport->dev);
-
-       spin_lock_irqsave(rport->rqst_q->queue_lock, flags);
-       flagset = test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags) &&
-                 !test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags);
-       if (flagset)
-               queue_flag_set(QUEUE_FLAG_REENTER, rport->rqst_q);
-       __blk_run_queue(rport->rqst_q, false);
-       if (flagset)
-               queue_flag_clear(QUEUE_FLAG_REENTER, rport->rqst_q);
-       spin_unlock_irqrestore(rport->rqst_q->queue_lock, flags);
-
+       blk_run_queue_async(rport->rqst_q);
        put_device(&rport->dev);
 }
 
-
 /**
  * fc_bsg_rport_dispatch - process rport bsg requests and dispatch to LLDD
  * @q:         rport request queue
index 5825370bad25bdba23823510fffc5293d05e1e59..08de58e7f59f7f6521ffb5122078103473c66117 100644 (file)
@@ -1555,7 +1555,7 @@ static int stop_queue(struct pl022 *pl022)
         * A wait_queue on the pl022->busy could be used, but then the common
         * execution path (pump_messages) would be required to call wake_up or
         * friends on every SPI message. Do this instead */
-       while (!list_empty(&pl022->queue) && pl022->busy && limit--) {
+       while ((!list_empty(&pl022->queue) || pl022->busy) && limit--) {
                spin_unlock_irqrestore(&pl022->queue_lock, flags);
                msleep(10);
                spin_lock_irqsave(&pl022->queue_lock, flags);
index b1a4b9f503ae06c1d7cef7eb0019c57c90453e24..871e337c917fe7313621e651be0da62891545b05 100644 (file)
@@ -821,7 +821,7 @@ static int stop_queue(struct dw_spi *dws)
 
        spin_lock_irqsave(&dws->lock, flags);
        dws->run = QUEUE_STOPPED;
-       while (!list_empty(&dws->queue) && dws->busy && limit--) {
+       while ((!list_empty(&dws->queue) || dws->busy) && limit--) {
                spin_unlock_irqrestore(&dws->lock, flags);
                msleep(10);
                spin_lock_irqsave(&dws->lock, flags);
index 9c74aad6be936edaf2c59d5a3f6bf815599dabf3..dc25bee8d33f1d6f93deea0030712a681579b1d0 100644 (file)
@@ -1493,7 +1493,7 @@ static int stop_queue(struct driver_data *drv_data)
         * execution path (pump_messages) would be required to call wake_up or
         * friends on every SPI message. Do this instead */
        drv_data->run = QUEUE_STOPPED;
-       while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) {
+       while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) {
                spin_unlock_irqrestore(&drv_data->lock, flags);
                msleep(10);
                spin_lock_irqsave(&drv_data->lock, flags);
index bdb7289a1d220bd6982d997d567305c39e6aa05c..f706dba165cf6812fc364271d3086424ce12aa36 100644 (file)
@@ -1284,7 +1284,7 @@ static inline int bfin_spi_stop_queue(struct bfin_spi_master_data *drv_data)
         * friends on every SPI message. Do this instead
         */
        drv_data->running = false;
-       while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) {
+       while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) {
                spin_unlock_irqrestore(&drv_data->lock, flags);
                msleep(10);
                spin_lock_irqsave(&drv_data->lock, flags);
index dca4a0bb6ca9f1523f187a5eaddd90f19731a08b..e3786f161bc34676294d89a1bfa2182bf64e44c9 100644 (file)
@@ -131,8 +131,6 @@ source "drivers/staging/wlags49_h2/Kconfig"
 
 source "drivers/staging/wlags49_h25/Kconfig"
 
-source "drivers/staging/samsung-laptop/Kconfig"
-
 source "drivers/staging/sm7xx/Kconfig"
 
 source "drivers/staging/dt3155v4l/Kconfig"
index eb93012b6f5936a7648b6c396cac77ae15879f20..f0d5c53156123e15b73d91368f85e56d75237284 100644 (file)
@@ -48,7 +48,6 @@ obj-$(CONFIG_XVMALLOC)                += zram/
 obj-$(CONFIG_ZCACHE)           += zcache/
 obj-$(CONFIG_WLAGS49_H2)       += wlags49_h2/
 obj-$(CONFIG_WLAGS49_H25)      += wlags49_h25/
-obj-$(CONFIG_SAMSUNG_LAPTOP)   += samsung-laptop/
 obj-$(CONFIG_FB_SM7XX)         += sm7xx/
 obj-$(CONFIG_VIDEO_DT3155)     += dt3155v4l/
 obj-$(CONFIG_CRYSTALHD)                += crystalhd/
diff --git a/drivers/staging/samsung-laptop/Kconfig b/drivers/staging/samsung-laptop/Kconfig
deleted file mode 100644 (file)
index f27c608..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-config SAMSUNG_LAPTOP
-       tristate "Samsung Laptop driver"
-       default n
-       depends on RFKILL && BACKLIGHT_CLASS_DEVICE && X86
-       help
-         This module implements a driver for the N128 Samsung Laptop
-         providing control over the Wireless LED and the LCD backlight
-
-         To compile this driver as a module, choose
-         M here: the module will be called samsung-laptop.
diff --git a/drivers/staging/samsung-laptop/Makefile b/drivers/staging/samsung-laptop/Makefile
deleted file mode 100644 (file)
index 3c6f420..0000000
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_SAMSUNG_LAPTOP)   += samsung-laptop.o
diff --git a/drivers/staging/samsung-laptop/TODO b/drivers/staging/samsung-laptop/TODO
deleted file mode 100644 (file)
index f7a6d58..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-TODO:
-       - review from other developers
-       - figure out ACPI video issues
-
-Please send patches to Greg Kroah-Hartman <gregkh@suse.de>
diff --git a/drivers/staging/samsung-laptop/samsung-laptop.c b/drivers/staging/samsung-laptop/samsung-laptop.c
deleted file mode 100644 (file)
index 2529446..0000000
+++ /dev/null
@@ -1,843 +0,0 @@
-/*
- * Samsung Laptop driver
- *
- * Copyright (C) 2009,2011 Greg Kroah-Hartman (gregkh@suse.de)
- * Copyright (C) 2009,2011 Novell Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- */
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/backlight.h>
-#include <linux/fb.h>
-#include <linux/dmi.h>
-#include <linux/platform_device.h>
-#include <linux/rfkill.h>
-
-/*
- * This driver is needed because a number of Samsung laptops do not hook
- * their control settings through ACPI.  So we have to poke around in the
- * BIOS to do things like brightness values, and "special" key controls.
- */
-
-/*
- * We have 0 - 8 as valid brightness levels.  The specs say that level 0 should
- * be reserved by the BIOS (which really doesn't make much sense), we tell
- * userspace that the value is 0 - 7 and then just tell the hardware 1 - 8
- */
-#define MAX_BRIGHT     0x07
-
-
-#define SABI_IFACE_MAIN                        0x00
-#define SABI_IFACE_SUB                 0x02
-#define SABI_IFACE_COMPLETE            0x04
-#define SABI_IFACE_DATA                        0x05
-
-/* Structure to get data back to the calling function */
-struct sabi_retval {
-       u8 retval[20];
-};
-
-struct sabi_header_offsets {
-       u8 port;
-       u8 re_mem;
-       u8 iface_func;
-       u8 en_mem;
-       u8 data_offset;
-       u8 data_segment;
-};
-
-struct sabi_commands {
-       /*
-        * Brightness is 0 - 8, as described above.
-        * Value 0 is for the BIOS to use
-        */
-       u8 get_brightness;
-       u8 set_brightness;
-
-       /*
-        * first byte:
-        * 0x00 - wireless is off
-        * 0x01 - wireless is on
-        * second byte:
-        * 0x02 - 3G is off
-        * 0x03 - 3G is on
-        * TODO, verify 3G is correct, that doesn't seem right...
-        */
-       u8 get_wireless_button;
-       u8 set_wireless_button;
-
-       /* 0 is off, 1 is on */
-       u8 get_backlight;
-       u8 set_backlight;
-
-       /*
-        * 0x80 or 0x00 - no action
-        * 0x81 - recovery key pressed
-        */
-       u8 get_recovery_mode;
-       u8 set_recovery_mode;
-
-       /*
-        * on seclinux: 0 is low, 1 is high,
-        * on swsmi: 0 is normal, 1 is silent, 2 is turbo
-        */
-       u8 get_performance_level;
-       u8 set_performance_level;
-
-       /*
-        * Tell the BIOS that Linux is running on this machine.
-        * 81 is on, 80 is off
-        */
-       u8 set_linux;
-};
-
-struct sabi_performance_level {
-       const char *name;
-       u8 value;
-};
-
-struct sabi_config {
-       const char *test_string;
-       u16 main_function;
-       const struct sabi_header_offsets header_offsets;
-       const struct sabi_commands commands;
-       const struct sabi_performance_level performance_levels[4];
-       u8 min_brightness;
-       u8 max_brightness;
-};
-
-static const struct sabi_config sabi_configs[] = {
-       {
-               .test_string = "SECLINUX",
-
-               .main_function = 0x4c49,
-
-               .header_offsets = {
-                       .port = 0x00,
-                       .re_mem = 0x02,
-                       .iface_func = 0x03,
-                       .en_mem = 0x04,
-                       .data_offset = 0x05,
-                       .data_segment = 0x07,
-               },
-
-               .commands = {
-                       .get_brightness = 0x00,
-                       .set_brightness = 0x01,
-
-                       .get_wireless_button = 0x02,
-                       .set_wireless_button = 0x03,
-
-                       .get_backlight = 0x04,
-                       .set_backlight = 0x05,
-
-                       .get_recovery_mode = 0x06,
-                       .set_recovery_mode = 0x07,
-
-                       .get_performance_level = 0x08,
-                       .set_performance_level = 0x09,
-
-                       .set_linux = 0x0a,
-               },
-
-               .performance_levels = {
-                       {
-                               .name = "silent",
-                               .value = 0,
-                       },
-                       {
-                               .name = "normal",
-                               .value = 1,
-                       },
-                       { },
-               },
-               .min_brightness = 1,
-               .max_brightness = 8,
-       },
-       {
-               .test_string = "SwSmi@",
-
-               .main_function = 0x5843,
-
-               .header_offsets = {
-                       .port = 0x00,
-                       .re_mem = 0x04,
-                       .iface_func = 0x02,
-                       .en_mem = 0x03,
-                       .data_offset = 0x05,
-                       .data_segment = 0x07,
-               },
-
-               .commands = {
-                       .get_brightness = 0x10,
-                       .set_brightness = 0x11,
-
-                       .get_wireless_button = 0x12,
-                       .set_wireless_button = 0x13,
-
-                       .get_backlight = 0x2d,
-                       .set_backlight = 0x2e,
-
-                       .get_recovery_mode = 0xff,
-                       .set_recovery_mode = 0xff,
-
-                       .get_performance_level = 0x31,
-                       .set_performance_level = 0x32,
-
-                       .set_linux = 0xff,
-               },
-
-               .performance_levels = {
-                       {
-                               .name = "normal",
-                               .value = 0,
-                       },
-                       {
-                               .name = "silent",
-                               .value = 1,
-                       },
-                       {
-                               .name = "overclock",
-                               .value = 2,
-                       },
-                       { },
-               },
-               .min_brightness = 0,
-               .max_brightness = 8,
-       },
-       { },
-};
-
-static const struct sabi_config *sabi_config;
-
-static void __iomem *sabi;
-static void __iomem *sabi_iface;
-static void __iomem *f0000_segment;
-static struct backlight_device *backlight_device;
-static struct mutex sabi_mutex;
-static struct platform_device *sdev;
-static struct rfkill *rfk;
-
-static int force;
-module_param(force, bool, 0);
-MODULE_PARM_DESC(force,
-               "Disable the DMI check and forces the driver to be loaded");
-
-static int debug;
-module_param(debug, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
-static int sabi_get_command(u8 command, struct sabi_retval *sretval)
-{
-       int retval = 0;
-       u16 port = readw(sabi + sabi_config->header_offsets.port);
-       u8 complete, iface_data;
-
-       mutex_lock(&sabi_mutex);
-
-       /* enable memory to be able to write to it */
-       outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
-
-       /* write out the command */
-       writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
-       writew(command, sabi_iface + SABI_IFACE_SUB);
-       writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
-       outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
-
-       /* write protect memory to make it safe */
-       outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
-
-       /* see if the command actually succeeded */
-       complete = readb(sabi_iface + SABI_IFACE_COMPLETE);
-       iface_data = readb(sabi_iface + SABI_IFACE_DATA);
-       if (complete != 0xaa || iface_data == 0xff) {
-               pr_warn("SABI get command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n",
-                       command, complete, iface_data);
-               retval = -EINVAL;
-               goto exit;
-       }
-       /*
-        * Save off the data into a structure so the caller use it.
-        * Right now we only want the first 4 bytes,
-        * There are commands that need more, but not for the ones we
-        * currently care about.
-        */
-       sretval->retval[0] = readb(sabi_iface + SABI_IFACE_DATA);
-       sretval->retval[1] = readb(sabi_iface + SABI_IFACE_DATA + 1);
-       sretval->retval[2] = readb(sabi_iface + SABI_IFACE_DATA + 2);
-       sretval->retval[3] = readb(sabi_iface + SABI_IFACE_DATA + 3);
-
-exit:
-       mutex_unlock(&sabi_mutex);
-       return retval;
-
-}
-
-static int sabi_set_command(u8 command, u8 data)
-{
-       int retval = 0;
-       u16 port = readw(sabi + sabi_config->header_offsets.port);
-       u8 complete, iface_data;
-
-       mutex_lock(&sabi_mutex);
-
-       /* enable memory to be able to write to it */
-       outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
-
-       /* write out the command */
-       writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
-       writew(command, sabi_iface + SABI_IFACE_SUB);
-       writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
-       writeb(data, sabi_iface + SABI_IFACE_DATA);
-       outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
-
-       /* write protect memory to make it safe */
-       outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
-
-       /* see if the command actually succeeded */
-       complete = readb(sabi_iface + SABI_IFACE_COMPLETE);
-       iface_data = readb(sabi_iface + SABI_IFACE_DATA);
-       if (complete != 0xaa || iface_data == 0xff) {
-               pr_warn("SABI set command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n",
-                      command, complete, iface_data);
-               retval = -EINVAL;
-       }
-
-       mutex_unlock(&sabi_mutex);
-       return retval;
-}
-
-static void test_backlight(void)
-{
-       struct sabi_retval sretval;
-
-       sabi_get_command(sabi_config->commands.get_backlight, &sretval);
-       printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
-
-       sabi_set_command(sabi_config->commands.set_backlight, 0);
-       printk(KERN_DEBUG "backlight should be off\n");
-
-       sabi_get_command(sabi_config->commands.get_backlight, &sretval);
-       printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
-
-       msleep(1000);
-
-       sabi_set_command(sabi_config->commands.set_backlight, 1);
-       printk(KERN_DEBUG "backlight should be on\n");
-
-       sabi_get_command(sabi_config->commands.get_backlight, &sretval);
-       printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
-}
-
-static void test_wireless(void)
-{
-       struct sabi_retval sretval;
-
-       sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
-       printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
-
-       sabi_set_command(sabi_config->commands.set_wireless_button, 0);
-       printk(KERN_DEBUG "wireless led should be off\n");
-
-       sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
-       printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
-
-       msleep(1000);
-
-       sabi_set_command(sabi_config->commands.set_wireless_button, 1);
-       printk(KERN_DEBUG "wireless led should be on\n");
-
-       sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
-       printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
-}
-
-static u8 read_brightness(void)
-{
-       struct sabi_retval sretval;
-       int user_brightness = 0;
-       int retval;
-
-       retval = sabi_get_command(sabi_config->commands.get_brightness,
-                                 &sretval);
-       if (!retval) {
-               user_brightness = sretval.retval[0];
-               if (user_brightness != 0)
-                       user_brightness -= sabi_config->min_brightness;
-       }
-       return user_brightness;
-}
-
-static void set_brightness(u8 user_brightness)
-{
-       u8 user_level = user_brightness - sabi_config->min_brightness;
-
-       sabi_set_command(sabi_config->commands.set_brightness, user_level);
-}
-
-static int get_brightness(struct backlight_device *bd)
-{
-       return (int)read_brightness();
-}
-
-static int update_status(struct backlight_device *bd)
-{
-       set_brightness(bd->props.brightness);
-
-       if (bd->props.power == FB_BLANK_UNBLANK)
-               sabi_set_command(sabi_config->commands.set_backlight, 1);
-       else
-               sabi_set_command(sabi_config->commands.set_backlight, 0);
-       return 0;
-}
-
-static const struct backlight_ops backlight_ops = {
-       .get_brightness = get_brightness,
-       .update_status  = update_status,
-};
-
-static int rfkill_set(void *data, bool blocked)
-{
-       /* Do something with blocked...*/
-       /*
-        * blocked == false is on
-        * blocked == true is off
-        */
-       if (blocked)
-               sabi_set_command(sabi_config->commands.set_wireless_button, 0);
-       else
-               sabi_set_command(sabi_config->commands.set_wireless_button, 1);
-
-       return 0;
-}
-
-static struct rfkill_ops rfkill_ops = {
-       .set_block = rfkill_set,
-};
-
-static int init_wireless(struct platform_device *sdev)
-{
-       int retval;
-
-       rfk = rfkill_alloc("samsung-wifi", &sdev->dev, RFKILL_TYPE_WLAN,
-                          &rfkill_ops, NULL);
-       if (!rfk)
-               return -ENOMEM;
-
-       retval = rfkill_register(rfk);
-       if (retval) {
-               rfkill_destroy(rfk);
-               return -ENODEV;
-       }
-
-       return 0;
-}
-
-static void destroy_wireless(void)
-{
-       rfkill_unregister(rfk);
-       rfkill_destroy(rfk);
-}
-
-static ssize_t get_performance_level(struct device *dev,
-                                    struct device_attribute *attr, char *buf)
-{
-       struct sabi_retval sretval;
-       int retval;
-       int i;
-
-       /* Read the state */
-       retval = sabi_get_command(sabi_config->commands.get_performance_level,
-                                 &sretval);
-       if (retval)
-               return retval;
-
-       /* The logic is backwards, yeah, lots of fun... */
-       for (i = 0; sabi_config->performance_levels[i].name; ++i) {
-               if (sretval.retval[0] == sabi_config->performance_levels[i].value)
-                       return sprintf(buf, "%s\n", sabi_config->performance_levels[i].name);
-       }
-       return sprintf(buf, "%s\n", "unknown");
-}
-
-static ssize_t set_performance_level(struct device *dev,
-                               struct device_attribute *attr, const char *buf,
-                               size_t count)
-{
-       if (count >= 1) {
-               int i;
-               for (i = 0; sabi_config->performance_levels[i].name; ++i) {
-                       const struct sabi_performance_level *level =
-                               &sabi_config->performance_levels[i];
-                       if (!strncasecmp(level->name, buf, strlen(level->name))) {
-                               sabi_set_command(sabi_config->commands.set_performance_level,
-                                                level->value);
-                               break;
-                       }
-               }
-               if (!sabi_config->performance_levels[i].name)
-                       return -EINVAL;
-       }
-       return count;
-}
-static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO,
-                  get_performance_level, set_performance_level);
-
-
-static int __init dmi_check_cb(const struct dmi_system_id *id)
-{
-       pr_info("found laptop model '%s'\n",
-               id->ident);
-       return 0;
-}
-
-static struct dmi_system_id __initdata samsung_dmi_table[] = {
-       {
-               .ident = "N128",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N128"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N128"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N130",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N130"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N130"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "X125",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "X125"),
-                       DMI_MATCH(DMI_BOARD_NAME, "X125"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "X120/X170",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "X120/X170"),
-                       DMI_MATCH(DMI_BOARD_NAME, "X120/X170"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "NC10",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "NC10"),
-                       DMI_MATCH(DMI_BOARD_NAME, "NC10"),
-               },
-               .callback = dmi_check_cb,
-       },
-               {
-               .ident = "NP-Q45",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"),
-                       DMI_MATCH(DMI_BOARD_NAME, "SQ45S70S"),
-               },
-               .callback = dmi_check_cb,
-               },
-       {
-               .ident = "X360",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "X360"),
-                       DMI_MATCH(DMI_BOARD_NAME, "X360"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R410 Plus",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "R410P"),
-                       DMI_MATCH(DMI_BOARD_NAME, "R460"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R518",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "R518"),
-                       DMI_MATCH(DMI_BOARD_NAME, "R518"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R519/R719",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "R519/R719"),
-                       DMI_MATCH(DMI_BOARD_NAME, "R519/R719"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N150/N210/N220/N230",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220/N230"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220/N230"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N150P/N210P/N220P",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N150P/N210P/N220P"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N150P/N210P/N220P"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R530/R730",
-               .matches = {
-                     DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                     DMI_MATCH(DMI_PRODUCT_NAME, "R530/R730"),
-                     DMI_MATCH(DMI_BOARD_NAME, "R530/R730"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "NF110/NF210/NF310",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
-                       DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "N145P/N250P/N260P",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
-                       DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "R70/R71",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR,
-                                       "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "R70/R71"),
-                       DMI_MATCH(DMI_BOARD_NAME, "R70/R71"),
-               },
-               .callback = dmi_check_cb,
-       },
-       {
-               .ident = "P460",
-               .matches = {
-                       DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "P460"),
-                       DMI_MATCH(DMI_BOARD_NAME, "P460"),
-               },
-               .callback = dmi_check_cb,
-       },
-       { },
-};
-MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
-
-static int find_signature(void __iomem *memcheck, const char *testStr)
-{
-       int i = 0;
-       int loca;
-
-       for (loca = 0; loca < 0xffff; loca++) {
-               char temp = readb(memcheck + loca);
-
-               if (temp == testStr[i]) {
-                       if (i == strlen(testStr)-1)
-                               break;
-                       ++i;
-               } else {
-                       i = 0;
-               }
-       }
-       return loca;
-}
-
-static int __init samsung_init(void)
-{
-       struct backlight_properties props;
-       struct sabi_retval sretval;
-       unsigned int ifaceP;
-       int i;
-       int loca;
-       int retval;
-
-       mutex_init(&sabi_mutex);
-
-       if (!force && !dmi_check_system(samsung_dmi_table))
-               return -ENODEV;
-
-       f0000_segment = ioremap_nocache(0xf0000, 0xffff);
-       if (!f0000_segment) {
-               pr_err("Can't map the segment at 0xf0000\n");
-               return -EINVAL;
-       }
-
-       /* Try to find one of the signatures in memory to find the header */
-       for (i = 0; sabi_configs[i].test_string != 0; ++i) {
-               sabi_config = &sabi_configs[i];
-               loca = find_signature(f0000_segment, sabi_config->test_string);
-               if (loca != 0xffff)
-                       break;
-       }
-
-       if (loca == 0xffff) {
-               pr_err("This computer does not support SABI\n");
-               goto error_no_signature;
-       }
-
-       /* point to the SMI port Number */
-       loca += 1;
-       sabi = (f0000_segment + loca);
-
-       if (debug) {
-               printk(KERN_DEBUG "This computer supports SABI==%x\n",
-                       loca + 0xf0000 - 6);
-               printk(KERN_DEBUG "SABI header:\n");
-               printk(KERN_DEBUG " SMI Port Number = 0x%04x\n",
-                       readw(sabi + sabi_config->header_offsets.port));
-               printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n",
-                       readb(sabi + sabi_config->header_offsets.iface_func));
-               printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n",
-                       readb(sabi + sabi_config->header_offsets.en_mem));
-               printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n",
-                       readb(sabi + sabi_config->header_offsets.re_mem));
-               printk(KERN_DEBUG " SABI data offset = 0x%04x\n",
-                       readw(sabi + sabi_config->header_offsets.data_offset));
-               printk(KERN_DEBUG " SABI data segment = 0x%04x\n",
-                       readw(sabi + sabi_config->header_offsets.data_segment));
-       }
-
-       /* Get a pointer to the SABI Interface */
-       ifaceP = (readw(sabi + sabi_config->header_offsets.data_segment) & 0x0ffff) << 4;
-       ifaceP += readw(sabi + sabi_config->header_offsets.data_offset) & 0x0ffff;
-       sabi_iface = ioremap_nocache(ifaceP, 16);
-       if (!sabi_iface) {
-               pr_err("Can't remap %x\n", ifaceP);
-               goto exit;
-       }
-       if (debug) {
-               printk(KERN_DEBUG "ifaceP = 0x%08x\n", ifaceP);
-               printk(KERN_DEBUG "sabi_iface = %p\n", sabi_iface);
-
-               test_backlight();
-               test_wireless();
-
-               retval = sabi_get_command(sabi_config->commands.get_brightness,
-                                         &sretval);
-               printk(KERN_DEBUG "brightness = 0x%02x\n", sretval.retval[0]);
-       }
-
-       /* Turn on "Linux" mode in the BIOS */
-       if (sabi_config->commands.set_linux != 0xff) {
-               retval = sabi_set_command(sabi_config->commands.set_linux,
-                                         0x81);
-               if (retval) {
-                       pr_warn("Linux mode was not set!\n");
-                       goto error_no_platform;
-               }
-       }
-
-       /* knock up a platform device to hang stuff off of */
-       sdev = platform_device_register_simple("samsung", -1, NULL, 0);
-       if (IS_ERR(sdev))
-               goto error_no_platform;
-
-       /* create a backlight device to talk to this one */
-       memset(&props, 0, sizeof(struct backlight_properties));
-       props.type = BACKLIGHT_PLATFORM;
-       props.max_brightness = sabi_config->max_brightness;
-       backlight_device = backlight_device_register("samsung", &sdev->dev,
-                                                    NULL, &backlight_ops,
-                                                    &props);
-       if (IS_ERR(backlight_device))
-               goto error_no_backlight;
-
-       backlight_device->props.brightness = read_brightness();
-       backlight_device->props.power = FB_BLANK_UNBLANK;
-       backlight_update_status(backlight_device);
-
-       retval = init_wireless(sdev);
-       if (retval)
-               goto error_no_rfk;
-
-       retval = device_create_file(&sdev->dev, &dev_attr_performance_level);
-       if (retval)
-               goto error_file_create;
-
-exit:
-       return 0;
-
-error_file_create:
-       destroy_wireless();
-
-error_no_rfk:
-       backlight_device_unregister(backlight_device);
-
-error_no_backlight:
-       platform_device_unregister(sdev);
-
-error_no_platform:
-       iounmap(sabi_iface);
-
-error_no_signature:
-       iounmap(f0000_segment);
-       return -EINVAL;
-}
-
-static void __exit samsung_exit(void)
-{
-       /* Turn off "Linux" mode in the BIOS */
-       if (sabi_config->commands.set_linux != 0xff)
-               sabi_set_command(sabi_config->commands.set_linux, 0x80);
-
-       device_remove_file(&sdev->dev, &dev_attr_performance_level);
-       backlight_device_unregister(backlight_device);
-       destroy_wireless();
-       iounmap(sabi_iface);
-       iounmap(f0000_segment);
-       platform_device_unregister(sdev);
-}
-
-module_init(samsung_init);
-module_exit(samsung_exit);
-
-MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
-MODULE_DESCRIPTION("Samsung Backlight driver");
-MODULE_LICENSE("GPL");
index 41b6e51188e44e4ac66590231c4a884b96a8b8f3..006489d82dc3dbc41b3f1d96fbea3511cb3e6d25 100644 (file)
@@ -66,6 +66,7 @@ config USB_ARCH_HAS_EHCI
        default y if ARCH_VT8500
        default y if PLAT_SPEAR
        default y if ARCH_MSM
+       default y if MICROBLAZE
        default PCI
 
 # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
index a3d2e2399655b84a348561e8aa27521212f21831..96fdfb815f895969e2d4c76750b8e0a5f7844c47 100644 (file)
@@ -221,7 +221,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
                break;
        case USB_ENDPOINT_XFER_INT:
                type = "Int.";
-               if (speed == USB_SPEED_HIGH)
+               if (speed == USB_SPEED_HIGH || speed == USB_SPEED_SUPER)
                        interval = 1 << (desc->bInterval - 1);
                else
                        interval = desc->bInterval;
@@ -229,7 +229,8 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end,
        default:        /* "can't happen" */
                return start;
        }
-       interval *= (speed == USB_SPEED_HIGH) ? 125 : 1000;
+       interval *= (speed == USB_SPEED_HIGH ||
+                    speed == USB_SPEED_SUPER) ? 125 : 1000;
        if (interval % 1000)
                unit = 'u';
        else {
@@ -542,8 +543,9 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes,
        if (level == 0) {
                int     max;
 
-               /* high speed reserves 80%, full/low reserves 90% */
-               if (usbdev->speed == USB_SPEED_HIGH)
+               /* super/high speed reserves 80%, full/low reserves 90% */
+               if (usbdev->speed == USB_SPEED_HIGH ||
+                   usbdev->speed == USB_SPEED_SUPER)
                        max = 800;
                else
                        max = FRAME_TIME_MAX_USECS_ALLOC;
index 8eed05d23838932aa0c412aed83c47d46a138e93..77a7faec8d78a0e7efa8c15f2d96a0b40a538130 100644 (file)
@@ -1908,7 +1908,7 @@ void usb_free_streams(struct usb_interface *interface,
 
        /* Streams only apply to bulk endpoints. */
        for (i = 0; i < num_eps; i++)
-               if (!usb_endpoint_xfer_bulk(&eps[i]->desc))
+               if (!eps[i] || !usb_endpoint_xfer_bulk(&eps[i]->desc))
                        return;
 
        hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags);
index 8fb754916c67e02d0e1b16625b7948c36b84dad1..93720bdc9efd4a9ff2e4f0d01023f2432edd1f51 100644 (file)
@@ -2285,7 +2285,17 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
        }
 
        /* see 7.1.7.6 */
-       status = set_port_feature(hub->hdev, port1, USB_PORT_FEAT_SUSPEND);
+       /* Clear PORT_POWER if it's a USB3.0 device connected to USB 3.0
+        * external hub.
+        * FIXME: this is a temporary workaround to make the system able
+        * to suspend/resume.
+        */
+       if ((hub->hdev->parent != NULL) && hub_is_superspeed(hub->hdev))
+               status = clear_port_feature(hub->hdev, port1,
+                                               USB_PORT_FEAT_POWER);
+       else
+               status = set_port_feature(hub->hdev, port1,
+                                               USB_PORT_FEAT_SUSPEND);
        if (status) {
                dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
                                port1, status);
index 9abecfddb27d1c489a59edfe29512adb93990a67..0111f8a9cf7fcc3f6345a9e6d612ea5683474530 100644 (file)
@@ -706,6 +706,7 @@ f_audio_unbind(struct usb_configuration *c, struct usb_function *f)
        struct f_audio          *audio = func_to_audio(f);
 
        usb_free_descriptors(f->descriptors);
+       usb_free_descriptors(f->hs_descriptors);
        kfree(audio);
 }
 
index 95dd4662d6a83acb3153433713c3e48889500f69..b3c304290150028cfafca5e9f192862617971ea8 100644 (file)
@@ -314,6 +314,9 @@ eem_unbind(struct usb_configuration *c, struct usb_function *f)
 
 static void eem_cmd_complete(struct usb_ep *ep, struct usb_request *req)
 {
+       struct sk_buff *skb = (struct sk_buff *)req->context;
+
+       dev_kfree_skb_any(skb);
 }
 
 /*
@@ -428,10 +431,11 @@ static int eem_unwrap(struct gether *port,
                                skb_trim(skb2, len);
                                put_unaligned_le16(BIT(15) | BIT(11) | len,
                                                        skb_push(skb2, 2));
-                               skb_copy_bits(skb, 0, req->buf, skb->len);
-                               req->length = skb->len;
+                               skb_copy_bits(skb2, 0, req->buf, skb2->len);
+                               req->length = skb2->len;
                                req->complete = eem_cmd_complete;
                                req->zero = 1;
+                               req->context = skb2;
                                if (usb_ep_queue(port->in_ep, req, GFP_ATOMIC))
                                        DBG(cdev, "echo response queue fail\n");
                                break;
index aee7e3c53c380bf625763ed2af17296591b02a7a..36613b37c50442c96a3bad47449365aaf31b1e89 100644 (file)
@@ -1148,6 +1148,12 @@ static int qe_ep_tx(struct qe_ep *ep, struct qe_frame *frame)
 static int txcomplete(struct qe_ep *ep, unsigned char restart)
 {
        if (ep->tx_req != NULL) {
+               struct qe_req *req = ep->tx_req;
+               unsigned zlp = 0, last_len = 0;
+
+               last_len = min_t(unsigned, req->req.length - ep->sent,
+                               ep->ep.maxpacket);
+
                if (!restart) {
                        int asent = ep->last;
                        ep->sent += asent;
@@ -1156,9 +1162,18 @@ static int txcomplete(struct qe_ep *ep, unsigned char restart)
                        ep->last = 0;
                }
 
+               /* zlp needed when req->re.zero is set */
+               if (req->req.zero) {
+                       if (last_len == 0 ||
+                               (req->req.length % ep->ep.maxpacket) != 0)
+                               zlp = 0;
+                       else
+                               zlp = 1;
+               } else
+                       zlp = 0;
+
                /* a request already were transmitted completely */
-               if ((ep->tx_req->req.length - ep->sent) <= 0) {
-                       ep->tx_req->req.actual = (unsigned int)ep->sent;
+               if (((ep->tx_req->req.length - ep->sent) <= 0) && !zlp) {
                        done(ep, ep->tx_req, 0);
                        ep->tx_req = NULL;
                        ep->last = 0;
@@ -1191,6 +1206,7 @@ static int qe_usb_senddata(struct qe_ep *ep, struct qe_frame *frame)
        buf = (u8 *)ep->tx_req->req.buf + ep->sent;
        if (buf && size) {
                ep->last = size;
+               ep->tx_req->req.actual += size;
                frame_set_data(frame, buf);
                frame_set_length(frame, size);
                frame_set_status(frame, FRAME_OK);
index 3ed73f49cf188cd98b92cc3e847a6e40f0062efb..a01383f71f38639c5539f5b82431ef1186ee6b60 100644 (file)
@@ -386,8 +386,10 @@ ep_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr)
 
        /* halt any endpoint by doing a "wrong direction" i/o call */
        if (usb_endpoint_dir_in(&data->desc)) {
-               if (usb_endpoint_xfer_isoc(&data->desc))
+               if (usb_endpoint_xfer_isoc(&data->desc)) {
+                       mutex_unlock(&data->lock);
                        return -EINVAL;
+               }
                DBG (data->dev, "%s halt\n", data->name);
                spin_lock_irq (&data->dev->lock);
                if (likely (data->ep != NULL))
index 3e4b35e50c2446b8926a687b1cb39e61d473cdff..68dbcc3e4cc2cb005bd2606a8bb64a4c35a12d81 100644 (file)
@@ -1608,7 +1608,7 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq,
                return -EINVAL;
        if (!dev->driver || (dev->gadget.speed == USB_SPEED_UNKNOWN))
                return -ESHUTDOWN;
-       spin_lock_irqsave(&ep->dev->lock, iflags);
+       spin_lock_irqsave(&dev->lock, iflags);
        /* map the buffer for dma */
        if (usbreq->length &&
            ((usbreq->dma == DMA_ADDR_INVALID) || !usbreq->dma)) {
@@ -1625,8 +1625,10 @@ static int pch_udc_pcd_queue(struct usb_ep *usbep, struct usb_request *usbreq,
                                                             DMA_FROM_DEVICE);
                } else {
                        req->buf = kzalloc(usbreq->length, GFP_ATOMIC);
-                       if (!req->buf)
-                               return -ENOMEM;
+                       if (!req->buf) {
+                               retval = -ENOMEM;
+                               goto probe_end;
+                       }
                        if (ep->in) {
                                memcpy(req->buf, usbreq->buf, usbreq->length);
                                req->dma = dma_map_single(&dev->pdev->dev,
index 015118535f77db3e8418909b850dfb0ed576fd00..6dcc1f68fa6041531e73eed8104d5c1acff1338b 100644 (file)
@@ -1083,7 +1083,9 @@ static void irq_device_state(struct r8a66597 *r8a66597)
 
        if (dvsq == DS_DFLT) {
                /* bus reset */
+               spin_unlock(&r8a66597->lock);
                r8a66597->driver->disconnect(&r8a66597->gadget);
+               spin_lock(&r8a66597->lock);
                r8a66597_update_usb_speed(r8a66597);
        }
        if (r8a66597->old_dvsq == DS_CNFG && dvsq != DS_CNFG)
index 98ded66e8d3fc5ccfbe4bfd9170c51e99cf3b752..42abd0f603bfbcd4291c78b0768b2d552b029500 100644 (file)
@@ -1247,24 +1247,27 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
 static void scan_async (struct ehci_hcd *ehci)
 {
+       bool                    stopped;
        struct ehci_qh          *qh;
        enum ehci_timer_action  action = TIMER_IO_WATCHDOG;
 
        ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
        timer_action_done (ehci, TIMER_ASYNC_SHRINK);
 rescan:
+       stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
        qh = ehci->async->qh_next.qh;
        if (likely (qh != NULL)) {
                do {
                        /* clean any finished work for this qh */
-                       if (!list_empty (&qh->qtd_list)
-                                       && qh->stamp != ehci->stamp) {
+                       if (!list_empty(&qh->qtd_list) && (stopped ||
+                                       qh->stamp != ehci->stamp)) {
                                int temp;
 
                                /* unlinks could happen here; completion
                                 * reporting drops the lock.  rescan using
                                 * the latest schedule, but don't rescan
-                                * qhs we already finished (no looping).
+                                * qhs we already finished (no looping)
+                                * unless the controller is stopped.
                                 */
                                qh = qh_get (qh);
                                qh->stamp = ehci->stamp;
@@ -1285,9 +1288,9 @@ rescan:
                         */
                        if (list_empty(&qh->qtd_list)
                                        && qh->qh_state == QH_STATE_LINKED) {
-                               if (!ehci->reclaim
-                                       && ((ehci->stamp - qh->stamp) & 0x1fff)
-                                               >= (EHCI_SHRINK_FRAMES * 8))
+                               if (!ehci->reclaim && (stopped ||
+                                       ((ehci->stamp - qh->stamp) & 0x1fff)
+                                               >= EHCI_SHRINK_FRAMES * 8))
                                        start_unlink_async(ehci, qh);
                                else
                                        action = TIMER_ASYNC_SHRINK;
index f50e84ac570aa9eced485e6372db76287fa9df76..795345ad45e62881fb8e28a1abce639a3088cac8 100644 (file)
@@ -295,7 +295,7 @@ static void alloc_mem(struct usb_hcd *hcd, struct isp1760_qtd *qtd)
        }
 
        dev_err(hcd->self.controller,
-                               "%s: Can not allocate %lu bytes of memory\n"
+                               "%s: Cannot allocate %zu bytes of memory\n"
                                "Current memory map:\n",
                                __func__, qtd->length);
        for (i = 0; i < BLOCKS; i++) {
index 17a6043c1fa072cba3d84c01fe8f6ba83005fff3..958d985f29513f36b2840b77a532c09a7bafa45e 100644 (file)
@@ -33,7 +33,7 @@
 
 #ifdef __LITTLE_ENDIAN
 #define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C)
-#elif __BIG_ENDIAN
+#elif defined(__BIG_ENDIAN)
 #define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C | \
                          USBH_ENABLE_BE)
 #else
index 1d586d4f7b56d5e3a0c38cf793dfec8dbf2554af..9b166d70ae91f8508642fee95097e958e21d2165 100644 (file)
@@ -84,65 +84,92 @@ int usb_amd_find_chipset_info(void)
 {
        u8 rev = 0;
        unsigned long flags;
+       struct amd_chipset_info info;
+       int ret;
 
        spin_lock_irqsave(&amd_lock, flags);
 
-       amd_chipset.probe_count++;
        /* probe only once */
-       if (amd_chipset.probe_count > 1) {
+       if (amd_chipset.probe_count > 0) {
+               amd_chipset.probe_count++;
                spin_unlock_irqrestore(&amd_lock, flags);
                return amd_chipset.probe_result;
        }
+       memset(&info, 0, sizeof(info));
+       spin_unlock_irqrestore(&amd_lock, flags);
 
-       amd_chipset.smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL);
-       if (amd_chipset.smbus_dev) {
-               rev = amd_chipset.smbus_dev->revision;
+       info.smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL);
+       if (info.smbus_dev) {
+               rev = info.smbus_dev->revision;
                if (rev >= 0x40)
-                       amd_chipset.sb_type = 1;
+                       info.sb_type = 1;
                else if (rev >= 0x30 && rev <= 0x3b)
-                       amd_chipset.sb_type = 3;
+                       info.sb_type = 3;
        } else {
-               amd_chipset.smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
-                                                       0x780b, NULL);
-               if (!amd_chipset.smbus_dev) {
-                       spin_unlock_irqrestore(&amd_lock, flags);
-                       return 0;
+               info.smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+                                               0x780b, NULL);
+               if (!info.smbus_dev) {
+                       ret = 0;
+                       goto commit;
                }
-               rev = amd_chipset.smbus_dev->revision;
+
+               rev = info.smbus_dev->revision;
                if (rev >= 0x11 && rev <= 0x18)
-                       amd_chipset.sb_type = 2;
+                       info.sb_type = 2;
        }
 
-       if (amd_chipset.sb_type == 0) {
-               if (amd_chipset.smbus_dev) {
-                       pci_dev_put(amd_chipset.smbus_dev);
-                       amd_chipset.smbus_dev = NULL;
+       if (info.sb_type == 0) {
+               if (info.smbus_dev) {
+                       pci_dev_put(info.smbus_dev);
+                       info.smbus_dev = NULL;
                }
-               spin_unlock_irqrestore(&amd_lock, flags);
-               return 0;
+               ret = 0;
+               goto commit;
        }
 
-       amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x9601, NULL);
-       if (amd_chipset.nb_dev) {
-               amd_chipset.nb_type = 1;
+       info.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x9601, NULL);
+       if (info.nb_dev) {
+               info.nb_type = 1;
        } else {
-               amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
-                                                       0x1510, NULL);
-               if (amd_chipset.nb_dev) {
-                       amd_chipset.nb_type = 2;
-               } else  {
-                       amd_chipset.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
-                                                               0x9600, NULL);
-                       if (amd_chipset.nb_dev)
-                               amd_chipset.nb_type = 3;
+               info.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL);
+               if (info.nb_dev) {
+                       info.nb_type = 2;
+               } else {
+                       info.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD,
+                                                    0x9600, NULL);
+                       if (info.nb_dev)
+                               info.nb_type = 3;
                }
        }
 
-       amd_chipset.probe_result = 1;
+       ret = info.probe_result = 1;
        printk(KERN_DEBUG "QUIRK: Enable AMD PLL fix\n");
 
-       spin_unlock_irqrestore(&amd_lock, flags);
-       return amd_chipset.probe_result;
+commit:
+
+       spin_lock_irqsave(&amd_lock, flags);
+       if (amd_chipset.probe_count > 0) {
+               /* race - someone else was faster - drop devices */
+
+               /* Mark that we where here */
+               amd_chipset.probe_count++;
+               ret = amd_chipset.probe_result;
+
+               spin_unlock_irqrestore(&amd_lock, flags);
+
+               if (info.nb_dev)
+                       pci_dev_put(info.nb_dev);
+               if (info.smbus_dev)
+                       pci_dev_put(info.smbus_dev);
+
+       } else {
+               /* no race - commit the result */
+               info.probe_count++;
+               amd_chipset = info;
+               spin_unlock_irqrestore(&amd_lock, flags);
+       }
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(usb_amd_find_chipset_info);
 
@@ -284,6 +311,7 @@ EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_enable);
 
 void usb_amd_dev_put(void)
 {
+       struct pci_dev *nb, *smbus;
        unsigned long flags;
 
        spin_lock_irqsave(&amd_lock, flags);
@@ -294,20 +322,23 @@ void usb_amd_dev_put(void)
                return;
        }
 
-       if (amd_chipset.nb_dev) {
-               pci_dev_put(amd_chipset.nb_dev);
-               amd_chipset.nb_dev = NULL;
-       }
-       if (amd_chipset.smbus_dev) {
-               pci_dev_put(amd_chipset.smbus_dev);
-               amd_chipset.smbus_dev = NULL;
-       }
+       /* save them to pci_dev_put outside of spinlock */
+       nb    = amd_chipset.nb_dev;
+       smbus = amd_chipset.smbus_dev;
+
+       amd_chipset.nb_dev = NULL;
+       amd_chipset.smbus_dev = NULL;
        amd_chipset.nb_type = 0;
        amd_chipset.sb_type = 0;
        amd_chipset.isoc_reqs = 0;
        amd_chipset.probe_result = 0;
 
        spin_unlock_irqrestore(&amd_lock, flags);
+
+       if (nb)
+               pci_dev_put(nb);
+       if (smbus)
+               pci_dev_put(smbus);
 }
 EXPORT_SYMBOL_GPL(usb_amd_dev_put);
 
index a003e79aacdc0e06efe85cfa3dc53a2579c850b2..627f3438028ce3a54d49fd7d691143b58f6fac18 100644 (file)
@@ -846,7 +846,7 @@ static u32 xhci_find_real_port_number(struct xhci_hcd *xhci,
                 * Skip ports that don't have known speeds, or have duplicate
                 * Extended Capabilities port speed entries.
                 */
-               if (port_speed == 0 || port_speed == -1)
+               if (port_speed == 0 || port_speed == DUPLICATE_ENTRY)
                        continue;
 
                /*
@@ -974,6 +974,47 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
        return 0;
 }
 
+/*
+ * Convert interval expressed as 2^(bInterval - 1) == interval into
+ * straight exponent value 2^n == interval.
+ *
+ */
+static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
+               struct usb_host_endpoint *ep)
+{
+       unsigned int interval;
+
+       interval = clamp_val(ep->desc.bInterval, 1, 16) - 1;
+       if (interval != ep->desc.bInterval - 1)
+               dev_warn(&udev->dev,
+                        "ep %#x - rounding interval to %d microframes\n",
+                        ep->desc.bEndpointAddress,
+                        1 << interval);
+
+       return interval;
+}
+
+/*
+ * Convert bInterval expressed in frames (in 1-255 range) to exponent of
+ * microframes, rounded down to nearest power of 2.
+ */
+static unsigned int xhci_parse_frame_interval(struct usb_device *udev,
+               struct usb_host_endpoint *ep)
+{
+       unsigned int interval;
+
+       interval = fls(8 * ep->desc.bInterval) - 1;
+       interval = clamp_val(interval, 3, 10);
+       if ((1 << interval) != 8 * ep->desc.bInterval)
+               dev_warn(&udev->dev,
+                        "ep %#x - rounding interval to %d microframes, ep desc says %d microframes\n",
+                        ep->desc.bEndpointAddress,
+                        1 << interval,
+                        8 * ep->desc.bInterval);
+
+       return interval;
+}
+
 /* Return the polling or NAK interval.
  *
  * The polling interval is expressed in "microframes".  If xHCI's Interval field
@@ -982,7 +1023,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
  * The NAK interval is one NAK per 1 to 255 microframes, or no NAKs if interval
  * is set to 0.
  */
-static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
+static unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
                struct usb_host_endpoint *ep)
 {
        unsigned int interval = 0;
@@ -991,45 +1032,38 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
        case USB_SPEED_HIGH:
                /* Max NAK rate */
                if (usb_endpoint_xfer_control(&ep->desc) ||
-                               usb_endpoint_xfer_bulk(&ep->desc))
+                   usb_endpoint_xfer_bulk(&ep->desc)) {
                        interval = ep->desc.bInterval;
+                       break;
+               }
                /* Fall through - SS and HS isoc/int have same decoding */
+
        case USB_SPEED_SUPER:
                if (usb_endpoint_xfer_int(&ep->desc) ||
-                               usb_endpoint_xfer_isoc(&ep->desc)) {
-                       if (ep->desc.bInterval == 0)
-                               interval = 0;
-                       else
-                               interval = ep->desc.bInterval - 1;
-                       if (interval > 15)
-                               interval = 15;
-                       if (interval != ep->desc.bInterval + 1)
-                               dev_warn(&udev->dev, "ep %#x - rounding interval to %d microframes\n",
-                                               ep->desc.bEndpointAddress, 1 << interval);
+                   usb_endpoint_xfer_isoc(&ep->desc)) {
+                       interval = xhci_parse_exponent_interval(udev, ep);
                }
                break;
-       /* Convert bInterval (in 1-255 frames) to microframes and round down to
-        * nearest power of 2.
-        */
+
        case USB_SPEED_FULL:
+               if (usb_endpoint_xfer_int(&ep->desc)) {
+                       interval = xhci_parse_exponent_interval(udev, ep);
+                       break;
+               }
+               /*
+                * Fall through for isochronous endpoint interval decoding
+                * since it uses the same rules as low speed interrupt
+                * endpoints.
+                */
+
        case USB_SPEED_LOW:
                if (usb_endpoint_xfer_int(&ep->desc) ||
-                               usb_endpoint_xfer_isoc(&ep->desc)) {
-                       interval = fls(8*ep->desc.bInterval) - 1;
-                       if (interval > 10)
-                               interval = 10;
-                       if (interval < 3)
-                               interval = 3;
-                       if ((1 << interval) != 8*ep->desc.bInterval)
-                               dev_warn(&udev->dev,
-                                               "ep %#x - rounding interval"
-                                               " to %d microframes, "
-                                               "ep desc says %d microframes\n",
-                                               ep->desc.bEndpointAddress,
-                                               1 << interval,
-                                               8*ep->desc.bInterval);
+                   usb_endpoint_xfer_isoc(&ep->desc)) {
+
+                       interval = xhci_parse_frame_interval(udev, ep);
                }
                break;
+
        default:
                BUG();
        }
@@ -1041,7 +1075,7 @@ static inline unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
  * transaction opportunities per microframe", but that goes in the Max Burst
  * endpoint context field.
  */
-static inline u32 xhci_get_endpoint_mult(struct usb_device *udev,
+static u32 xhci_get_endpoint_mult(struct usb_device *udev,
                struct usb_host_endpoint *ep)
 {
        if (udev->speed != USB_SPEED_SUPER ||
@@ -1050,7 +1084,7 @@ static inline u32 xhci_get_endpoint_mult(struct usb_device *udev,
        return ep->ss_ep_comp.bmAttributes;
 }
 
-static inline u32 xhci_get_endpoint_type(struct usb_device *udev,
+static u32 xhci_get_endpoint_type(struct usb_device *udev,
                struct usb_host_endpoint *ep)
 {
        int in;
@@ -1084,7 +1118,7 @@ static inline u32 xhci_get_endpoint_type(struct usb_device *udev,
  * Basically, this is the maxpacket size, multiplied by the burst size
  * and mult size.
  */
-static inline u32 xhci_get_max_esit_payload(struct xhci_hcd *xhci,
+static u32 xhci_get_max_esit_payload(struct xhci_hcd *xhci,
                struct usb_device *udev,
                struct usb_host_endpoint *ep)
 {
@@ -1727,12 +1761,12 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
                         * found a similar duplicate.
                         */
                        if (xhci->port_array[i] != major_revision &&
-                               xhci->port_array[i] != (u8) -1) {
+                               xhci->port_array[i] != DUPLICATE_ENTRY) {
                                if (xhci->port_array[i] == 0x03)
                                        xhci->num_usb3_ports--;
                                else
                                        xhci->num_usb2_ports--;
-                               xhci->port_array[i] = (u8) -1;
+                               xhci->port_array[i] = DUPLICATE_ENTRY;
                        }
                        /* FIXME: Should we disable the port? */
                        continue;
@@ -1831,7 +1865,7 @@ static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
                for (i = 0; i < num_ports; i++) {
                        if (xhci->port_array[i] == 0x03 ||
                                        xhci->port_array[i] == 0 ||
-                                       xhci->port_array[i] == -1)
+                                       xhci->port_array[i] == DUPLICATE_ENTRY)
                                continue;
 
                        xhci->usb2_ports[port_index] =
index ceea9f33491c0d1dd379bc48db4fc9fd486a518b..a10494c2f3c7749a83fe52b2479c469da47e9d0e 100644 (file)
@@ -114,6 +114,10 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
        if (pdev->vendor == PCI_VENDOR_ID_NEC)
                xhci->quirks |= XHCI_NEC_HOST;
 
+       /* AMD PLL quirk */
+       if (pdev->vendor == PCI_VENDOR_ID_AMD && usb_amd_find_chipset_info())
+               xhci->quirks |= XHCI_AMD_PLL_FIX;
+
        /* Make sure the HC is halted. */
        retval = xhci_halt(xhci);
        if (retval)
index cfc1ad92473f5f5ae77403a07e55ae03c2f71690..7437386a9a50afeea3ad87bfd5b2f66f0a861947 100644 (file)
@@ -93,7 +93,7 @@ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg,
 /* Does this link TRB point to the first segment in a ring,
  * or was the previous TRB the last TRB on the last segment in the ERST?
  */
-static inline bool last_trb_on_last_seg(struct xhci_hcd *xhci, struct xhci_ring *ring,
+static bool last_trb_on_last_seg(struct xhci_hcd *xhci, struct xhci_ring *ring,
                struct xhci_segment *seg, union xhci_trb *trb)
 {
        if (ring == xhci->event_ring)
@@ -107,7 +107,7 @@ static inline bool last_trb_on_last_seg(struct xhci_hcd *xhci, struct xhci_ring
  * segment?  I.e. would the updated event TRB pointer step off the end of the
  * event seg?
  */
-static inline int last_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
+static int last_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
                struct xhci_segment *seg, union xhci_trb *trb)
 {
        if (ring == xhci->event_ring)
@@ -116,7 +116,7 @@ static inline int last_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
                return (trb->link.control & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK);
 }
 
-static inline int enqueue_is_link_trb(struct xhci_ring *ring)
+static int enqueue_is_link_trb(struct xhci_ring *ring)
 {
        struct xhci_link_trb *link = &ring->enqueue->link;
        return ((link->control & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK));
@@ -592,7 +592,7 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
        ep->ep_state |= SET_DEQ_PENDING;
 }
 
-static inline void xhci_stop_watchdog_timer_in_irq(struct xhci_hcd *xhci,
+static void xhci_stop_watchdog_timer_in_irq(struct xhci_hcd *xhci,
                struct xhci_virt_ep *ep)
 {
        ep->ep_state &= ~EP_HALT_PENDING;
@@ -619,6 +619,13 @@ static void xhci_giveback_urb_in_irq(struct xhci_hcd *xhci,
 
        /* Only giveback urb when this is the last td in urb */
        if (urb_priv->td_cnt == urb_priv->length) {
+               if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+                       xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs--;
+                       if (xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs == 0) {
+                               if (xhci->quirks & XHCI_AMD_PLL_FIX)
+                                       usb_amd_quirk_pll_enable();
+                       }
+               }
                usb_hcd_unlink_urb_from_ep(hcd, urb);
                xhci_dbg(xhci, "Giveback %s URB %p\n", adjective, urb);
 
@@ -1209,7 +1216,7 @@ static unsigned int find_faked_portnum_from_hw_portnum(struct usb_hcd *hcd,
                 * Skip ports that don't have known speeds, or have duplicate
                 * Extended Capabilities port speed entries.
                 */
-               if (port_speed == 0 || port_speed == -1)
+               if (port_speed == 0 || port_speed == DUPLICATE_ENTRY)
                        continue;
 
                /*
@@ -1235,6 +1242,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
        u8 major_revision;
        struct xhci_bus_state *bus_state;
        u32 __iomem **port_array;
+       bool bogus_port_status = false;
 
        /* Port status change events always have a successful completion code */
        if (GET_COMP_CODE(event->generic.field[2]) != COMP_SUCCESS) {
@@ -1247,6 +1255,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
        max_ports = HCS_MAX_PORTS(xhci->hcs_params1);
        if ((port_id <= 0) || (port_id > max_ports)) {
                xhci_warn(xhci, "Invalid port id %d\n", port_id);
+               bogus_port_status = true;
                goto cleanup;
        }
 
@@ -1258,12 +1267,14 @@ static void handle_port_status(struct xhci_hcd *xhci,
                xhci_warn(xhci, "Event for port %u not in "
                                "Extended Capabilities, ignoring.\n",
                                port_id);
+               bogus_port_status = true;
                goto cleanup;
        }
-       if (major_revision == (u8) -1) {
+       if (major_revision == DUPLICATE_ENTRY) {
                xhci_warn(xhci, "Event for port %u duplicated in"
                                "Extended Capabilities, ignoring.\n",
                                port_id);
+               bogus_port_status = true;
                goto cleanup;
        }
 
@@ -1335,6 +1346,13 @@ cleanup:
        /* Update event ring dequeue pointer before dropping the lock */
        inc_deq(xhci, xhci->event_ring, true);
 
+       /* Don't make the USB core poll the roothub if we got a bad port status
+        * change event.  Besides, at that point we can't tell which roothub
+        * (USB 2.0 or USB 3.0) to kick.
+        */
+       if (bogus_port_status)
+               return;
+
        spin_unlock(&xhci->lock);
        /* Pass this up to the core */
        usb_hcd_poll_rh_status(hcd);
@@ -1554,8 +1572,17 @@ td_cleanup:
 
                urb_priv->td_cnt++;
                /* Giveback the urb when all the tds are completed */
-               if (urb_priv->td_cnt == urb_priv->length)
+               if (urb_priv->td_cnt == urb_priv->length) {
                        ret = 1;
+                       if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
+                               xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs--;
+                               if (xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs
+                                       == 0) {
+                                       if (xhci->quirks & XHCI_AMD_PLL_FIX)
+                                               usb_amd_quirk_pll_enable();
+                               }
+                       }
+               }
        }
 
        return ret;
@@ -1675,71 +1702,52 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
        struct urb_priv *urb_priv;
        int idx;
        int len = 0;
-       int skip_td = 0;
        union xhci_trb *cur_trb;
        struct xhci_segment *cur_seg;
+       struct usb_iso_packet_descriptor *frame;
        u32 trb_comp_code;
+       bool skip_td = false;
 
        ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
        trb_comp_code = GET_COMP_CODE(event->transfer_len);
        urb_priv = td->urb->hcpriv;
        idx = urb_priv->td_cnt;
+       frame = &td->urb->iso_frame_desc[idx];
 
-       if (ep->skip) {
-               /* The transfer is partly done */
-               *status = -EXDEV;
-               td->urb->iso_frame_desc[idx].status = -EXDEV;
-       } else {
-               /* handle completion code */
-               switch (trb_comp_code) {
-               case COMP_SUCCESS:
-                       td->urb->iso_frame_desc[idx].status = 0;
-                       xhci_dbg(xhci, "Successful isoc transfer!\n");
-                       break;
-               case COMP_SHORT_TX:
-                       if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
-                               td->urb->iso_frame_desc[idx].status =
-                                        -EREMOTEIO;
-                       else
-                               td->urb->iso_frame_desc[idx].status = 0;
-                       break;
-               case COMP_BW_OVER:
-                       td->urb->iso_frame_desc[idx].status = -ECOMM;
-                       skip_td = 1;
-                       break;
-               case COMP_BUFF_OVER:
-               case COMP_BABBLE:
-                       td->urb->iso_frame_desc[idx].status = -EOVERFLOW;
-                       skip_td = 1;
-                       break;
-               case COMP_STALL:
-                       td->urb->iso_frame_desc[idx].status = -EPROTO;
-                       skip_td = 1;
-                       break;
-               case COMP_STOP:
-               case COMP_STOP_INVAL:
-                       break;
-               default:
-                       td->urb->iso_frame_desc[idx].status = -1;
-                       break;
-               }
-       }
-
-       /* calc actual length */
-       if (ep->skip) {
-               td->urb->iso_frame_desc[idx].actual_length = 0;
-               /* Update ring dequeue pointer */
-               while (ep_ring->dequeue != td->last_trb)
-                       inc_deq(xhci, ep_ring, false);
-               inc_deq(xhci, ep_ring, false);
-               return finish_td(xhci, td, event_trb, event, ep, status, true);
+       /* handle completion code */
+       switch (trb_comp_code) {
+       case COMP_SUCCESS:
+               frame->status = 0;
+               xhci_dbg(xhci, "Successful isoc transfer!\n");
+               break;
+       case COMP_SHORT_TX:
+               frame->status = td->urb->transfer_flags & URB_SHORT_NOT_OK ?
+                               -EREMOTEIO : 0;
+               break;
+       case COMP_BW_OVER:
+               frame->status = -ECOMM;
+               skip_td = true;
+               break;
+       case COMP_BUFF_OVER:
+       case COMP_BABBLE:
+               frame->status = -EOVERFLOW;
+               skip_td = true;
+               break;
+       case COMP_STALL:
+               frame->status = -EPROTO;
+               skip_td = true;
+               break;
+       case COMP_STOP:
+       case COMP_STOP_INVAL:
+               break;
+       default:
+               frame->status = -1;
+               break;
        }
 
-       if (trb_comp_code == COMP_SUCCESS || skip_td == 1) {
-               td->urb->iso_frame_desc[idx].actual_length =
-                       td->urb->iso_frame_desc[idx].length;
-               td->urb->actual_length +=
-                       td->urb->iso_frame_desc[idx].length;
+       if (trb_comp_code == COMP_SUCCESS || skip_td) {
+               frame->actual_length = frame->length;
+               td->urb->actual_length += frame->length;
        } else {
                for (cur_trb = ep_ring->dequeue,
                     cur_seg = ep_ring->deq_seg; cur_trb != event_trb;
@@ -1755,7 +1763,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
                        TRB_LEN(event->transfer_len);
 
                if (trb_comp_code != COMP_STOP_INVAL) {
-                       td->urb->iso_frame_desc[idx].actual_length = len;
+                       frame->actual_length = len;
                        td->urb->actual_length += len;
                }
        }
@@ -1766,6 +1774,35 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
        return finish_td(xhci, td, event_trb, event, ep, status, false);
 }
 
+static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
+                       struct xhci_transfer_event *event,
+                       struct xhci_virt_ep *ep, int *status)
+{
+       struct xhci_ring *ep_ring;
+       struct urb_priv *urb_priv;
+       struct usb_iso_packet_descriptor *frame;
+       int idx;
+
+       ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
+       urb_priv = td->urb->hcpriv;
+       idx = urb_priv->td_cnt;
+       frame = &td->urb->iso_frame_desc[idx];
+
+       /* The transfer is partly done */
+       *status = -EXDEV;
+       frame->status = -EXDEV;
+
+       /* calc actual length */
+       frame->actual_length = 0;
+
+       /* Update ring dequeue pointer */
+       while (ep_ring->dequeue != td->last_trb)
+               inc_deq(xhci, ep_ring, false);
+       inc_deq(xhci, ep_ring, false);
+
+       return finish_td(xhci, td, NULL, event, ep, status, true);
+}
+
 /*
  * Process bulk and interrupt tds, update urb status and actual_length.
  */
@@ -2024,36 +2061,42 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                }
 
                td = list_entry(ep_ring->td_list.next, struct xhci_td, td_list);
+
                /* Is this a TRB in the currently executing TD? */
                event_seg = trb_in_td(ep_ring->deq_seg, ep_ring->dequeue,
                                td->last_trb, event_dma);
-               if (event_seg && ep->skip) {
+               if (!event_seg) {
+                       if (!ep->skip ||
+                           !usb_endpoint_xfer_isoc(&td->urb->ep->desc)) {
+                               /* HC is busted, give up! */
+                               xhci_err(xhci,
+                                       "ERROR Transfer event TRB DMA ptr not "
+                                       "part of current TD\n");
+                               return -ESHUTDOWN;
+                       }
+
+                       ret = skip_isoc_td(xhci, td, event, ep, &status);
+                       goto cleanup;
+               }
+
+               if (ep->skip) {
                        xhci_dbg(xhci, "Found td. Clear skip flag.\n");
                        ep->skip = false;
                }
-               if (!event_seg &&
-                  (!ep->skip || !usb_endpoint_xfer_isoc(&td->urb->ep->desc))) {
-                       /* HC is busted, give up! */
-                       xhci_err(xhci, "ERROR Transfer event TRB DMA ptr not "
-                                       "part of current TD\n");
-                       return -ESHUTDOWN;
-               }
 
-               if (event_seg) {
-                       event_trb = &event_seg->trbs[(event_dma -
-                                        event_seg->dma) / sizeof(*event_trb)];
-                       /*
-                        * No-op TRB should not trigger interrupts.
-                        * If event_trb is a no-op TRB, it means the
-                        * corresponding TD has been cancelled. Just ignore
-                        * the TD.
-                        */
-                       if ((event_trb->generic.field[3] & TRB_TYPE_BITMASK)
-                                        == TRB_TYPE(TRB_TR_NOOP)) {
-                               xhci_dbg(xhci, "event_trb is a no-op TRB. "
-                                               "Skip it\n");
-                               goto cleanup;
-                       }
+               event_trb = &event_seg->trbs[(event_dma - event_seg->dma) /
+                                               sizeof(*event_trb)];
+               /*
+                * No-op TRB should not trigger interrupts.
+                * If event_trb is a no-op TRB, it means the
+                * corresponding TD has been cancelled. Just ignore
+                * the TD.
+                */
+               if ((event_trb->generic.field[3] & TRB_TYPE_BITMASK)
+                                == TRB_TYPE(TRB_TR_NOOP)) {
+                       xhci_dbg(xhci,
+                                "event_trb is a no-op TRB. Skip it\n");
+                       goto cleanup;
                }
 
                /* Now update the urb's actual_length and give back to
@@ -3126,6 +3169,12 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
                }
        }
 
+       if (xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs == 0) {
+               if (xhci->quirks & XHCI_AMD_PLL_FIX)
+                       usb_amd_quirk_pll_disable();
+       }
+       xhci_to_hcd(xhci)->self.bandwidth_isoc_reqs++;
+
        giveback_first_trb(xhci, slot_id, ep_index, urb->stream_id,
                        start_cycle, start_trb);
        return 0;
index 196e0181b2ed6e5f56c0a8ea2330a3399c8f739b..81b976e45880900065b505611c0fb762d5852015 100644 (file)
@@ -550,6 +550,9 @@ void xhci_stop(struct usb_hcd *hcd)
        del_timer_sync(&xhci->event_ring_timer);
 #endif
 
+       if (xhci->quirks & XHCI_AMD_PLL_FIX)
+               usb_amd_dev_put();
+
        xhci_dbg(xhci, "// Disabling event ring interrupts\n");
        temp = xhci_readl(xhci, &xhci->op_regs->status);
        xhci_writel(xhci, temp & ~STS_EINT, &xhci->op_regs->status);
@@ -771,7 +774,9 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 
        /* If restore operation fails, re-initialize the HC during resume */
        if ((temp & STS_SRE) || hibernated) {
-               usb_root_hub_lost_power(hcd->self.root_hub);
+               /* Let the USB core know _both_ roothubs lost power. */
+               usb_root_hub_lost_power(xhci->main_hcd->self.root_hub);
+               usb_root_hub_lost_power(xhci->shared_hcd->self.root_hub);
 
                xhci_dbg(xhci, "Stop HCD\n");
                xhci_halt(xhci);
@@ -2386,10 +2391,18 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
        /* Everything but endpoint 0 is disabled, so free or cache the rings. */
        last_freed_endpoint = 1;
        for (i = 1; i < 31; ++i) {
-               if (!virt_dev->eps[i].ring)
-                       continue;
-               xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
-               last_freed_endpoint = i;
+               struct xhci_virt_ep *ep = &virt_dev->eps[i];
+
+               if (ep->ep_state & EP_HAS_STREAMS) {
+                       xhci_free_stream_info(xhci, ep->stream_info);
+                       ep->stream_info = NULL;
+                       ep->ep_state &= ~EP_HAS_STREAMS;
+               }
+
+               if (ep->ring) {
+                       xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
+                       last_freed_endpoint = i;
+               }
        }
        xhci_dbg(xhci, "Output context after successful reset device cmd:\n");
        xhci_dbg_ctx(xhci, virt_dev->out_ctx, last_freed_endpoint);
index 07e263063e373ad9fc45e7832f6700fb0b56b2e6..ba1be6b7cc6d91774323e9dd0848e759fe338c9f 100644 (file)
@@ -30,6 +30,7 @@
 
 /* Code sharing between pci-quirks and xhci hcd */
 #include       "xhci-ext-caps.h"
+#include "pci-quirks.h"
 
 /* xHCI PCI Configuration Registers */
 #define XHCI_SBRN_OFFSET       (0x60)
@@ -232,7 +233,7 @@ struct xhci_op_regs {
  * notification type that matches a bit set in this bit field.
  */
 #define        DEV_NOTE_MASK           (0xffff)
-#define ENABLE_DEV_NOTE(x)     (1 << x)
+#define ENABLE_DEV_NOTE(x)     (1 << (x))
 /* Most of the device notification types should only be used for debug.
  * SW does need to pay attention to function wake notifications.
  */
@@ -348,6 +349,9 @@ struct xhci_op_regs {
 /* Initiate a warm port reset - complete when PORT_WRC is '1' */
 #define PORT_WR                (1 << 31)
 
+/* We mark duplicate entries with -1 */
+#define DUPLICATE_ENTRY ((u8)(-1))
+
 /* Port Power Management Status and Control - port_power_base bitmasks */
 /* Inactivity timer value for transitions into U1, in microseconds.
  * Timeout can be up to 127us.  0xFF means an infinite timeout.
@@ -601,11 +605,11 @@ struct xhci_ep_ctx {
 #define EP_STATE_STOPPED       3
 #define EP_STATE_ERROR         4
 /* Mult - Max number of burtst within an interval, in EP companion desc. */
-#define EP_MULT(p)             ((p & 0x3) << 8)
+#define EP_MULT(p)             (((p) & 0x3) << 8)
 /* bits 10:14 are Max Primary Streams */
 /* bit 15 is Linear Stream Array */
 /* Interval - period between requests to an endpoint - 125u increments. */
-#define EP_INTERVAL(p)         ((p & 0xff) << 16)
+#define EP_INTERVAL(p)         (((p) & 0xff) << 16)
 #define EP_INTERVAL_TO_UFRAMES(p)              (1 << (((p) >> 16) & 0xff))
 #define EP_MAXPSTREAMS_MASK    (0x1f << 10)
 #define EP_MAXPSTREAMS(p)      (((p) << 10) & EP_MAXPSTREAMS_MASK)
@@ -1276,6 +1280,7 @@ struct xhci_hcd {
 #define        XHCI_LINK_TRB_QUIRK     (1 << 0)
 #define XHCI_RESET_EP_QUIRK    (1 << 1)
 #define XHCI_NEC_HOST          (1 << 2)
+#define XHCI_AMD_PLL_FIX       (1 << 3)
        /* There are two roothubs to keep track of bus suspend info for */
        struct xhci_bus_state   bus_state[2];
        /* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */
index 4cbb7e4b368d24d3461b02c28804bcf5badf76ba..74073b363c30f86536daa948a43961654e23bbb7 100644 (file)
@@ -14,7 +14,7 @@ config USB_MUSB_HDRC
        select TWL4030_USB if MACH_OMAP_3430SDP
        select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
        select USB_OTG_UTILS
-       tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
+       bool 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
        help
          Say Y here if your system has a dual role high speed USB
          controller based on the Mentor Graphics silicon IP.  Then
@@ -30,8 +30,8 @@ config USB_MUSB_HDRC
 
          If you do not know what this is, please say N.
 
-         To compile this driver as a module, choose M here; the
-         module will be called "musb-hdrc".
+#        To compile this driver as a module, choose M here; the
+#        module will be called "musb-hdrc".
 
 choice
        prompt "Platform Glue Layer"
index 52312e8af213a4d0d6cdd515aa50757fd06bfa56..8e2a1ff8a35a8b71cbe6296bf5d546b0d46035c6 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/cacheflush.h>
 
 #include "musb_core.h"
+#include "musbhsdma.h"
 #include "blackfin.h"
 
 struct bfin_glue {
@@ -332,6 +333,27 @@ static int bfin_musb_set_mode(struct musb *musb, u8 musb_mode)
        return -EIO;
 }
 
+static int bfin_musb_adjust_channel_params(struct dma_channel *channel,
+                               u16 packet_sz, u8 *mode,
+                               dma_addr_t *dma_addr, u32 *len)
+{
+       struct musb_dma_channel *musb_channel = channel->private_data;
+
+       /*
+        * Anomaly 05000450 might cause data corruption when using DMA
+        * MODE 1 transmits with short packet.  So to work around this,
+        * we truncate all MODE 1 transfers down to a multiple of the
+        * max packet size, and then do the last short packet transfer
+        * (if there is any) using MODE 0.
+        */
+       if (ANOMALY_05000450) {
+               if (musb_channel->transmit && *mode == 1)
+                       *len = *len - (*len % packet_sz);
+       }
+
+       return 0;
+}
+
 static void bfin_musb_reg_init(struct musb *musb)
 {
        if (ANOMALY_05000346) {
@@ -430,6 +452,8 @@ static const struct musb_platform_ops bfin_ops = {
 
        .vbus_status    = bfin_musb_vbus_status,
        .set_vbus       = bfin_musb_set_vbus,
+
+       .adjust_channel_params = bfin_musb_adjust_channel_params,
 };
 
 static u64 bfin_dmamask = DMA_BIT_MASK(32);
index de55a3c3259ac1a403e3c4d730781eeb63fda77c..ab434fbd8c35446863052fb7df19607c295b8228 100644 (file)
@@ -597,12 +597,12 @@ cppi_next_tx_segment(struct musb *musb, struct cppi_channel *tx)
                length = min(n_bds * maxpacket, length);
        }
 
-       DBG(4, "TX DMA%d, pktSz %d %s bds %d dma 0x%x len %u\n",
+       DBG(4, "TX DMA%d, pktSz %d %s bds %d dma 0x%llx len %u\n",
                        tx->index,
                        maxpacket,
                        rndis ? "rndis" : "transparent",
                        n_bds,
-                       addr, length);
+                       (unsigned long long)addr, length);
 
        cppi_rndis_update(tx, 0, musb->ctrl_base, rndis);
 
@@ -820,7 +820,7 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
        length = min(n_bds * maxpacket, length);
 
        DBG(4, "RX DMA%d seg, maxp %d %s bds %d (cnt %d) "
-                       "dma 0x%x len %u %u/%u\n",
+                       "dma 0x%llx len %u %u/%u\n",
                        rx->index, maxpacket,
                        onepacket
                                ? (is_rndis ? "rndis" : "onepacket")
@@ -829,7 +829,8 @@ cppi_next_rx_segment(struct musb *musb, struct cppi_channel *rx, int onepacket)
                        musb_readl(tibase,
                                DAVINCI_RXCPPI_BUFCNT0_REG + (rx->index * 4))
                                        & 0xffff,
-                       addr, length, rx->channel.actual_len, rx->buf_len);
+                       (unsigned long long)addr, length,
+                       rx->channel.actual_len, rx->buf_len);
 
        /* only queue one segment at a time, since the hardware prevents
         * correct queue shutdown after unexpected short packets
@@ -1039,9 +1040,9 @@ static bool cppi_rx_scan(struct cppi *cppi, unsigned ch)
                if (!completed && (bd->hw_options & CPPI_OWN_SET))
                        break;
 
-               DBG(5, "C/RXBD %08x: nxt %08x buf %08x "
+               DBG(5, "C/RXBD %llx: nxt %08x buf %08x "
                        "off.len %08x opt.len %08x (%d)\n",
-                       bd->dma, bd->hw_next, bd->hw_bufp,
+                       (unsigned long long)bd->dma, bd->hw_next, bd->hw_bufp,
                        bd->hw_off_len, bd->hw_options,
                        rx->channel.actual_len);
 
@@ -1111,11 +1112,12 @@ static bool cppi_rx_scan(struct cppi *cppi, unsigned ch)
                musb_ep_select(cppi->mregs, rx->index + 1);
                csr = musb_readw(regs, MUSB_RXCSR);
                if (csr & MUSB_RXCSR_DMAENAB) {
-                       DBG(4, "list%d %p/%p, last %08x%s, csr %04x\n",
+                       DBG(4, "list%d %p/%p, last %llx%s, csr %04x\n",
                                rx->index,
                                rx->head, rx->tail,
                                rx->last_processed
-                                       ? rx->last_processed->dma
+                                       ? (unsigned long long)
+                                               rx->last_processed->dma
                                        : 0,
                                completed ? ", completed" : "",
                                csr);
@@ -1167,8 +1169,11 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id)
        tx = musb_readl(tibase, DAVINCI_TXCPPI_MASKED_REG);
        rx = musb_readl(tibase, DAVINCI_RXCPPI_MASKED_REG);
 
-       if (!tx && !rx)
+       if (!tx && !rx) {
+               if (cppi->irq)
+                       spin_unlock_irqrestore(&musb->lock, flags);
                return IRQ_NONE;
+       }
 
        DBG(4, "CPPI IRQ Tx%x Rx%x\n", tx, rx);
 
@@ -1199,7 +1204,7 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id)
                 */
                if (NULL == bd) {
                        DBG(1, "null BD\n");
-                       tx_ram->tx_complete = 0;
+                       musb_writel(&tx_ram->tx_complete, 0, 0);
                        continue;
                }
 
@@ -1452,7 +1457,7 @@ static int cppi_channel_abort(struct dma_channel *channel)
                 *    compare mode by writing 1 to the tx_complete register.
                 */
                cppi_reset_tx(tx_ram, 1);
-               cppi_ch->head = 0;
+               cppi_ch->head = NULL;
                musb_writel(&tx_ram->tx_complete, 0, 1);
                cppi_dump_tx(5, cppi_ch, " (done teardown)");
 
index 630ae7f3cd4cf1ff9288f38cbca245b504d38629..f10ff00ca09ea377bbd7dd6167e3723260bd78f9 100644 (file)
@@ -1030,6 +1030,7 @@ static void musb_shutdown(struct platform_device *pdev)
        struct musb     *musb = dev_to_musb(&pdev->dev);
        unsigned long   flags;
 
+       pm_runtime_get_sync(musb->controller);
        spin_lock_irqsave(&musb->lock, flags);
        musb_platform_disable(musb);
        musb_generic_disable(musb);
@@ -1040,6 +1041,7 @@ static void musb_shutdown(struct platform_device *pdev)
        musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
        musb_platform_exit(musb);
 
+       pm_runtime_put(musb->controller);
        /* FIXME power down */
 }
 
index 4bd9e2145ee416dec1cf516538b0597cf94fa08f..0e053b5879601fa93a77a8caede70773b1360f27 100644 (file)
@@ -261,6 +261,7 @@ enum musb_g_ep0_state {
  * @try_ilde:  tries to idle the IP
  * @vbus_status: returns vbus status if possible
  * @set_vbus:  forces vbus status
+ * @channel_program: pre check for standard dma channel_program func
  */
 struct musb_platform_ops {
        int     (*init)(struct musb *musb);
@@ -274,6 +275,10 @@ struct musb_platform_ops {
 
        int     (*vbus_status)(struct musb *musb);
        void    (*set_vbus)(struct musb *musb, int on);
+
+       int     (*adjust_channel_params)(struct dma_channel *channel,
+                               u16 packet_sz, u8 *mode,
+                               dma_addr_t *dma_addr, u32 *len);
 };
 
 /*
index 98519c5d8b5cc23e5407dac87a521004d8885f59..6dfbf9ffd7a63660ef472b6b3a932ecf22fd0341 100644 (file)
@@ -535,7 +535,7 @@ void musb_g_tx(struct musb *musb, u8 epnum)
                        is_dma = 1;
                        csr |= MUSB_TXCSR_P_WZC_BITS;
                        csr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_P_UNDERRUN |
-                                MUSB_TXCSR_TXPKTRDY);
+                                MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_AUTOSET);
                        musb_writew(epio, MUSB_TXCSR, csr);
                        /* Ensure writebuffer is empty. */
                        csr = musb_readw(epio, MUSB_TXCSR);
@@ -1296,7 +1296,7 @@ static int musb_gadget_dequeue(struct usb_ep *ep, struct usb_request *request)
        }
 
        /* if the hardware doesn't have the request, easy ... */
-       if (musb_ep->req_list.next != &request->list || musb_ep->busy)
+       if (musb_ep->req_list.next != &req->list || musb_ep->busy)
                musb_g_giveback(musb_ep, request, -ECONNRESET);
 
        /* ... else abort the dma transfer ... */
index 0144a2d481fd8daf8b8c3ab30102e57154096c5e..d281792db05c414cc0a6f2c30a62967dd8a458e9 100644 (file)
@@ -169,6 +169,14 @@ static int dma_channel_program(struct dma_channel *channel,
        BUG_ON(channel->status == MUSB_DMA_STATUS_UNKNOWN ||
                channel->status == MUSB_DMA_STATUS_BUSY);
 
+       /* Let targets check/tweak the arguments */
+       if (musb->ops->adjust_channel_params) {
+               int ret = musb->ops->adjust_channel_params(channel,
+                       packet_sz, &mode, &dma_addr, &len);
+               if (ret)
+                       return ret;
+       }
+
        /*
         * The DMA engine in RTL1.8 and above cannot handle
         * DMA addresses that are not aligned to a 4 byte boundary.
index 25cb8b0003b152c751087251a593c39e482c326e..57a27fa954b41fdd7b0fba880fd3c9da2b64b19c 100644 (file)
@@ -259,9 +259,10 @@ static int musb_otg_notifications(struct notifier_block *nb,
        case USB_EVENT_VBUS:
                DBG(4, "VBUS Connect\n");
 
+#ifdef CONFIG_USB_GADGET_MUSB_HDRC
                if (musb->gadget_driver)
                        pm_runtime_get_sync(musb->controller);
-
+#endif
                otg_init(musb->xceiv);
                break;
 
index d6384e4aeef96ba77448fa048cbc6560a4d2353d..f7e04bf34a13a86f7439b2033b255137f10d039b 100644 (file)
@@ -93,6 +93,8 @@ static int __init ux500_probe(struct platform_device *pdev)
        }
 
        musb->dev.parent                = &pdev->dev;
+       musb->dev.dma_mask              = pdev->dev.dma_mask;
+       musb->dev.coherent_dma_mask     = pdev->dev.coherent_dma_mask;
 
        glue->dev                       = &pdev->dev;
        glue->musb                      = musb;
index a973c7a29d6ef1458baf0c76044d5ecbd83bc134..4de6ef0ae52af2b541890a920641e1e792f8c3d7 100644 (file)
@@ -151,6 +151,8 @@ static struct ftdi_sio_quirk ftdi_stmclite_quirk = {
  * /sys/bus/usb/ftdi_sio/new_id, then send patch/report!
  */
 static struct usb_device_id id_table_combined [] = {
+       { USB_DEVICE(FTDI_VID, FTDI_CTI_MINI_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_CTI_NANO_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) },
@@ -525,6 +527,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(SEALEVEL_VID, SEALEVEL_2803_8_PID) },
        { USB_DEVICE(IDTECH_VID, IDTECH_IDT1221U_PID) },
        { USB_DEVICE(OCT_VID, OCT_US101_PID) },
+       { USB_DEVICE(OCT_VID, OCT_DK201_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_HE_TIRA1_PID),
                .driver_info = (kernel_ulong_t)&ftdi_HE_TIRA1_quirk },
        { USB_DEVICE(FTDI_VID, FTDI_USB_UIRT_PID),
@@ -787,6 +790,8 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) },
+       { USB_DEVICE(FTDI_VID, HAMEG_HO720_PID) },
+       { USB_DEVICE(FTDI_VID, HAMEG_HO730_PID) },
        { USB_DEVICE(FTDI_VID, HAMEG_HO870_PID) },
        { USB_DEVICE(FTDI_VID, MJSG_GENERIC_PID) },
        { USB_DEVICE(FTDI_VID, MJSG_SR_RADIO_PID) },
index c543e55bafbaff09fbc3c1d31b3726c58532486c..efffc23723bdf94aae454a025b9b419453f54b3f 100644 (file)
  * Hameg HO820 and HO870 interface (using VID 0x0403)
  */
 #define HAMEG_HO820_PID                        0xed74
+#define HAMEG_HO730_PID                        0xed73
+#define HAMEG_HO720_PID                        0xed72
 #define HAMEG_HO870_PID                        0xed71
 
 /*
 /* Note: OCT US101 is also rebadged as Dick Smith Electronics (NZ) XH6381 */
 /* Also rebadged as Dick Smith Electronics (Aus) XH6451 */
 /* Also rebadged as SIIG Inc. model US2308 hardware version 1 */
+#define OCT_DK201_PID          0x0103  /* OCT DK201 USB docking station */
 #define OCT_US101_PID          0x0421  /* OCT US101 USB to RS-232 */
 
 /*
 #define QIHARDWARE_VID                 0x20B7
 #define MILKYMISTONE_JTAGSERIAL_PID    0x0713
 
+/*
+ * CTI GmbH RS485 Converter http://www.cti-lean.com/
+ */
+/* USB-485-Mini*/
+#define FTDI_CTI_MINI_PID      0xF608
+/* USB-Nano-485*/
+#define FTDI_CTI_NANO_PID      0xF60B
+
+
index 75c7f456eed52880bb181e8dd3d53d5aca01a3c3..d77ff0435896bf098c39fda885d2370de685cc0c 100644 (file)
@@ -407,6 +407,10 @@ static void option_instat_callback(struct urb *urb);
 /* ONDA MT825UP HSDPA 14.2 modem */
 #define ONDA_MT825UP         0x000b
 
+/* Samsung products */
+#define SAMSUNG_VENDOR_ID                       0x04e8
+#define SAMSUNG_PRODUCT_GT_B3730                0x6889
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
                OPTION_BLACKLIST_NONE = 0,
@@ -968,6 +972,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
        { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
        { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
+       { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730/GT-B3710 LTE USB modem.*/
        { } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
index 8858201eb1d39cddb1150d2077f954226a4b833e..54a9dab1f33b4e4d335201d04572499ab701c424 100644 (file)
@@ -111,7 +111,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
        ifnum = intf->desc.bInterfaceNumber;
        dbg("This Interface = %d", ifnum);
 
-       data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private),
+       data = kzalloc(sizeof(struct usb_wwan_intf_private),
                                         GFP_KERNEL);
        if (!data)
                return -ENOMEM;
@@ -134,8 +134,10 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
                    usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) {
                        dbg("QDL port found");
 
-                       if (serial->interface->num_altsetting == 1)
-                               return 0;
+                       if (serial->interface->num_altsetting == 1) {
+                               retval = 0; /* Success */
+                               break;
+                       }
 
                        retval = usb_set_interface(serial->dev, ifnum, 1);
                        if (retval < 0) {
@@ -145,7 +147,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
                                retval = -ENODEV;
                                kfree(data);
                        }
-                       return retval;
                }
                break;
 
@@ -166,6 +167,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
                                        "Could not set interface, error %d\n",
                                        retval);
                                retval = -ENODEV;
+                               kfree(data);
                        }
                } else if (ifnum == 2) {
                        dbg("Modem port found");
@@ -177,7 +179,6 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
                                retval = -ENODEV;
                                kfree(data);
                        }
-                       return retval;
                } else if (ifnum==3) {
                        /*
                         * NMEA (serial line 9600 8N1)
@@ -191,6 +192,7 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
                                        "Could not set interface, error %d\n",
                                        retval);
                                retval = -ENODEV;
+                               kfree(data);
                        }
                }
                break;
@@ -199,12 +201,27 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
                dev_err(&serial->dev->dev,
                        "unknown number of interfaces: %d\n", nintf);
                kfree(data);
-               return -ENODEV;
+               retval = -ENODEV;
        }
 
+       /* Set serial->private if not returning -ENODEV */
+       if (retval != -ENODEV)
+               usb_set_serial_data(serial, data);
        return retval;
 }
 
+static void qc_release(struct usb_serial *serial)
+{
+       struct usb_wwan_intf_private *priv = usb_get_serial_data(serial);
+
+       dbg("%s", __func__);
+
+       /* Call usb_wwan release & free the private data allocated in qcprobe */
+       usb_wwan_release(serial);
+       usb_set_serial_data(serial, NULL);
+       kfree(priv);
+}
+
 static struct usb_serial_driver qcdevice = {
        .driver = {
                .owner     = THIS_MODULE,
@@ -222,7 +239,7 @@ static struct usb_serial_driver qcdevice = {
        .chars_in_buffer     = usb_wwan_chars_in_buffer,
        .attach              = usb_wwan_startup,
        .disconnect          = usb_wwan_disconnect,
-       .release             = usb_wwan_release,
+       .release             = qc_release,
 #ifdef CONFIG_PM
        .suspend             = usb_wwan_suspend,
        .resume              = usb_wwan_resume,
index a2e5b5100ab4edd8a8756905a0fbeefdd4091c4f..0f4e8c942f9e082e7410de7983ac28f81576c5f3 100644 (file)
@@ -1648,7 +1648,9 @@ pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data)
 
        switch (val) {
        case CPUFREQ_PRECHANGE:
-               if (!fbi->overlay[0].usage && !fbi->overlay[1].usage)
+#ifdef CONFIG_FB_PXA_OVERLAY
+               if (!(fbi->overlay[0].usage || fbi->overlay[1].usage))
+#endif
                        set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
                break;
 
index 42d6c930cc87c3dab4ec512c6948ceb4a913e43f..33167b43ac7e4ad9ae981b53ad6ee9069d453296 100644 (file)
@@ -912,8 +912,7 @@ int bind_evtchn_to_irqhandler(unsigned int evtchn,
                              unsigned long irqflags,
                              const char *devname, void *dev_id)
 {
-       unsigned int irq;
-       int retval;
+       int irq, retval;
 
        irq = bind_evtchn_to_irq(evtchn);
        if (irq < 0)
@@ -955,8 +954,7 @@ int bind_virq_to_irqhandler(unsigned int virq, unsigned int cpu,
                            irq_handler_t handler,
                            unsigned long irqflags, const char *devname, void *dev_id)
 {
-       unsigned int irq;
-       int retval;
+       int irq, retval;
 
        irq = bind_virq_to_irq(virq, cpu);
        if (irq < 0)
index 95143dd6904daf459286079e769532f666014603..1ac94125bf93c38bb98342828490e9633a12c75f 100644 (file)
@@ -61,7 +61,7 @@ static void xen_post_suspend(int cancelled)
        xen_mm_unpin_all();
 }
 
-#ifdef CONFIG_HIBERNATION
+#ifdef CONFIG_HIBERNATE_CALLBACKS
 static int xen_suspend(void *data)
 {
        struct suspend_info *si = data;
@@ -173,7 +173,7 @@ out:
 #endif
        shutting_down = SHUTDOWN_INVALID;
 }
-#endif /* CONFIG_HIBERNATION */
+#endif /* CONFIG_HIBERNATE_CALLBACKS */
 
 struct shutdown_handler {
        const char *command;
@@ -202,7 +202,7 @@ static void shutdown_handler(struct xenbus_watch *watch,
                { "poweroff",   do_poweroff },
                { "halt",       do_poweroff },
                { "reboot",     do_reboot   },
-#ifdef CONFIG_HIBERNATION
+#ifdef CONFIG_HIBERNATE_CALLBACKS
                { "suspend",    do_suspend  },
 #endif
                {NULL, NULL},
index 0ee594569dcceb60f4ff795f48fe83c87003fd47..85b67ffa2a43eb184250b1a167eae215deaa0399 100644 (file)
@@ -286,11 +286,9 @@ static struct p9_fid *v9fs_fid_clone_with_uid(struct dentry *dentry, uid_t uid)
 
 struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
 {
-       int err, flags;
+       int err;
        struct p9_fid *fid;
-       struct v9fs_session_info *v9ses;
 
-       v9ses = v9fs_dentry2v9ses(dentry);
        fid = v9fs_fid_clone_with_uid(dentry, 0);
        if (IS_ERR(fid))
                goto error_out;
@@ -299,17 +297,8 @@ struct p9_fid *v9fs_writeback_fid(struct dentry *dentry)
         * dirty pages. We always request for the open fid in read-write
         * mode so that a partial page write which result in page
         * read can work.
-        *
-        * we don't have a tsyncfs operation for older version
-        * of protocol. So make sure the write back fid is
-        * opened in O_SYNC mode.
         */
-       if (!v9fs_proto_dotl(v9ses))
-               flags = O_RDWR | O_SYNC;
-       else
-               flags = O_RDWR;
-
-       err = p9_client_open(fid, flags);
+       err = p9_client_open(fid, O_RDWR);
        if (err < 0) {
                p9_client_clunk(fid);
                fid = ERR_PTR(err);
index 9665c2b840e6442a11b550f59da6ddf0ed73f256..e5ebedfc5ed8d345e366cd1482978a2ff2f2e4ae 100644 (file)
@@ -116,7 +116,6 @@ struct v9fs_session_info {
        struct list_head slist; /* list of sessions registered with v9fs */
        struct backing_dev_info bdi;
        struct rw_semaphore rename_sem;
-       struct p9_fid *root_fid; /* Used for file system sync */
 };
 
 /* cache_validity flags */
index b6a3b9f7fe4d85c428ce6ccacf3d84826075d24c..e022890c6f403283b4da166b7c56e4a27e14b975 100644 (file)
@@ -126,7 +126,9 @@ static int v9fs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
                        retval = v9fs_refresh_inode_dotl(fid, inode);
                else
                        retval = v9fs_refresh_inode(fid, inode);
-               if (retval <= 0)
+               if (retval == -ENOENT)
+                       return 0;
+               if (retval < 0)
                        return retval;
        }
 out_valid:
index ffbb113d5f33537892fd001dd0d75af9e6d1fd69..82a7c38ddad0dec0c9ecded6fcc4d3eb93a50350 100644 (file)
@@ -811,7 +811,7 @@ v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd)
        fid = v9fs_fid_lookup(dentry);
        if (IS_ERR(fid)) {
                __putname(link);
-               link = ERR_PTR(PTR_ERR(fid));
+               link = ERR_CAST(fid);
                goto ndset;
        }
        retval = p9_client_readlink(fid, &target);
index f3eed3383e4fdeb87dddc890ad732925f0245319..feef6cdc1fd22d23ba45a8f98f2f21ec0a0dc95a 100644 (file)
@@ -154,6 +154,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
                retval = PTR_ERR(inode);
                goto release_sb;
        }
+
        root = d_alloc_root(inode);
        if (!root) {
                iput(inode);
@@ -185,21 +186,10 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
                p9stat_free(st);
                kfree(st);
        }
-       v9fs_fid_add(root, fid);
        retval = v9fs_get_acl(inode, fid);
        if (retval)
                goto release_sb;
-       /*
-        * Add the root fid to session info. This is used
-        * for file system sync. We want a cloned fid here
-        * so that we can do a sync_filesystem after a
-        * shrink_dcache_for_umount
-        */
-       v9ses->root_fid = v9fs_fid_clone(root);
-       if (IS_ERR(v9ses->root_fid)) {
-               retval = PTR_ERR(v9ses->root_fid);
-               goto release_sb;
-       }
+       v9fs_fid_add(root, fid);
 
        P9_DPRINTK(P9_DEBUG_VFS, " simple set mount, return 0\n");
        return dget(sb->s_root);
@@ -210,11 +200,15 @@ close_session:
        v9fs_session_close(v9ses);
        kfree(v9ses);
        return ERR_PTR(retval);
+
 release_sb:
        /*
-        * we will do the session_close and root dentry
-        * release in the below call.
+        * we will do the session_close and root dentry release
+        * in the below call. But we need to clunk fid, because we haven't
+        * attached the fid to dentry so it won't get clunked
+        * automatically.
         */
+       p9_client_clunk(fid);
        deactivate_locked_super(sb);
        return ERR_PTR(retval);
 }
@@ -232,7 +226,7 @@ static void v9fs_kill_super(struct super_block *s)
        P9_DPRINTK(P9_DEBUG_VFS, " %p\n", s);
 
        kill_anon_super(s);
-       p9_client_clunk(v9ses->root_fid);
+
        v9fs_session_cancel(v9ses);
        v9fs_session_close(v9ses);
        kfree(v9ses);
@@ -285,14 +279,6 @@ done:
        return res;
 }
 
-static int v9fs_sync_fs(struct super_block *sb, int wait)
-{
-       struct v9fs_session_info *v9ses = sb->s_fs_info;
-
-       P9_DPRINTK(P9_DEBUG_VFS, "v9fs_sync_fs: super_block %p\n", sb);
-       return p9_client_sync_fs(v9ses->root_fid);
-}
-
 static int v9fs_drop_inode(struct inode *inode)
 {
        struct v9fs_session_info *v9ses;
@@ -307,6 +293,51 @@ static int v9fs_drop_inode(struct inode *inode)
        return 1;
 }
 
+static int v9fs_write_inode(struct inode *inode,
+                           struct writeback_control *wbc)
+{
+       int ret;
+       struct p9_wstat wstat;
+       struct v9fs_inode *v9inode;
+       /*
+        * send an fsync request to server irrespective of
+        * wbc->sync_mode.
+        */
+       P9_DPRINTK(P9_DEBUG_VFS, "%s: inode %p\n", __func__, inode);
+       v9inode = V9FS_I(inode);
+       if (!v9inode->writeback_fid)
+               return 0;
+       v9fs_blank_wstat(&wstat);
+
+       ret = p9_client_wstat(v9inode->writeback_fid, &wstat);
+       if (ret < 0) {
+               __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
+               return ret;
+       }
+       return 0;
+}
+
+static int v9fs_write_inode_dotl(struct inode *inode,
+                                struct writeback_control *wbc)
+{
+       int ret;
+       struct v9fs_inode *v9inode;
+       /*
+        * send an fsync request to server irrespective of
+        * wbc->sync_mode.
+        */
+       P9_DPRINTK(P9_DEBUG_VFS, "%s: inode %p\n", __func__, inode);
+       v9inode = V9FS_I(inode);
+       if (!v9inode->writeback_fid)
+               return 0;
+       ret = p9_client_fsync(v9inode->writeback_fid, 0);
+       if (ret < 0) {
+               __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
+               return ret;
+       }
+       return 0;
+}
+
 static const struct super_operations v9fs_super_ops = {
        .alloc_inode = v9fs_alloc_inode,
        .destroy_inode = v9fs_destroy_inode,
@@ -314,17 +345,18 @@ static const struct super_operations v9fs_super_ops = {
        .evict_inode = v9fs_evict_inode,
        .show_options = generic_show_options,
        .umount_begin = v9fs_umount_begin,
+       .write_inode = v9fs_write_inode,
 };
 
 static const struct super_operations v9fs_super_ops_dotl = {
        .alloc_inode = v9fs_alloc_inode,
        .destroy_inode = v9fs_destroy_inode,
-       .sync_fs = v9fs_sync_fs,
        .statfs = v9fs_statfs,
        .drop_inode = v9fs_drop_inode,
        .evict_inode = v9fs_evict_inode,
        .show_options = generic_show_options,
        .umount_begin = v9fs_umount_begin,
+       .write_inode = v9fs_write_inode_dotl,
 };
 
 struct file_system_type v9fs_fs_type = {
index f34078d702d3bdbe1ee69bc1122b63d3facf5009..303983fabfd63391f3961a58be352303b7af0064 100644 (file)
@@ -941,9 +941,13 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
        current->mm->start_stack = bprm->p;
 
 #ifdef arch_randomize_brk
-       if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1))
+       if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) {
                current->mm->brk = current->mm->start_brk =
                        arch_randomize_brk(current->mm);
+#ifdef CONFIG_COMPAT_BRK
+               current->brk_randomized = 1;
+#endif
+       }
 #endif
 
        if (current->personality & MMAP_PAGE_ZERO) {
index de34bfad9ec3cab33f35ead4f31d9605f48af66c..5d505aaa72fb8326eb451687590b336c2e04052a 100644 (file)
@@ -178,16 +178,17 @@ static int btrfs_xattr_acl_set(struct dentry *dentry, const char *name,
 
        if (value) {
                acl = posix_acl_from_xattr(value, size);
-               if (acl == NULL) {
-                       value = NULL;
-                       size = 0;
+               if (acl) {
+                       ret = posix_acl_valid(acl);
+                       if (ret)
+                               goto out;
                } else if (IS_ERR(acl)) {
                        return PTR_ERR(acl);
                }
        }
 
        ret = btrfs_set_acl(NULL, dentry->d_inode, acl, type);
-
+out:
        posix_acl_release(acl);
 
        return ret;
index 3458b5725540c511103421bf8f1749833c2998f7..2e61fe1b6b8cc76111f62c3f4b4aded03f7a0cce 100644 (file)
@@ -740,8 +740,10 @@ struct btrfs_space_info {
         */
        unsigned long reservation_progress;
 
-       int full;               /* indicates that we cannot allocate any more
+       int full:1;             /* indicates that we cannot allocate any more
                                   chunks for this space */
+       int chunk_alloc:1;      /* set if we are allocating a chunk */
+
        int force_alloc;        /* set if we need to force a chunk alloc for
                                   this space */
 
@@ -2576,6 +2578,11 @@ int btrfs_drop_extents(struct btrfs_trans_handle *trans, struct inode *inode,
 int btrfs_mark_extent_written(struct btrfs_trans_handle *trans,
                              struct inode *inode, u64 start, u64 end);
 int btrfs_release_file(struct inode *inode, struct file *file);
+void btrfs_drop_pages(struct page **pages, size_t num_pages);
+int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode,
+                     struct page **pages, size_t num_pages,
+                     loff_t pos, size_t write_bytes,
+                     struct extent_state **cached);
 
 /* tree-defrag.c */
 int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
index 8f1d44ba332f487aa42e3291daa63e45b04d44e0..68c84c8c24bdd3f77762b230ccb7efd614e3cab5 100644 (file)
@@ -3057,7 +3057,7 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)
                btrfs_destroy_pinned_extent(root,
                                            root->fs_info->pinned_extents);
 
-               t->use_count = 0;
+               atomic_set(&t->use_count, 0);
                list_del_init(&t->list);
                memset(t, 0, sizeof(*t));
                kmem_cache_free(btrfs_transaction_cachep, t);
index f619c3cb13b7006cc7f95e273996917bbcebcf67..31f33ba56fe823d40ecf308f32eb777315548376 100644 (file)
 #include "locking.h"
 #include "free-space-cache.h"
 
+/* control flags for do_chunk_alloc's force field
+ * CHUNK_ALLOC_NO_FORCE means to only allocate a chunk
+ * if we really need one.
+ *
+ * CHUNK_ALLOC_FORCE means it must try to allocate one
+ *
+ * CHUNK_ALLOC_LIMITED means to only try and allocate one
+ * if we have very few chunks already allocated.  This is
+ * used as part of the clustering code to help make sure
+ * we have a good pool of storage to cluster in, without
+ * filling the FS with empty chunks
+ *
+ */
+enum {
+       CHUNK_ALLOC_NO_FORCE = 0,
+       CHUNK_ALLOC_FORCE = 1,
+       CHUNK_ALLOC_LIMITED = 2,
+};
+
 static int update_block_group(struct btrfs_trans_handle *trans,
                              struct btrfs_root *root,
                              u64 bytenr, u64 num_bytes, int alloc);
@@ -3019,7 +3038,8 @@ static int update_space_info(struct btrfs_fs_info *info, u64 flags,
        found->bytes_readonly = 0;
        found->bytes_may_use = 0;
        found->full = 0;
-       found->force_alloc = 0;
+       found->force_alloc = CHUNK_ALLOC_NO_FORCE;
+       found->chunk_alloc = 0;
        *space_info = found;
        list_add_rcu(&found->list, &info->space_info);
        atomic_set(&found->caching_threads, 0);
@@ -3150,7 +3170,7 @@ again:
                if (!data_sinfo->full && alloc_chunk) {
                        u64 alloc_target;
 
-                       data_sinfo->force_alloc = 1;
+                       data_sinfo->force_alloc = CHUNK_ALLOC_FORCE;
                        spin_unlock(&data_sinfo->lock);
 alloc:
                        alloc_target = btrfs_get_alloc_profile(root, 1);
@@ -3160,7 +3180,8 @@ alloc:
 
                        ret = do_chunk_alloc(trans, root->fs_info->extent_root,
                                             bytes + 2 * 1024 * 1024,
-                                            alloc_target, 0);
+                                            alloc_target,
+                                            CHUNK_ALLOC_NO_FORCE);
                        btrfs_end_transaction(trans, root);
                        if (ret < 0) {
                                if (ret != -ENOSPC)
@@ -3239,31 +3260,56 @@ static void force_metadata_allocation(struct btrfs_fs_info *info)
        rcu_read_lock();
        list_for_each_entry_rcu(found, head, list) {
                if (found->flags & BTRFS_BLOCK_GROUP_METADATA)
-                       found->force_alloc = 1;
+                       found->force_alloc = CHUNK_ALLOC_FORCE;
        }
        rcu_read_unlock();
 }
 
 static int should_alloc_chunk(struct btrfs_root *root,
-                             struct btrfs_space_info *sinfo, u64 alloc_bytes)
+                             struct btrfs_space_info *sinfo, u64 alloc_bytes,
+                             int force)
 {
        u64 num_bytes = sinfo->total_bytes - sinfo->bytes_readonly;
+       u64 num_allocated = sinfo->bytes_used + sinfo->bytes_reserved;
        u64 thresh;
 
-       if (sinfo->bytes_used + sinfo->bytes_reserved +
-           alloc_bytes + 256 * 1024 * 1024 < num_bytes)
+       if (force == CHUNK_ALLOC_FORCE)
+               return 1;
+
+       /*
+        * in limited mode, we want to have some free space up to
+        * about 1% of the FS size.
+        */
+       if (force == CHUNK_ALLOC_LIMITED) {
+               thresh = btrfs_super_total_bytes(&root->fs_info->super_copy);
+               thresh = max_t(u64, 64 * 1024 * 1024,
+                              div_factor_fine(thresh, 1));
+
+               if (num_bytes - num_allocated < thresh)
+                       return 1;
+       }
+
+       /*
+        * we have two similar checks here, one based on percentage
+        * and once based on a hard number of 256MB.  The idea
+        * is that if we have a good amount of free
+        * room, don't allocate a chunk.  A good mount is
+        * less than 80% utilized of the chunks we have allocated,
+        * or more than 256MB free
+        */
+       if (num_allocated + alloc_bytes + 256 * 1024 * 1024 < num_bytes)
                return 0;
 
-       if (sinfo->bytes_used + sinfo->bytes_reserved +
-           alloc_bytes < div_factor(num_bytes, 8))
+       if (num_allocated + alloc_bytes < div_factor(num_bytes, 8))
                return 0;
 
        thresh = btrfs_super_total_bytes(&root->fs_info->super_copy);
+
+       /* 256MB or 5% of the FS */
        thresh = max_t(u64, 256 * 1024 * 1024, div_factor_fine(thresh, 5));
 
        if (num_bytes > thresh && sinfo->bytes_used < div_factor(num_bytes, 3))
                return 0;
-
        return 1;
 }
 
@@ -3273,10 +3319,9 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
 {
        struct btrfs_space_info *space_info;
        struct btrfs_fs_info *fs_info = extent_root->fs_info;
+       int wait_for_alloc = 0;
        int ret = 0;
 
-       mutex_lock(&fs_info->chunk_mutex);
-
        flags = btrfs_reduce_alloc_profile(extent_root, flags);
 
        space_info = __find_space_info(extent_root->fs_info, flags);
@@ -3287,21 +3332,40 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
        }
        BUG_ON(!space_info);
 
+again:
        spin_lock(&space_info->lock);
        if (space_info->force_alloc)
-               force = 1;
+               force = space_info->force_alloc;
        if (space_info->full) {
                spin_unlock(&space_info->lock);
-               goto out;
+               return 0;
        }
 
-       if (!force && !should_alloc_chunk(extent_root, space_info,
-                                         alloc_bytes)) {
+       if (!should_alloc_chunk(extent_root, space_info, alloc_bytes, force)) {
                spin_unlock(&space_info->lock);
-               goto out;
+               return 0;
+       } else if (space_info->chunk_alloc) {
+               wait_for_alloc = 1;
+       } else {
+               space_info->chunk_alloc = 1;
        }
+
        spin_unlock(&space_info->lock);
 
+       mutex_lock(&fs_info->chunk_mutex);
+
+       /*
+        * The chunk_mutex is held throughout the entirety of a chunk
+        * allocation, so once we've acquired the chunk_mutex we know that the
+        * other guy is done and we need to recheck and see if we should
+        * allocate.
+        */
+       if (wait_for_alloc) {
+               mutex_unlock(&fs_info->chunk_mutex);
+               wait_for_alloc = 0;
+               goto again;
+       }
+
        /*
         * If we have mixed data/metadata chunks we want to make sure we keep
         * allocating mixed chunks instead of individual chunks.
@@ -3327,9 +3391,10 @@ static int do_chunk_alloc(struct btrfs_trans_handle *trans,
                space_info->full = 1;
        else
                ret = 1;
-       space_info->force_alloc = 0;
+
+       space_info->force_alloc = CHUNK_ALLOC_NO_FORCE;
+       space_info->chunk_alloc = 0;
        spin_unlock(&space_info->lock);
-out:
        mutex_unlock(&extent_root->fs_info->chunk_mutex);
        return ret;
 }
@@ -5303,11 +5368,13 @@ loop:
 
                if (allowed_chunk_alloc) {
                        ret = do_chunk_alloc(trans, root, num_bytes +
-                                            2 * 1024 * 1024, data, 1);
+                                            2 * 1024 * 1024, data,
+                                            CHUNK_ALLOC_LIMITED);
                        allowed_chunk_alloc = 0;
                        done_chunk_alloc = 1;
-               } else if (!done_chunk_alloc) {
-                       space_info->force_alloc = 1;
+               } else if (!done_chunk_alloc &&
+                          space_info->force_alloc == CHUNK_ALLOC_NO_FORCE) {
+                       space_info->force_alloc = CHUNK_ALLOC_LIMITED;
                }
 
                if (loop < LOOP_NO_EMPTY_SIZE) {
@@ -5393,7 +5460,8 @@ again:
         */
        if (empty_size || root->ref_cows)
                ret = do_chunk_alloc(trans, root->fs_info->extent_root,
-                                    num_bytes + 2 * 1024 * 1024, data, 0);
+                                    num_bytes + 2 * 1024 * 1024, data,
+                                    CHUNK_ALLOC_NO_FORCE);
 
        WARN_ON(num_bytes < root->sectorsize);
        ret = find_free_extent(trans, root, num_bytes, empty_size,
@@ -5405,7 +5473,7 @@ again:
                num_bytes = num_bytes & ~(root->sectorsize - 1);
                num_bytes = max(num_bytes, min_alloc_size);
                do_chunk_alloc(trans, root->fs_info->extent_root,
-                              num_bytes, data, 1);
+                              num_bytes, data, CHUNK_ALLOC_FORCE);
                goto again;
        }
        if (ret == -ENOSPC && btrfs_test_opt(root, ENOSPC_DEBUG)) {
@@ -8109,13 +8177,15 @@ int btrfs_set_block_group_ro(struct btrfs_root *root,
 
        alloc_flags = update_block_group_flags(root, cache->flags);
        if (alloc_flags != cache->flags)
-               do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, 1);
+               do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags,
+                              CHUNK_ALLOC_FORCE);
 
        ret = set_block_group_ro(cache);
        if (!ret)
                goto out;
        alloc_flags = get_alloc_profile(root, cache->space_info->flags);
-       ret = do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, 1);
+       ret = do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags,
+                            CHUNK_ALLOC_FORCE);
        if (ret < 0)
                goto out;
        ret = set_block_group_ro(cache);
@@ -8128,7 +8198,8 @@ int btrfs_force_chunk_alloc(struct btrfs_trans_handle *trans,
                            struct btrfs_root *root, u64 type)
 {
        u64 alloc_flags = get_alloc_profile(root, type);
-       return do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags, 1);
+       return do_chunk_alloc(trans, root, 2 * 1024 * 1024, alloc_flags,
+                             CHUNK_ALLOC_FORCE);
 }
 
 /*
index 20ddb28602a8fa0c0eb4c082966741f2f7fd15c8..31513860508829b352ae7679003c7832777196e8 100644 (file)
@@ -690,6 +690,15 @@ static void cache_state(struct extent_state *state,
        }
 }
 
+static void uncache_state(struct extent_state **cached_ptr)
+{
+       if (cached_ptr && (*cached_ptr)) {
+               struct extent_state *state = *cached_ptr;
+               *cached_ptr = NULL;
+               free_extent_state(state);
+       }
+}
+
 /*
  * set some bits on a range in the tree.  This may require allocations or
  * sleeping, so the gfp mask is used to indicate what is allowed.
@@ -940,10 +949,10 @@ static int clear_extent_new(struct extent_io_tree *tree, u64 start, u64 end,
 }
 
 int set_extent_uptodate(struct extent_io_tree *tree, u64 start, u64 end,
-                       gfp_t mask)
+                       struct extent_state **cached_state, gfp_t mask)
 {
-       return set_extent_bit(tree, start, end, EXTENT_UPTODATE, 0, NULL,
-                             NULL, mask);
+       return set_extent_bit(tree, start, end, EXTENT_UPTODATE, 0,
+                             NULL, cached_state, mask);
 }
 
 static int clear_extent_uptodate(struct extent_io_tree *tree, u64 start,
@@ -1012,8 +1021,7 @@ int unlock_extent_cached(struct extent_io_tree *tree, u64 start, u64 end,
                                mask);
 }
 
-int unlock_extent(struct extent_io_tree *tree, u64 start, u64 end,
-                 gfp_t mask)
+int unlock_extent(struct extent_io_tree *tree, u64 start, u64 end, gfp_t mask)
 {
        return clear_extent_bit(tree, start, end, EXTENT_LOCKED, 1, 0, NULL,
                                mask);
@@ -1735,6 +1743,9 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
 
        do {
                struct page *page = bvec->bv_page;
+               struct extent_state *cached = NULL;
+               struct extent_state *state;
+
                tree = &BTRFS_I(page->mapping->host)->io_tree;
 
                start = ((u64)page->index << PAGE_CACHE_SHIFT) +
@@ -1749,9 +1760,20 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                if (++bvec <= bvec_end)
                        prefetchw(&bvec->bv_page->flags);
 
+               spin_lock(&tree->lock);
+               state = find_first_extent_bit_state(tree, start, EXTENT_LOCKED);
+               if (state && state->start == start) {
+                       /*
+                        * take a reference on the state, unlock will drop
+                        * the ref
+                        */
+                       cache_state(state, &cached);
+               }
+               spin_unlock(&tree->lock);
+
                if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) {
                        ret = tree->ops->readpage_end_io_hook(page, start, end,
-                                                             NULL);
+                                                             state);
                        if (ret)
                                uptodate = 0;
                }
@@ -1764,15 +1786,16 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                                        test_bit(BIO_UPTODATE, &bio->bi_flags);
                                if (err)
                                        uptodate = 0;
+                               uncache_state(&cached);
                                continue;
                        }
                }
 
                if (uptodate) {
-                       set_extent_uptodate(tree, start, end,
+                       set_extent_uptodate(tree, start, end, &cached,
                                            GFP_ATOMIC);
                }
-               unlock_extent(tree, start, end, GFP_ATOMIC);
+               unlock_extent_cached(tree, start, end, &cached, GFP_ATOMIC);
 
                if (whole_page) {
                        if (uptodate) {
@@ -1811,6 +1834,7 @@ static void end_bio_extent_preparewrite(struct bio *bio, int err)
 
        do {
                struct page *page = bvec->bv_page;
+               struct extent_state *cached = NULL;
                tree = &BTRFS_I(page->mapping->host)->io_tree;
 
                start = ((u64)page->index << PAGE_CACHE_SHIFT) +
@@ -1821,13 +1845,14 @@ static void end_bio_extent_preparewrite(struct bio *bio, int err)
                        prefetchw(&bvec->bv_page->flags);
 
                if (uptodate) {
-                       set_extent_uptodate(tree, start, end, GFP_ATOMIC);
+                       set_extent_uptodate(tree, start, end, &cached,
+                                           GFP_ATOMIC);
                } else {
                        ClearPageUptodate(page);
                        SetPageError(page);
                }
 
-               unlock_extent(tree, start, end, GFP_ATOMIC);
+               unlock_extent_cached(tree, start, end, &cached, GFP_ATOMIC);
 
        } while (bvec >= bio->bi_io_vec);
 
@@ -2016,14 +2041,17 @@ static int __extent_read_full_page(struct extent_io_tree *tree,
        while (cur <= end) {
                if (cur >= last_byte) {
                        char *userpage;
+                       struct extent_state *cached = NULL;
+
                        iosize = PAGE_CACHE_SIZE - page_offset;
                        userpage = kmap_atomic(page, KM_USER0);
                        memset(userpage + page_offset, 0, iosize);
                        flush_dcache_page(page);
                        kunmap_atomic(userpage, KM_USER0);
                        set_extent_uptodate(tree, cur, cur + iosize - 1,
-                                           GFP_NOFS);
-                       unlock_extent(tree, cur, cur + iosize - 1, GFP_NOFS);
+                                           &cached, GFP_NOFS);
+                       unlock_extent_cached(tree, cur, cur + iosize - 1,
+                                            &cached, GFP_NOFS);
                        break;
                }
                em = get_extent(inode, page, page_offset, cur,
@@ -2063,14 +2091,17 @@ static int __extent_read_full_page(struct extent_io_tree *tree,
                /* we've found a hole, just zero and go on */
                if (block_start == EXTENT_MAP_HOLE) {
                        char *userpage;
+                       struct extent_state *cached = NULL;
+
                        userpage = kmap_atomic(page, KM_USER0);
                        memset(userpage + page_offset, 0, iosize);
                        flush_dcache_page(page);
                        kunmap_atomic(userpage, KM_USER0);
 
                        set_extent_uptodate(tree, cur, cur + iosize - 1,
-                                           GFP_NOFS);
-                       unlock_extent(tree, cur, cur + iosize - 1, GFP_NOFS);
+                                           &cached, GFP_NOFS);
+                       unlock_extent_cached(tree, cur, cur + iosize - 1,
+                                            &cached, GFP_NOFS);
                        cur = cur + iosize;
                        page_offset += iosize;
                        continue;
@@ -2789,9 +2820,12 @@ int extent_prepare_write(struct extent_io_tree *tree,
                        iocount++;
                        block_start = block_start + iosize;
                } else {
-                       set_extent_uptodate(tree, block_start, cur_end,
+                       struct extent_state *cached = NULL;
+
+                       set_extent_uptodate(tree, block_start, cur_end, &cached,
                                            GFP_NOFS);
-                       unlock_extent(tree, block_start, cur_end, GFP_NOFS);
+                       unlock_extent_cached(tree, block_start, cur_end,
+                                            &cached, GFP_NOFS);
                        block_start = cur_end + 1;
                }
                page_offset = block_start & (PAGE_CACHE_SIZE - 1);
@@ -3457,7 +3491,7 @@ int set_extent_buffer_uptodate(struct extent_io_tree *tree,
        num_pages = num_extent_pages(eb->start, eb->len);
 
        set_extent_uptodate(tree, eb->start, eb->start + eb->len - 1,
-                           GFP_NOFS);
+                           NULL, GFP_NOFS);
        for (i = 0; i < num_pages; i++) {
                page = extent_buffer_page(eb, i);
                if ((i == 0 && (eb->start & (PAGE_CACHE_SIZE - 1))) ||
@@ -3885,6 +3919,12 @@ static void move_pages(struct page *dst_page, struct page *src_page,
        kunmap_atomic(dst_kaddr, KM_USER0);
 }
 
+static inline bool areas_overlap(unsigned long src, unsigned long dst, unsigned long len)
+{
+       unsigned long distance = (src > dst) ? src - dst : dst - src;
+       return distance < len;
+}
+
 static void copy_pages(struct page *dst_page, struct page *src_page,
                       unsigned long dst_off, unsigned long src_off,
                       unsigned long len)
@@ -3892,10 +3932,12 @@ static void copy_pages(struct page *dst_page, struct page *src_page,
        char *dst_kaddr = kmap_atomic(dst_page, KM_USER0);
        char *src_kaddr;
 
-       if (dst_page != src_page)
+       if (dst_page != src_page) {
                src_kaddr = kmap_atomic(src_page, KM_USER1);
-       else
+       } else {
                src_kaddr = dst_kaddr;
+               BUG_ON(areas_overlap(src_off, dst_off, len));
+       }
 
        memcpy(dst_kaddr + dst_off, src_kaddr + src_off, len);
        kunmap_atomic(dst_kaddr, KM_USER0);
@@ -3970,7 +4012,7 @@ void memmove_extent_buffer(struct extent_buffer *dst, unsigned long dst_offset,
                       "len %lu len %lu\n", dst_offset, len, dst->len);
                BUG_ON(1);
        }
-       if (dst_offset < src_offset) {
+       if (!areas_overlap(src_offset, dst_offset, len)) {
                memcpy_extent_buffer(dst, dst_offset, src_offset, len);
                return;
        }
index f62c5442835d1ab70da88d510ef6e073d050c794..af2d7179c37288f50371bfd2ffa5dd307b16af00 100644 (file)
@@ -208,7 +208,7 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end,
                   int bits, int exclusive_bits, u64 *failed_start,
                   struct extent_state **cached_state, gfp_t mask);
 int set_extent_uptodate(struct extent_io_tree *tree, u64 start, u64 end,
-                       gfp_t mask);
+                       struct extent_state **cached_state, gfp_t mask);
 int set_extent_new(struct extent_io_tree *tree, u64 start, u64 end,
                   gfp_t mask);
 int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end,
index e621ea54a3fd64bcf3dae29e4f96e887b6eff95c..75899a01dded75042b4c99f15a44cc83882730a4 100644 (file)
@@ -104,7 +104,7 @@ static noinline int btrfs_copy_from_user(loff_t pos, int num_pages,
 /*
  * unlocks pages after btrfs_file_write is done with them
  */
-static noinline void btrfs_drop_pages(struct page **pages, size_t num_pages)
+void btrfs_drop_pages(struct page **pages, size_t num_pages)
 {
        size_t i;
        for (i = 0; i < num_pages; i++) {
@@ -127,16 +127,13 @@ static noinline void btrfs_drop_pages(struct page **pages, size_t num_pages)
  * this also makes the decision about creating an inline extent vs
  * doing real data extents, marking pages dirty and delalloc as required.
  */
-static noinline int dirty_and_release_pages(struct btrfs_root *root,
-                                           struct file *file,
-                                           struct page **pages,
-                                           size_t num_pages,
-                                           loff_t pos,
-                                           size_t write_bytes)
+int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode,
+                     struct page **pages, size_t num_pages,
+                     loff_t pos, size_t write_bytes,
+                     struct extent_state **cached)
 {
        int err = 0;
        int i;
-       struct inode *inode = fdentry(file)->d_inode;
        u64 num_bytes;
        u64 start_pos;
        u64 end_of_last_block;
@@ -149,7 +146,7 @@ static noinline int dirty_and_release_pages(struct btrfs_root *root,
 
        end_of_last_block = start_pos + num_bytes - 1;
        err = btrfs_set_extent_delalloc(inode, start_pos, end_of_last_block,
-                                       NULL);
+                                       cached);
        if (err)
                return err;
 
@@ -992,9 +989,9 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file,
                }
 
                if (copied > 0) {
-                       ret = dirty_and_release_pages(root, file, pages,
-                                                     dirty_pages, pos,
-                                                     copied);
+                       ret = btrfs_dirty_pages(root, inode, pages,
+                                               dirty_pages, pos, copied,
+                                               NULL);
                        if (ret) {
                                btrfs_delalloc_release_space(inode,
                                        dirty_pages << PAGE_CACHE_SHIFT);
index f561c953205bfb5dca0c53608c1770388a9db875..11d2e9cea09e95b329cfe4e37aec5b50bcc46135 100644 (file)
@@ -508,6 +508,7 @@ int btrfs_write_out_cache(struct btrfs_root *root,
        struct inode *inode;
        struct rb_node *node;
        struct list_head *pos, *n;
+       struct page **pages;
        struct page *page;
        struct extent_state *cached_state = NULL;
        struct btrfs_free_cluster *cluster = NULL;
@@ -517,13 +518,13 @@ int btrfs_write_out_cache(struct btrfs_root *root,
        u64 start, end, len;
        u64 bytes = 0;
        u32 *crc, *checksums;
-       pgoff_t index = 0, last_index = 0;
        unsigned long first_page_offset;
-       int num_checksums;
+       int index = 0, num_pages = 0;
        int entries = 0;
        int bitmaps = 0;
        int ret = 0;
        bool next_page = false;
+       bool out_of_space = false;
 
        root = root->fs_info->tree_root;
 
@@ -551,24 +552,31 @@ int btrfs_write_out_cache(struct btrfs_root *root,
                return 0;
        }
 
-       last_index = (i_size_read(inode) - 1) >> PAGE_CACHE_SHIFT;
+       num_pages = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >>
+               PAGE_CACHE_SHIFT;
        filemap_write_and_wait(inode->i_mapping);
        btrfs_wait_ordered_range(inode, inode->i_size &
                                 ~(root->sectorsize - 1), (u64)-1);
 
        /* We need a checksum per page. */
-       num_checksums = i_size_read(inode) / PAGE_CACHE_SIZE;
-       crc = checksums  = kzalloc(sizeof(u32) * num_checksums, GFP_NOFS);
+       crc = checksums = kzalloc(sizeof(u32) * num_pages, GFP_NOFS);
        if (!crc) {
                iput(inode);
                return 0;
        }
 
+       pages = kzalloc(sizeof(struct page *) * num_pages, GFP_NOFS);
+       if (!pages) {
+               kfree(crc);
+               iput(inode);
+               return 0;
+       }
+
        /* Since the first page has all of our checksums and our generation we
         * need to calculate the offset into the page that we can start writing
         * our entries.
         */
-       first_page_offset = (sizeof(u32) * num_checksums) + sizeof(u64);
+       first_page_offset = (sizeof(u32) * num_pages) + sizeof(u64);
 
        /* Get the cluster for this block_group if it exists */
        if (!list_empty(&block_group->cluster_list))
@@ -590,20 +598,18 @@ int btrfs_write_out_cache(struct btrfs_root *root,
         * after find_get_page at this point.  Just putting this here so people
         * know and don't freak out.
         */
-       while (index <= last_index) {
+       while (index < num_pages) {
                page = grab_cache_page(inode->i_mapping, index);
                if (!page) {
-                       pgoff_t i = 0;
+                       int i;
 
-                       while (i < index) {
-                               page = find_get_page(inode->i_mapping, i);
-                               unlock_page(page);
-                               page_cache_release(page);
-                               page_cache_release(page);
-                               i++;
+                       for (i = 0; i < num_pages; i++) {
+                               unlock_page(pages[i]);
+                               page_cache_release(pages[i]);
                        }
                        goto out_free;
                }
+               pages[index] = page;
                index++;
        }
 
@@ -631,7 +637,12 @@ int btrfs_write_out_cache(struct btrfs_root *root,
                        offset = start_offset;
                }
 
-               page = find_get_page(inode->i_mapping, index);
+               if (index >= num_pages) {
+                       out_of_space = true;
+                       break;
+               }
+
+               page = pages[index];
 
                addr = kmap(page);
                entry = addr + start_offset;
@@ -708,23 +719,6 @@ int btrfs_write_out_cache(struct btrfs_root *root,
 
                bytes += PAGE_CACHE_SIZE;
 
-               ClearPageChecked(page);
-               set_page_extent_mapped(page);
-               SetPageUptodate(page);
-               set_page_dirty(page);
-
-               /*
-                * We need to release our reference we got for grab_cache_page,
-                * except for the first page which will hold our checksums, we
-                * do that below.
-                */
-               if (index != 0) {
-                       unlock_page(page);
-                       page_cache_release(page);
-               }
-
-               page_cache_release(page);
-
                index++;
        } while (node || next_page);
 
@@ -734,7 +728,11 @@ int btrfs_write_out_cache(struct btrfs_root *root,
                struct btrfs_free_space *entry =
                        list_entry(pos, struct btrfs_free_space, list);
 
-               page = find_get_page(inode->i_mapping, index);
+               if (index >= num_pages) {
+                       out_of_space = true;
+                       break;
+               }
+               page = pages[index];
 
                addr = kmap(page);
                memcpy(addr, entry->bitmap, PAGE_CACHE_SIZE);
@@ -745,64 +743,58 @@ int btrfs_write_out_cache(struct btrfs_root *root,
                crc++;
                bytes += PAGE_CACHE_SIZE;
 
-               ClearPageChecked(page);
-               set_page_extent_mapped(page);
-               SetPageUptodate(page);
-               set_page_dirty(page);
-               unlock_page(page);
-               page_cache_release(page);
-               page_cache_release(page);
                list_del_init(&entry->list);
                index++;
        }
 
+       if (out_of_space) {
+               btrfs_drop_pages(pages, num_pages);
+               unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
+                                    i_size_read(inode) - 1, &cached_state,
+                                    GFP_NOFS);
+               ret = 0;
+               goto out_free;
+       }
+
        /* Zero out the rest of the pages just to make sure */
-       while (index <= last_index) {
+       while (index < num_pages) {
                void *addr;
 
-               page = find_get_page(inode->i_mapping, index);
-
+               page = pages[index];
                addr = kmap(page);
                memset(addr, 0, PAGE_CACHE_SIZE);
                kunmap(page);
-               ClearPageChecked(page);
-               set_page_extent_mapped(page);
-               SetPageUptodate(page);
-               set_page_dirty(page);
-               unlock_page(page);
-               page_cache_release(page);
-               page_cache_release(page);
                bytes += PAGE_CACHE_SIZE;
                index++;
        }
 
-       btrfs_set_extent_delalloc(inode, 0, bytes - 1, &cached_state);
-
        /* Write the checksums and trans id to the first page */
        {
                void *addr;
                u64 *gen;
 
-               page = find_get_page(inode->i_mapping, 0);
+               page = pages[0];
 
                addr = kmap(page);
-               memcpy(addr, checksums, sizeof(u32) * num_checksums);
-               gen = addr + (sizeof(u32) * num_checksums);
+               memcpy(addr, checksums, sizeof(u32) * num_pages);
+               gen = addr + (sizeof(u32) * num_pages);
                *gen = trans->transid;
                kunmap(page);
-               ClearPageChecked(page);
-               set_page_extent_mapped(page);
-               SetPageUptodate(page);
-               set_page_dirty(page);
-               unlock_page(page);
-               page_cache_release(page);
-               page_cache_release(page);
        }
-       BTRFS_I(inode)->generation = trans->transid;
 
+       ret = btrfs_dirty_pages(root, inode, pages, num_pages, 0,
+                                           bytes, &cached_state);
+       btrfs_drop_pages(pages, num_pages);
        unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
                             i_size_read(inode) - 1, &cached_state, GFP_NOFS);
 
+       if (ret) {
+               ret = 0;
+               goto out_free;
+       }
+
+       BTRFS_I(inode)->generation = trans->transid;
+
        filemap_write_and_wait(inode->i_mapping);
 
        key.objectid = BTRFS_FREE_SPACE_OBJECTID;
@@ -853,6 +845,7 @@ out_free:
                BTRFS_I(inode)->generation = 0;
        }
        kfree(checksums);
+       kfree(pages);
        btrfs_update_inode(trans, root, inode);
        iput(inode);
        return ret;
index 5cc64ab9c4851c5b1fe9adbebabcf083c4581b14..fcd66b6a80864c9612975163473240c4e8cb34fd 100644 (file)
@@ -1770,9 +1770,12 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end)
        add_pending_csums(trans, inode, ordered_extent->file_offset,
                          &ordered_extent->list);
 
-       btrfs_ordered_update_i_size(inode, 0, ordered_extent);
-       ret = btrfs_update_inode(trans, root, inode);
-       BUG_ON(ret);
+       ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent);
+       if (!ret) {
+               ret = btrfs_update_inode(trans, root, inode);
+               BUG_ON(ret);
+       }
+       ret = 0;
 out:
        if (nolock) {
                if (trans)
@@ -2590,6 +2593,13 @@ static void fill_inode_item(struct btrfs_trans_handle *trans,
                            struct btrfs_inode_item *item,
                            struct inode *inode)
 {
+       if (!leaf->map_token)
+               map_private_extent_buffer(leaf, (unsigned long)item,
+                                         sizeof(struct btrfs_inode_item),
+                                         &leaf->map_token, &leaf->kaddr,
+                                         &leaf->map_start, &leaf->map_len,
+                                         KM_USER1);
+
        btrfs_set_inode_uid(leaf, item, inode->i_uid);
        btrfs_set_inode_gid(leaf, item, inode->i_gid);
        btrfs_set_inode_size(leaf, item, BTRFS_I(inode)->disk_i_size);
@@ -2618,6 +2628,11 @@ static void fill_inode_item(struct btrfs_trans_handle *trans,
        btrfs_set_inode_rdev(leaf, item, inode->i_rdev);
        btrfs_set_inode_flags(leaf, item, BTRFS_I(inode)->flags);
        btrfs_set_inode_block_group(leaf, item, BTRFS_I(inode)->block_group);
+
+       if (leaf->map_token) {
+               unmap_extent_buffer(leaf, leaf->map_token, KM_USER1);
+               leaf->map_token = NULL;
+       }
 }
 
 /*
@@ -4207,10 +4222,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
        struct btrfs_key found_key;
        struct btrfs_path *path;
        int ret;
-       u32 nritems;
        struct extent_buffer *leaf;
        int slot;
-       int advance;
        unsigned char d_type;
        int over = 0;
        u32 di_cur;
@@ -4253,27 +4266,19 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
        ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
        if (ret < 0)
                goto err;
-       advance = 0;
 
        while (1) {
                leaf = path->nodes[0];
-               nritems = btrfs_header_nritems(leaf);
                slot = path->slots[0];
-               if (advance || slot >= nritems) {
-                       if (slot >= nritems - 1) {
-                               ret = btrfs_next_leaf(root, path);
-                               if (ret)
-                                       break;
-                               leaf = path->nodes[0];
-                               nritems = btrfs_header_nritems(leaf);
-                               slot = path->slots[0];
-                       } else {
-                               slot++;
-                               path->slots[0]++;
-                       }
+               if (slot >= btrfs_header_nritems(leaf)) {
+                       ret = btrfs_next_leaf(root, path);
+                       if (ret < 0)
+                               goto err;
+                       else if (ret > 0)
+                               break;
+                       continue;
                }
 
-               advance = 1;
                item = btrfs_item_nr(leaf, slot);
                btrfs_item_key_to_cpu(leaf, &found_key, slot);
 
@@ -4282,7 +4287,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
                if (btrfs_key_type(&found_key) != key_type)
                        break;
                if (found_key.offset < filp->f_pos)
-                       continue;
+                       goto next;
 
                filp->f_pos = found_key.offset;
 
@@ -4335,6 +4340,8 @@ skip:
                        di_cur += di_len;
                        di = (struct btrfs_dir_item *)((char *)di + di_len);
                }
+next:
+               path->slots[0]++;
        }
 
        /* Reached end of directory/root. Bump pos past the last item. */
@@ -4527,14 +4534,17 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
        BUG_ON(!path);
 
        inode = new_inode(root->fs_info->sb);
-       if (!inode)
+       if (!inode) {
+               btrfs_free_path(path);
                return ERR_PTR(-ENOMEM);
+       }
 
        if (dir) {
                trace_btrfs_inode_request(dir);
 
                ret = btrfs_set_inode_index(dir, index);
                if (ret) {
+                       btrfs_free_path(path);
                        iput(inode);
                        return ERR_PTR(ret);
                }
@@ -4834,9 +4844,6 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
        if (inode->i_nlink == ~0U)
                return -EMLINK;
 
-       btrfs_inc_nlink(inode);
-       inode->i_ctime = CURRENT_TIME;
-
        err = btrfs_set_inode_index(dir, &index);
        if (err)
                goto fail;
@@ -4852,6 +4859,9 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
                goto fail;
        }
 
+       btrfs_inc_nlink(inode);
+       inode->i_ctime = CURRENT_TIME;
+
        btrfs_set_trans_block_group(trans, dir);
        ihold(inode);
 
@@ -5221,7 +5231,7 @@ again:
                        btrfs_mark_buffer_dirty(leaf);
                }
                set_extent_uptodate(io_tree, em->start,
-                                   extent_map_end(em) - 1, GFP_NOFS);
+                                   extent_map_end(em) - 1, NULL, GFP_NOFS);
                goto insert;
        } else {
                printk(KERN_ERR "btrfs unknown found_type %d\n", found_type);
@@ -5428,17 +5438,30 @@ out:
 }
 
 static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
+                                                 struct extent_map *em,
                                                  u64 start, u64 len)
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_trans_handle *trans;
-       struct extent_map *em;
        struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
        struct btrfs_key ins;
        u64 alloc_hint;
        int ret;
+       bool insert = false;
 
-       btrfs_drop_extent_cache(inode, start, start + len - 1, 0);
+       /*
+        * Ok if the extent map we looked up is a hole and is for the exact
+        * range we want, there is no reason to allocate a new one, however if
+        * it is not right then we need to free this one and drop the cache for
+        * our range.
+        */
+       if (em->block_start != EXTENT_MAP_HOLE || em->start != start ||
+           em->len != len) {
+               free_extent_map(em);
+               em = NULL;
+               insert = true;
+               btrfs_drop_extent_cache(inode, start, start + len - 1, 0);
+       }
 
        trans = btrfs_join_transaction(root, 0);
        if (IS_ERR(trans))
@@ -5454,10 +5477,12 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
                goto out;
        }
 
-       em = alloc_extent_map(GFP_NOFS);
        if (!em) {
-               em = ERR_PTR(-ENOMEM);
-               goto out;
+               em = alloc_extent_map(GFP_NOFS);
+               if (!em) {
+                       em = ERR_PTR(-ENOMEM);
+                       goto out;
+               }
        }
 
        em->start = start;
@@ -5467,9 +5492,15 @@ static struct extent_map *btrfs_new_extent_direct(struct inode *inode,
        em->block_start = ins.objectid;
        em->block_len = ins.offset;
        em->bdev = root->fs_info->fs_devices->latest_bdev;
+
+       /*
+        * We need to do this because if we're using the original em we searched
+        * for, we could have EXTENT_FLAG_VACANCY set, and we don't want that.
+        */
+       em->flags = 0;
        set_bit(EXTENT_FLAG_PINNED, &em->flags);
 
-       while (1) {
+       while (insert) {
                write_lock(&em_tree->lock);
                ret = add_extent_mapping(em_tree, em);
                write_unlock(&em_tree->lock);
@@ -5687,8 +5718,7 @@ must_cow:
         * it above
         */
        len = bh_result->b_size;
-       free_extent_map(em);
-       em = btrfs_new_extent_direct(inode, start, len);
+       em = btrfs_new_extent_direct(inode, em, start, len);
        if (IS_ERR(em))
                return PTR_ERR(em);
        len = min(len, em->len - (start - em->start));
@@ -5851,8 +5881,10 @@ again:
        }
 
        add_pending_csums(trans, inode, ordered->file_offset, &ordered->list);
-       btrfs_ordered_update_i_size(inode, 0, ordered);
-       btrfs_update_inode(trans, root, inode);
+       ret = btrfs_ordered_update_i_size(inode, 0, ordered);
+       if (!ret)
+               btrfs_update_inode(trans, root, inode);
+       ret = 0;
 out_unlock:
        unlock_extent_cached(&BTRFS_I(inode)->io_tree, ordered->file_offset,
                             ordered->file_offset + ordered->len - 1,
@@ -5938,7 +5970,7 @@ static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev,
 
 static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
                                         int rw, u64 file_offset, int skip_sum,
-                                        u32 *csums)
+                                        u32 *csums, int async_submit)
 {
        int write = rw & REQ_WRITE;
        struct btrfs_root *root = BTRFS_I(inode)->root;
@@ -5949,13 +5981,24 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
        if (ret)
                goto err;
 
-       if (write && !skip_sum) {
+       if (skip_sum)
+               goto map;
+
+       if (write && async_submit) {
                ret = btrfs_wq_submit_bio(root->fs_info,
                                   inode, rw, bio, 0, 0,
                                   file_offset,
                                   __btrfs_submit_bio_start_direct_io,
                                   __btrfs_submit_bio_done);
                goto err;
+       } else if (write) {
+               /*
+                * If we aren't doing async submit, calculate the csum of the
+                * bio now.
+                */
+               ret = btrfs_csum_one_bio(root, inode, bio, file_offset, 1);
+               if (ret)
+                       goto err;
        } else if (!skip_sum) {
                ret = btrfs_lookup_bio_sums_dio(root, inode, bio,
                                          file_offset, csums);
@@ -5963,7 +6006,8 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
                        goto err;
        }
 
-       ret = btrfs_map_bio(root, rw, bio, 0, 1);
+map:
+       ret = btrfs_map_bio(root, rw, bio, 0, async_submit);
 err:
        bio_put(bio);
        return ret;
@@ -5985,15 +6029,9 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
        int nr_pages = 0;
        u32 *csums = dip->csums;
        int ret = 0;
+       int async_submit = 0;
        int write = rw & REQ_WRITE;
 
-       bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS);
-       if (!bio)
-               return -ENOMEM;
-       bio->bi_private = dip;
-       bio->bi_end_io = btrfs_end_dio_bio;
-       atomic_inc(&dip->pending_bios);
-
        map_length = orig_bio->bi_size;
        ret = btrfs_map_block(map_tree, READ, start_sector << 9,
                              &map_length, NULL, 0);
@@ -6002,6 +6040,19 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
                return -EIO;
        }
 
+       if (map_length >= orig_bio->bi_size) {
+               bio = orig_bio;
+               goto submit;
+       }
+
+       async_submit = 1;
+       bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS);
+       if (!bio)
+               return -ENOMEM;
+       bio->bi_private = dip;
+       bio->bi_end_io = btrfs_end_dio_bio;
+       atomic_inc(&dip->pending_bios);
+
        while (bvec <= (orig_bio->bi_io_vec + orig_bio->bi_vcnt - 1)) {
                if (unlikely(map_length < submit_len + bvec->bv_len ||
                    bio_add_page(bio, bvec->bv_page, bvec->bv_len,
@@ -6015,7 +6066,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
                        atomic_inc(&dip->pending_bios);
                        ret = __btrfs_submit_dio_bio(bio, inode, rw,
                                                     file_offset, skip_sum,
-                                                    csums);
+                                                    csums, async_submit);
                        if (ret) {
                                bio_put(bio);
                                atomic_dec(&dip->pending_bios);
@@ -6052,8 +6103,9 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
                }
        }
 
+submit:
        ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum,
-                                    csums);
+                                    csums, async_submit);
        if (!ret)
                return 0;
 
@@ -6148,6 +6200,7 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io
                        unsigned long nr_segs)
 {
        int seg;
+       int i;
        size_t size;
        unsigned long addr;
        unsigned blocksize_mask = root->sectorsize - 1;
@@ -6162,8 +6215,22 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io
                addr = (unsigned long)iov[seg].iov_base;
                size = iov[seg].iov_len;
                end += size;
-               if ((addr & blocksize_mask) || (size & blocksize_mask)) 
+               if ((addr & blocksize_mask) || (size & blocksize_mask))
                        goto out;
+
+               /* If this is a write we don't need to check anymore */
+               if (rw & WRITE)
+                       continue;
+
+               /*
+                * Check to make sure we don't have duplicate iov_base's in this
+                * iovec, if so return EINVAL, otherwise we'll get csum errors
+                * when reading back.
+                */
+               for (i = seg + 1; i < nr_segs; i++) {
+                       if (iov[seg].iov_base == iov[i].iov_base)
+                               goto out;
+               }
        }
        retval = 0;
 out:
index cfc264fefdb0e61d419673205304bf54ca285179..ffb48d6c54334ab8fe0d29ae4d69cfa1b22d613c 100644 (file)
@@ -2287,7 +2287,7 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg)
        struct btrfs_ioctl_space_info space;
        struct btrfs_ioctl_space_info *dest;
        struct btrfs_ioctl_space_info *dest_orig;
-       struct btrfs_ioctl_space_info *user_dest;
+       struct btrfs_ioctl_space_info __user *user_dest;
        struct btrfs_space_info *info;
        u64 types[] = {BTRFS_BLOCK_GROUP_DATA,
                       BTRFS_BLOCK_GROUP_SYSTEM,
index 58e7de9cc90cb47d2c4047acb9a8d14cdc933f40..0ac712efcdf293ac8e858fef443b57316b039037 100644 (file)
@@ -159,7 +159,7 @@ enum {
        Opt_compress_type, Opt_compress_force, Opt_compress_force_type,
        Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard,
        Opt_space_cache, Opt_clear_cache, Opt_user_subvol_rm_allowed,
-       Opt_enospc_debug, Opt_err,
+       Opt_enospc_debug, Opt_subvolrootid, Opt_err,
 };
 
 static match_table_t tokens = {
@@ -189,6 +189,7 @@ static match_table_t tokens = {
        {Opt_clear_cache, "clear_cache"},
        {Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"},
        {Opt_enospc_debug, "enospc_debug"},
+       {Opt_subvolrootid, "subvolrootid=%d"},
        {Opt_err, NULL},
 };
 
@@ -232,6 +233,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                        break;
                case Opt_subvol:
                case Opt_subvolid:
+               case Opt_subvolrootid:
                case Opt_device:
                        /*
                         * These are parsed by btrfs_parse_early_options
@@ -388,7 +390,7 @@ out:
  */
 static int btrfs_parse_early_options(const char *options, fmode_t flags,
                void *holder, char **subvol_name, u64 *subvol_objectid,
-               struct btrfs_fs_devices **fs_devices)
+               u64 *subvol_rootid, struct btrfs_fs_devices **fs_devices)
 {
        substring_t args[MAX_OPT_ARGS];
        char *opts, *orig, *p;
@@ -429,6 +431,18 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags,
                                        *subvol_objectid = intarg;
                        }
                        break;
+               case Opt_subvolrootid:
+                       intarg = 0;
+                       error = match_int(&args[0], &intarg);
+                       if (!error) {
+                               /* we want the original fs_tree */
+                               if (!intarg)
+                                       *subvol_rootid =
+                                               BTRFS_FS_TREE_OBJECTID;
+                               else
+                                       *subvol_rootid = intarg;
+                       }
+                       break;
                case Opt_device:
                        error = btrfs_scan_one_device(match_strdup(&args[0]),
                                        flags, holder, fs_devices);
@@ -736,6 +750,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        fmode_t mode = FMODE_READ;
        char *subvol_name = NULL;
        u64 subvol_objectid = 0;
+       u64 subvol_rootid = 0;
        int error = 0;
 
        if (!(flags & MS_RDONLY))
@@ -743,7 +758,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
 
        error = btrfs_parse_early_options(data, mode, fs_type,
                                          &subvol_name, &subvol_objectid,
-                                         &fs_devices);
+                                         &subvol_rootid, &fs_devices);
        if (error)
                return ERR_PTR(error);
 
@@ -807,15 +822,17 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
                s->s_flags |= MS_ACTIVE;
        }
 
-       root = get_default_root(s, subvol_objectid);
-       if (IS_ERR(root)) {
-               error = PTR_ERR(root);
-               deactivate_locked_super(s);
-               goto error_free_subvol_name;
-       }
        /* if they gave us a subvolume name bind mount into that */
        if (strcmp(subvol_name, ".")) {
                struct dentry *new_root;
+
+               root = get_default_root(s, subvol_rootid);
+               if (IS_ERR(root)) {
+                       error = PTR_ERR(root);
+                       deactivate_locked_super(s);
+                       goto error_free_subvol_name;
+               }
+
                mutex_lock(&root->d_inode->i_mutex);
                new_root = lookup_one_len(subvol_name, root,
                                      strlen(subvol_name));
@@ -836,6 +853,13 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
                }
                dput(root);
                root = new_root;
+       } else {
+               root = get_default_root(s, subvol_objectid);
+               if (IS_ERR(root)) {
+                       error = PTR_ERR(root);
+                       deactivate_locked_super(s);
+                       goto error_free_subvol_name;
+               }
        }
 
        kfree(subvol_name);
index 5b158da7e0bb7816710859ee47f7fad4007fb4a2..c571734d5e5a802ea73a0c6458dd41c0b2e56659 100644 (file)
 
 static noinline void put_transaction(struct btrfs_transaction *transaction)
 {
-       WARN_ON(transaction->use_count == 0);
-       transaction->use_count--;
-       if (transaction->use_count == 0) {
-               list_del_init(&transaction->list);
+       WARN_ON(atomic_read(&transaction->use_count) == 0);
+       if (atomic_dec_and_test(&transaction->use_count)) {
                memset(transaction, 0, sizeof(*transaction));
                kmem_cache_free(btrfs_transaction_cachep, transaction);
        }
@@ -60,14 +58,14 @@ static noinline int join_transaction(struct btrfs_root *root)
                if (!cur_trans)
                        return -ENOMEM;
                root->fs_info->generation++;
-               cur_trans->num_writers = 1;
+               atomic_set(&cur_trans->num_writers, 1);
                cur_trans->num_joined = 0;
                cur_trans->transid = root->fs_info->generation;
                init_waitqueue_head(&cur_trans->writer_wait);
                init_waitqueue_head(&cur_trans->commit_wait);
                cur_trans->in_commit = 0;
                cur_trans->blocked = 0;
-               cur_trans->use_count = 1;
+               atomic_set(&cur_trans->use_count, 1);
                cur_trans->commit_done = 0;
                cur_trans->start_time = get_seconds();
 
@@ -88,7 +86,7 @@ static noinline int join_transaction(struct btrfs_root *root)
                root->fs_info->running_transaction = cur_trans;
                spin_unlock(&root->fs_info->new_trans_lock);
        } else {
-               cur_trans->num_writers++;
+               atomic_inc(&cur_trans->num_writers);
                cur_trans->num_joined++;
        }
 
@@ -145,7 +143,7 @@ static void wait_current_trans(struct btrfs_root *root)
        cur_trans = root->fs_info->running_transaction;
        if (cur_trans && cur_trans->blocked) {
                DEFINE_WAIT(wait);
-               cur_trans->use_count++;
+               atomic_inc(&cur_trans->use_count);
                while (1) {
                        prepare_to_wait(&root->fs_info->transaction_wait, &wait,
                                        TASK_UNINTERRUPTIBLE);
@@ -181,6 +179,7 @@ static struct btrfs_trans_handle *start_transaction(struct btrfs_root *root,
 {
        struct btrfs_trans_handle *h;
        struct btrfs_transaction *cur_trans;
+       int retries = 0;
        int ret;
 
        if (root->fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)
@@ -204,7 +203,7 @@ again:
        }
 
        cur_trans = root->fs_info->running_transaction;
-       cur_trans->use_count++;
+       atomic_inc(&cur_trans->use_count);
        if (type != TRANS_JOIN_NOLOCK)
                mutex_unlock(&root->fs_info->trans_mutex);
 
@@ -224,10 +223,18 @@ again:
 
        if (num_items > 0) {
                ret = btrfs_trans_reserve_metadata(h, root, num_items);
-               if (ret == -EAGAIN) {
+               if (ret == -EAGAIN && !retries) {
+                       retries++;
                        btrfs_commit_transaction(h, root);
                        goto again;
+               } else if (ret == -EAGAIN) {
+                       /*
+                        * We have already retried and got EAGAIN, so really we
+                        * don't have space, so set ret to -ENOSPC.
+                        */
+                       ret = -ENOSPC;
                }
+
                if (ret < 0) {
                        btrfs_end_transaction(h, root);
                        return ERR_PTR(ret);
@@ -327,7 +334,7 @@ int btrfs_wait_for_commit(struct btrfs_root *root, u64 transid)
                        goto out_unlock;  /* nothing committing|committed */
        }
 
-       cur_trans->use_count++;
+       atomic_inc(&cur_trans->use_count);
        mutex_unlock(&root->fs_info->trans_mutex);
 
        wait_for_commit(root, cur_trans);
@@ -457,18 +464,14 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
                        wake_up_process(info->transaction_kthread);
        }
 
-       if (lock)
-               mutex_lock(&info->trans_mutex);
        WARN_ON(cur_trans != info->running_transaction);
-       WARN_ON(cur_trans->num_writers < 1);
-       cur_trans->num_writers--;
+       WARN_ON(atomic_read(&cur_trans->num_writers) < 1);
+       atomic_dec(&cur_trans->num_writers);
 
        smp_mb();
        if (waitqueue_active(&cur_trans->writer_wait))
                wake_up(&cur_trans->writer_wait);
        put_transaction(cur_trans);
-       if (lock)
-               mutex_unlock(&info->trans_mutex);
 
        if (current->journal_info == trans)
                current->journal_info = NULL;
@@ -1178,7 +1181,7 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans,
        /* take transaction reference */
        mutex_lock(&root->fs_info->trans_mutex);
        cur_trans = trans->transaction;
-       cur_trans->use_count++;
+       atomic_inc(&cur_trans->use_count);
        mutex_unlock(&root->fs_info->trans_mutex);
 
        btrfs_end_transaction(trans, root);
@@ -1237,7 +1240,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 
        mutex_lock(&root->fs_info->trans_mutex);
        if (cur_trans->in_commit) {
-               cur_trans->use_count++;
+               atomic_inc(&cur_trans->use_count);
                mutex_unlock(&root->fs_info->trans_mutex);
                btrfs_end_transaction(trans, root);
 
@@ -1259,7 +1262,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
                prev_trans = list_entry(cur_trans->list.prev,
                                        struct btrfs_transaction, list);
                if (!prev_trans->commit_done) {
-                       prev_trans->use_count++;
+                       atomic_inc(&prev_trans->use_count);
                        mutex_unlock(&root->fs_info->trans_mutex);
 
                        wait_for_commit(root, prev_trans);
@@ -1300,14 +1303,14 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
                                TASK_UNINTERRUPTIBLE);
 
                smp_mb();
-               if (cur_trans->num_writers > 1)
+               if (atomic_read(&cur_trans->num_writers) > 1)
                        schedule_timeout(MAX_SCHEDULE_TIMEOUT);
                else if (should_grow)
                        schedule_timeout(1);
 
                mutex_lock(&root->fs_info->trans_mutex);
                finish_wait(&cur_trans->writer_wait, &wait);
-       } while (cur_trans->num_writers > 1 ||
+       } while (atomic_read(&cur_trans->num_writers) > 1 ||
                 (should_grow && cur_trans->num_joined != joined));
 
        ret = create_pending_snapshots(trans, root->fs_info);
@@ -1394,6 +1397,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans,
 
        wake_up(&cur_trans->commit_wait);
 
+       list_del_init(&cur_trans->list);
        put_transaction(cur_trans);
        put_transaction(cur_trans);
 
index 229a594cacd5a15c8bbd71ed1575f57d615945e4..e441acc6c584a7e03859d3e63cd3e455312ff631 100644 (file)
@@ -27,11 +27,11 @@ struct btrfs_transaction {
         * total writers in this transaction, it must be zero before the
         * transaction can end
         */
-       unsigned long num_writers;
+       atomic_t num_writers;
 
        unsigned long num_joined;
        int in_commit;
-       int use_count;
+       atomic_t use_count;
        int commit_done;
        int blocked;
        struct list_head list;
index a5303b871b13874d574edb6dec5642cf2286e7cb..cfd660550ded035fd2fad7aadce102aa23fc27fb 100644 (file)
@@ -180,11 +180,10 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
        struct btrfs_path *path;
        struct extent_buffer *leaf;
        struct btrfs_dir_item *di;
-       int ret = 0, slot, advance;
+       int ret = 0, slot;
        size_t total_size = 0, size_left = size;
        unsigned long name_ptr;
        size_t name_len;
-       u32 nritems;
 
        /*
         * ok we want all objects associated with this id.
@@ -204,34 +203,24 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
        ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
        if (ret < 0)
                goto err;
-       advance = 0;
+
        while (1) {
                leaf = path->nodes[0];
-               nritems = btrfs_header_nritems(leaf);
                slot = path->slots[0];
 
                /* this is where we start walking through the path */
-               if (advance || slot >= nritems) {
+               if (slot >= btrfs_header_nritems(leaf)) {
                        /*
                         * if we've reached the last slot in this leaf we need
                         * to go to the next leaf and reset everything
                         */
-                       if (slot >= nritems-1) {
-                               ret = btrfs_next_leaf(root, path);
-                               if (ret)
-                                       break;
-                               leaf = path->nodes[0];
-                               nritems = btrfs_header_nritems(leaf);
-                               slot = path->slots[0];
-                       } else {
-                               /*
-                                * just walking through the slots on this leaf
-                                */
-                               slot++;
-                               path->slots[0]++;
-                       }
+                       ret = btrfs_next_leaf(root, path);
+                       if (ret < 0)
+                               goto err;
+                       else if (ret > 0)
+                               break;
+                       continue;
                }
-               advance = 1;
 
                btrfs_item_key_to_cpu(leaf, &found_key, slot);
 
@@ -250,7 +239,7 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
 
                /* we are just looking for how big our buffer needs to be */
                if (!size)
-                       continue;
+                       goto next;
 
                if (!buffer || (name_len + 1) > size_left) {
                        ret = -ERANGE;
@@ -263,6 +252,8 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
 
                size_left -= name_len + 1;
                buffer += name_len + 1;
+next:
+               path->slots[0]++;
        }
        ret = total_size;
 
index fe1683590828a0ed011fa4a2e6ca6cc157292dca..74ab165fc646aea64d873900b64696a2ef35f471 100644 (file)
@@ -685,22 +685,6 @@ LinuxExtensionsEnabled     If set to one then the client will attempt to
                        support and want to map the uid and gid fields 
                        to values supplied at mount (rather than the 
                        actual values, then set this to zero. (default 1)
-Experimental            When set to 1 used to enable certain experimental
-                       features (currently enables multipage writes
-                       when signing is enabled, the multipage write
-                       performance enhancement was disabled when
-                       signing turned on in case buffer was modified
-                       just before it was sent, also this flag will
-                       be used to use the new experimental directory change 
-                       notification code).  When set to 2 enables
-                       an additional experimental feature, "raw ntlmssp"
-                       session establishment support (which allows
-                       specifying "sec=ntlmssp" on mount). The Linux cifs
-                       module will use ntlmv2 authentication encapsulated
-                       in "raw ntlmssp" (not using SPNEGO) when
-                       "sec=ntlmssp" is specified on mount.
-                       This support also requires building cifs with
-                       the CONFIG_CIFS_EXPERIMENTAL configuration flag.
 
 These experimental features and tracing can be enabled by changing flags in 
 /proc/fs/cifs (after the cifs module has been installed or built into the 
index e654dfd092c3a8d0333af9771156898d1c9ed65e..53d57a3fe427c3d94218a7f54b4ab87df3d68031 100644 (file)
@@ -50,7 +50,7 @@ void cifs_fscache_unregister(void)
  */
 struct cifs_server_key {
        uint16_t        family;         /* address family */
-       uint16_t        port;           /* IP port */
+       __be16          port;           /* IP port */
        union {
                struct in_addr  ipv4_addr;
                struct in6_addr ipv6_addr;
index 65829d32128c253a661ecd61dc50f4893bc9f52d..30d01bc9085556bc810ce4d233f358728e6bea44 100644 (file)
@@ -423,7 +423,6 @@ static const struct file_operations cifs_lookup_cache_proc_fops;
 static const struct file_operations traceSMB_proc_fops;
 static const struct file_operations cifs_multiuser_mount_proc_fops;
 static const struct file_operations cifs_security_flags_proc_fops;
-static const struct file_operations cifs_experimental_proc_fops;
 static const struct file_operations cifs_linux_ext_proc_fops;
 
 void
@@ -441,8 +440,6 @@ cifs_proc_init(void)
        proc_create("cifsFYI", 0, proc_fs_cifs, &cifsFYI_proc_fops);
        proc_create("traceSMB", 0, proc_fs_cifs, &traceSMB_proc_fops);
        proc_create("OplockEnabled", 0, proc_fs_cifs, &cifs_oplock_proc_fops);
-       proc_create("Experimental", 0, proc_fs_cifs,
-                   &cifs_experimental_proc_fops);
        proc_create("LinuxExtensionsEnabled", 0, proc_fs_cifs,
                    &cifs_linux_ext_proc_fops);
        proc_create("MultiuserMount", 0, proc_fs_cifs,
@@ -469,7 +466,6 @@ cifs_proc_clean(void)
        remove_proc_entry("OplockEnabled", proc_fs_cifs);
        remove_proc_entry("SecurityFlags", proc_fs_cifs);
        remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
-       remove_proc_entry("Experimental", proc_fs_cifs);
        remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
        remove_proc_entry("fs/cifs", NULL);
 }
@@ -550,45 +546,6 @@ static const struct file_operations cifs_oplock_proc_fops = {
        .write          = cifs_oplock_proc_write,
 };
 
-static int cifs_experimental_proc_show(struct seq_file *m, void *v)
-{
-       seq_printf(m, "%d\n", experimEnabled);
-       return 0;
-}
-
-static int cifs_experimental_proc_open(struct inode *inode, struct file *file)
-{
-       return single_open(file, cifs_experimental_proc_show, NULL);
-}
-
-static ssize_t cifs_experimental_proc_write(struct file *file,
-               const char __user *buffer, size_t count, loff_t *ppos)
-{
-       char c;
-       int rc;
-
-       rc = get_user(c, buffer);
-       if (rc)
-               return rc;
-       if (c == '0' || c == 'n' || c == 'N')
-               experimEnabled = 0;
-       else if (c == '1' || c == 'y' || c == 'Y')
-               experimEnabled = 1;
-       else if (c == '2')
-               experimEnabled = 2;
-
-       return count;
-}
-
-static const struct file_operations cifs_experimental_proc_fops = {
-       .owner          = THIS_MODULE,
-       .open           = cifs_experimental_proc_open,
-       .read           = seq_read,
-       .llseek         = seq_lseek,
-       .release        = single_release,
-       .write          = cifs_experimental_proc_write,
-};
-
 static int cifs_linux_ext_proc_show(struct seq_file *m, void *v)
 {
        seq_printf(m, "%d\n", linuxExtEnabled);
index 4dfba82831654910b3aab62a9803dc95855a52f1..33d221394acae068807adea4eeca47317a821888 100644 (file)
@@ -113,7 +113,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
                   MAX_MECH_STR_LEN +
                   UID_KEY_LEN + (sizeof(uid_t) * 2) +
                   CREDUID_KEY_LEN + (sizeof(uid_t) * 2) +
-                  USER_KEY_LEN + strlen(sesInfo->userName) +
+                  USER_KEY_LEN + strlen(sesInfo->user_name) +
                   PID_KEY_LEN + (sizeof(pid_t) * 2) + 1;
 
        spnego_key = ERR_PTR(-ENOMEM);
@@ -153,7 +153,7 @@ cifs_get_spnego_key(struct cifsSesInfo *sesInfo)
        sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid);
 
        dp = description + strlen(description);
-       sprintf(dp, ";user=%s", sesInfo->userName);
+       sprintf(dp, ";user=%s", sesInfo->user_name);
 
        dp = description + strlen(description);
        sprintf(dp, ";pid=0x%x", current->pid);
index fc0fd4fde306b989c1593ef11ce2611fd49dca54..23d43cde4306042407dcd3df76d78ab81b793db7 100644 (file)
@@ -90,7 +90,7 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp,
        case UNI_COLON:
                *target = ':';
                break;
-       case UNI_ASTERIK:
+       case UNI_ASTERISK:
                *target = '*';
                break;
        case UNI_QUESTION:
@@ -264,40 +264,40 @@ cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode,
  * names are little endian 16 bit Unicode on the wire
  */
 int
-cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
+cifsConvertToUCS(__le16 *target, const char *source, int srclen,
                 const struct nls_table *cp, int mapChars)
 {
        int i, j, charlen;
-       int len_remaining = maxlen;
        char src_char;
-       __u16 temp;
+       __le16 dst_char;
+       wchar_t tmp;
 
        if (!mapChars)
                return cifs_strtoUCS(target, source, PATH_MAX, cp);
 
-       for (i = 0, j = 0; i < maxlen; j++) {
+       for (i = 0, j = 0; i < srclen; j++) {
                src_char = source[i];
                switch (src_char) {
                case 0:
-                       put_unaligned_le16(0, &target[j]);
+                       put_unaligned(0, &target[j]);
                        goto ctoUCS_out;
                case ':':
-                       temp = UNI_COLON;
+                       dst_char = cpu_to_le16(UNI_COLON);
                        break;
                case '*':
-                       temp = UNI_ASTERIK;
+                       dst_char = cpu_to_le16(UNI_ASTERISK);
                        break;
                case '?':
-                       temp = UNI_QUESTION;
+                       dst_char = cpu_to_le16(UNI_QUESTION);
                        break;
                case '<':
-                       temp = UNI_LESSTHAN;
+                       dst_char = cpu_to_le16(UNI_LESSTHAN);
                        break;
                case '>':
-                       temp = UNI_GRTRTHAN;
+                       dst_char = cpu_to_le16(UNI_GRTRTHAN);
                        break;
                case '|':
-                       temp = UNI_PIPE;
+                       dst_char = cpu_to_le16(UNI_PIPE);
                        break;
                /*
                 * FIXME: We can not handle remapping backslash (UNI_SLASH)
@@ -305,17 +305,17 @@ cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
                 * as they use backslash as separator.
                 */
                default:
-                       charlen = cp->char2uni(source+i, len_remaining,
-                                               &temp);
+                       charlen = cp->char2uni(source + i, srclen - i, &tmp);
+                       dst_char = cpu_to_le16(tmp);
+
                        /*
                         * if no match, use question mark, which at least in
                         * some cases serves as wild card
                         */
                        if (charlen < 1) {
-                               temp = 0x003f;
+                               dst_char = cpu_to_le16(0x003f);
                                charlen = 1;
                        }
-                       len_remaining -= charlen;
                        /*
                         * character may take more than one byte in the source
                         * string, but will take exactly two bytes in the
@@ -324,9 +324,8 @@ cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
                        i += charlen;
                        continue;
                }
-               put_unaligned_le16(temp, &target[j]);
+               put_unaligned(dst_char, &target[j]);
                i++; /* move to next char in source string */
-               len_remaining--;
        }
 
 ctoUCS_out:
index 7fe6b52df5076a2eb14a7ec563403795e2e4c041..644dd882a5604c5ed6f900aad2a47478bc31b49a 100644 (file)
@@ -44,7 +44,7 @@
  * reserved symbols (along with \ and /), otherwise illegal to store
  * in filenames in NTFS
  */
-#define UNI_ASTERI    (__u16) ('*' + 0xF000)
+#define UNI_ASTERISK    (__u16) ('*' + 0xF000)
 #define UNI_QUESTION    (__u16) ('?' + 0xF000)
 #define UNI_COLON       (__u16) (':' + 0xF000)
 #define UNI_GRTRTHAN    (__u16) ('>' + 0xF000)
index a51585f9852b4627735e318e83478cbf512c9fbc..d1a016be73ba75c7a70cb099cd5fdb55150926a9 100644 (file)
 #include <linux/ctype.h>
 #include <linux/random.h>
 
-/* Calculate and return the CIFS signature based on the mac key and SMB PDU */
-/* the 16 byte signature must be allocated by the caller  */
-/* Note we only use the 1st eight bytes */
-/* Note that the smb header signature field on input contains the
-       sequence number before this function is called */
-
+/*
+ * Calculate and return the CIFS signature based on the mac key and SMB PDU.
+ * The 16 byte signature must be allocated by the caller. Note we only use the
+ * 1st eight bytes and that the smb header signature field on input contains
+ * the sequence number before this function is called. Also, this function
+ * should be called with the server->srv_mutex held.
+ */
 static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu,
                                struct TCP_Server_Info *server, char *signature)
 {
@@ -209,8 +210,10 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
                                        cpu_to_le32(expected_sequence_number);
        cifs_pdu->Signature.Sequence.Reserved = 0;
 
+       mutex_lock(&server->srv_mutex);
        rc = cifs_calculate_signature(cifs_pdu, server,
                what_we_think_sig_should_be);
+       mutex_unlock(&server->srv_mutex);
 
        if (rc)
                return rc;
@@ -469,15 +472,15 @@ static int calc_ntlmv2_hash(struct cifsSesInfo *ses, char *ntlmv2_hash,
                return rc;
        }
 
-       /* convert ses->userName to unicode and uppercase */
-       len = strlen(ses->userName);
+       /* convert ses->user_name to unicode and uppercase */
+       len = strlen(ses->user_name);
        user = kmalloc(2 + (len * 2), GFP_KERNEL);
        if (user == NULL) {
                cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n");
                rc = -ENOMEM;
                goto calc_exit_2;
        }
-       len = cifs_strtoUCS((__le16 *)user, ses->userName, len, nls_cp);
+       len = cifs_strtoUCS((__le16 *)user, ses->user_name, len, nls_cp);
        UniStrupr(user);
 
        crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash,
index f2970136d17d06c27e0654bbf4f13e302b3dc815..5c412b33cd7c3ba11d584befbcffd12c210e760c 100644 (file)
@@ -53,7 +53,6 @@ int cifsFYI = 0;
 int cifsERROR = 1;
 int traceSMB = 0;
 unsigned int oplockEnabled = 1;
-unsigned int experimEnabled = 0;
 unsigned int linuxExtEnabled = 1;
 unsigned int lookupCacheEnabled = 1;
 unsigned int multiuser_mount = 0;
@@ -127,6 +126,7 @@ cifs_read_super(struct super_block *sb, void *data,
                kfree(cifs_sb);
                return rc;
        }
+       cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages;
 
 #ifdef CONFIG_CIFS_DFS_UPCALL
        /* copy mount params to sb for use in submounts */
@@ -409,8 +409,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m)
 
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER)
                seq_printf(s, ",multiuser");
-       else if (tcon->ses->userName)
-               seq_printf(s, ",username=%s", tcon->ses->userName);
+       else if (tcon->ses->user_name)
+               seq_printf(s, ",username=%s", tcon->ses->user_name);
 
        if (tcon->ses->domainName)
                seq_printf(s, ",domain=%s", tcon->ses->domainName);
index 17afb0fbcaed362b85935d43d12702f8e815efb5..a5d1106fcbde82ea8b5ab5f61de9a29dc72148d2 100644 (file)
 
 #define MAX_TREE_SIZE (2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1)
 #define MAX_SERVER_SIZE 15
-#define MAX_SHARE_SIZE  64     /* used to be 20, this should still be enough */
-#define MAX_USERNAME_SIZE 32   /* 32 is to allow for 15 char names + null
-                                  termination then *2 for unicode versions */
-#define MAX_PASSWORD_SIZE 512  /* max for windows seems to be 256 wide chars */
+#define MAX_SHARE_SIZE 80
+#define MAX_USERNAME_SIZE 256  /* reasonable maximum for current servers */
+#define MAX_PASSWORD_SIZE 512  /* max for windows seems to be 256 wide chars */
 
 #define CIFS_MIN_RCV_POOL 4
 
@@ -92,7 +91,8 @@ enum statusEnum {
        CifsNew = 0,
        CifsGood,
        CifsExiting,
-       CifsNeedReconnect
+       CifsNeedReconnect,
+       CifsNeedNegotiate
 };
 
 enum securityEnum {
@@ -274,7 +274,7 @@ struct cifsSesInfo {
        int capabilities;
        char serverName[SERVER_NAME_LEN_WITH_NULL * 2]; /* BB make bigger for
                                TCP names - will ipv6 and sctp addresses fit? */
-       char userName[MAX_USERNAME_SIZE + 1];
+       char *user_name;
        char *domainName;
        char *password;
        struct session_key auth_key;
@@ -817,7 +817,6 @@ GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions
                                have the uid/password or Kerberos credential
                                or equivalent for current user */
 GLOBAL_EXTERN unsigned int oplockEnabled;
-GLOBAL_EXTERN unsigned int experimEnabled;
 GLOBAL_EXTERN unsigned int lookupCacheEnabled;
 GLOBAL_EXTERN unsigned int global_secflags;    /* if on, session setup sent
                                with more secure ntlmssp2 challenge/resp */
index 2644a5d6cc67d91002810da3d7f05c3d4be11b5a..df959bae67281597a2c1b4ce643eb3893b0e6ee2 100644 (file)
@@ -142,9 +142,9 @@ cifs_reconnect_tcon(struct cifsTconInfo *tcon, int smb_command)
         */
        while (server->tcpStatus == CifsNeedReconnect) {
                wait_event_interruptible_timeout(server->response_q,
-                       (server->tcpStatus == CifsGood), 10 * HZ);
+                       (server->tcpStatus != CifsNeedReconnect), 10 * HZ);
 
-               /* is TCP session is reestablished now ?*/
+               /* are we still trying to reconnect? */
                if (server->tcpStatus != CifsNeedReconnect)
                        break;
 
@@ -729,7 +729,7 @@ CIFSSMBEcho(struct TCP_Server_Info *server)
                return rc;
 
        /* set up echo request */
-       smb->hdr.Tid = cpu_to_le16(0xffff);
+       smb->hdr.Tid = 0xffff;
        smb->hdr.WordCount = 1;
        put_unaligned_le16(1, &smb->EchoCount);
        put_bcc_le(1, &smb->hdr);
@@ -1884,10 +1884,10 @@ CIFSSMBPosixLock(const int xid, struct cifsTconInfo *tcon,
                                        __constant_cpu_to_le16(CIFS_WRLCK))
                                pLockData->fl_type = F_WRLCK;
 
-                       pLockData->fl_start = parm_data->start;
-                       pLockData->fl_end = parm_data->start +
-                                               parm_data->length - 1;
-                       pLockData->fl_pid = parm_data->pid;
+                       pLockData->fl_start = le64_to_cpu(parm_data->start);
+                       pLockData->fl_end = pLockData->fl_start +
+                                       le64_to_cpu(parm_data->length) - 1;
+                       pLockData->fl_pid = le32_to_cpu(parm_data->pid);
                }
        }
 
index 6e2b2addfc78a184ca6663fcc528c2f242e1056b..db9d55b507d0afe36b816889165975edd3a7198b 100644 (file)
@@ -199,8 +199,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
        }
        spin_unlock(&GlobalMid_Lock);
 
-       while ((server->tcpStatus != CifsExiting) &&
-              (server->tcpStatus != CifsGood)) {
+       while (server->tcpStatus == CifsNeedReconnect) {
                try_to_freeze();
 
                /* we should try only the port we connected to before */
@@ -212,7 +211,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
                        atomic_inc(&tcpSesReconnectCount);
                        spin_lock(&GlobalMid_Lock);
                        if (server->tcpStatus != CifsExiting)
-                               server->tcpStatus = CifsGood;
+                               server->tcpStatus = CifsNeedNegotiate;
                        spin_unlock(&GlobalMid_Lock);
                }
        }
@@ -248,24 +247,24 @@ static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize)
        total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount);
        data_in_this_rsp = get_unaligned_le16(&pSMBt->t2_rsp.DataCount);
 
-       remaining = total_data_size - data_in_this_rsp;
-
-       if (remaining == 0)
+       if (total_data_size == data_in_this_rsp)
                return 0;
-       else if (remaining < 0) {
+       else if (total_data_size < data_in_this_rsp) {
                cFYI(1, "total data %d smaller than data in frame %d",
                        total_data_size, data_in_this_rsp);
                return -EINVAL;
-       } else {
-               cFYI(1, "missing %d bytes from transact2, check next response",
-                       remaining);
-               if (total_data_size > maxBufSize) {
-                       cERROR(1, "TotalDataSize %d is over maximum buffer %d",
-                               total_data_size, maxBufSize);
-                       return -EINVAL;
-               }
-               return remaining;
        }
+
+       remaining = total_data_size - data_in_this_rsp;
+
+       cFYI(1, "missing %d bytes from transact2, check next response",
+               remaining);
+       if (total_data_size > maxBufSize) {
+               cERROR(1, "TotalDataSize %d is over maximum buffer %d",
+                       total_data_size, maxBufSize);
+               return -EINVAL;
+       }
+       return remaining;
 }
 
 static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB)
@@ -421,7 +420,7 @@ cifs_demultiplex_thread(struct TCP_Server_Info *server)
                pdu_length = 4; /* enough to get RFC1001 header */
 
 incomplete_rcv:
-               if (echo_retries > 0 &&
+               if (echo_retries > 0 && server->tcpStatus == CifsGood &&
                    time_after(jiffies, server->lstrp +
                                        (echo_retries * SMB_ECHO_INTERVAL))) {
                        cERROR(1, "Server %s has not responded in %d seconds. "
@@ -881,7 +880,8 @@ cifs_parse_mount_options(char *options, const char *devname,
                                /* null user, ie anonymous, authentication */
                                vol->nullauth = 1;
                        }
-                       if (strnlen(value, 200) < 200) {
+                       if (strnlen(value, MAX_USERNAME_SIZE) <
+                                               MAX_USERNAME_SIZE) {
                                vol->username = value;
                        } else {
                                printk(KERN_WARNING "CIFS: username too long\n");
@@ -1472,7 +1472,7 @@ srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
 static bool
 match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
 {
-       unsigned short int port, *sport;
+       __be16 port, *sport;
 
        switch (addr->sa_family) {
        case AF_INET:
@@ -1765,6 +1765,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
                module_put(THIS_MODULE);
                goto out_err_crypto_release;
        }
+       tcp_ses->tcpStatus = CifsNeedNegotiate;
 
        /* thread spawned, put it on the list */
        spin_lock(&cifs_tcp_ses_lock);
@@ -1808,7 +1809,9 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb_vol *vol)
                        break;
                default:
                        /* anything else takes username/password */
-                       if (strncmp(ses->userName, vol->username,
+                       if (ses->user_name == NULL)
+                               continue;
+                       if (strncmp(ses->user_name, vol->username,
                                    MAX_USERNAME_SIZE))
                                continue;
                        if (strlen(vol->username) != 0 &&
@@ -1851,6 +1854,8 @@ cifs_put_smb_ses(struct cifsSesInfo *ses)
        cifs_put_tcp_session(server);
 }
 
+static bool warned_on_ntlm;  /* globals init to false automatically */
+
 static struct cifsSesInfo *
 cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
 {
@@ -1906,9 +1911,11 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
        else
                sprintf(ses->serverName, "%pI4", &addr->sin_addr);
 
-       if (volume_info->username)
-               strncpy(ses->userName, volume_info->username,
-                       MAX_USERNAME_SIZE);
+       if (volume_info->username) {
+               ses->user_name = kstrdup(volume_info->username, GFP_KERNEL);
+               if (!ses->user_name)
+                       goto get_ses_fail;
+       }
 
        /* volume_info->password freed at unmount */
        if (volume_info->password) {
@@ -1923,6 +1930,15 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
        }
        ses->cred_uid = volume_info->cred_uid;
        ses->linux_uid = volume_info->linux_uid;
+
+       /* ntlmv2 is much stronger than ntlm security, and has been broadly
+       supported for many years, time to update default security mechanism */
+       if ((volume_info->secFlg == 0) && warned_on_ntlm == false) {
+               warned_on_ntlm = true;
+               cERROR(1, "default security mechanism requested.  The default "
+                       "security mechanism will be upgraded from ntlm to "
+                       "ntlmv2 in kernel release 2.6.41");
+       }
        ses->overrideSecFlg = volume_info->secFlg;
 
        mutex_lock(&ses->session_mutex);
@@ -2276,7 +2292,7 @@ static int
 generic_ip_connect(struct TCP_Server_Info *server)
 {
        int rc = 0;
-       unsigned short int sport;
+       __be16 sport;
        int slen, sfamily;
        struct socket *socket = server->ssocket;
        struct sockaddr *saddr;
@@ -2361,7 +2377,7 @@ generic_ip_connect(struct TCP_Server_Info *server)
 static int
 ip_connect(struct TCP_Server_Info *server)
 {
-       unsigned short int *sport;
+       __be16 *sport;
        struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&server->dstaddr;
        struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
 
@@ -2826,7 +2842,7 @@ try_mount_again:
 
 remote_path_check:
        /* check if a whole path (including prepath) is not remote */
-       if (!rc && cifs_sb->prepathlen && tcon) {
+       if (!rc && tcon) {
                /* build_path_to_root works only when we have a valid tcon */
                full_path = cifs_build_path_to_root(cifs_sb, tcon);
                if (full_path == NULL) {
index c27d236738fc08ff80d32eceabc8f412140afbb2..faf59529e847a2adceb9728d10e739adc822f1f5 100644 (file)
@@ -575,8 +575,10 @@ reopen_error_exit:
 
 int cifs_close(struct inode *inode, struct file *file)
 {
-       cifsFileInfo_put(file->private_data);
-       file->private_data = NULL;
+       if (file->private_data != NULL) {
+               cifsFileInfo_put(file->private_data);
+               file->private_data = NULL;
+       }
 
        /* return code from the ->release op is always ignored */
        return 0;
@@ -970,6 +972,9 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
             total_written += bytes_written) {
                rc = -EAGAIN;
                while (rc == -EAGAIN) {
+                       struct kvec iov[2];
+                       unsigned int len;
+
                        if (open_file->invalidHandle) {
                                /* we could deadlock if we called
                                   filemap_fdatawait from here so tell
@@ -979,31 +984,14 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file,
                                if (rc != 0)
                                        break;
                        }
-                       if (experimEnabled || (pTcon->ses->server &&
-                               ((pTcon->ses->server->secMode &
-                               (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
-                               == 0))) {
-                               struct kvec iov[2];
-                               unsigned int len;
-
-                               len = min((size_t)cifs_sb->wsize,
-                                         write_size - total_written);
-                               /* iov[0] is reserved for smb header */
-                               iov[1].iov_base = (char *)write_data +
-                                                 total_written;
-                               iov[1].iov_len = len;
-                               rc = CIFSSMBWrite2(xid, pTcon,
-                                               open_file->netfid, len,
-                                               *poffset, &bytes_written,
-                                               iov, 1, 0);
-                       } else
-                               rc = CIFSSMBWrite(xid, pTcon,
-                                        open_file->netfid,
-                                        min_t(const int, cifs_sb->wsize,
-                                              write_size - total_written),
-                                        *poffset, &bytes_written,
-                                        write_data + total_written,
-                                        NULL, 0);
+
+                       len = min((size_t)cifs_sb->wsize,
+                                 write_size - total_written);
+                       /* iov[0] is reserved for smb header */
+                       iov[1].iov_base = (char *)write_data + total_written;
+                       iov[1].iov_len = len;
+                       rc = CIFSSMBWrite2(xid, pTcon, open_file->netfid, len,
+                                          *poffset, &bytes_written, iov, 1, 0);
                }
                if (rc || (bytes_written == 0)) {
                        if (total_written)
@@ -1240,12 +1228,6 @@ static int cifs_writepages(struct address_space *mapping,
        }
 
        tcon = tlink_tcon(open_file->tlink);
-       if (!experimEnabled && tcon->ses->server->secMode &
-                       (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
-               cifsFileInfo_put(open_file);
-               kfree(iov);
-               return generic_writepages(mapping, wbc);
-       }
        cifsFileInfo_put(open_file);
 
        xid = GetXid();
@@ -1980,6 +1962,24 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size,
        return total_read;
 }
 
+/*
+ * If the page is mmap'ed into a process' page tables, then we need to make
+ * sure that it doesn't change while being written back.
+ */
+static int
+cifs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+       struct page *page = vmf->page;
+
+       lock_page(page);
+       return VM_FAULT_LOCKED;
+}
+
+static struct vm_operations_struct cifs_file_vm_ops = {
+       .fault = filemap_fault,
+       .page_mkwrite = cifs_page_mkwrite,
+};
+
 int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
 {
        int rc, xid;
@@ -1991,6 +1991,8 @@ int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
                cifs_invalidate_mapping(inode);
 
        rc = generic_file_mmap(file, vma);
+       if (rc == 0)
+               vma->vm_ops = &cifs_file_vm_ops;
        FreeXid(xid);
        return rc;
 }
@@ -2007,6 +2009,8 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma)
                return rc;
        }
        rc = generic_file_mmap(file, vma);
+       if (rc == 0)
+               vma->vm_ops = &cifs_file_vm_ops;
        FreeXid(xid);
        return rc;
 }
index e8804d3734044f578da6d4427e4961431d61ae5a..ce417a9764a3fe5c3963e1e93fe5e5b17bf7390c 100644 (file)
@@ -239,7 +239,7 @@ CIFSQueryMFSymLink(const int xid, struct cifsTconInfo *tcon,
        if (rc != 0)
                return rc;
 
-       if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) {
+       if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
                CIFSSMBClose(xid, tcon, netfid);
                /* it's not a symlink */
                return -EINVAL;
@@ -316,7 +316,7 @@ CIFSCheckMFSymlink(struct cifs_fattr *fattr,
        if (rc != 0)
                goto out;
 
-       if (file_info.EndOfFile != CIFS_MF_SYMLINK_FILE_SIZE) {
+       if (file_info.EndOfFile != cpu_to_le64(CIFS_MF_SYMLINK_FILE_SIZE)) {
                CIFSSMBClose(xid, pTcon, netfid);
                /* it's not a symlink */
                goto out;
index 2a930a752a784faea9ee912211c3f7a88e1ce9d5..0c684ae4c07163140f4d9009b2d2ccd1f0c86dd2 100644 (file)
@@ -100,6 +100,7 @@ sesInfoFree(struct cifsSesInfo *buf_to_free)
                memset(buf_to_free->password, 0, strlen(buf_to_free->password));
                kfree(buf_to_free->password);
        }
+       kfree(buf_to_free->user_name);
        kfree(buf_to_free->domainName);
        kfree(buf_to_free);
 }
@@ -520,7 +521,7 @@ is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv)
                        (struct smb_com_transaction_change_notify_rsp *)buf;
                struct file_notify_information *pnotify;
                __u32 data_offset = 0;
-               if (pSMBr->ByteCount > sizeof(struct file_notify_information)) {
+               if (get_bcc_le(buf) > sizeof(struct file_notify_information)) {
                        data_offset = le32_to_cpu(pSMBr->DataOffset);
 
                        pnotify = (struct file_notify_information *)
index 16765703131be6288e41f0d22d6994ffe3d7685f..f6728eb6f4b94774431136a8700ce9e96b4d2940 100644 (file)
@@ -219,12 +219,12 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
                bcc_ptr++;
        } */
        /* copy user */
-       if (ses->userName == NULL) {
+       if (ses->user_name == NULL) {
                /* null user mount */
                *bcc_ptr = 0;
                *(bcc_ptr+1) = 0;
        } else {
-               bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->userName,
+               bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->user_name,
                                          MAX_USERNAME_SIZE, nls_cp);
        }
        bcc_ptr += 2 * bytes_ret;
@@ -244,12 +244,11 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifsSesInfo *ses,
        /* copy user */
        /* BB what about null user mounts - check that we do this BB */
        /* copy user */
-       if (ses->userName == NULL) {
-               /* BB what about null user mounts - check that we do this BB */
-       } else {
-               strncpy(bcc_ptr, ses->userName, MAX_USERNAME_SIZE);
-       }
-       bcc_ptr += strnlen(ses->userName, MAX_USERNAME_SIZE);
+       if (ses->user_name != NULL)
+               strncpy(bcc_ptr, ses->user_name, MAX_USERNAME_SIZE);
+       /* else null user mount */
+
+       bcc_ptr += strnlen(ses->user_name, MAX_USERNAME_SIZE);
        *bcc_ptr = 0;
        bcc_ptr++; /* account for null termination */
 
@@ -405,8 +404,8 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
        /* BB spec says that if AvId field of MsvAvTimestamp is populated then
                we must set the MIC field of the AUTHENTICATE_MESSAGE */
        ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags);
-       tioffset = cpu_to_le16(pblob->TargetInfoArray.BufferOffset);
-       tilen = cpu_to_le16(pblob->TargetInfoArray.Length);
+       tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset);
+       tilen = le16_to_cpu(pblob->TargetInfoArray.Length);
        if (tilen) {
                ses->auth_key.response = kmalloc(tilen, GFP_KERNEL);
                if (!ses->auth_key.response) {
@@ -523,14 +522,14 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
                tmp += len;
        }
 
-       if (ses->userName == NULL) {
+       if (ses->user_name == NULL) {
                sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
                sec_blob->UserName.Length = 0;
                sec_blob->UserName.MaximumLength = 0;
                tmp += 2;
        } else {
                int len;
-               len = cifs_strtoUCS((__le16 *)tmp, ses->userName,
+               len = cifs_strtoUCS((__le16 *)tmp, ses->user_name,
                                    MAX_USERNAME_SIZE, nls_cp);
                len *= 2; /* unicode is 2 bytes each */
                sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
index ad25c4cec7d50a7185459609bf6e5f63b9e9dcbd..129a357309946291b62f670e4ebdf978c7d8b947 100644 (file)
@@ -2131,7 +2131,7 @@ EXPORT_SYMBOL(d_rehash);
  */
 void dentry_update_name_case(struct dentry *dentry, struct qstr *name)
 {
-       BUG_ON(!mutex_is_locked(&dentry->d_inode->i_mutex));
+       BUG_ON(!mutex_is_locked(&dentry->d_parent->d_inode->i_mutex));
        BUG_ON(dentry->d_name.len != name->len); /* d_lookup gives this */
 
        spin_lock(&dentry->d_lock);
index e25e99bf7ee13321afc8702bf91506a08557f148..d0f53538a57fd8663b03443898e4d12492ff399b 100644 (file)
@@ -86,8 +86,8 @@
 
 #ifdef CONFIG_QUOTA
 /* Amount of blocks needed for quota update - we know that the structure was
- * allocated so we need to update only inode+data */
-#define EXT4_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 2 : 0)
+ * allocated so we need to update only data block */
+#define EXT4_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 1 : 0)
 /* Amount of blocks needed for quota insert/delete - we do some block writes
  * but inode, sb and group updates are done only once */
 #define EXT4_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\
index 4673bc05274f4a9aa3cde9c9d933a2232954d17d..e9473cbe80dfd00a7245e13f4de57229011a7bb2 100644 (file)
@@ -125,9 +125,11 @@ extern int ext4_flush_completed_IO(struct inode *inode)
  * the parent directory's parent as well, and so on recursively, if
  * they are also freshly created.
  */
-static void ext4_sync_parent(struct inode *inode)
+static int ext4_sync_parent(struct inode *inode)
 {
+       struct writeback_control wbc;
        struct dentry *dentry = NULL;
+       int ret = 0;
 
        while (inode && ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) {
                ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY);
@@ -136,8 +138,17 @@ static void ext4_sync_parent(struct inode *inode)
                if (!dentry || !dentry->d_parent || !dentry->d_parent->d_inode)
                        break;
                inode = dentry->d_parent->d_inode;
-               sync_mapping_buffers(inode->i_mapping);
+               ret = sync_mapping_buffers(inode->i_mapping);
+               if (ret)
+                       break;
+               memset(&wbc, 0, sizeof(wbc));
+               wbc.sync_mode = WB_SYNC_ALL;
+               wbc.nr_to_write = 0;         /* only write out the inode */
+               ret = sync_inode(inode, &wbc);
+               if (ret)
+                       break;
        }
+       return ret;
 }
 
 /*
@@ -176,7 +187,7 @@ int ext4_sync_file(struct file *file, int datasync)
        if (!journal) {
                ret = generic_file_fsync(file, datasync);
                if (!ret && !list_empty(&inode->i_dentry))
-                       ext4_sync_parent(inode);
+                       ret = ext4_sync_parent(inode);
                goto out;
        }
 
index ad8e303c0d2997c396489d80b8b210fdad67a092..f2fa5e8a582caf92dba32df3cfad714920a85721 100644 (file)
@@ -2502,6 +2502,7 @@ static int ext4_da_get_block_prep(struct inode *inode, sector_t iblock,
                 * for partial write.
                 */
                set_buffer_new(bh);
+               set_buffer_mapped(bh);
        }
        return 0;
 }
@@ -4429,8 +4430,8 @@ void ext4_truncate(struct inode *inode)
        Indirect chain[4];
        Indirect *partial;
        __le32 nr = 0;
-       int n;
-       ext4_lblk_t last_block;
+       int n = 0;
+       ext4_lblk_t last_block, max_block;
        unsigned blocksize = inode->i_sb->s_blocksize;
 
        trace_ext4_truncate_enter(inode);
@@ -4455,14 +4456,18 @@ void ext4_truncate(struct inode *inode)
 
        last_block = (inode->i_size + blocksize-1)
                                        >> EXT4_BLOCK_SIZE_BITS(inode->i_sb);
+       max_block = (EXT4_SB(inode->i_sb)->s_bitmap_maxbytes + blocksize-1)
+                                       >> EXT4_BLOCK_SIZE_BITS(inode->i_sb);
 
        if (inode->i_size & (blocksize - 1))
                if (ext4_block_truncate_page(handle, mapping, inode->i_size))
                        goto out_stop;
 
-       n = ext4_block_to_path(inode, last_block, offsets, NULL);
-       if (n == 0)
-               goto out_stop;  /* error */
+       if (last_block != max_block) {
+               n = ext4_block_to_path(inode, last_block, offsets, NULL);
+               if (n == 0)
+                       goto out_stop;  /* error */
+       }
 
        /*
         * OK.  This truncate is going to happen.  We add the inode to the
@@ -4493,7 +4498,13 @@ void ext4_truncate(struct inode *inode)
         */
        ei->i_disksize = inode->i_size;
 
-       if (n == 1) {           /* direct blocks */
+       if (last_block == max_block) {
+               /*
+                * It is unnecessary to free any data blocks if last_block is
+                * equal to the indirect block limit.
+                */
+               goto out_unlock;
+       } else if (n == 1) {            /* direct blocks */
                ext4_free_data(handle, inode, NULL, i_data+offsets[0],
                               i_data + EXT4_NDIR_BLOCKS);
                goto do_indirects;
@@ -4553,6 +4564,7 @@ do_indirects:
                ;
        }
 
+out_unlock:
        up_write(&ei->i_data_sem);
        inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
        ext4_mark_inode_dirty(handle, inode);
@@ -5398,13 +5410,12 @@ static int ext4_indirect_trans_blocks(struct inode *inode, int nrblocks,
        /* if nrblocks are contiguous */
        if (chunk) {
                /*
-                * With N contiguous data blocks, it need at most
-                * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) indirect blocks
-                * 2 dindirect blocks
-                * 1 tindirect block
+                * With N contiguous data blocks, we need at most
+                * N/EXT4_ADDR_PER_BLOCK(inode->i_sb) + 1 indirect blocks,
+                * 2 dindirect blocks, and 1 tindirect block
                 */
-               indirects = nrblocks / EXT4_ADDR_PER_BLOCK(inode->i_sb);
-               return indirects + 3;
+               return DIV_ROUND_UP(nrblocks,
+                                   EXT4_ADDR_PER_BLOCK(inode->i_sb)) + 4;
        }
        /*
         * if nrblocks are not contiguous, worse case, each block touch
index 056474b7b8e0a364f0dff94912b47f0000692118..8553dfb310afd7ac2209d186125287e99a867f61 100644 (file)
@@ -242,27 +242,44 @@ static void ext4_put_nojournal(handle_t *handle)
  * journal_end calls result in the superblock being marked dirty, so
  * that sync() will call the filesystem's write_super callback if
  * appropriate.
+ *
+ * To avoid j_barrier hold in userspace when a user calls freeze(),
+ * ext4 prevents a new handle from being started by s_frozen, which
+ * is in an upper layer.
  */
 handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks)
 {
        journal_t *journal;
+       handle_t  *handle;
 
        if (sb->s_flags & MS_RDONLY)
                return ERR_PTR(-EROFS);
 
-       vfs_check_frozen(sb, SB_FREEZE_TRANS);
-       /* Special case here: if the journal has aborted behind our
-        * backs (eg. EIO in the commit thread), then we still need to
-        * take the FS itself readonly cleanly. */
        journal = EXT4_SB(sb)->s_journal;
-       if (journal) {
-               if (is_journal_aborted(journal)) {
-                       ext4_abort(sb, "Detected aborted journal");
-                       return ERR_PTR(-EROFS);
-               }
-               return jbd2_journal_start(journal, nblocks);
+       handle = ext4_journal_current_handle();
+
+       /*
+        * If a handle has been started, it should be allowed to
+        * finish, otherwise deadlock could happen between freeze
+        * and others(e.g. truncate) due to the restart of the
+        * journal handle if the filesystem is forzen and active
+        * handles are not stopped.
+        */
+       if (!handle)
+               vfs_check_frozen(sb, SB_FREEZE_TRANS);
+
+       if (!journal)
+               return ext4_get_nojournal();
+       /*
+        * Special case here: if the journal has aborted behind our
+        * backs (eg. EIO in the commit thread), then we still need to
+        * take the FS itself readonly cleanly.
+        */
+       if (is_journal_aborted(journal)) {
+               ext4_abort(sb, "Detected aborted journal");
+               return ERR_PTR(-EROFS);
        }
-       return ext4_get_nojournal();
+       return jbd2_journal_start(journal, nblocks);
 }
 
 /*
@@ -2975,6 +2992,12 @@ static int ext4_register_li_request(struct super_block *sb,
        mutex_unlock(&ext4_li_info->li_list_mtx);
 
        sbi->s_li_request = elr;
+       /*
+        * set elr to NULL here since it has been inserted to
+        * the request_list and the removal and free of it is
+        * handled by ext4_clear_request_list from now on.
+        */
+       elr = NULL;
 
        if (!(ext4_li_info->li_state & EXT4_LAZYINIT_RUNNING)) {
                ret = ext4_run_lazyinit_thread();
@@ -3385,6 +3408,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
        get_random_bytes(&sbi->s_next_generation, sizeof(u32));
        spin_lock_init(&sbi->s_next_gen_lock);
 
+       init_timer(&sbi->s_err_report);
+       sbi->s_err_report.function = print_daily_error_info;
+       sbi->s_err_report.data = (unsigned long) sb;
+
        err = percpu_counter_init(&sbi->s_freeblocks_counter,
                        ext4_count_free_blocks(sb));
        if (!err) {
@@ -3646,9 +3673,6 @@ no_journal:
                 "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
                 *sbi->s_es->s_mount_opts ? "; " : "", orig_data);
 
-       init_timer(&sbi->s_err_report);
-       sbi->s_err_report.function = print_daily_error_info;
-       sbi->s_err_report.data = (unsigned long) sb;
        if (es->s_error_count)
                mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */
 
@@ -3672,6 +3696,7 @@ failed_mount_wq:
                sbi->s_journal = NULL;
        }
 failed_mount3:
+       del_timer(&sbi->s_err_report);
        if (sbi->s_flex_groups) {
                if (is_vmalloc_addr(sbi->s_flex_groups))
                        vfree(sbi->s_flex_groups);
@@ -4138,6 +4163,11 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
 /*
  * LVM calls this function before a (read-only) snapshot is created.  This
  * gives us a chance to flush the journal completely and mark the fs clean.
+ *
+ * Note that only this function cannot bring a filesystem to be in a clean
+ * state independently, because ext4 prevents a new handle from being started
+ * by @sb->s_frozen, which stays in an upper layer.  It thus needs help from
+ * the upper layer.
  */
 static int ext4_freeze(struct super_block *sb)
 {
@@ -4614,11 +4644,24 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id,
 
 static int ext4_quota_off(struct super_block *sb, int type)
 {
+       struct inode *inode = sb_dqopt(sb)->files[type];
+       handle_t *handle;
+
        /* Force all delayed allocation blocks to be allocated.
         * Caller already holds s_umount sem */
        if (test_opt(sb, DELALLOC))
                sync_filesystem(sb);
 
+       /* Update modification times of quota files when userspace can
+        * start looking at them */
+       handle = ext4_journal_start(inode, 1);
+       if (IS_ERR(handle))
+               goto out;
+       inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+       ext4_mark_inode_dirty(handle, inode);
+       ext4_journal_stop(handle);
+
+out:
        return dquot_quota_off(sb, type);
 }
 
@@ -4714,9 +4757,8 @@ out:
        if (inode->i_size < off + len) {
                i_size_write(inode, off + len);
                EXT4_I(inode)->i_disksize = inode->i_size;
+               ext4_mark_inode_dirty(handle, inode);
        }
-       inode->i_mtime = inode->i_ctime = CURRENT_TIME;
-       ext4_mark_inode_dirty(handle, inode);
        mutex_unlock(&inode->i_mutex);
        return len;
 }
index bf93ad2bee07fb9e8d0c6475a029bf740f0f6d6c..6b088641f5bf24ce72311a3b8073ce44516b8624 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/exportfs.h>
 #include <linux/fs_struct.h>
 #include <linux/fsnotify.h>
+#include <linux/personality.h>
 #include <asm/uaccess.h>
 #include "internal.h"
 
index 751d6b255a12ab1abcf71e817f80f4ce11bbd647..0845f84f2a5fe2b8eaf95aaac05a06cfe21f79e0 100644 (file)
@@ -110,14 +110,13 @@ int unregister_filesystem(struct file_system_type * fs)
                        *tmp = fs->next;
                        fs->next = NULL;
                        write_unlock(&file_systems_lock);
+                       synchronize_rcu();
                        return 0;
                }
                tmp = &(*tmp)->next;
        }
        write_unlock(&file_systems_lock);
 
-       synchronize_rcu();
-
        return -EINVAL;
 }
 
index c71995b111bf6f4347ffb313692c4ee66ff6f74e..0f5c4f9d5d62beee06937a8d0c98bd015f7dc5ee 100644 (file)
@@ -884,8 +884,8 @@ static int gfs2_write_end(struct file *file, struct address_space *mapping,
        }
 
        brelse(dibh);
-       gfs2_trans_end(sdp);
 failed:
+       gfs2_trans_end(sdp);
        if (al) {
                gfs2_inplace_release(ip);
                gfs2_quota_unlock(ip);
index 5c356d09c321c10133afc7cf93aba2eddd1cb3c1..f789c5732b7c5fc695c7fdb97183402613dfd3c5 100644 (file)
@@ -1506,7 +1506,7 @@ struct inode *gfs2_dir_search(struct inode *dir, const struct qstr *name)
                inode = gfs2_inode_lookup(dir->i_sb, 
                                be16_to_cpu(dent->de_type),
                                be64_to_cpu(dent->de_inum.no_addr),
-                               be64_to_cpu(dent->de_inum.no_formal_ino));
+                               be64_to_cpu(dent->de_inum.no_formal_ino), 0);
                brelse(bh);
                return inode;
        }
index b2682e073eee0a593b1ab43c74291aa08e6af674..e48310885c48e8866c35647f7ea242e702df4ab2 100644 (file)
@@ -617,18 +617,51 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        return generic_file_aio_write(iocb, iov, nr_segs, pos);
 }
 
-static void empty_write_end(struct page *page, unsigned from,
-                          unsigned to)
+static int empty_write_end(struct page *page, unsigned from,
+                          unsigned to, int mode)
 {
-       struct gfs2_inode *ip = GFS2_I(page->mapping->host);
+       struct inode *inode = page->mapping->host;
+       struct gfs2_inode *ip = GFS2_I(inode);
+       struct buffer_head *bh;
+       unsigned offset, blksize = 1 << inode->i_blkbits;
+       pgoff_t end_index = i_size_read(inode) >> PAGE_CACHE_SHIFT;
 
        zero_user(page, from, to-from);
        mark_page_accessed(page);
 
-       if (!gfs2_is_writeback(ip))
-               gfs2_page_add_databufs(ip, page, from, to);
+       if (page->index < end_index || !(mode & FALLOC_FL_KEEP_SIZE)) {
+               if (!gfs2_is_writeback(ip))
+                       gfs2_page_add_databufs(ip, page, from, to);
+
+               block_commit_write(page, from, to);
+               return 0;
+       }
+
+       offset = 0;
+       bh = page_buffers(page);
+       while (offset < to) {
+               if (offset >= from) {
+                       set_buffer_uptodate(bh);
+                       mark_buffer_dirty(bh);
+                       clear_buffer_new(bh);
+                       write_dirty_buffer(bh, WRITE);
+               }
+               offset += blksize;
+               bh = bh->b_this_page;
+       }
 
-       block_commit_write(page, from, to);
+       offset = 0;
+       bh = page_buffers(page);
+       while (offset < to) {
+               if (offset >= from) {
+                       wait_on_buffer(bh);
+                       if (!buffer_uptodate(bh))
+                               return -EIO;
+               }
+               offset += blksize;
+               bh = bh->b_this_page;
+       }
+       return 0;
 }
 
 static int needs_empty_write(sector_t block, struct inode *inode)
@@ -643,7 +676,8 @@ static int needs_empty_write(sector_t block, struct inode *inode)
        return !buffer_mapped(&bh_map);
 }
 
-static int write_empty_blocks(struct page *page, unsigned from, unsigned to)
+static int write_empty_blocks(struct page *page, unsigned from, unsigned to,
+                             int mode)
 {
        struct inode *inode = page->mapping->host;
        unsigned start, end, next, blksize;
@@ -668,7 +702,9 @@ static int write_empty_blocks(struct page *page, unsigned from, unsigned to)
                                                          gfs2_block_map);
                                if (unlikely(ret))
                                        return ret;
-                               empty_write_end(page, start, end);
+                               ret = empty_write_end(page, start, end, mode);
+                               if (unlikely(ret))
+                                       return ret;
                                end = 0;
                        }
                        start = next;
@@ -682,7 +718,9 @@ static int write_empty_blocks(struct page *page, unsigned from, unsigned to)
                ret = __block_write_begin(page, start, end - start, gfs2_block_map);
                if (unlikely(ret))
                        return ret;
-               empty_write_end(page, start, end);
+               ret = empty_write_end(page, start, end, mode);
+               if (unlikely(ret))
+                       return ret;
        }
 
        return 0;
@@ -731,7 +769,7 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len,
 
                if (curr == end)
                        to = end_offset;
-               error = write_empty_blocks(page, from, to);
+               error = write_empty_blocks(page, from, to, mode);
                if (!error && offset + to > inode->i_size &&
                    !(mode & FALLOC_FL_KEEP_SIZE)) {
                        i_size_write(inode, offset + to);
index 3754e3cbf02bce2bf04b683bc9d36d48ec6a8bbe..25eeb2bcee47e4e10d289510718d7c08539a3acb 100644 (file)
@@ -385,6 +385,10 @@ static int trans_go_demote_ok(const struct gfs2_glock *gl)
 static void iopen_go_callback(struct gfs2_glock *gl)
 {
        struct gfs2_inode *ip = (struct gfs2_inode *)gl->gl_object;
+       struct gfs2_sbd *sdp = gl->gl_sbd;
+
+       if (sdp->sd_vfs->s_flags & MS_RDONLY)
+               return;
 
        if (gl->gl_demote_state == LM_ST_UNLOCKED &&
            gl->gl_state == LM_ST_SHARED && ip) {
index 97d54a28776a1851a004b62a7b7ecc41a84d0e04..9134dcb894790adfd487101565703e4e24a37075 100644 (file)
@@ -40,37 +40,61 @@ struct gfs2_inum_range_host {
        u64 ir_length;
 };
 
+struct gfs2_skip_data {
+       u64 no_addr;
+       int skipped;
+       int non_block;
+};
+
 static int iget_test(struct inode *inode, void *opaque)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
-       u64 *no_addr = opaque;
+       struct gfs2_skip_data *data = opaque;
 
-       if (ip->i_no_addr == *no_addr)
+       if (ip->i_no_addr == data->no_addr) {
+               if (data->non_block &&
+                   inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE)) {
+                       data->skipped = 1;
+                       return 0;
+               }
                return 1;
-
+       }
        return 0;
 }
 
 static int iget_set(struct inode *inode, void *opaque)
 {
        struct gfs2_inode *ip = GFS2_I(inode);
-       u64 *no_addr = opaque;
+       struct gfs2_skip_data *data = opaque;
 
-       inode->i_ino = (unsigned long)*no_addr;
-       ip->i_no_addr = *no_addr;
+       if (data->skipped)
+               return -ENOENT;
+       inode->i_ino = (unsigned long)(data->no_addr);
+       ip->i_no_addr = data->no_addr;
        return 0;
 }
 
 struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr)
 {
        unsigned long hash = (unsigned long)no_addr;
-       return ilookup5(sb, hash, iget_test, &no_addr);
+       struct gfs2_skip_data data;
+
+       data.no_addr = no_addr;
+       data.skipped = 0;
+       data.non_block = 0;
+       return ilookup5(sb, hash, iget_test, &data);
 }
 
-static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr)
+static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr,
+                              int non_block)
 {
+       struct gfs2_skip_data data;
        unsigned long hash = (unsigned long)no_addr;
-       return iget5_locked(sb, hash, iget_test, iget_set, &no_addr);
+
+       data.no_addr = no_addr;
+       data.skipped = 0;
+       data.non_block = non_block;
+       return iget5_locked(sb, hash, iget_test, iget_set, &data);
 }
 
 /**
@@ -111,19 +135,20 @@ static void gfs2_set_iop(struct inode *inode)
  * @sb: The super block
  * @no_addr: The inode number
  * @type: The type of the inode
+ * non_block: Can we block on inodes that are being freed?
  *
  * Returns: A VFS inode, or an error
  */
 
 struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type,
-                               u64 no_addr, u64 no_formal_ino)
+                               u64 no_addr, u64 no_formal_ino, int non_block)
 {
        struct inode *inode;
        struct gfs2_inode *ip;
        struct gfs2_glock *io_gl = NULL;
        int error;
 
-       inode = gfs2_iget(sb, no_addr);
+       inode = gfs2_iget(sb, no_addr, non_block);
        ip = GFS2_I(inode);
 
        if (!inode)
@@ -185,11 +210,12 @@ struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr,
 {
        struct super_block *sb = sdp->sd_vfs;
        struct gfs2_holder i_gh;
-       struct inode *inode;
+       struct inode *inode = NULL;
        int error;
 
+       /* Must not read in block until block type is verified */
        error = gfs2_glock_nq_num(sdp, no_addr, &gfs2_inode_glops,
-                                 LM_ST_SHARED, LM_FLAG_ANY, &i_gh);
+                                 LM_ST_EXCLUSIVE, GL_SKIP, &i_gh);
        if (error)
                return ERR_PTR(error);
 
@@ -197,7 +223,7 @@ struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr,
        if (error)
                goto fail;
 
-       inode = gfs2_inode_lookup(sb, DT_UNKNOWN, no_addr, 0);
+       inode = gfs2_inode_lookup(sb, DT_UNKNOWN, no_addr, 0, 1);
        if (IS_ERR(inode))
                goto fail;
 
@@ -843,7 +869,7 @@ struct inode *gfs2_createi(struct gfs2_holder *ghs, const struct qstr *name,
                goto fail_gunlock2;
 
        inode = gfs2_inode_lookup(dir->i_sb, IF2DT(mode), inum.no_addr,
-                                 inum.no_formal_ino);
+                                 inum.no_formal_ino, 0);
        if (IS_ERR(inode))
                goto fail_gunlock2;
 
index 3e00a66e7cbd04c707ce22686647e5800c7621a4..099ca305e518d25c8251e5163456635087b26828 100644 (file)
@@ -97,7 +97,8 @@ err:
 }
 
 extern struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned type, 
-                                      u64 no_addr, u64 no_formal_ino);
+                                      u64 no_addr, u64 no_formal_ino,
+                                      int non_block);
 extern struct inode *gfs2_lookup_by_inum(struct gfs2_sbd *sdp, u64 no_addr,
                                         u64 *no_formal_ino,
                                         unsigned int blktype);
index 42ef24355afbdb112e366269d3835cc40b37cff6..d3c69eb91c74e29c05af120f3938bffb9ebb1d75 100644 (file)
@@ -430,7 +430,7 @@ static int gfs2_lookup_root(struct super_block *sb, struct dentry **dptr,
        struct dentry *dentry;
        struct inode *inode;
 
-       inode = gfs2_inode_lookup(sb, DT_DIR, no_addr, 0);
+       inode = gfs2_inode_lookup(sb, DT_DIR, no_addr, 0, 0);
        if (IS_ERR(inode)) {
                fs_err(sdp, "can't read in %s inode: %ld\n", name, PTR_ERR(inode));
                return PTR_ERR(inode);
index cf930cd9664af9ca0c351e08c0d852f52c52417d..6fcae8469f6d76a178710ee2ece82108c8ec2ba1 100644 (file)
@@ -945,7 +945,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip
                /* rgblk_search can return a block < goal, so we need to
                   keep it marching forward. */
                no_addr = block + rgd->rd_data0;
-               goal++;
+               goal = max(block + 1, goal + 1);
                if (*last_unlinked != NO_BLOCK && no_addr <= *last_unlinked)
                        continue;
                if (no_addr == skip)
@@ -971,7 +971,7 @@ static void try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, u64 skip
                        found++;
 
                /* Limit reclaim to sensible number of tasks */
-               if (found > 2*NR_CPUS)
+               if (found > NR_CPUS)
                        return;
        }
 
index a4e23d68a39862f08848c8a7d19136c1d6bb881e..b9f28e66dad190af29b389b2830f1ff66efff024 100644 (file)
@@ -1318,15 +1318,17 @@ static int gfs2_show_options(struct seq_file *s, struct vfsmount *mnt)
 
 static void gfs2_evict_inode(struct inode *inode)
 {
-       struct gfs2_sbd *sdp = inode->i_sb->s_fs_info;
+       struct super_block *sb = inode->i_sb;
+       struct gfs2_sbd *sdp = sb->s_fs_info;
        struct gfs2_inode *ip = GFS2_I(inode);
        struct gfs2_holder gh;
        int error;
 
-       if (inode->i_nlink)
+       if (inode->i_nlink || (sb->s_flags & MS_RDONLY))
                goto out;
 
-       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
+       /* Must not read inode block until block type has been verified */
+       error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, &gh);
        if (unlikely(error)) {
                gfs2_glock_dq_uninit(&ip->i_iopen_gh);
                goto out;
@@ -1336,6 +1338,12 @@ static void gfs2_evict_inode(struct inode *inode)
        if (error)
                goto out_truncate;
 
+       if (test_bit(GIF_INVALID, &ip->i_flags)) {
+               error = gfs2_inode_refresh(ip);
+               if (error)
+                       goto out_truncate;
+       }
+
        ip->i_iopen_gh.gh_flags |= GL_NOCACHE;
        gfs2_glock_dq_wait(&ip->i_iopen_gh);
        gfs2_holder_reinit(LM_ST_EXCLUSIVE, LM_FLAG_TRY_1CB | GL_NOCACHE, &ip->i_iopen_gh);
index 20af62f4304bc0624d6be46cefe68747a99689e3..6e28000a4b2168c36d1cee255058ac41b72f34eb 100644 (file)
@@ -105,6 +105,8 @@ static int journal_submit_commit_record(journal_t *journal,
        int ret;
        struct timespec now = current_kernel_time();
 
+       *cbh = NULL;
+
        if (is_journal_aborted(journal))
                return 0;
 
@@ -806,7 +808,7 @@ wait_for_iobuf:
                if (err)
                        __jbd2_journal_abort_hard(journal);
        }
-       if (!err && !is_journal_aborted(journal))
+       if (cbh)
                err = journal_wait_on_commit_record(journal, cbh);
        if (JBD2_HAS_INCOMPAT_FEATURE(journal,
                                      JBD2_FEATURE_INCOMPAT_ASYNC_COMMIT) &&
index aba8ebaec25c433dc2a6830d96e0082e1bedc696..e0ec3db1c395b6c338acc6f7c14af6a2c11eb067 100644 (file)
@@ -2413,10 +2413,12 @@ const char *jbd2_dev_to_name(dev_t device)
        new_dev = kmalloc(sizeof(struct devname_cache), GFP_KERNEL);
        if (!new_dev)
                return "NODEV-ALLOCFAILURE"; /* Something non-NULL */
+       bd = bdget(device);
        spin_lock(&devname_cache_lock);
        if (devcache[i]) {
                if (devcache[i]->device == device) {
                        kfree(new_dev);
+                       bdput(bd);
                        ret = devcache[i]->devname;
                        spin_unlock(&devname_cache_lock);
                        return ret;
@@ -2425,7 +2427,6 @@ const char *jbd2_dev_to_name(dev_t device)
        }
        devcache[i] = new_dev;
        devcache[i]->device = device;
-       bd = bdget(device);
        if (bd) {
                bdevname(bd, devcache[i]->devname);
                bdput(bd);
index e6cd6113872ccd4db1dadfa5deff08f90a45c8a0..54fc993e3027d4dff98dcf4f14ebbb4d817cdb0f 100644 (file)
@@ -697,6 +697,7 @@ static __always_inline void set_root_rcu(struct nameidata *nd)
                do {
                        seq = read_seqcount_begin(&fs->seq);
                        nd->root = fs->root;
+                       nd->seq = __read_seqcount_begin(&nd->root.dentry->d_seq);
                } while (read_seqcount_retry(&fs->seq, seq));
        }
 }
index 7dba2ed03429460f27aba058955208ed5dd929ec..d99bcf59e4c2fd23b2c03d2c9ed7471f7b2b230e 100644 (file)
@@ -1030,18 +1030,6 @@ const struct seq_operations mounts_op = {
        .show   = show_vfsmnt
 };
 
-static int uuid_is_nil(u8 *uuid)
-{
-       int i;
-       u8  *cp = (u8 *)uuid;
-
-       for (i = 0; i < 16; i++) {
-               if (*cp++)
-                       return 0;
-       }
-       return 1;
-}
-
 static int show_mountinfo(struct seq_file *m, void *v)
 {
        struct proc_mounts *p = m->private;
@@ -1085,10 +1073,6 @@ static int show_mountinfo(struct seq_file *m, void *v)
        if (IS_MNT_UNBINDABLE(mnt))
                seq_puts(m, " unbindable");
 
-       if (!uuid_is_nil(mnt->mnt_sb->s_uuid))
-               /* print the uuid */
-               seq_printf(m, " uuid:%pU", mnt->mnt_sb->s_uuid);
-
        /* Filesystem specific data */
        seq_puts(m, " - ");
        show_type(m, sb);
index af0c6279a4a7c131cd9c2a80e0764ba8ea50a6c9..e4cbc11a74ab56238687c5445989177a7714dd5a 100644 (file)
@@ -542,11 +542,15 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, u
        if (!nfs_need_commit(nfsi))
                return 0;
 
+       spin_lock(&inode->i_lock);
        ret = nfs_scan_list(nfsi, dst, idx_start, npages, NFS_PAGE_TAG_COMMIT);
        if (ret > 0)
                nfsi->ncommit -= ret;
+       spin_unlock(&inode->i_lock);
+
        if (nfs_need_commit(NFS_I(inode)))
                __mark_inode_dirty(inode, I_DIRTY_DATASYNC);
+
        return ret;
 }
 #else
@@ -1483,9 +1487,7 @@ int nfs_commit_inode(struct inode *inode, int how)
        res = nfs_commit_set_lock(NFS_I(inode), may_wait);
        if (res <= 0)
                goto out_mark_dirty;
-       spin_lock(&inode->i_lock);
        res = nfs_scan_commit(inode, &head, 0, 0);
-       spin_unlock(&inode->i_lock);
        if (res) {
                int error;
 
index 0c6d8167013749dce9028af641315dac7c3e4fa2..7c831a2731fa1210cf7b909113e12cfffc472c25 100644 (file)
@@ -38,7 +38,6 @@ nlm_fopen(struct svc_rqst *rqstp, struct nfs_fh *f, struct file **filp)
        exp_readlock();
        nfserr = nfsd_open(rqstp, &fh, S_IFREG, NFSD_MAY_LOCK, filp);
        fh_put(&fh);
-       rqstp->rq_client = NULL;
        exp_readunlock();
        /* We return nlm error codes as nlm doesn't know
         * about nfsd, but nfsd does know about nlm..
index 4b36ec3eb8eae69a422a7d235ef3fd930d90014d..4cf04e11c66ca39c80dc6b54b6854842de246826 100644 (file)
@@ -258,6 +258,7 @@ static void nfs4_put_deleg_lease(struct nfs4_file *fp)
        if (atomic_dec_and_test(&fp->fi_delegees)) {
                vfs_setlease(fp->fi_deleg_file, F_UNLCK, &fp->fi_lease);
                fp->fi_lease = NULL;
+               fput(fp->fi_deleg_file);
                fp->fi_deleg_file = NULL;
        }
 }
@@ -397,9 +398,12 @@ static void unhash_generic_stateid(struct nfs4_stateid *stp)
 
 static void free_generic_stateid(struct nfs4_stateid *stp)
 {
-       int oflag = nfs4_access_bmap_to_omode(stp);
+       int oflag;
 
-       nfs4_file_put_access(stp->st_file, oflag);
+       if (stp->st_access_bmap) {
+               oflag = nfs4_access_bmap_to_omode(stp);
+               nfs4_file_put_access(stp->st_file, oflag);
+       }
        put_nfs4_file(stp->st_file);
        kmem_cache_free(stateid_slab, stp);
 }
index 2e1cebde90df4c69baa21635e959f9d81c9809f1..129f3c9f62d589f44b947fccd04c8f745cdfb485 100644 (file)
@@ -1363,7 +1363,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
                goto out;
        if (!(iap->ia_valid & ATTR_MODE))
                iap->ia_mode = 0;
-       err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
+       err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_EXEC);
        if (err)
                goto out;
 
@@ -1385,6 +1385,13 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
        if (IS_ERR(dchild))
                goto out_nfserr;
 
+       /* If file doesn't exist, check for permissions to create one */
+       if (!dchild->d_inode) {
+               err = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
+               if (err)
+                       goto out;
+       }
+
        err = fh_compose(resfhp, fhp->fh_export, dchild, fhp);
        if (err)
                goto out;
index b10e3540d5b711e3077d44b9ad1a5b44f210c19a..ce4f624404255f899e1b10262abf3b862aec6be4 100644 (file)
@@ -1299,6 +1299,11 @@ static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags)
 
        BUG_ON (!data || !frags);
 
+       if (size < 2 * VBLK_SIZE_HEAD) {
+               ldm_error("Value of size is to small.");
+               return false;
+       }
+
        group = get_unaligned_be32(data + 0x08);
        rec   = get_unaligned_be16(data + 0x0C);
        num   = get_unaligned_be16(data + 0x0E);
@@ -1306,6 +1311,10 @@ static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags)
                ldm_error ("A VBLK claims to have %d parts.", num);
                return false;
        }
+       if (rec >= num) {
+               ldm_error("REC value (%d) exceeds NUM value (%d)", rec, num);
+               return false;
+       }
 
        list_for_each (item, frags) {
                f = list_entry (item, struct frag, list);
@@ -1334,10 +1343,9 @@ found:
 
        f->map |= (1 << rec);
 
-       if (num > 0) {
-               data += VBLK_SIZE_HEAD;
-               size -= VBLK_SIZE_HEAD;
-       }
+       data += VBLK_SIZE_HEAD;
+       size -= VBLK_SIZE_HEAD;
+
        memcpy (f->data+rec*(size-VBLK_SIZE_HEAD)+VBLK_SIZE_HEAD, data, size);
 
        return true;
index dd6628d3ba42e136b4e0f35165798899633332a6..dfa532730e55788a7459095ca9c788dbb58d6af9 100644 (file)
@@ -3124,11 +3124,16 @@ static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldi
 /* for the /proc/ directory itself, after non-process stuff has been done */
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
-       unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
-       struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode);
+       unsigned int nr;
+       struct task_struct *reaper;
        struct tgid_iter iter;
        struct pid_namespace *ns;
 
+       if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET)
+               goto out_no_task;
+       nr = filp->f_pos - FIRST_PROCESS_ENTRY;
+
+       reaper = get_proc_task(filp->f_path.dentry->d_inode);
        if (!reaper)
                goto out_no_task;
 
index 9eead2c796b7f5a77d242e0e7eda702f16ec297a..fbb0b478a346fbc77c854696c5e0e508760125ad 100644 (file)
@@ -112,6 +112,7 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize)
                SetPageDirty(page);
 
                unlock_page(page);
+               put_page(page);
        }
 
        return 0;
index 919f0de29d8f378cee69bb3c035d53eea6ddb312..e6493cac193d60d92c6e3e72d743d03f46a5796d 100644 (file)
 #ifndef __UBIFS_DEBUG_H__
 #define __UBIFS_DEBUG_H__
 
+/* Checking helper functions */
+typedef int (*dbg_leaf_callback)(struct ubifs_info *c,
+                                struct ubifs_zbranch *zbr, void *priv);
+typedef int (*dbg_znode_callback)(struct ubifs_info *c,
+                                 struct ubifs_znode *znode, void *priv);
+
 #ifdef CONFIG_UBIFS_FS_DEBUG
 
 /**
@@ -270,11 +276,6 @@ void dbg_dump_tnc(struct ubifs_info *c);
 void dbg_dump_index(struct ubifs_info *c);
 void dbg_dump_lpt_lebs(const struct ubifs_info *c);
 
-/* Checking helper functions */
-typedef int (*dbg_leaf_callback)(struct ubifs_info *c,
-                                struct ubifs_zbranch *zbr, void *priv);
-typedef int (*dbg_znode_callback)(struct ubifs_info *c,
-                                 struct ubifs_znode *znode, void *priv);
 int dbg_walk_index(struct ubifs_info *c, dbg_leaf_callback leaf_cb,
                   dbg_znode_callback znode_cb, void *priv);
 
@@ -295,7 +296,6 @@ int dbg_check_idx_size(struct ubifs_info *c, long long idx_size);
 int dbg_check_filesystem(struct ubifs_info *c);
 void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat,
                    int add_pos);
-int dbg_check_lprops(struct ubifs_info *c);
 int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
                        int row, int col);
 int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,
@@ -401,58 +401,94 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c);
 #define DBGKEY(key)  ((char *)(key))
 #define DBGKEY1(key) ((char *)(key))
 
-#define ubifs_debugging_init(c)                0
-#define ubifs_debugging_exit(c)                ({})
-
-#define dbg_ntype(type)                        ""
-#define dbg_cstate(cmt_state)                  ""
-#define dbg_jhead(jhead)                       ""
-#define dbg_get_key_dump(c, key)               ({})
-#define dbg_dump_inode(c, inode)               ({})
-#define dbg_dump_node(c, node)                 ({})
-#define dbg_dump_lpt_node(c, node, lnum, offs) ({})
-#define dbg_dump_budget_req(req)               ({})
-#define dbg_dump_lstats(lst)                   ({})
-#define dbg_dump_budg(c)                       ({})
-#define dbg_dump_lprop(c, lp)                  ({})
-#define dbg_dump_lprops(c)                     ({})
-#define dbg_dump_lpt_info(c)                   ({})
-#define dbg_dump_leb(c, lnum)                  ({})
-#define dbg_dump_znode(c, znode)               ({})
-#define dbg_dump_heap(c, heap, cat)            ({})
-#define dbg_dump_pnode(c, pnode, parent, iip)  ({})
-#define dbg_dump_tnc(c)                        ({})
-#define dbg_dump_index(c)                      ({})
-#define dbg_dump_lpt_lebs(c)                   ({})
-
-#define dbg_walk_index(c, leaf_cb, znode_cb, priv) 0
-#define dbg_old_index_check_init(c, zroot)         0
-#define dbg_save_space_info(c)                     ({})
-#define dbg_check_space_info(c)                    0
-#define dbg_check_old_index(c, zroot)              0
-#define dbg_check_cats(c)                          0
-#define dbg_check_ltab(c)                          0
-#define dbg_chk_lpt_free_spc(c)                    0
-#define dbg_chk_lpt_sz(c, action, len)             0
-#define dbg_check_synced_i_size(inode)             0
-#define dbg_check_dir_size(c, dir)                 0
-#define dbg_check_tnc(c, x)                        0
-#define dbg_check_idx_size(c, idx_size)            0
-#define dbg_check_filesystem(c)                    0
-#define dbg_check_heap(c, heap, cat, add_pos)      ({})
-#define dbg_check_lprops(c)                        0
-#define dbg_check_lpt_nodes(c, cnode, row, col)    0
-#define dbg_check_inode_size(c, inode, size)       0
-#define dbg_check_data_nodes_order(c, head)        0
-#define dbg_check_nondata_nodes_order(c, head)     0
-#define dbg_force_in_the_gaps_enabled              0
-#define dbg_force_in_the_gaps()                    0
-#define dbg_failure_mode                           0
-
-#define dbg_debugfs_init()                         0
-#define dbg_debugfs_exit()
-#define dbg_debugfs_init_fs(c)                     0
-#define dbg_debugfs_exit_fs(c)                     0
+static inline int ubifs_debugging_init(struct ubifs_info *c)      { return 0; }
+static inline void ubifs_debugging_exit(struct ubifs_info *c)     { return; }
+static inline const char *dbg_ntype(int type)                     { return ""; }
+static inline const char *dbg_cstate(int cmt_state)               { return ""; }
+static inline const char *dbg_jhead(int jhead)                    { return ""; }
+static inline const char *
+dbg_get_key_dump(const struct ubifs_info *c,
+                const union ubifs_key *key)                      { return ""; }
+static inline void dbg_dump_inode(const struct ubifs_info *c,
+                                 const struct inode *inode)      { return; }
+static inline void dbg_dump_node(const struct ubifs_info *c,
+                                const void *node)                { return; }
+static inline void dbg_dump_lpt_node(const struct ubifs_info *c,
+                                    void *node, int lnum,
+                                    int offs)                    { return; }
+static inline void
+dbg_dump_budget_req(const struct ubifs_budget_req *req)           { return; }
+static inline void
+dbg_dump_lstats(const struct ubifs_lp_stats *lst)                 { return; }
+static inline void dbg_dump_budg(struct ubifs_info *c)            { return; }
+static inline void dbg_dump_lprop(const struct ubifs_info *c,
+                                 const struct ubifs_lprops *lp)  { return; }
+static inline void dbg_dump_lprops(struct ubifs_info *c)          { return; }
+static inline void dbg_dump_lpt_info(struct ubifs_info *c)        { return; }
+static inline void dbg_dump_leb(const struct ubifs_info *c,
+                               int lnum)                         { return; }
+static inline void
+dbg_dump_znode(const struct ubifs_info *c,
+              const struct ubifs_znode *znode)                   { return; }
+static inline void dbg_dump_heap(struct ubifs_info *c,
+                                struct ubifs_lpt_heap *heap,
+                                int cat)                         { return; }
+static inline void dbg_dump_pnode(struct ubifs_info *c,
+                                 struct ubifs_pnode *pnode,
+                                 struct ubifs_nnode *parent,
+                                 int iip)                        { return; }
+static inline void dbg_dump_tnc(struct ubifs_info *c)             { return; }
+static inline void dbg_dump_index(struct ubifs_info *c)           { return; }
+static inline void dbg_dump_lpt_lebs(const struct ubifs_info *c)  { return; }
+
+static inline int dbg_walk_index(struct ubifs_info *c,
+                                dbg_leaf_callback leaf_cb,
+                                dbg_znode_callback znode_cb,
+                                void *priv)                      { return 0; }
+static inline void dbg_save_space_info(struct ubifs_info *c)      { return; }
+static inline int dbg_check_space_info(struct ubifs_info *c)      { return 0; }
+static inline int dbg_check_lprops(struct ubifs_info *c)          { return 0; }
+static inline int
+dbg_old_index_check_init(struct ubifs_info *c,
+                        struct ubifs_zbranch *zroot)             { return 0; }
+static inline int
+dbg_check_old_index(struct ubifs_info *c,
+                   struct ubifs_zbranch *zroot)                  { return 0; }
+static inline int dbg_check_cats(struct ubifs_info *c)            { return 0; }
+static inline int dbg_check_ltab(struct ubifs_info *c)            { return 0; }
+static inline int dbg_chk_lpt_free_spc(struct ubifs_info *c)      { return 0; }
+static inline int dbg_chk_lpt_sz(struct ubifs_info *c,
+                                int action, int len)             { return 0; }
+static inline int dbg_check_synced_i_size(struct inode *inode)    { return 0; }
+static inline int dbg_check_dir_size(struct ubifs_info *c,
+                                    const struct inode *dir)     { return 0; }
+static inline int dbg_check_tnc(struct ubifs_info *c, int extra)  { return 0; }
+static inline int dbg_check_idx_size(struct ubifs_info *c,
+                                    long long idx_size)          { return 0; }
+static inline int dbg_check_filesystem(struct ubifs_info *c)      { return 0; }
+static inline void dbg_check_heap(struct ubifs_info *c,
+                                 struct ubifs_lpt_heap *heap,
+                                 int cat, int add_pos)           { return; }
+static inline int dbg_check_lpt_nodes(struct ubifs_info *c,
+       struct ubifs_cnode *cnode, int row, int col)              { return 0; }
+static inline int dbg_check_inode_size(struct ubifs_info *c,
+                                      const struct inode *inode,
+                                      loff_t size)               { return 0; }
+static inline int
+dbg_check_data_nodes_order(struct ubifs_info *c,
+                          struct list_head *head)                { return 0; }
+static inline int
+dbg_check_nondata_nodes_order(struct ubifs_info *c,
+                             struct list_head *head)             { return 0; }
+
+static inline int dbg_force_in_the_gaps(void)                     { return 0; }
+#define dbg_force_in_the_gaps_enabled 0
+#define dbg_failure_mode              0
+
+static inline int dbg_debugfs_init(void)                          { return 0; }
+static inline void dbg_debugfs_exit(void)                         { return; }
+static inline int dbg_debugfs_init_fs(struct ubifs_info *c)       { return 0; }
+static inline int dbg_debugfs_exit_fs(struct ubifs_info *c)       { return 0; }
 
 #endif /* !CONFIG_UBIFS_FS_DEBUG */
 #endif /* !__UBIFS_DEBUG_H__ */
index 28be1e6a65e8c1af71fc754cb3ecf7dd6eaf2ca2..b286db79c686597bb593208ff577905d2663f7bf 100644 (file)
@@ -1312,6 +1312,9 @@ int ubifs_fsync(struct file *file, int datasync)
 
        dbg_gen("syncing inode %lu", inode->i_ino);
 
+       if (inode->i_sb->s_flags & MS_RDONLY)
+               return 0;
+
        /*
         * VFS has already synchronized dirty pages for this inode. Synchronize
         * the inode unless this is a 'datasync()' call.
index a19acdb81cd1270c174711c851b17013edb9ca80..f1ef94974dea12f10beceff4a12899851ba7aeab 100644 (file)
@@ -666,7 +666,7 @@ generic_setxattr(struct dentry *dentry, const char *name, const void *value, siz
        handler = xattr_resolve_name(dentry->d_sb->s_xattr, &name);
        if (!handler)
                return -EOPNOTSUPP;
-       return handler->set(dentry, name, value, size, 0, handler->flags);
+       return handler->set(dentry, name, value, size, flags, handler->flags);
 }
 
 /*
index 5ea402023ebd9353c2b725250d498cd0e3c9ed5e..9ef9ed2cfe2efee9aa3d9ed1de1d3e47fc9bc4df 100644 (file)
@@ -293,7 +293,6 @@ xfs_buf_allocate_memory(
        size_t                  nbytes, offset;
        gfp_t                   gfp_mask = xb_to_gfp(flags);
        unsigned short          page_count, i;
-       pgoff_t                 first;
        xfs_off_t               end;
        int                     error;
 
@@ -333,7 +332,6 @@ use_alloc_page:
                return error;
 
        offset = bp->b_offset;
-       first = bp->b_file_offset >> PAGE_SHIFT;
        bp->b_flags |= _XBF_PAGES;
 
        for (i = 0; i < bp->b_page_count; i++) {
@@ -657,8 +655,6 @@ xfs_buf_readahead(
        xfs_off_t               ioff,
        size_t                  isize)
 {
-       struct backing_dev_info *bdi;
-
        if (bdi_read_congested(target->bt_bdi))
                return;
 
@@ -919,8 +915,6 @@ xfs_buf_lock(
 
        if (atomic_read(&bp->b_pin_count) && (bp->b_flags & XBF_STALE))
                xfs_log_force(bp->b_target->bt_mount, 0);
-       if (atomic_read(&bp->b_io_remaining))
-               blk_flush_plug(current);
        down(&bp->b_sema);
        XB_SET_OWNER(bp);
 
@@ -1309,8 +1303,6 @@ xfs_buf_iowait(
 {
        trace_xfs_buf_iowait(bp, _RET_IP_);
 
-       if (atomic_read(&bp->b_io_remaining))
-               blk_flush_plug(current);
        wait_for_completion(&bp->b_iowait);
 
        trace_xfs_buf_iowait_done(bp, _RET_IP_);
@@ -1747,8 +1739,8 @@ xfsbufd(
        do {
                long    age = xfs_buf_age_centisecs * msecs_to_jiffies(10);
                long    tout = xfs_buf_timer_centisecs * msecs_to_jiffies(10);
-               int     count = 0;
                struct list_head tmp;
+               struct blk_plug plug;
 
                if (unlikely(freezing(current))) {
                        set_bit(XBT_FORCE_SLEEP, &target->bt_flags);
@@ -1764,16 +1756,15 @@ xfsbufd(
 
                xfs_buf_delwri_split(target, &tmp, age);
                list_sort(NULL, &tmp, xfs_buf_cmp);
+
+               blk_start_plug(&plug);
                while (!list_empty(&tmp)) {
                        struct xfs_buf *bp;
                        bp = list_first_entry(&tmp, struct xfs_buf, b_list);
                        list_del_init(&bp->b_list);
                        xfs_bdstrat_cb(bp);
-                       count++;
                }
-               if (count)
-                       blk_flush_plug(current);
-
+               blk_finish_plug(&plug);
        } while (!kthread_should_stop());
 
        return 0;
@@ -1793,6 +1784,7 @@ xfs_flush_buftarg(
        int             pincount = 0;
        LIST_HEAD(tmp_list);
        LIST_HEAD(wait_list);
+       struct blk_plug plug;
 
        xfs_buf_runall_queues(xfsconvertd_workqueue);
        xfs_buf_runall_queues(xfsdatad_workqueue);
@@ -1807,6 +1799,8 @@ xfs_flush_buftarg(
         * we do that after issuing all the IO.
         */
        list_sort(NULL, &tmp_list, xfs_buf_cmp);
+
+       blk_start_plug(&plug);
        while (!list_empty(&tmp_list)) {
                bp = list_first_entry(&tmp_list, struct xfs_buf, b_list);
                ASSERT(target == bp->b_target);
@@ -1817,10 +1811,10 @@ xfs_flush_buftarg(
                }
                xfs_bdstrat_cb(bp);
        }
+       blk_finish_plug(&plug);
 
        if (wait) {
-               /* Expedite and wait for IO to complete. */
-               blk_flush_plug(current);
+               /* Wait for IO to complete. */
                while (!list_empty(&wait_list)) {
                        bp = list_first_entry(&wait_list, struct xfs_buf, b_list);
 
index 508e06fd7d1e67451402424eb4251408c04e6010..3ca795609113c259483099d0bbdaae9815b2cc0e 100644 (file)
 /*
  * XFS logging functions
  */
-static int
+static void
 __xfs_printk(
        const char              *level,
        const struct xfs_mount  *mp,
        struct va_format        *vaf)
 {
        if (mp && mp->m_fsname)
-               return printk("%sXFS (%s): %pV\n", level, mp->m_fsname, vaf);
-       return printk("%sXFS: %pV\n", level, vaf);
+               printk("%sXFS (%s): %pV\n", level, mp->m_fsname, vaf);
+       printk("%sXFS: %pV\n", level, vaf);
 }
 
-int xfs_printk(
+void xfs_printk(
        const char              *level,
        const struct xfs_mount  *mp,
        const char              *fmt, ...)
 {
        struct va_format        vaf;
        va_list                 args;
-       int                      r;
 
        va_start(args, fmt);
 
        vaf.fmt = fmt;
        vaf.va = &args;
 
-       r = __xfs_printk(level, mp, &vaf);
+       __xfs_printk(level, mp, &vaf);
        va_end(args);
-
-       return r;
 }
 
 #define define_xfs_printk_level(func, kern_level)              \
-int func(const struct xfs_mount *mp, const char *fmt, ...)     \
+void func(const struct xfs_mount *mp, const char *fmt, ...)    \
 {                                                              \
        struct va_format        vaf;                            \
        va_list                 args;                           \
-       int                     r;                              \
                                                                \
        va_start(args, fmt);                                    \
                                                                \
        vaf.fmt = fmt;                                          \
        vaf.va = &args;                                         \
                                                                \
-       r = __xfs_printk(kern_level, mp, &vaf);                 \
+       __xfs_printk(kern_level, mp, &vaf);                     \
        va_end(args);                                           \
-                                                               \
-       return r;                                               \
 }                                                              \
 
 define_xfs_printk_level(xfs_emerg, KERN_EMERG);
@@ -88,7 +82,7 @@ define_xfs_printk_level(xfs_info, KERN_INFO);
 define_xfs_printk_level(xfs_debug, KERN_DEBUG);
 #endif
 
-int
+void
 xfs_alert_tag(
        const struct xfs_mount  *mp,
        int                     panic_tag,
@@ -97,7 +91,6 @@ xfs_alert_tag(
        struct va_format        vaf;
        va_list                 args;
        int                     do_panic = 0;
-       int                     r;
 
        if (xfs_panic_mask && (xfs_panic_mask & panic_tag)) {
                xfs_printk(KERN_ALERT, mp,
@@ -110,12 +103,10 @@ xfs_alert_tag(
        vaf.fmt = fmt;
        vaf.va = &args;
 
-       r = __xfs_printk(KERN_ALERT, mp, &vaf);
+       __xfs_printk(KERN_ALERT, mp, &vaf);
        va_end(args);
 
        BUG_ON(do_panic);
-
-       return r;
 }
 
 void
index e77ffa16745b2a58f9c60953a80b7dadf88b171e..f1b3fc1b6c4ec9d4ecb09b075d6b336ce430ec40 100644 (file)
@@ -3,32 +3,34 @@
 
 struct xfs_mount;
 
-extern int xfs_printk(const char *level, const struct xfs_mount *mp,
+extern void xfs_printk(const char *level, const struct xfs_mount *mp,
                       const char *fmt, ...)
         __attribute__ ((format (printf, 3, 4)));
-extern int xfs_emerg(const struct xfs_mount *mp, const char *fmt, ...)
+extern void xfs_emerg(const struct xfs_mount *mp, const char *fmt, ...)
         __attribute__ ((format (printf, 2, 3)));
-extern int xfs_alert(const struct xfs_mount *mp, const char *fmt, ...)
+extern void xfs_alert(const struct xfs_mount *mp, const char *fmt, ...)
         __attribute__ ((format (printf, 2, 3)));
-extern int xfs_alert_tag(const struct xfs_mount *mp, int tag,
+extern void xfs_alert_tag(const struct xfs_mount *mp, int tag,
                         const char *fmt, ...)
         __attribute__ ((format (printf, 3, 4)));
-extern int xfs_crit(const struct xfs_mount *mp, const char *fmt, ...)
+extern void xfs_crit(const struct xfs_mount *mp, const char *fmt, ...)
         __attribute__ ((format (printf, 2, 3)));
-extern int xfs_err(const struct xfs_mount *mp, const char *fmt, ...)
+extern void xfs_err(const struct xfs_mount *mp, const char *fmt, ...)
         __attribute__ ((format (printf, 2, 3)));
-extern int xfs_warn(const struct xfs_mount *mp, const char *fmt, ...)
+extern void xfs_warn(const struct xfs_mount *mp, const char *fmt, ...)
         __attribute__ ((format (printf, 2, 3)));
-extern int xfs_notice(const struct xfs_mount *mp, const char *fmt, ...)
+extern void xfs_notice(const struct xfs_mount *mp, const char *fmt, ...)
         __attribute__ ((format (printf, 2, 3)));
-extern int xfs_info(const struct xfs_mount *mp, const char *fmt, ...)
+extern void xfs_info(const struct xfs_mount *mp, const char *fmt, ...)
         __attribute__ ((format (printf, 2, 3)));
 
 #ifdef DEBUG
-extern int xfs_debug(const struct xfs_mount *mp, const char *fmt, ...)
+extern void xfs_debug(const struct xfs_mount *mp, const char *fmt, ...)
         __attribute__ ((format (printf, 2, 3)));
 #else
-#define xfs_debug(mp, fmt, ...)        (0)
+static inline void xfs_debug(const struct xfs_mount *mp, const char *fmt, ...)
+{
+}
 #endif
 
 extern void assfail(char *expr, char *f, int l);
index 1ba5c451da36a094629f6130815a70a8ee047bb8..b38e58d02299b40571c6350f3b040907f6853f14 100644 (file)
@@ -816,75 +816,6 @@ xfs_setup_devices(
        return 0;
 }
 
-/*
- * XFS AIL push thread support
- */
-void
-xfsaild_wakeup(
-       struct xfs_ail          *ailp,
-       xfs_lsn_t               threshold_lsn)
-{
-       /* only ever move the target forwards */
-       if (XFS_LSN_CMP(threshold_lsn, ailp->xa_target) > 0) {
-               ailp->xa_target = threshold_lsn;
-               wake_up_process(ailp->xa_task);
-       }
-}
-
-STATIC int
-xfsaild(
-       void    *data)
-{
-       struct xfs_ail  *ailp = data;
-       xfs_lsn_t       last_pushed_lsn = 0;
-       long            tout = 0; /* milliseconds */
-
-       while (!kthread_should_stop()) {
-               /*
-                * for short sleeps indicating congestion, don't allow us to
-                * get woken early. Otherwise all we do is bang on the AIL lock
-                * without making progress.
-                */
-               if (tout && tout <= 20)
-                       __set_current_state(TASK_KILLABLE);
-               else
-                       __set_current_state(TASK_INTERRUPTIBLE);
-               schedule_timeout(tout ?
-                                msecs_to_jiffies(tout) : MAX_SCHEDULE_TIMEOUT);
-
-               /* swsusp */
-               try_to_freeze();
-
-               ASSERT(ailp->xa_mount->m_log);
-               if (XFS_FORCED_SHUTDOWN(ailp->xa_mount))
-                       continue;
-
-               tout = xfsaild_push(ailp, &last_pushed_lsn);
-       }
-
-       return 0;
-}      /* xfsaild */
-
-int
-xfsaild_start(
-       struct xfs_ail  *ailp)
-{
-       ailp->xa_target = 0;
-       ailp->xa_task = kthread_run(xfsaild, ailp, "xfsaild/%s",
-                                   ailp->xa_mount->m_fsname);
-       if (IS_ERR(ailp->xa_task))
-               return -PTR_ERR(ailp->xa_task);
-       return 0;
-}
-
-void
-xfsaild_stop(
-       struct xfs_ail  *ailp)
-{
-       kthread_stop(ailp->xa_task);
-}
-
-
 /* Catch misguided souls that try to use this interface on XFS */
 STATIC struct inode *
 xfs_fs_alloc_inode(
@@ -1191,22 +1122,12 @@ xfs_fs_sync_fs(
                return -error;
 
        if (laptop_mode) {
-               int     prev_sync_seq = mp->m_sync_seq;
-
                /*
                 * The disk must be active because we're syncing.
                 * We schedule xfssyncd now (now that the disk is
                 * active) instead of later (when it might not be).
                 */
-               wake_up_process(mp->m_sync_task);
-               /*
-                * We have to wait for the sync iteration to complete.
-                * If we don't, the disk activity caused by the sync
-                * will come after the sync is completed, and that
-                * triggers another sync from laptop mode.
-                */
-               wait_event(mp->m_wait_single_sync_task,
-                               mp->m_sync_seq != prev_sync_seq);
+               flush_delayed_work_sync(&mp->m_sync_work);
        }
 
        return 0;
@@ -1490,9 +1411,6 @@ xfs_fs_fill_super(
        spin_lock_init(&mp->m_sb_lock);
        mutex_init(&mp->m_growlock);
        atomic_set(&mp->m_active_trans, 0);
-       INIT_LIST_HEAD(&mp->m_sync_list);
-       spin_lock_init(&mp->m_sync_lock);
-       init_waitqueue_head(&mp->m_wait_single_sync_task);
 
        mp->m_super = sb;
        sb->s_fs_info = mp;
@@ -1798,6 +1716,38 @@ xfs_destroy_zones(void)
 
 }
 
+STATIC int __init
+xfs_init_workqueues(void)
+{
+       /*
+        * max_active is set to 8 to give enough concurency to allow
+        * multiple work operations on each CPU to run. This allows multiple
+        * filesystems to be running sync work concurrently, and scales with
+        * the number of CPUs in the system.
+        */
+       xfs_syncd_wq = alloc_workqueue("xfssyncd", WQ_CPU_INTENSIVE, 8);
+       if (!xfs_syncd_wq)
+               goto out;
+
+       xfs_ail_wq = alloc_workqueue("xfsail", WQ_CPU_INTENSIVE, 8);
+       if (!xfs_ail_wq)
+               goto out_destroy_syncd;
+
+       return 0;
+
+out_destroy_syncd:
+       destroy_workqueue(xfs_syncd_wq);
+out:
+       return -ENOMEM;
+}
+
+STATIC void
+xfs_destroy_workqueues(void)
+{
+       destroy_workqueue(xfs_ail_wq);
+       destroy_workqueue(xfs_syncd_wq);
+}
+
 STATIC int __init
 init_xfs_fs(void)
 {
@@ -1813,10 +1763,14 @@ init_xfs_fs(void)
        if (error)
                goto out;
 
-       error = xfs_mru_cache_init();
+       error = xfs_init_workqueues();
        if (error)
                goto out_destroy_zones;
 
+       error = xfs_mru_cache_init();
+       if (error)
+               goto out_destroy_wq;
+
        error = xfs_filestream_init();
        if (error)
                goto out_mru_cache_uninit;
@@ -1833,6 +1787,10 @@ init_xfs_fs(void)
        if (error)
                goto out_cleanup_procfs;
 
+       error = xfs_init_workqueues();
+       if (error)
+               goto out_sysctl_unregister;
+
        vfs_initquota();
 
        error = register_filesystem(&xfs_fs_type);
@@ -1850,6 +1808,8 @@ init_xfs_fs(void)
        xfs_filestream_uninit();
  out_mru_cache_uninit:
        xfs_mru_cache_uninit();
+ out_destroy_wq:
+       xfs_destroy_workqueues();
  out_destroy_zones:
        xfs_destroy_zones();
  out:
@@ -1866,6 +1826,7 @@ exit_xfs_fs(void)
        xfs_buf_terminate();
        xfs_filestream_uninit();
        xfs_mru_cache_uninit();
+       xfs_destroy_workqueues();
        xfs_destroy_zones();
 }
 
index 9cf35a688f53787e47bdf6ad695b2d318432d34d..e4f9c1b0836c9ef8ef9feb3515d2f29a97565004 100644 (file)
@@ -22,6 +22,7 @@
 #include "xfs_log.h"
 #include "xfs_inum.h"
 #include "xfs_trans.h"
+#include "xfs_trans_priv.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
 #include "xfs_mount.h"
@@ -39,6 +40,8 @@
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 
+struct workqueue_struct        *xfs_syncd_wq;  /* sync workqueue */
+
 /*
  * The inode lookup is done in batches to keep the amount of lock traffic and
  * radix tree lookups to a minimum. The batch size is a trade off between
@@ -431,62 +434,12 @@ xfs_quiesce_attr(
        xfs_unmountfs_writesb(mp);
 }
 
-/*
- * Enqueue a work item to be picked up by the vfs xfssyncd thread.
- * Doing this has two advantages:
- * - It saves on stack space, which is tight in certain situations
- * - It can be used (with care) as a mechanism to avoid deadlocks.
- * Flushing while allocating in a full filesystem requires both.
- */
-STATIC void
-xfs_syncd_queue_work(
-       struct xfs_mount *mp,
-       void            *data,
-       void            (*syncer)(struct xfs_mount *, void *),
-       struct completion *completion)
-{
-       struct xfs_sync_work *work;
-
-       work = kmem_alloc(sizeof(struct xfs_sync_work), KM_SLEEP);
-       INIT_LIST_HEAD(&work->w_list);
-       work->w_syncer = syncer;
-       work->w_data = data;
-       work->w_mount = mp;
-       work->w_completion = completion;
-       spin_lock(&mp->m_sync_lock);
-       list_add_tail(&work->w_list, &mp->m_sync_list);
-       spin_unlock(&mp->m_sync_lock);
-       wake_up_process(mp->m_sync_task);
-}
-
-/*
- * Flush delayed allocate data, attempting to free up reserved space
- * from existing allocations.  At this point a new allocation attempt
- * has failed with ENOSPC and we are in the process of scratching our
- * heads, looking about for more room...
- */
-STATIC void
-xfs_flush_inodes_work(
-       struct xfs_mount *mp,
-       void            *arg)
-{
-       struct inode    *inode = arg;
-       xfs_sync_data(mp, SYNC_TRYLOCK);
-       xfs_sync_data(mp, SYNC_TRYLOCK | SYNC_WAIT);
-       iput(inode);
-}
-
-void
-xfs_flush_inodes(
-       xfs_inode_t     *ip)
+static void
+xfs_syncd_queue_sync(
+       struct xfs_mount        *mp)
 {
-       struct inode    *inode = VFS_I(ip);
-       DECLARE_COMPLETION_ONSTACK(completion);
-
-       igrab(inode);
-       xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inodes_work, &completion);
-       wait_for_completion(&completion);
-       xfs_log_force(ip->i_mount, XFS_LOG_SYNC);
+       queue_delayed_work(xfs_syncd_wq, &mp->m_sync_work,
+                               msecs_to_jiffies(xfs_syncd_centisecs * 10));
 }
 
 /*
@@ -496,9 +449,10 @@ xfs_flush_inodes(
  */
 STATIC void
 xfs_sync_worker(
-       struct xfs_mount *mp,
-       void            *unused)
+       struct work_struct *work)
 {
+       struct xfs_mount *mp = container_of(to_delayed_work(work),
+                                       struct xfs_mount, m_sync_work);
        int             error;
 
        if (!(mp->m_flags & XFS_MOUNT_RDONLY)) {
@@ -508,73 +462,106 @@ xfs_sync_worker(
                        error = xfs_fs_log_dummy(mp);
                else
                        xfs_log_force(mp, 0);
-               xfs_reclaim_inodes(mp, 0);
                error = xfs_qm_sync(mp, SYNC_TRYLOCK);
+
+               /* start pushing all the metadata that is currently dirty */
+               xfs_ail_push_all(mp->m_ail);
        }
-       mp->m_sync_seq++;
-       wake_up(&mp->m_wait_single_sync_task);
+
+       /* queue us up again */
+       xfs_syncd_queue_sync(mp);
 }
 
-STATIC int
-xfssyncd(
-       void                    *arg)
+/*
+ * Queue a new inode reclaim pass if there are reclaimable inodes and there
+ * isn't a reclaim pass already in progress. By default it runs every 5s based
+ * on the xfs syncd work default of 30s. Perhaps this should have it's own
+ * tunable, but that can be done if this method proves to be ineffective or too
+ * aggressive.
+ */
+static void
+xfs_syncd_queue_reclaim(
+       struct xfs_mount        *mp)
 {
-       struct xfs_mount        *mp = arg;
-       long                    timeleft;
-       xfs_sync_work_t         *work, *n;
-       LIST_HEAD               (tmp);
-
-       set_freezable();
-       timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10);
-       for (;;) {
-               if (list_empty(&mp->m_sync_list))
-                       timeleft = schedule_timeout_interruptible(timeleft);
-               /* swsusp */
-               try_to_freeze();
-               if (kthread_should_stop() && list_empty(&mp->m_sync_list))
-                       break;
 
-               spin_lock(&mp->m_sync_lock);
-               /*
-                * We can get woken by laptop mode, to do a sync -
-                * that's the (only!) case where the list would be
-                * empty with time remaining.
-                */
-               if (!timeleft || list_empty(&mp->m_sync_list)) {
-                       if (!timeleft)
-                               timeleft = xfs_syncd_centisecs *
-                                                       msecs_to_jiffies(10);
-                       INIT_LIST_HEAD(&mp->m_sync_work.w_list);
-                       list_add_tail(&mp->m_sync_work.w_list,
-                                       &mp->m_sync_list);
-               }
-               list_splice_init(&mp->m_sync_list, &tmp);
-               spin_unlock(&mp->m_sync_lock);
+       /*
+        * We can have inodes enter reclaim after we've shut down the syncd
+        * workqueue during unmount, so don't allow reclaim work to be queued
+        * during unmount.
+        */
+       if (!(mp->m_super->s_flags & MS_ACTIVE))
+               return;
 
-               list_for_each_entry_safe(work, n, &tmp, w_list) {
-                       (*work->w_syncer)(mp, work->w_data);
-                       list_del(&work->w_list);
-                       if (work == &mp->m_sync_work)
-                               continue;
-                       if (work->w_completion)
-                               complete(work->w_completion);
-                       kmem_free(work);
-               }
+       rcu_read_lock();
+       if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_RECLAIM_TAG)) {
+               queue_delayed_work(xfs_syncd_wq, &mp->m_reclaim_work,
+                       msecs_to_jiffies(xfs_syncd_centisecs / 6 * 10));
        }
+       rcu_read_unlock();
+}
 
-       return 0;
+/*
+ * This is a fast pass over the inode cache to try to get reclaim moving on as
+ * many inodes as possible in a short period of time. It kicks itself every few
+ * seconds, as well as being kicked by the inode cache shrinker when memory
+ * goes low. It scans as quickly as possible avoiding locked inodes or those
+ * already being flushed, and once done schedules a future pass.
+ */
+STATIC void
+xfs_reclaim_worker(
+       struct work_struct *work)
+{
+       struct xfs_mount *mp = container_of(to_delayed_work(work),
+                                       struct xfs_mount, m_reclaim_work);
+
+       xfs_reclaim_inodes(mp, SYNC_TRYLOCK);
+       xfs_syncd_queue_reclaim(mp);
+}
+
+/*
+ * Flush delayed allocate data, attempting to free up reserved space
+ * from existing allocations.  At this point a new allocation attempt
+ * has failed with ENOSPC and we are in the process of scratching our
+ * heads, looking about for more room.
+ *
+ * Queue a new data flush if there isn't one already in progress and
+ * wait for completion of the flush. This means that we only ever have one
+ * inode flush in progress no matter how many ENOSPC events are occurring and
+ * so will prevent the system from bogging down due to every concurrent
+ * ENOSPC event scanning all the active inodes in the system for writeback.
+ */
+void
+xfs_flush_inodes(
+       struct xfs_inode        *ip)
+{
+       struct xfs_mount        *mp = ip->i_mount;
+
+       queue_work(xfs_syncd_wq, &mp->m_flush_work);
+       flush_work_sync(&mp->m_flush_work);
+}
+
+STATIC void
+xfs_flush_worker(
+       struct work_struct *work)
+{
+       struct xfs_mount *mp = container_of(work,
+                                       struct xfs_mount, m_flush_work);
+
+       xfs_sync_data(mp, SYNC_TRYLOCK);
+       xfs_sync_data(mp, SYNC_TRYLOCK | SYNC_WAIT);
 }
 
 int
 xfs_syncd_init(
        struct xfs_mount        *mp)
 {
-       mp->m_sync_work.w_syncer = xfs_sync_worker;
-       mp->m_sync_work.w_mount = mp;
-       mp->m_sync_work.w_completion = NULL;
-       mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd/%s", mp->m_fsname);
-       if (IS_ERR(mp->m_sync_task))
-               return -PTR_ERR(mp->m_sync_task);
+       INIT_WORK(&mp->m_flush_work, xfs_flush_worker);
+       INIT_DELAYED_WORK(&mp->m_sync_work, xfs_sync_worker);
+       INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker);
+
+       xfs_syncd_queue_sync(mp);
+       xfs_syncd_queue_reclaim(mp);
+
        return 0;
 }
 
@@ -582,7 +569,9 @@ void
 xfs_syncd_stop(
        struct xfs_mount        *mp)
 {
-       kthread_stop(mp->m_sync_task);
+       cancel_delayed_work_sync(&mp->m_sync_work);
+       cancel_delayed_work_sync(&mp->m_reclaim_work);
+       cancel_work_sync(&mp->m_flush_work);
 }
 
 void
@@ -601,6 +590,10 @@ __xfs_inode_set_reclaim_tag(
                                XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino),
                                XFS_ICI_RECLAIM_TAG);
                spin_unlock(&ip->i_mount->m_perag_lock);
+
+               /* schedule periodic background inode reclaim */
+               xfs_syncd_queue_reclaim(ip->i_mount);
+
                trace_xfs_perag_set_reclaim(ip->i_mount, pag->pag_agno,
                                                        -1, _RET_IP_);
        }
@@ -1017,7 +1010,13 @@ xfs_reclaim_inodes(
 }
 
 /*
- * Shrinker infrastructure.
+ * Inode cache shrinker.
+ *
+ * When called we make sure that there is a background (fast) inode reclaim in
+ * progress, while we will throttle the speed of reclaim via doiing synchronous
+ * reclaim of inodes. That means if we come across dirty inodes, we wait for
+ * them to be cleaned, which we hope will not be very long due to the
+ * background walker having already kicked the IO off on those dirty inodes.
  */
 static int
 xfs_reclaim_inode_shrink(
@@ -1032,10 +1031,15 @@ xfs_reclaim_inode_shrink(
 
        mp = container_of(shrink, struct xfs_mount, m_inode_shrink);
        if (nr_to_scan) {
+               /* kick background reclaimer and push the AIL */
+               xfs_syncd_queue_reclaim(mp);
+               xfs_ail_push_all(mp->m_ail);
+
                if (!(gfp_mask & __GFP_FS))
                        return -1;
 
-               xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK, &nr_to_scan);
+               xfs_reclaim_inodes_ag(mp, SYNC_TRYLOCK | SYNC_WAIT,
+                                       &nr_to_scan);
                /* terminate if we don't exhaust the scan */
                if (nr_to_scan > 0)
                        return -1;
index 32ba6628290ce4f14162d28c20eba63a23db1ffb..e3a6ad27415f77c07484941e1b6a79b07d2a3a34 100644 (file)
@@ -32,6 +32,8 @@ typedef struct xfs_sync_work {
 #define SYNC_WAIT              0x0001  /* wait for i/o to complete */
 #define SYNC_TRYLOCK           0x0002  /* only try to lock inodes */
 
+extern struct workqueue_struct *xfs_syncd_wq;  /* sync workqueue */
+
 int xfs_syncd_init(struct xfs_mount *mp);
 void xfs_syncd_stop(struct xfs_mount *mp);
 
index 254ee062bd7dde135e0c238ca3696fe180ec78fe..69228aa8605a9f6e07d1f66845c0e4c0c7beff2c 100644 (file)
@@ -461,12 +461,10 @@ xfs_qm_dqflush_all(
        struct xfs_quotainfo    *q = mp->m_quotainfo;
        int                     recl;
        struct xfs_dquot        *dqp;
-       int                     niters;
        int                     error;
 
        if (!q)
                return 0;
-       niters = 0;
 again:
        mutex_lock(&q->qi_dqlist_lock);
        list_for_each_entry(dqp, &q->qi_dqlist, q_mplist) {
@@ -1314,14 +1312,9 @@ xfs_qm_dqiter_bufs(
 {
        xfs_buf_t       *bp;
        int             error;
-       int             notcommitted;
-       int             incr;
        int             type;
 
        ASSERT(blkcnt > 0);
-       notcommitted = 0;
-       incr = (blkcnt > XFS_QM_MAX_DQCLUSTER_LOGSZ) ?
-               XFS_QM_MAX_DQCLUSTER_LOGSZ : blkcnt;
        type = flags & XFS_QMOPT_UQUOTA ? XFS_DQ_USER :
                (flags & XFS_QMOPT_PQUOTA ? XFS_DQ_PROJ : XFS_DQ_GROUP);
        error = 0;
index c9446f1c726d89e7cdaf78a08bb02e42a1752e72..567b29b9f1b390048e61e32c2168b8db05fdbb24 100644 (file)
@@ -65,11 +65,6 @@ extern kmem_zone_t   *qm_dqtrxzone;
  * block in the dquot/xqm code.
  */
 #define XFS_DQUOT_CLUSTER_SIZE_FSB     (xfs_filblks_t)1
-/*
- * When doing a quotacheck, we log dquot clusters of this many FSBs at most
- * in a single transaction. We don't want to ask for too huge a log reservation.
- */
-#define XFS_QM_MAX_DQCLUSTER_LOGSZ     3
 
 typedef xfs_dqhash_t   xfs_dqlist_t;
 
index 0d62a07b7fd8493e7d14af79f0690cdb6eb4c196..2dadb15d5ca90d3b15b485241427c4b739e4b8ec 100644 (file)
@@ -313,14 +313,12 @@ xfs_qm_scall_quotaon(
 {
        int             error;
        uint            qf;
-       uint            accflags;
        __int64_t       sbflags;
 
        flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
        /*
         * Switching on quota accounting must be done at mount time.
         */
-       accflags = flags & XFS_ALL_QUOTA_ACCT;
        flags &= ~(XFS_ALL_QUOTA_ACCT);
 
        sbflags = 0;
index 4bc3c649aee4bb35a6c7ebaa790ef8b73d264073..27d64d752eab70afa92187a8f35a6d736a37e14d 100644 (file)
@@ -2395,17 +2395,33 @@ xfs_free_extent(
        memset(&args, 0, sizeof(xfs_alloc_arg_t));
        args.tp = tp;
        args.mp = tp->t_mountp;
+
+       /*
+        * validate that the block number is legal - the enables us to detect
+        * and handle a silent filesystem corruption rather than crashing.
+        */
        args.agno = XFS_FSB_TO_AGNO(args.mp, bno);
-       ASSERT(args.agno < args.mp->m_sb.sb_agcount);
+       if (args.agno >= args.mp->m_sb.sb_agcount)
+               return EFSCORRUPTED;
+
        args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno);
+       if (args.agbno >= args.mp->m_sb.sb_agblocks)
+               return EFSCORRUPTED;
+
        args.pag = xfs_perag_get(args.mp, args.agno);
-       if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING)))
+       ASSERT(args.pag);
+
+       error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING);
+       if (error)
                goto error0;
-#ifdef DEBUG
-       ASSERT(args.agbp != NULL);
-       ASSERT((args.agbno + len) <=
-               be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length));
-#endif
+
+       /* validate the extent size is legal now we have the agf locked */
+       if (args.agbno + len >
+                       be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)) {
+               error = EFSCORRUPTED;
+               goto error0;
+       }
+
        error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0);
 error0:
        xfs_perag_put(args.pag);
index 46cc40131d4a43c91ec5eb1d188c46e967c5193c..576fdfe81d603176abb31cf35c1b90901ca1ca5c 100644 (file)
@@ -197,6 +197,41 @@ xfs_inode_item_size(
        return nvecs;
 }
 
+/*
+ * xfs_inode_item_format_extents - convert in-core extents to on-disk form
+ *
+ * For either the data or attr fork in extent format, we need to endian convert
+ * the in-core extent as we place them into the on-disk inode. In this case, we
+ * need to do this conversion before we write the extents into the log. Because
+ * we don't have the disk inode to write into here, we allocate a buffer and
+ * format the extents into it via xfs_iextents_copy(). We free the buffer in
+ * the unlock routine after the copy for the log has been made.
+ *
+ * In the case of the data fork, the in-core and on-disk fork sizes can be
+ * different due to delayed allocation extents. We only log on-disk extents
+ * here, so always use the physical fork size to determine the size of the
+ * buffer we need to allocate.
+ */
+STATIC void
+xfs_inode_item_format_extents(
+       struct xfs_inode        *ip,
+       struct xfs_log_iovec    *vecp,
+       int                     whichfork,
+       int                     type)
+{
+       xfs_bmbt_rec_t          *ext_buffer;
+
+       ext_buffer = kmem_alloc(XFS_IFORK_SIZE(ip, whichfork), KM_SLEEP);
+       if (whichfork == XFS_DATA_FORK)
+               ip->i_itemp->ili_extents_buf = ext_buffer;
+       else
+               ip->i_itemp->ili_aextents_buf = ext_buffer;
+
+       vecp->i_addr = ext_buffer;
+       vecp->i_len = xfs_iextents_copy(ip, ext_buffer, whichfork);
+       vecp->i_type = type;
+}
+
 /*
  * This is called to fill in the vector of log iovecs for the
  * given inode log item.  It fills the first item with an inode
@@ -213,7 +248,6 @@ xfs_inode_item_format(
        struct xfs_inode        *ip = iip->ili_inode;
        uint                    nvecs;
        size_t                  data_bytes;
-       xfs_bmbt_rec_t          *ext_buffer;
        xfs_mount_t             *mp;
 
        vecp->i_addr = &iip->ili_format;
@@ -320,22 +354,8 @@ xfs_inode_item_format(
                        } else
 #endif
                        {
-                               /*
-                                * There are delayed allocation extents
-                                * in the inode, or we need to convert
-                                * the extents to on disk format.
-                                * Use xfs_iextents_copy()
-                                * to copy only the real extents into
-                                * a separate buffer.  We'll free the
-                                * buffer in the unlock routine.
-                                */
-                               ext_buffer = kmem_alloc(ip->i_df.if_bytes,
-                                       KM_SLEEP);
-                               iip->ili_extents_buf = ext_buffer;
-                               vecp->i_addr = ext_buffer;
-                               vecp->i_len = xfs_iextents_copy(ip, ext_buffer,
-                                               XFS_DATA_FORK);
-                               vecp->i_type = XLOG_REG_TYPE_IEXT;
+                               xfs_inode_item_format_extents(ip, vecp,
+                                       XFS_DATA_FORK, XLOG_REG_TYPE_IEXT);
                        }
                        ASSERT(vecp->i_len <= ip->i_df.if_bytes);
                        iip->ili_format.ilf_dsize = vecp->i_len;
@@ -445,19 +465,12 @@ xfs_inode_item_format(
                         */
                        vecp->i_addr = ip->i_afp->if_u1.if_extents;
                        vecp->i_len = ip->i_afp->if_bytes;
+                       vecp->i_type = XLOG_REG_TYPE_IATTR_EXT;
 #else
                        ASSERT(iip->ili_aextents_buf == NULL);
-                       /*
-                        * Need to endian flip before logging
-                        */
-                       ext_buffer = kmem_alloc(ip->i_afp->if_bytes,
-                               KM_SLEEP);
-                       iip->ili_aextents_buf = ext_buffer;
-                       vecp->i_addr = ext_buffer;
-                       vecp->i_len = xfs_iextents_copy(ip, ext_buffer,
-                                       XFS_ATTR_FORK);
+                       xfs_inode_item_format_extents(ip, vecp,
+                                       XFS_ATTR_FORK, XLOG_REG_TYPE_IATTR_EXT);
 #endif
-                       vecp->i_type = XLOG_REG_TYPE_IATTR_EXT;
                        iip->ili_format.ilf_asize = vecp->i_len;
                        vecp++;
                        nvecs++;
index dc1882adaf54e1da714eed5aefe095875fbd102a..751e94fe1f77e2694790da48952cf03f30a554e4 100644 (file)
@@ -204,7 +204,6 @@ xfs_bulkstat(
        xfs_agi_t               *agi;   /* agi header data */
        xfs_agino_t             agino;  /* inode # in allocation group */
        xfs_agnumber_t          agno;   /* allocation group number */
-       xfs_daddr_t             bno;    /* inode cluster start daddr */
        int                     chunkidx; /* current index into inode chunk */
        int                     clustidx; /* current index into inode cluster */
        xfs_btree_cur_t         *cur;   /* btree cursor for ialloc btree */
@@ -463,7 +462,6 @@ xfs_bulkstat(
                                                 mp->m_sb.sb_inopblog);
                                }
                                ino = XFS_AGINO_TO_INO(mp, agno, agino);
-                               bno = XFS_AGB_TO_DADDR(mp, agno, agbno);
                                /*
                                 * Skip if this inode is free.
                                 */
index 25efa9b8a6029ac35df73942459132abd71dc228..b612ce4520aebef7cbc38a066b48133d37f2636d 100644 (file)
@@ -761,7 +761,7 @@ xfs_log_need_covered(xfs_mount_t *mp)
                break;
        case XLOG_STATE_COVER_NEED:
        case XLOG_STATE_COVER_NEED2:
-               if (!xfs_trans_ail_tail(log->l_ailp) &&
+               if (!xfs_ail_min_lsn(log->l_ailp) &&
                    xlog_iclogs_empty(log)) {
                        if (log->l_covered_state == XLOG_STATE_COVER_NEED)
                                log->l_covered_state = XLOG_STATE_COVER_DONE;
@@ -801,7 +801,7 @@ xlog_assign_tail_lsn(
        xfs_lsn_t               tail_lsn;
        struct log              *log = mp->m_log;
 
-       tail_lsn = xfs_trans_ail_tail(mp->m_ail);
+       tail_lsn = xfs_ail_min_lsn(mp->m_ail);
        if (!tail_lsn)
                tail_lsn = atomic64_read(&log->l_last_sync_lsn);
 
@@ -1239,7 +1239,7 @@ xlog_grant_push_ail(
         * the filesystem is shutting down.
         */
        if (!XLOG_FORCED_SHUTDOWN(log))
-               xfs_trans_ail_push(log->l_ailp, threshold_lsn);
+               xfs_ail_push(log->l_ailp, threshold_lsn);
 }
 
 /*
@@ -3407,6 +3407,17 @@ xlog_verify_dest_ptr(
                xfs_emerg(log->l_mp, "%s: invalid ptr", __func__);
 }
 
+/*
+ * Check to make sure the grant write head didn't just over lap the tail.  If
+ * the cycles are the same, we can't be overlapping.  Otherwise, make sure that
+ * the cycles differ by exactly one and check the byte count.
+ *
+ * This check is run unlocked, so can give false positives. Rather than assert
+ * on failures, use a warn-once flag and a panic tag to allow the admin to
+ * determine if they want to panic the machine when such an error occurs. For
+ * debug kernels this will have the same effect as using an assert but, unlinke
+ * an assert, it can be turned off at runtime.
+ */
 STATIC void
 xlog_verify_grant_tail(
        struct log      *log)
@@ -3414,17 +3425,22 @@ xlog_verify_grant_tail(
        int             tail_cycle, tail_blocks;
        int             cycle, space;
 
-       /*
-        * Check to make sure the grant write head didn't just over lap the
-        * tail.  If the cycles are the same, we can't be overlapping.
-        * Otherwise, make sure that the cycles differ by exactly one and
-        * check the byte count.
-        */
        xlog_crack_grant_head(&log->l_grant_write_head, &cycle, &space);
        xlog_crack_atomic_lsn(&log->l_tail_lsn, &tail_cycle, &tail_blocks);
        if (tail_cycle != cycle) {
-               ASSERT(cycle - 1 == tail_cycle);
-               ASSERT(space <= BBTOB(tail_blocks));
+               if (cycle - 1 != tail_cycle &&
+                   !(log->l_flags & XLOG_TAIL_WARN)) {
+                       xfs_alert_tag(log->l_mp, XFS_PTAG_LOGRES,
+                               "%s: cycle - 1 != tail_cycle", __func__);
+                       log->l_flags |= XLOG_TAIL_WARN;
+               }
+
+               if (space > BBTOB(tail_blocks) &&
+                   !(log->l_flags & XLOG_TAIL_WARN)) {
+                       xfs_alert_tag(log->l_mp, XFS_PTAG_LOGRES,
+                               "%s: space > BBTOB(tail_blocks)", __func__);
+                       log->l_flags |= XLOG_TAIL_WARN;
+               }
        }
 }
 
index ffae692c983279cfad7057756a5efee059544579..5864850e9e34039507b003ff3e8570a500701bc3 100644 (file)
@@ -144,6 +144,7 @@ static inline uint xlog_get_client_id(__be32 i)
 #define        XLOG_RECOVERY_NEEDED    0x4     /* log was recovered */
 #define XLOG_IO_ERROR          0x8     /* log hit an I/O error, and being
                                           shutdown */
+#define XLOG_TAIL_WARN         0x10    /* log tail verify warning issued */
 
 #ifdef __KERNEL__
 /*
index a62e8971539da79743e47b0a7429c14443c4effb..19af0ab0d0c6c6c1cab862016dbe258263e39d31 100644 (file)
@@ -203,12 +203,9 @@ typedef struct xfs_mount {
        struct mutex            m_icsb_mutex;   /* balancer sync lock */
 #endif
        struct xfs_mru_cache    *m_filestream;  /* per-mount filestream data */
-       struct task_struct      *m_sync_task;   /* generalised sync thread */
-       xfs_sync_work_t         m_sync_work;    /* work item for VFS_SYNC */
-       struct list_head        m_sync_list;    /* sync thread work item list */
-       spinlock_t              m_sync_lock;    /* work item list lock */
-       int                     m_sync_seq;     /* sync thread generation no. */
-       wait_queue_head_t       m_wait_single_sync_task;
+       struct delayed_work     m_sync_work;    /* background sync work */
+       struct delayed_work     m_reclaim_work; /* background inode reclaim */
+       struct work_struct      m_flush_work;   /* background inode flush */
        __int64_t               m_update_flags; /* sb flags we need to update
                                                   on the next remount,rw */
        struct shrinker         m_inode_shrink; /* inode reclaim shrinker */
index 12aff9584e299a2d026a84f1871c669f0fdb9a4c..acdb92f14d518fe43ac9c0be62d67ae49831ca1d 100644 (file)
 #include "xfs_trans_priv.h"
 #include "xfs_error.h"
 
-STATIC void xfs_ail_splice(struct xfs_ail *, struct list_head *, xfs_lsn_t);
-STATIC void xfs_ail_delete(struct xfs_ail *, xfs_log_item_t *);
-STATIC xfs_log_item_t * xfs_ail_min(struct xfs_ail *);
-STATIC xfs_log_item_t * xfs_ail_next(struct xfs_ail *, xfs_log_item_t *);
+struct workqueue_struct        *xfs_ail_wq;    /* AIL workqueue */
 
 #ifdef DEBUG
-STATIC void xfs_ail_check(struct xfs_ail *, xfs_log_item_t *);
-#else
+/*
+ * Check that the list is sorted as it should be.
+ */
+STATIC void
+xfs_ail_check(
+       struct xfs_ail  *ailp,
+       xfs_log_item_t  *lip)
+{
+       xfs_log_item_t  *prev_lip;
+
+       if (list_empty(&ailp->xa_ail))
+               return;
+
+       /*
+        * Check the next and previous entries are valid.
+        */
+       ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0);
+       prev_lip = list_entry(lip->li_ail.prev, xfs_log_item_t, li_ail);
+       if (&prev_lip->li_ail != &ailp->xa_ail)
+               ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0);
+
+       prev_lip = list_entry(lip->li_ail.next, xfs_log_item_t, li_ail);
+       if (&prev_lip->li_ail != &ailp->xa_ail)
+               ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) >= 0);
+
+
+#ifdef XFS_TRANS_DEBUG
+       /*
+        * Walk the list checking lsn ordering, and that every entry has the
+        * XFS_LI_IN_AIL flag set. This is really expensive, so only do it
+        * when specifically debugging the transaction subsystem.
+        */
+       prev_lip = list_entry(&ailp->xa_ail, xfs_log_item_t, li_ail);
+       list_for_each_entry(lip, &ailp->xa_ail, li_ail) {
+               if (&prev_lip->li_ail != &ailp->xa_ail)
+                       ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0);
+               ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0);
+               prev_lip = lip;
+       }
+#endif /* XFS_TRANS_DEBUG */
+}
+#else /* !DEBUG */
 #define        xfs_ail_check(a,l)
 #endif /* DEBUG */
 
+/*
+ * Return a pointer to the first item in the AIL.  If the AIL is empty, then
+ * return NULL.
+ */
+static xfs_log_item_t *
+xfs_ail_min(
+       struct xfs_ail  *ailp)
+{
+       if (list_empty(&ailp->xa_ail))
+               return NULL;
+
+       return list_first_entry(&ailp->xa_ail, xfs_log_item_t, li_ail);
+}
+
+ /*
+ * Return a pointer to the last item in the AIL.  If the AIL is empty, then
+ * return NULL.
+ */
+static xfs_log_item_t *
+xfs_ail_max(
+       struct xfs_ail  *ailp)
+{
+       if (list_empty(&ailp->xa_ail))
+               return NULL;
+
+       return list_entry(ailp->xa_ail.prev, xfs_log_item_t, li_ail);
+}
+
+/*
+ * Return a pointer to the item which follows the given item in the AIL.  If
+ * the given item is the last item in the list, then return NULL.
+ */
+static xfs_log_item_t *
+xfs_ail_next(
+       struct xfs_ail  *ailp,
+       xfs_log_item_t  *lip)
+{
+       if (lip->li_ail.next == &ailp->xa_ail)
+               return NULL;
+
+       return list_first_entry(&lip->li_ail, xfs_log_item_t, li_ail);
+}
 
 /*
- * This is called by the log manager code to determine the LSN
- * of the tail of the log.  This is exactly the LSN of the first
- * item in the AIL.  If the AIL is empty, then this function
- * returns 0.
+ * This is called by the log manager code to determine the LSN of the tail of
+ * the log.  This is exactly the LSN of the first item in the AIL.  If the AIL
+ * is empty, then this function returns 0.
  *
- * We need the AIL lock in order to get a coherent read of the
- * lsn of the last item in the AIL.
+ * We need the AIL lock in order to get a coherent read of the lsn of the last
+ * item in the AIL.
  */
 xfs_lsn_t
-xfs_trans_ail_tail(
+xfs_ail_min_lsn(
        struct xfs_ail  *ailp)
 {
-       xfs_lsn_t       lsn;
+       xfs_lsn_t       lsn = 0;
        xfs_log_item_t  *lip;
 
        spin_lock(&ailp->xa_lock);
        lip = xfs_ail_min(ailp);
-       if (lip == NULL) {
-               lsn = (xfs_lsn_t)0;
-       } else {
+       if (lip)
                lsn = lip->li_lsn;
-       }
        spin_unlock(&ailp->xa_lock);
 
        return lsn;
 }
 
 /*
- * xfs_trans_push_ail
- *
- * This routine is called to move the tail of the AIL forward.  It does this by
- * trying to flush items in the AIL whose lsns are below the given
- * threshold_lsn.
- *
- * the push is run asynchronously in a separate thread, so we return the tail
- * of the log right now instead of the tail after the push. This means we will
- * either continue right away, or we will sleep waiting on the async thread to
- * do its work.
- *
- * We do this unlocked - we only need to know whether there is anything in the
- * AIL at the time we are called. We don't need to access the contents of
- * any of the objects, so the lock is not needed.
+ * Return the maximum lsn held in the AIL, or zero if the AIL is empty.
  */
-void
-xfs_trans_ail_push(
-       struct xfs_ail  *ailp,
-       xfs_lsn_t       threshold_lsn)
+static xfs_lsn_t
+xfs_ail_max_lsn(
+       struct xfs_ail  *ailp)
 {
-       xfs_log_item_t  *lip;
+       xfs_lsn_t       lsn = 0;
+       xfs_log_item_t  *lip;
 
-       lip = xfs_ail_min(ailp);
-       if (lip && !XFS_FORCED_SHUTDOWN(ailp->xa_mount)) {
-               if (XFS_LSN_CMP(threshold_lsn, ailp->xa_target) > 0)
-                       xfsaild_wakeup(ailp, threshold_lsn);
-       }
+       spin_lock(&ailp->xa_lock);
+       lip = xfs_ail_max(ailp);
+       if (lip)
+               lsn = lip->li_lsn;
+       spin_unlock(&ailp->xa_lock);
+
+       return lsn;
 }
 
 /*
@@ -236,16 +300,57 @@ out:
 }
 
 /*
- * xfsaild_push does the work of pushing on the AIL.  Returning a timeout of
- * zero indicates that the caller should sleep until woken.
+ * splice the log item list into the AIL at the given LSN.
  */
-long
-xfsaild_push(
-       struct xfs_ail  *ailp,
-       xfs_lsn_t       *last_lsn)
+static void
+xfs_ail_splice(
+       struct xfs_ail  *ailp,
+       struct list_head *list,
+       xfs_lsn_t       lsn)
 {
-       long            tout = 0;
-       xfs_lsn_t       last_pushed_lsn = *last_lsn;
+       xfs_log_item_t  *next_lip;
+
+       /* If the list is empty, just insert the item.  */
+       if (list_empty(&ailp->xa_ail)) {
+               list_splice(list, &ailp->xa_ail);
+               return;
+       }
+
+       list_for_each_entry_reverse(next_lip, &ailp->xa_ail, li_ail) {
+               if (XFS_LSN_CMP(next_lip->li_lsn, lsn) <= 0)
+                       break;
+       }
+
+       ASSERT(&next_lip->li_ail == &ailp->xa_ail ||
+              XFS_LSN_CMP(next_lip->li_lsn, lsn) <= 0);
+
+       list_splice_init(list, &next_lip->li_ail);
+}
+
+/*
+ * Delete the given item from the AIL.  Return a pointer to the item.
+ */
+static void
+xfs_ail_delete(
+       struct xfs_ail  *ailp,
+       xfs_log_item_t  *lip)
+{
+       xfs_ail_check(ailp, lip);
+       list_del(&lip->li_ail);
+       xfs_trans_ail_cursor_clear(ailp, lip);
+}
+
+/*
+ * xfs_ail_worker does the work of pushing on the AIL. It will requeue itself
+ * to run at a later time if there is more work to do to complete the push.
+ */
+STATIC void
+xfs_ail_worker(
+       struct work_struct *work)
+{
+       struct xfs_ail  *ailp = container_of(to_delayed_work(work),
+                                       struct xfs_ail, xa_work);
+       long            tout;
        xfs_lsn_t       target =  ailp->xa_target;
        xfs_lsn_t       lsn;
        xfs_log_item_t  *lip;
@@ -256,15 +361,15 @@ xfsaild_push(
 
        spin_lock(&ailp->xa_lock);
        xfs_trans_ail_cursor_init(ailp, cur);
-       lip = xfs_trans_ail_cursor_first(ailp, cur, *last_lsn);
+       lip = xfs_trans_ail_cursor_first(ailp, cur, ailp->xa_last_pushed_lsn);
        if (!lip || XFS_FORCED_SHUTDOWN(mp)) {
                /*
                 * AIL is empty or our push has reached the end.
                 */
                xfs_trans_ail_cursor_done(ailp, cur);
                spin_unlock(&ailp->xa_lock);
-               *last_lsn = 0;
-               return tout;
+               ailp->xa_last_pushed_lsn = 0;
+               return;
        }
 
        XFS_STATS_INC(xs_push_ail);
@@ -301,13 +406,13 @@ xfsaild_push(
                case XFS_ITEM_SUCCESS:
                        XFS_STATS_INC(xs_push_ail_success);
                        IOP_PUSH(lip);
-                       last_pushed_lsn = lsn;
+                       ailp->xa_last_pushed_lsn = lsn;
                        break;
 
                case XFS_ITEM_PUSHBUF:
                        XFS_STATS_INC(xs_push_ail_pushbuf);
                        IOP_PUSHBUF(lip);
-                       last_pushed_lsn = lsn;
+                       ailp->xa_last_pushed_lsn = lsn;
                        push_xfsbufd = 1;
                        break;
 
@@ -319,7 +424,7 @@ xfsaild_push(
 
                case XFS_ITEM_LOCKED:
                        XFS_STATS_INC(xs_push_ail_locked);
-                       last_pushed_lsn = lsn;
+                       ailp->xa_last_pushed_lsn = lsn;
                        stuck++;
                        break;
 
@@ -374,9 +479,23 @@ xfsaild_push(
                wake_up_process(mp->m_ddev_targp->bt_task);
        }
 
+       /* assume we have more work to do in a short while */
+       tout = 10;
        if (!count) {
                /* We're past our target or empty, so idle */
-               last_pushed_lsn = 0;
+               ailp->xa_last_pushed_lsn = 0;
+
+               /*
+                * Check for an updated push target before clearing the
+                * XFS_AIL_PUSHING_BIT. If the target changed, we've got more
+                * work to do. Wait a bit longer before starting that work.
+                */
+               smp_rmb();
+               if (ailp->xa_target == target) {
+                       clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags);
+                       return;
+               }
+               tout = 50;
        } else if (XFS_LSN_CMP(lsn, target) >= 0) {
                /*
                 * We reached the target so wait a bit longer for I/O to
@@ -384,7 +503,7 @@ xfsaild_push(
                 * start the next scan from the start of the AIL.
                 */
                tout = 50;
-               last_pushed_lsn = 0;
+               ailp->xa_last_pushed_lsn = 0;
        } else if ((stuck * 100) / count > 90) {
                /*
                 * Either there is a lot of contention on the AIL or we
@@ -396,14 +515,61 @@ xfsaild_push(
                 * continuing from where we were.
                 */
                tout = 20;
-       } else {
-               /* more to do, but wait a short while before continuing */
-               tout = 10;
        }
-       *last_lsn = last_pushed_lsn;
-       return tout;
+
+       /* There is more to do, requeue us.  */
+       queue_delayed_work(xfs_syncd_wq, &ailp->xa_work,
+                                       msecs_to_jiffies(tout));
+}
+
+/*
+ * This routine is called to move the tail of the AIL forward.  It does this by
+ * trying to flush items in the AIL whose lsns are below the given
+ * threshold_lsn.
+ *
+ * The push is run asynchronously in a workqueue, which means the caller needs
+ * to handle waiting on the async flush for space to become available.
+ * We don't want to interrupt any push that is in progress, hence we only queue
+ * work if we set the pushing bit approriately.
+ *
+ * We do this unlocked - we only need to know whether there is anything in the
+ * AIL at the time we are called. We don't need to access the contents of
+ * any of the objects, so the lock is not needed.
+ */
+void
+xfs_ail_push(
+       struct xfs_ail  *ailp,
+       xfs_lsn_t       threshold_lsn)
+{
+       xfs_log_item_t  *lip;
+
+       lip = xfs_ail_min(ailp);
+       if (!lip || XFS_FORCED_SHUTDOWN(ailp->xa_mount) ||
+           XFS_LSN_CMP(threshold_lsn, ailp->xa_target) <= 0)
+               return;
+
+       /*
+        * Ensure that the new target is noticed in push code before it clears
+        * the XFS_AIL_PUSHING_BIT.
+        */
+       smp_wmb();
+       ailp->xa_target = threshold_lsn;
+       if (!test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags))
+               queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, 0);
 }
 
+/*
+ * Push out all items in the AIL immediately
+ */
+void
+xfs_ail_push_all(
+       struct xfs_ail  *ailp)
+{
+       xfs_lsn_t       threshold_lsn = xfs_ail_max_lsn(ailp);
+
+       if (threshold_lsn)
+               xfs_ail_push(ailp, threshold_lsn);
+}
 
 /*
  * This is to be called when an item is unlocked that may have
@@ -615,7 +781,6 @@ xfs_trans_ail_init(
        xfs_mount_t     *mp)
 {
        struct xfs_ail  *ailp;
-       int             error;
 
        ailp = kmem_zalloc(sizeof(struct xfs_ail), KM_MAYFAIL);
        if (!ailp)
@@ -624,15 +789,9 @@ xfs_trans_ail_init(
        ailp->xa_mount = mp;
        INIT_LIST_HEAD(&ailp->xa_ail);
        spin_lock_init(&ailp->xa_lock);
-       error = xfsaild_start(ailp);
-       if (error)
-               goto out_free_ailp;
+       INIT_DELAYED_WORK(&ailp->xa_work, xfs_ail_worker);
        mp->m_ail = ailp;
        return 0;
-
-out_free_ailp:
-       kmem_free(ailp);
-       return error;
 }
 
 void
@@ -641,124 +800,6 @@ xfs_trans_ail_destroy(
 {
        struct xfs_ail  *ailp = mp->m_ail;
 
-       xfsaild_stop(ailp);
+       cancel_delayed_work_sync(&ailp->xa_work);
        kmem_free(ailp);
 }
-
-/*
- * splice the log item list into the AIL at the given LSN.
- */
-STATIC void
-xfs_ail_splice(
-       struct xfs_ail  *ailp,
-       struct list_head *list,
-       xfs_lsn_t       lsn)
-{
-       xfs_log_item_t  *next_lip;
-
-       /*
-        * If the list is empty, just insert the item.
-        */
-       if (list_empty(&ailp->xa_ail)) {
-               list_splice(list, &ailp->xa_ail);
-               return;
-       }
-
-       list_for_each_entry_reverse(next_lip, &ailp->xa_ail, li_ail) {
-               if (XFS_LSN_CMP(next_lip->li_lsn, lsn) <= 0)
-                       break;
-       }
-
-       ASSERT((&next_lip->li_ail == &ailp->xa_ail) ||
-              (XFS_LSN_CMP(next_lip->li_lsn, lsn) <= 0));
-
-       list_splice_init(list, &next_lip->li_ail);
-       return;
-}
-
-/*
- * Delete the given item from the AIL.  Return a pointer to the item.
- */
-STATIC void
-xfs_ail_delete(
-       struct xfs_ail  *ailp,
-       xfs_log_item_t  *lip)
-{
-       xfs_ail_check(ailp, lip);
-       list_del(&lip->li_ail);
-       xfs_trans_ail_cursor_clear(ailp, lip);
-}
-
-/*
- * Return a pointer to the first item in the AIL.
- * If the AIL is empty, then return NULL.
- */
-STATIC xfs_log_item_t *
-xfs_ail_min(
-       struct xfs_ail  *ailp)
-{
-       if (list_empty(&ailp->xa_ail))
-               return NULL;
-
-       return list_first_entry(&ailp->xa_ail, xfs_log_item_t, li_ail);
-}
-
-/*
- * Return a pointer to the item which follows
- * the given item in the AIL.  If the given item
- * is the last item in the list, then return NULL.
- */
-STATIC xfs_log_item_t *
-xfs_ail_next(
-       struct xfs_ail  *ailp,
-       xfs_log_item_t  *lip)
-{
-       if (lip->li_ail.next == &ailp->xa_ail)
-               return NULL;
-
-       return list_first_entry(&lip->li_ail, xfs_log_item_t, li_ail);
-}
-
-#ifdef DEBUG
-/*
- * Check that the list is sorted as it should be.
- */
-STATIC void
-xfs_ail_check(
-       struct xfs_ail  *ailp,
-       xfs_log_item_t  *lip)
-{
-       xfs_log_item_t  *prev_lip;
-
-       if (list_empty(&ailp->xa_ail))
-               return;
-
-       /*
-        * Check the next and previous entries are valid.
-        */
-       ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0);
-       prev_lip = list_entry(lip->li_ail.prev, xfs_log_item_t, li_ail);
-       if (&prev_lip->li_ail != &ailp->xa_ail)
-               ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0);
-
-       prev_lip = list_entry(lip->li_ail.next, xfs_log_item_t, li_ail);
-       if (&prev_lip->li_ail != &ailp->xa_ail)
-               ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) >= 0);
-
-
-#ifdef XFS_TRANS_DEBUG
-       /*
-        * Walk the list checking lsn ordering, and that every entry has the
-        * XFS_LI_IN_AIL flag set. This is really expensive, so only do it
-        * when specifically debugging the transaction subsystem.
-        */
-       prev_lip = list_entry(&ailp->xa_ail, xfs_log_item_t, li_ail);
-       list_for_each_entry(lip, &ailp->xa_ail, li_ail) {
-               if (&prev_lip->li_ail != &ailp->xa_ail)
-                       ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0);
-               ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0);
-               prev_lip = lip;
-       }
-#endif /* XFS_TRANS_DEBUG */
-}
-#endif /* DEBUG */
index 35162c238fa380e8ec4464392f2b45c617730551..6b164e9e9a1f50499be0a216d36706193b97d646 100644 (file)
@@ -65,16 +65,22 @@ struct xfs_ail_cursor {
 struct xfs_ail {
        struct xfs_mount        *xa_mount;
        struct list_head        xa_ail;
-       uint                    xa_gen;
-       struct task_struct      *xa_task;
        xfs_lsn_t               xa_target;
        struct xfs_ail_cursor   xa_cursors;
        spinlock_t              xa_lock;
+       struct delayed_work     xa_work;
+       xfs_lsn_t               xa_last_pushed_lsn;
+       unsigned long           xa_flags;
 };
 
+#define XFS_AIL_PUSHING_BIT    0
+
 /*
  * From xfs_trans_ail.c
  */
+
+extern struct workqueue_struct *xfs_ail_wq;    /* AIL workqueue */
+
 void   xfs_trans_ail_update_bulk(struct xfs_ail *ailp,
                                struct xfs_log_item **log_items, int nr_items,
                                xfs_lsn_t lsn) __releases(ailp->xa_lock);
@@ -98,12 +104,13 @@ xfs_trans_ail_delete(
        xfs_trans_ail_delete_bulk(ailp, &lip, 1);
 }
 
-void                   xfs_trans_ail_push(struct xfs_ail *, xfs_lsn_t);
+void                   xfs_ail_push(struct xfs_ail *, xfs_lsn_t);
+void                   xfs_ail_push_all(struct xfs_ail *);
+xfs_lsn_t              xfs_ail_min_lsn(struct xfs_ail *ailp);
+
 void                   xfs_trans_unlocked_item(struct xfs_ail *,
                                        xfs_log_item_t *);
 
-xfs_lsn_t              xfs_trans_ail_tail(struct xfs_ail *ailp);
-
 struct xfs_log_item    *xfs_trans_ail_cursor_first(struct xfs_ail *ailp,
                                        struct xfs_ail_cursor *cur,
                                        xfs_lsn_t lsn);
@@ -112,11 +119,6 @@ struct xfs_log_item        *xfs_trans_ail_cursor_next(struct xfs_ail *ailp,
 void                   xfs_trans_ail_cursor_done(struct xfs_ail *ailp,
                                        struct xfs_ail_cursor *cur);
 
-long   xfsaild_push(struct xfs_ail *, xfs_lsn_t *);
-void   xfsaild_wakeup(struct xfs_ail *, xfs_lsn_t);
-int    xfsaild_start(struct xfs_ail *);
-void   xfsaild_stop(struct xfs_ail *);
-
 #if BITS_PER_LONG != 64
 static inline void
 xfs_trans_ail_copy_lsn(
index 32176cc8e715e450a40e7ba24d39010603cf75f3..2ad95fa1d130f8c8f5cfd68e5fe7a0108aec31d9 100644 (file)
@@ -388,20 +388,19 @@ struct request_queue
 #define        QUEUE_FLAG_SYNCFULL     3       /* read queue has been filled */
 #define QUEUE_FLAG_ASYNCFULL   4       /* write queue has been filled */
 #define QUEUE_FLAG_DEAD                5       /* queue being torn down */
-#define QUEUE_FLAG_REENTER     6       /* Re-entrancy avoidance */
-#define QUEUE_FLAG_ELVSWITCH   7       /* don't use elevator, just do FIFO */
-#define QUEUE_FLAG_BIDI                8       /* queue supports bidi requests */
-#define QUEUE_FLAG_NOMERGES     9      /* disable merge attempts */
-#define QUEUE_FLAG_SAME_COMP   10      /* force complete on same CPU */
-#define QUEUE_FLAG_FAIL_IO     11      /* fake timeout */
-#define QUEUE_FLAG_STACKABLE   12      /* supports request stacking */
-#define QUEUE_FLAG_NONROT      13      /* non-rotational device (SSD) */
+#define QUEUE_FLAG_ELVSWITCH   6       /* don't use elevator, just do FIFO */
+#define QUEUE_FLAG_BIDI                7       /* queue supports bidi requests */
+#define QUEUE_FLAG_NOMERGES     8      /* disable merge attempts */
+#define QUEUE_FLAG_SAME_COMP   9       /* force complete on same CPU */
+#define QUEUE_FLAG_FAIL_IO     10      /* fake timeout */
+#define QUEUE_FLAG_STACKABLE   11      /* supports request stacking */
+#define QUEUE_FLAG_NONROT      12      /* non-rotational device (SSD) */
 #define QUEUE_FLAG_VIRT        QUEUE_FLAG_NONROT /* paravirt device */
-#define QUEUE_FLAG_IO_STAT     15      /* do IO stats */
-#define QUEUE_FLAG_DISCARD     16      /* supports DISCARD */
-#define QUEUE_FLAG_NOXMERGES   17      /* No extended merges */
-#define QUEUE_FLAG_ADD_RANDOM  18      /* Contributes to random pool */
-#define QUEUE_FLAG_SECDISCARD  19      /* supports SECDISCARD */
+#define QUEUE_FLAG_IO_STAT     13      /* do IO stats */
+#define QUEUE_FLAG_DISCARD     14      /* supports DISCARD */
+#define QUEUE_FLAG_NOXMERGES   15      /* No extended merges */
+#define QUEUE_FLAG_ADD_RANDOM  16      /* Contributes to random pool */
+#define QUEUE_FLAG_SECDISCARD  17      /* supports SECDISCARD */
 
 #define QUEUE_FLAG_DEFAULT     ((1 << QUEUE_FLAG_IO_STAT) |            \
                                 (1 << QUEUE_FLAG_STACKABLE)    |       \
@@ -697,8 +696,9 @@ extern void blk_start_queue(struct request_queue *q);
 extern void blk_stop_queue(struct request_queue *q);
 extern void blk_sync_queue(struct request_queue *q);
 extern void __blk_stop_queue(struct request_queue *q);
-extern void __blk_run_queue(struct request_queue *q, bool force_kblockd);
+extern void __blk_run_queue(struct request_queue *q);
 extern void blk_run_queue(struct request_queue *);
+extern void blk_run_queue_async(struct request_queue *q);
 extern int blk_rq_map_user(struct request_queue *, struct request *,
                           struct rq_map_data *, void __user *, unsigned long,
                           gfp_t);
@@ -857,26 +857,39 @@ extern void blk_put_queue(struct request_queue *);
 struct blk_plug {
        unsigned long magic;
        struct list_head list;
+       struct list_head cb_list;
        unsigned int should_sort;
 };
+struct blk_plug_cb {
+       struct list_head list;
+       void (*callback)(struct blk_plug_cb *);
+};
 
 extern void blk_start_plug(struct blk_plug *);
 extern void blk_finish_plug(struct blk_plug *);
-extern void __blk_flush_plug(struct task_struct *, struct blk_plug *);
+extern void blk_flush_plug_list(struct blk_plug *, bool);
 
 static inline void blk_flush_plug(struct task_struct *tsk)
 {
        struct blk_plug *plug = tsk->plug;
 
-       if (unlikely(plug))
-               __blk_flush_plug(tsk, plug);
+       if (plug)
+               blk_flush_plug_list(plug, false);
+}
+
+static inline void blk_schedule_flush_plug(struct task_struct *tsk)
+{
+       struct blk_plug *plug = tsk->plug;
+
+       if (plug)
+               blk_flush_plug_list(plug, true);
 }
 
 static inline bool blk_needs_flush_plug(struct task_struct *tsk)
 {
        struct blk_plug *plug = tsk->plug;
 
-       return plug && !list_empty(&plug->list);
+       return plug && (!list_empty(&plug->list) || !list_empty(&plug->cb_list));
 }
 
 /*
@@ -1314,6 +1327,11 @@ static inline void blk_flush_plug(struct task_struct *task)
 {
 }
 
+static inline void blk_schedule_flush_plug(struct task_struct *task)
+{
+}
+
+
 static inline bool blk_needs_flush_plug(struct task_struct *tsk)
 {
        return false;
index 8e20540043f55dfffc4b2096ceee6ca817e994df..089fe43211a492ec8258256b63a07a90ca2660b7 100644 (file)
@@ -12,6 +12,7 @@
 /**
  * struct mcp251x_platform_data - MCP251X SPI CAN controller platform data
  * @oscillator_frequency:       - oscillator frequency in Hz
+ * @irq_flags:                  - IRQF configuration flags
  * @board_specific_setup:       - called before probing the chip (power,reset)
  * @transceiver_enable:         - called to power on/off the transceiver
  * @power_enable:               - called to power on/off the mcp *and* the
@@ -24,6 +25,7 @@
 
 struct mcp251x_platform_data {
        unsigned long oscillator_frequency;
+       unsigned long irq_flags;
        int (*board_specific_setup)(struct spi_device *spi);
        int (*transceiver_enable)(int enable);
        int (*power_enable) (int enable);
index e2768834f39775f4baeae6e5e9316b64184a823c..32a4423710f51e54045413415a53b6b8cd0afd56 100644 (file)
@@ -197,7 +197,6 @@ struct dm_target {
 struct dm_target_callbacks {
        struct list_head list;
        int (*congested_fn) (struct dm_target_callbacks *, int);
-       void (*unplug_fn)(struct dm_target_callbacks *);
 };
 
 int dm_register_target(struct target_type *t);
index f3a7794a18c4d6de24065f797baf4ba97c34694b..771d6d85667d68a17c24c452979f8d37cc628082 100644 (file)
@@ -167,6 +167,7 @@ struct input_keymap_entry {
 #define SYN_REPORT             0
 #define SYN_CONFIG             1
 #define SYN_MT_REPORT          2
+#define SYN_DROPPED            3
 
 /*
  * Keys and buttons
@@ -553,8 +554,8 @@ struct input_keymap_entry {
 #define KEY_DVD                        0x185   /* Media Select DVD */
 #define KEY_AUX                        0x186
 #define KEY_MP3                        0x187
-#define KEY_AUDIO              0x188
-#define KEY_VIDEO              0x189
+#define KEY_AUDIO              0x188   /* AL Audio Browser */
+#define KEY_VIDEO              0x189   /* AL Movie Browser */
 #define KEY_DIRECTORY          0x18a
 #define KEY_LIST               0x18b
 #define KEY_MEMO               0x18c   /* Media Select Messages */
@@ -603,8 +604,9 @@ struct input_keymap_entry {
 #define KEY_FRAMEFORWARD       0x1b5
 #define KEY_CONTEXT_MENU       0x1b6   /* GenDesc - system context menu */
 #define KEY_MEDIA_REPEAT       0x1b7   /* Consumer - transport control */
-#define KEY_10CHANNELSUP        0x1b8   /* 10 channels up (10+) */
-#define KEY_10CHANNELSDOWN      0x1b9   /* 10 channels down (10-) */
+#define KEY_10CHANNELSUP       0x1b8   /* 10 channels up (10+) */
+#define KEY_10CHANNELSDOWN     0x1b9   /* 10 channels down (10-) */
+#define KEY_IMAGES             0x1ba   /* AL Image Browser */
 
 #define KEY_DEL_EOL            0x1c0
 #define KEY_DEL_EOS            0x1c1
index b3ac06a4435d1114fde8fad1bbd548874641915b..318bb82325a6fa59e4b3d9a13a17a99152dc5674 100644 (file)
@@ -48,6 +48,12 @@ static inline void input_mt_slot(struct input_dev *dev, int slot)
        input_event(dev, EV_ABS, ABS_MT_SLOT, slot);
 }
 
+static inline bool input_is_mt_axis(int axis)
+{
+       return axis == ABS_MT_SLOT ||
+               (axis >= ABS_MT_FIRST && axis <= ABS_MT_LAST);
+}
+
 void input_mt_report_slot_state(struct input_dev *dev,
                                unsigned int tool_type, bool active);
 
index 5a5ce7055839b607ed688ba4c19c595b4686f875..5e9840f509804df5e49224a12bbbd079177ee4f6 100644 (file)
@@ -216,7 +216,7 @@ static inline void mem_cgroup_del_lru_list(struct page *page, int lru)
        return ;
 }
 
-static inline inline void mem_cgroup_rotate_reclaimable_page(struct page *page)
+static inline void mem_cgroup_rotate_reclaimable_page(struct page *page)
 {
        return ;
 }
index ad1b19aa6508eb58af14a64535dcdcd05d454eb9..aef23309a742334d9f3fb33d3f3b5af38b7f024d 100644 (file)
@@ -86,16 +86,25 @@ extern int mfd_clone_cell(const char *cell, const char **clones,
  */
 static inline const struct mfd_cell *mfd_get_cell(struct platform_device *pdev)
 {
-       return pdev->dev.platform_data;
+       return pdev->mfd_cell;
 }
 
 /*
  * Given a platform device that's been created by mfd_add_devices(), fetch
  * the .mfd_data entry from the mfd_cell that created it.
+ * Otherwise just return the platform_data pointer.
+ * This maintains compatibility with platform drivers whose devices aren't
+ * created by the mfd layer, and expect platform_data to contain what would've
+ * otherwise been in mfd_data.
  */
 static inline void *mfd_get_data(struct platform_device *pdev)
 {
-       return mfd_get_cell(pdev)->mfd_data;
+       const struct mfd_cell *cell = mfd_get_cell(pdev);
+
+       if (cell)
+               return cell->mfd_data;
+       else
+               return pdev->dev.platform_data;
 }
 
 extern int mfd_add_devices(struct device *parent, int id,
index eeec00abb6648911f2aaf2edca07b1edca99e3ba..7fa95df60146f2920cf89e2163289017230a91a6 100644 (file)
@@ -270,7 +270,8 @@ struct nf_afinfo {
                                            unsigned int dataoff,
                                            unsigned int len,
                                            u_int8_t protocol);
-       int             (*route)(struct dst_entry **dst, struct flowi *fl);
+       int             (*route)(struct net *net, struct dst_entry **dst,
+                                struct flowi *fl, bool strict);
        void            (*saveroute)(const struct sk_buff *skb,
                                     struct nf_queue_entry *entry);
        int             (*reroute)(struct sk_buff *skb,
index ec333d83f3b4abdc62e912152838fa3131987220..5a262e3ae715999d1082801cfa25cc215b301cf3 100644 (file)
@@ -293,7 +293,7 @@ struct ip_set {
        /* Lock protecting the set data */
        rwlock_t lock;
        /* References to the set */
-       atomic_t ref;
+       u32 ref;
        /* The core set type */
        struct ip_set_type *type;
        /* The type variant doing the real job */
index ec9d9bea1e370e937aaf3006c70c157bc45eb7b4..a0196ac790513b9c8dcbb8f33b04218a7fa67b01 100644 (file)
@@ -515,8 +515,7 @@ type_pf_head(struct ip_set *set, struct sk_buff *skb)
        if (h->netmask != HOST_MASK)
                NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, h->netmask);
 #endif
-       NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
-                     htonl(atomic_read(&set->ref) - 1));
+       NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
        NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize));
        if (with_timeout(h->timeout))
                NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(h->timeout));
index 31afb7ecbe1f12b2bc97f9d251ef9fff9df785bf..cdced84261d79d125a8d6031c76638b72d259c20 100644 (file)
@@ -117,7 +117,7 @@ extern struct pid *find_vpid(int nr);
  */
 extern struct pid *find_get_pid(int nr);
 extern struct pid *find_ge_pid(int nr, struct pid_namespace *);
-int next_pidmap(struct pid_namespace *pid_ns, int last);
+int next_pidmap(struct pid_namespace *pid_ns, unsigned int last);
 
 extern struct pid *alloc_pid(struct pid_namespace *ns);
 extern void free_pid(struct pid *pid);
index d96db98257086cb51341af56d6f9db8615e0d462..744942c95fec478ff9b0e687e9496b9ff76a84bd 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
 
+struct mfd_cell;
+
 struct platform_device {
        const char      * name;
        int             id;
@@ -23,6 +25,9 @@ struct platform_device {
 
        const struct platform_device_id *id_entry;
 
+       /* MFD cell pointer */
+       struct mfd_cell *mfd_cell;
+
        /* arch specific additions */
        struct pdev_archdata    archdata;
 };
index 369e19d3750ba9ac4365cf8e778d61f6a9e239a5..7f1183dcd119e0e25dfd959827364e30f7ee291c 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/fs.h>
 #include <linux/poll.h>
 #include <linux/posix-timers.h>
+#include <linux/rwsem.h>
 
 struct posix_clock;
 
@@ -104,7 +105,7 @@ struct posix_clock_operations {
  * @ops:     Functional interface to the clock
  * @cdev:    Character device instance for this clock
  * @kref:    Reference count.
- * @mutex:   Protects the 'zombie' field from concurrent access.
+ * @rwsem:   Protects the 'zombie' field from concurrent access.
  * @zombie:  If 'zombie' is true, then the hardware has disappeared.
  * @release: A function to free the structure when the reference count reaches
  *           zero. May be NULL if structure is statically allocated.
@@ -117,7 +118,7 @@ struct posix_clock {
        struct posix_clock_operations ops;
        struct cdev cdev;
        struct kref kref;
-       struct mutex mutex;
+       struct rw_semaphore rwsem;
        bool zombie;
        void (*release)(struct posix_clock *clk);
 };
index 4e37a7cfa726f07dd65114c37a5ae3bc798904ab..4d50611112ba118e69df87888a81f764aee4c346 100644 (file)
@@ -396,7 +396,7 @@ union rio_pw_msg {
 };
 
 /* Architecture and hardware-specific functions */
-extern void rio_register_mport(struct rio_mport *);
+extern int rio_register_mport(struct rio_mport *);
 extern int rio_open_inb_mbox(struct rio_mport *, void *, int, int);
 extern void rio_close_inb_mbox(struct rio_mport *, int);
 extern int rio_open_outb_mbox(struct rio_mport *, void *, int, int);
index 7410d3365e2ad5472f28631e90397501d3fed6a4..0cee0152aca9a17c07658612f85ceec9f9986101 100644 (file)
@@ -35,6 +35,7 @@
 #define RIO_DID_IDTCPS6Q               0x035f
 #define RIO_DID_IDTCPS10Q              0x035e
 #define RIO_DID_IDTCPS1848             0x0374
+#define RIO_DID_IDTCPS1432             0x0375
 #define RIO_DID_IDTCPS1616             0x0379
 #define RIO_DID_IDTVPS1616             0x0377
 #define RIO_DID_IDTSPS1616             0x0378
index 2ca7e8a78060f24057d1c2290e05289393092e27..877ece45426f6c3eb0fa3850f0c93db0ee84468a 100644 (file)
@@ -228,6 +228,8 @@ extern int rtc_read_alarm(struct rtc_device *rtc,
                        struct rtc_wkalrm *alrm);
 extern int rtc_set_alarm(struct rtc_device *rtc,
                                struct rtc_wkalrm *alrm);
+extern int rtc_initialize_alarm(struct rtc_device *rtc,
+                               struct rtc_wkalrm *alrm);
 extern void rtc_update_irq(struct rtc_device *rtc,
                        unsigned long num, unsigned long events);
 
index 4ec2c027e92c969e04154677fbfe5813772aa422..18d63cea28481c478906f791e384b520ad1f483b 100644 (file)
@@ -1254,6 +1254,9 @@ struct task_struct {
 #endif
 
        struct mm_struct *mm, *active_mm;
+#ifdef CONFIG_COMPAT_BRK
+       unsigned brk_randomized:1;
+#endif
 #if defined(SPLIT_RSS_COUNTING)
        struct task_rss_stat    rss_stat;
 #endif
index 5a89e3612875b017760d365c99113a5e76c0d61f..083ffea7ba183de0251224928c67077a0c17d79f 100644 (file)
@@ -249,6 +249,8 @@ extern void hibernation_set_ops(const struct platform_hibernation_ops *ops);
 extern int hibernate(void);
 extern bool system_entering_hibernation(void);
 #else /* CONFIG_HIBERNATION */
+static inline void register_nosave_region(unsigned long b, unsigned long e) {}
+static inline void register_nosave_region_late(unsigned long b, unsigned long e) {}
 static inline int swsusp_page_is_forbidden(struct page *p) { return 0; }
 static inline void swsusp_set_page_free(struct page *p) {}
 static inline void swsusp_unset_page_free(struct page *p) {}
@@ -297,14 +299,7 @@ static inline bool pm_wakeup_pending(void) { return false; }
 
 extern struct mutex pm_mutex;
 
-#ifndef CONFIG_HIBERNATION
-static inline void register_nosave_region(unsigned long b, unsigned long e)
-{
-}
-static inline void register_nosave_region_late(unsigned long b, unsigned long e)
-{
-}
-
+#ifndef CONFIG_HIBERNATE_CALLBACKS
 static inline void lock_system_sleep(void) {}
 static inline void unlock_system_sleep(void) {}
 
index 3c7329b8ea0e466a11fef6a176570138de116424..0e1855079fbbbea3eab3f1f224a7fd2430cd5874 100644 (file)
@@ -103,8 +103,8 @@ struct driver_info {
  * Indicates to usbnet, that USB driver accumulates multiple IP packets.
  * Affects statistic (counters) and short packet handling.
  */
-#define FLAG_MULTI_PACKET      0x1000
-#define FLAG_RX_ASSEMBLE       0x2000  /* rx packets may span >1 frames */
+#define FLAG_MULTI_PACKET      0x2000
+#define FLAG_RX_ASSEMBLE       0x4000  /* rx packets may span >1 frames */
 
        /* init device ... can sleep, or cause probe() failure */
        int     (*bind)(struct usbnet *, struct usb_interface *);
index 461c0119664ff88d2bf8797f2541ccae74ce0698..2b3831b58aa4312a754c41b2608431db85e31887 100644 (file)
@@ -58,6 +58,13 @@ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
                UNEVICTABLE_PGCLEARED,  /* on COW, page truncate */
                UNEVICTABLE_PGSTRANDED, /* unable to isolate on unlock */
                UNEVICTABLE_MLOCKFREED,
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+               THP_FAULT_ALLOC,
+               THP_FAULT_FALLBACK,
+               THP_COLLAPSE_ALLOC,
+               THP_COLLAPSE_ALLOC_FAILED,
+               THP_SPLIT,
+#endif
                NR_VM_EVENT_ITEMS
 };
 
index cdf2e8ac4309576631abea0e05767d7edf5af027..d2df55b0c2134a35044a583429ac34e01b37f065 100644 (file)
@@ -139,8 +139,6 @@ do { \
  */
 
 enum p9_msg_t {
-       P9_TSYNCFS = 0,
-       P9_RSYNCFS,
        P9_TLERROR = 6,
        P9_RLERROR,
        P9_TSTATFS = 8,
index 85c1413f054d773ee79005cb01e6affc55f4adf1..051a99f79769a59021fdcb958a6f850e1f2ddc71 100644 (file)
@@ -218,8 +218,8 @@ void p9_client_disconnect(struct p9_client *clnt);
 void p9_client_begin_disconnect(struct p9_client *clnt);
 struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
                                        char *uname, u32 n_uname, char *aname);
-struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
-                                                               int clone);
+struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
+               char **wnames, int clone);
 int p9_client_open(struct p9_fid *fid, int mode);
 int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
                                                        char *extension);
@@ -230,7 +230,6 @@ int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode,
                gid_t gid, struct p9_qid *qid);
 int p9_client_clunk(struct p9_fid *fid);
 int p9_client_fsync(struct p9_fid *fid, int datasync);
-int p9_client_sync_fs(struct p9_fid *fid);
 int p9_client_remove(struct p9_fid *fid);
 int p9_client_read(struct p9_fid *fid, char *data, char __user *udata,
                                                        u64 offset, u32 count);
index 814b434db749d2d6f9bcc49cd99f05f120e11c53..d516f00c8e0fc39c9aa0dc8a75aa2728df635388 100644 (file)
@@ -52,7 +52,7 @@ static inline struct net *skb_net(const struct sk_buff *skb)
         */
        if (likely(skb->dev && skb->dev->nd_net))
                return dev_net(skb->dev);
-       if (skb_dst(skb)->dev)
+       if (skb_dst(skb) && skb_dst(skb)->dev)
                return dev_net(skb_dst(skb)->dev);
        WARN(skb->sk, "Maybe skb_sknet should be used in %s() at line:%d\n",
                      __func__, __LINE__);
index cb13239fe8e33be82a17bcf2269c75e74aea5951..025d4cc7bbf800c846113496bfec7a375afa07c4 100644 (file)
@@ -1753,8 +1753,19 @@ enum ieee80211_ampdu_mlme_action {
  *     that TX/RX_STOP can pass NULL for this parameter.
  *     The @buf_size parameter is only valid when the action is set to
  *     %IEEE80211_AMPDU_TX_OPERATIONAL and indicates the peer's reorder
- *     buffer size (number of subframes) for this session -- aggregates
- *     containing more subframes than this may not be transmitted to the peer.
+ *     buffer size (number of subframes) for this session -- the driver
+ *     may neither send aggregates containing more subframes than this
+ *     nor send aggregates in a way that lost frames would exceed the
+ *     buffer size. If just limiting the aggregate size, this would be
+ *     possible with a buf_size of 8:
+ *      - TX: 1.....7
+ *      - RX:  2....7 (lost frame #1)
+ *      - TX:        8..1...
+ *     which is invalid since #1 was now re-transmitted well past the
+ *     buffer size of 8. Correct ways to retransmit #1 would be:
+ *      - TX:       1 or 18 or 81
+ *     Even "189" would be wrong since 1 could be lost again.
+ *
  *     Returns a negative error code on failure.
  *     The callback can sleep.
  *
index f88429cad52a197a714cb138ad8d7e0473a5e9d0..8fce0621cad10a3e11a6a06dfa272f6583e65cd9 100644 (file)
@@ -64,6 +64,7 @@ struct rtable {
 
        __be32                  rt_dst; /* Path destination     */
        __be32                  rt_src; /* Path source          */
+       int                     rt_route_iif;
        int                     rt_iif;
        int                     rt_oif;
        __u32                   rt_mark;
@@ -80,12 +81,12 @@ struct rtable {
 
 static inline bool rt_is_input_route(struct rtable *rt)
 {
-       return rt->rt_iif != 0;
+       return rt->rt_route_iif != 0;
 }
 
 static inline bool rt_is_output_route(struct rtable *rt)
 {
-       return rt->rt_iif == 0;
+       return rt->rt_route_iif == 0;
 }
 
 struct ip_rt_acct {
index 78f18adb49c88fee50ef7a6e2bf3dabf23f851a2..bf366547da252077cf168522a1ff22735a10d3a5 100644 (file)
@@ -401,9 +401,9 @@ TRACE_EVENT(block_plug,
 
 DECLARE_EVENT_CLASS(block_unplug,
 
-       TP_PROTO(struct request_queue *q),
+       TP_PROTO(struct request_queue *q, unsigned int depth, bool explicit),
 
-       TP_ARGS(q),
+       TP_ARGS(q, depth, explicit),
 
        TP_STRUCT__entry(
                __field( int,           nr_rq                   )
@@ -411,7 +411,7 @@ DECLARE_EVENT_CLASS(block_unplug,
        ),
 
        TP_fast_assign(
-               __entry->nr_rq  = q->rq.count[READ] + q->rq.count[WRITE];
+               __entry->nr_rq = depth;
                memcpy(__entry->comm, current->comm, TASK_COMM_LEN);
        ),
 
@@ -419,31 +419,19 @@ DECLARE_EVENT_CLASS(block_unplug,
 );
 
 /**
- * block_unplug_timer - timed release of operations requests in queue to device driver
- * @q: request queue to unplug
- *
- * Unplug the request queue @q because a timer expired and allow block
- * operation requests to be sent to the device driver.
- */
-DEFINE_EVENT(block_unplug, block_unplug_timer,
-
-       TP_PROTO(struct request_queue *q),
-
-       TP_ARGS(q)
-);
-
-/**
- * block_unplug_io - release of operations requests in request queue
+ * block_unplug - release of operations requests in request queue
  * @q: request queue to unplug
+ * @depth: number of requests just added to the queue
+ * @explicit: whether this was an explicit unplug, or one from schedule()
  *
  * Unplug request queue @q because device driver is scheduled to work
  * on elements in the request queue.
  */
-DEFINE_EVENT(block_unplug, block_unplug_io,
+DEFINE_EVENT(block_unplug, block_unplug,
 
-       TP_PROTO(struct request_queue *q),
+       TP_PROTO(struct request_queue *q, unsigned int depth, bool explicit),
 
-       TP_ARGS(q)
+       TP_ARGS(q, depth, explicit)
 );
 
 /**
index dfb924ffe65ba758627864ac45c55bb9bda290bc..fe28dc282eae43af920d2937e8f9c5dc631ffa43 100644 (file)
@@ -1886,7 +1886,7 @@ retry:
        restart->futex.val = val;
        restart->futex.time = abs_time->tv64;
        restart->futex.bitset = bitset;
-       restart->futex.flags = flags;
+       restart->futex.flags = flags | FLAGS_HAS_TIMEOUT;
 
        ret = -ERESTART_RESTARTBLOCK;
 
index 27960f114efd73f9fb6ebec3d90952a643cd4284..8e81a9860a0d543c436716345b2ce0871229915b 100644 (file)
@@ -364,6 +364,7 @@ void perf_cgroup_switch(struct task_struct *task, int mode)
                        }
 
                        if (mode & PERF_CGROUP_SWIN) {
+                               WARN_ON_ONCE(cpuctx->cgrp);
                                /* set cgrp before ctxsw in to
                                 * allow event_filter_match() to not
                                 * have to pass task around
@@ -2423,6 +2424,14 @@ static void perf_event_enable_on_exec(struct perf_event_context *ctx)
        if (!ctx || !ctx->nr_events)
                goto out;
 
+       /*
+        * We must ctxsw out cgroup events to avoid conflict
+        * when invoking perf_task_event_sched_in() later on
+        * in this function. Otherwise we end up trying to
+        * ctxswin cgroup events which are already scheduled
+        * in.
+        */
+       perf_cgroup_sched_out(current);
        task_ctx_sched_out(ctx, EVENT_ALL);
 
        raw_spin_lock(&ctx->lock);
@@ -2447,6 +2456,9 @@ static void perf_event_enable_on_exec(struct perf_event_context *ctx)
 
        raw_spin_unlock(&ctx->lock);
 
+       /*
+        * Also calls ctxswin for cgroup events, if any:
+        */
        perf_event_context_sched_in(ctx, ctx->task);
 out:
        local_irq_restore(flags);
index 02f221274265ead8f24d98be78d669d5888e62fe..57a8346a270e07702e21d7bab15303427bf2fce0 100644 (file)
@@ -217,11 +217,14 @@ static int alloc_pidmap(struct pid_namespace *pid_ns)
        return -1;
 }
 
-int next_pidmap(struct pid_namespace *pid_ns, int last)
+int next_pidmap(struct pid_namespace *pid_ns, unsigned int last)
 {
        int offset;
        struct pidmap *map, *end;
 
+       if (last >= PID_MAX_LIMIT)
+               return -1;
+
        offset = (last + 1) & BITS_PER_PAGE_MASK;
        map = &pid_ns->pidmap[(last + 1)/BITS_PER_PAGE];
        end = &pid_ns->pidmap[PIDMAP_ENTRIES];
index 4603f08dc47b1e7687b09ca51e31b3e7c48b4c55..6de9a8fc34179448c0768a1c4a12ad4849cb1ce6 100644 (file)
@@ -18,9 +18,13 @@ config SUSPEND_FREEZER
 
          Turning OFF this setting is NOT recommended! If in doubt, say Y.
 
+config HIBERNATE_CALLBACKS
+       bool
+
 config HIBERNATION
        bool "Hibernation (aka 'suspend to disk')"
        depends on SWAP && ARCH_HIBERNATION_POSSIBLE
+       select HIBERNATE_CALLBACKS
        select LZO_COMPRESS
        select LZO_DECOMPRESS
        ---help---
@@ -85,7 +89,7 @@ config PM_STD_PARTITION
 
 config PM_SLEEP
        def_bool y
-       depends on SUSPEND || HIBERNATION || XEN_SAVE_RESTORE
+       depends on SUSPEND || HIBERNATE_CALLBACKS
 
 config PM_SLEEP_SMP
        def_bool y
index 48013633d792f4682b0777dd96caf10beb6c8e73..312f8b95c2d44fbbc7c7097de04b52d92abc0648 100644 (file)
@@ -4111,20 +4111,20 @@ need_resched:
                                        try_to_wake_up_local(to_wakeup);
                        }
                        deactivate_task(rq, prev, DEQUEUE_SLEEP);
+
+                       /*
+                        * If we are going to sleep and we have plugged IO queued, make
+                        * sure to submit it to avoid deadlocks.
+                        */
+                       if (blk_needs_flush_plug(prev)) {
+                               raw_spin_unlock(&rq->lock);
+                               blk_schedule_flush_plug(prev);
+                               raw_spin_lock(&rq->lock);
+                       }
                }
                switch_count = &prev->nvcsw;
        }
 
-       /*
-        * If we are going to sleep and we have plugged IO queued, make
-        * sure to submit it to avoid deadlocks.
-        */
-       if (prev->state != TASK_RUNNING && blk_needs_flush_plug(prev)) {
-               raw_spin_unlock(&rq->lock);
-               blk_flush_plug(prev);
-               raw_spin_lock(&rq->lock);
-       }
-
        pre_schedule(rq, prev);
 
        if (unlikely(!rq->nr_running))
index 7f00772e57c90b9b5ee62a65b55f3b1a2f5af706..6fa833ab2cb80ebac3e3f38007f0d7c47995769e 100644 (file)
@@ -2104,21 +2104,20 @@ balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest,
              enum cpu_idle_type idle, int *all_pinned,
              int *this_best_prio, struct cfs_rq *busiest_cfs_rq)
 {
-       int loops = 0, pulled = 0, pinned = 0;
+       int loops = 0, pulled = 0;
        long rem_load_move = max_load_move;
        struct task_struct *p, *n;
 
        if (max_load_move == 0)
                goto out;
 
-       pinned = 1;
-
        list_for_each_entry_safe(p, n, &busiest_cfs_rq->tasks, se.group_node) {
                if (loops++ > sysctl_sched_nr_migrate)
                        break;
 
                if ((p->se.load.weight >> 1) > rem_load_move ||
-                   !can_migrate_task(p, busiest, this_cpu, sd, idle, &pinned))
+                   !can_migrate_task(p, busiest, this_cpu, sd, idle,
+                                     all_pinned))
                        continue;
 
                pull_task(busiest, p, this_rq, this_cpu);
@@ -2153,9 +2152,6 @@ out:
         */
        schedstat_add(sd, lb_gained[idle], pulled);
 
-       if (all_pinned)
-               *all_pinned = pinned;
-
        return max_load_move - rem_load_move;
 }
 
@@ -3127,6 +3123,8 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
        if (!sds.busiest || sds.busiest_nr_running == 0)
                goto out_balanced;
 
+       sds.avg_load = (SCHED_LOAD_SCALE * sds.total_load) / sds.total_pwr;
+
        /*
         * If the busiest group is imbalanced the below checks don't
         * work because they assumes all things are equal, which typically
@@ -3151,7 +3149,6 @@ find_busiest_group(struct sched_domain *sd, int this_cpu,
         * Don't pull any tasks if this group is already above the domain
         * average load.
         */
-       sds.avg_load = (SCHED_LOAD_SCALE * sds.total_load) / sds.total_pwr;
        if (sds.this_load >= sds.avg_load)
                goto out_balanced;
 
@@ -3340,6 +3337,7 @@ redo:
                 * still unbalanced. ld_moved simply stays zero, so it is
                 * correctly treated as an imbalance.
                 */
+               all_pinned = 1;
                local_irq_save(flags);
                double_rq_lock(this_rq, busiest);
                ld_moved = move_tasks(this_rq, this_cpu, busiest,
index 25028dd4fa18044846caa1098bf87b28c1c81be4..c340ca658f37a0c09726a31a6f126f18c9380355 100644 (file)
@@ -19,7 +19,6 @@
  */
 #include <linux/device.h>
 #include <linux/file.h>
-#include <linux/mutex.h>
 #include <linux/posix-clock.h>
 #include <linux/slab.h>
 #include <linux/syscalls.h>
@@ -34,19 +33,19 @@ static struct posix_clock *get_posix_clock(struct file *fp)
 {
        struct posix_clock *clk = fp->private_data;
 
-       mutex_lock(&clk->mutex);
+       down_read(&clk->rwsem);
 
        if (!clk->zombie)
                return clk;
 
-       mutex_unlock(&clk->mutex);
+       up_read(&clk->rwsem);
 
        return NULL;
 }
 
 static void put_posix_clock(struct posix_clock *clk)
 {
-       mutex_unlock(&clk->mutex);
+       up_read(&clk->rwsem);
 }
 
 static ssize_t posix_clock_read(struct file *fp, char __user *buf,
@@ -156,7 +155,7 @@ static int posix_clock_open(struct inode *inode, struct file *fp)
        struct posix_clock *clk =
                container_of(inode->i_cdev, struct posix_clock, cdev);
 
-       mutex_lock(&clk->mutex);
+       down_read(&clk->rwsem);
 
        if (clk->zombie) {
                err = -ENODEV;
@@ -172,7 +171,7 @@ static int posix_clock_open(struct inode *inode, struct file *fp)
                fp->private_data = clk;
        }
 out:
-       mutex_unlock(&clk->mutex);
+       up_read(&clk->rwsem);
        return err;
 }
 
@@ -211,25 +210,20 @@ int posix_clock_register(struct posix_clock *clk, dev_t devid)
        int err;
 
        kref_init(&clk->kref);
-       mutex_init(&clk->mutex);
+       init_rwsem(&clk->rwsem);
 
        cdev_init(&clk->cdev, &posix_clock_file_operations);
        clk->cdev.owner = clk->ops.owner;
        err = cdev_add(&clk->cdev, devid, 1);
-       if (err)
-               goto no_cdev;
 
        return err;
-no_cdev:
-       mutex_destroy(&clk->mutex);
-       return err;
 }
 EXPORT_SYMBOL_GPL(posix_clock_register);
 
 static void delete_clock(struct kref *kref)
 {
        struct posix_clock *clk = container_of(kref, struct posix_clock, kref);
-       mutex_destroy(&clk->mutex);
+
        if (clk->release)
                clk->release(clk);
 }
@@ -238,9 +232,9 @@ void posix_clock_unregister(struct posix_clock *clk)
 {
        cdev_del(&clk->cdev);
 
-       mutex_lock(&clk->mutex);
+       down_write(&clk->rwsem);
        clk->zombie = true;
-       mutex_unlock(&clk->mutex);
+       up_write(&clk->rwsem);
 
        kref_put(&clk->kref, delete_clock);
 }
index 7aa40f8e182d569bcba8c0a3f33bb0f73b6f4950..6957aa298dfa45581b45832b7251a2ee4029000e 100644 (file)
@@ -850,29 +850,21 @@ static void blk_add_trace_plug(void *ignore, struct request_queue *q)
                __blk_add_trace(bt, 0, 0, 0, BLK_TA_PLUG, 0, 0, NULL);
 }
 
-static void blk_add_trace_unplug_io(void *ignore, struct request_queue *q)
+static void blk_add_trace_unplug(void *ignore, struct request_queue *q,
+                                   unsigned int depth, bool explicit)
 {
        struct blk_trace *bt = q->blk_trace;
 
        if (bt) {
-               unsigned int pdu = q->rq.count[READ] + q->rq.count[WRITE];
-               __be64 rpdu = cpu_to_be64(pdu);
+               __be64 rpdu = cpu_to_be64(depth);
+               u32 what;
 
-               __blk_add_trace(bt, 0, 0, 0, BLK_TA_UNPLUG_IO, 0,
-                               sizeof(rpdu), &rpdu);
-       }
-}
-
-static void blk_add_trace_unplug_timer(void *ignore, struct request_queue *q)
-{
-       struct blk_trace *bt = q->blk_trace;
-
-       if (bt) {
-               unsigned int pdu = q->rq.count[READ] + q->rq.count[WRITE];
-               __be64 rpdu = cpu_to_be64(pdu);
+               if (explicit)
+                       what = BLK_TA_UNPLUG_IO;
+               else
+                       what = BLK_TA_UNPLUG_TIMER;
 
-               __blk_add_trace(bt, 0, 0, 0, BLK_TA_UNPLUG_TIMER, 0,
-                               sizeof(rpdu), &rpdu);
+               __blk_add_trace(bt, 0, 0, 0, what, 0, sizeof(rpdu), &rpdu);
        }
 }
 
@@ -1015,9 +1007,7 @@ static void blk_register_tracepoints(void)
        WARN_ON(ret);
        ret = register_trace_block_plug(blk_add_trace_plug, NULL);
        WARN_ON(ret);
-       ret = register_trace_block_unplug_timer(blk_add_trace_unplug_timer, NULL);
-       WARN_ON(ret);
-       ret = register_trace_block_unplug_io(blk_add_trace_unplug_io, NULL);
+       ret = register_trace_block_unplug(blk_add_trace_unplug, NULL);
        WARN_ON(ret);
        ret = register_trace_block_split(blk_add_trace_split, NULL);
        WARN_ON(ret);
@@ -1032,8 +1022,7 @@ static void blk_unregister_tracepoints(void)
        unregister_trace_block_rq_remap(blk_add_trace_rq_remap, NULL);
        unregister_trace_block_bio_remap(blk_add_trace_bio_remap, NULL);
        unregister_trace_block_split(blk_add_trace_split, NULL);
-       unregister_trace_block_unplug_io(blk_add_trace_unplug_io, NULL);
-       unregister_trace_block_unplug_timer(blk_add_trace_unplug_timer, NULL);
+       unregister_trace_block_unplug(blk_add_trace_unplug, NULL);
        unregister_trace_block_plug(blk_add_trace_plug, NULL);
        unregister_trace_block_sleeprq(blk_add_trace_sleeprq, NULL);
        unregister_trace_block_getrq(blk_add_trace_getrq, NULL);
index 05672e819f8c4c9164dd40e3752d23b8b5f63577..a235f3cc471c6d427fd4c2e713a701fa0b1e7e1b 100644 (file)
@@ -49,12 +49,9 @@ static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res)
                        val = *s - '0';
                else if ('a' <= _tolower(*s) && _tolower(*s) <= 'f')
                        val = _tolower(*s) - 'a' + 10;
-               else if (*s == '\n') {
-                       if (*(s + 1) == '\0')
-                               break;
-                       else
-                               return -EINVAL;
-               } else
+               else if (*s == '\n' && *(s + 1) == '\0')
+                       break;
+               else
                        return -EINVAL;
 
                if (val >= base)
index 325c2f9ecebdc431e87fc1ab375c1ac5e1365d64..d55769d63cb8b3efb8182a0f58a73ed496768b21 100644 (file)
@@ -315,12 +315,12 @@ static void __init test_kstrtou64_ok(void)
                {"65537",       10,     65537},
                {"2147483646",  10,     2147483646},
                {"2147483647",  10,     2147483647},
-               {"2147483648",  10,     2147483648},
-               {"2147483649",  10,     2147483649},
-               {"4294967294",  10,     4294967294},
-               {"4294967295",  10,     4294967295},
-               {"4294967296",  10,     4294967296},
-               {"4294967297",  10,     4294967297},
+               {"2147483648",  10,     2147483648ULL},
+               {"2147483649",  10,     2147483649ULL},
+               {"4294967294",  10,     4294967294ULL},
+               {"4294967295",  10,     4294967295ULL},
+               {"4294967296",  10,     4294967296ULL},
+               {"4294967297",  10,     4294967297ULL},
                {"9223372036854775806", 10,     9223372036854775806ULL},
                {"9223372036854775807", 10,     9223372036854775807ULL},
                {"9223372036854775808", 10,     9223372036854775808ULL},
@@ -369,12 +369,12 @@ static void __init test_kstrtos64_ok(void)
                {"65537",       10,     65537},
                {"2147483646",  10,     2147483646},
                {"2147483647",  10,     2147483647},
-               {"2147483648",  10,     2147483648},
-               {"2147483649",  10,     2147483649},
-               {"4294967294",  10,     4294967294},
-               {"4294967295",  10,     4294967295},
-               {"4294967296",  10,     4294967296},
-               {"4294967297",  10,     4294967297},
+               {"2147483648",  10,     2147483648LL},
+               {"2147483649",  10,     2147483649LL},
+               {"4294967294",  10,     4294967294LL},
+               {"4294967295",  10,     4294967295LL},
+               {"4294967296",  10,     4294967296LL},
+               {"4294967297",  10,     4294967297LL},
                {"9223372036854775806", 10,     9223372036854775806LL},
                {"9223372036854775807", 10,     9223372036854775807LL},
        };
@@ -418,10 +418,10 @@ static void __init test_kstrtou32_ok(void)
                {"65537",       10,     65537},
                {"2147483646",  10,     2147483646},
                {"2147483647",  10,     2147483647},
-               {"2147483648",  10,     2147483648},
-               {"2147483649",  10,     2147483649},
-               {"4294967294",  10,     4294967294},
-               {"4294967295",  10,     4294967295},
+               {"2147483648",  10,     2147483648U},
+               {"2147483649",  10,     2147483649U},
+               {"4294967294",  10,     4294967294U},
+               {"4294967295",  10,     4294967295U},
        };
        TEST_OK(kstrtou32, u32, "%u", test_u32_ok);
 }
index 0a619e0e2e0bd26da68b26948f065e1be72a8aa0..470dcda10addbc68e1470c9bc8c92b5dba103623 100644 (file)
@@ -244,24 +244,28 @@ static ssize_t single_flag_show(struct kobject *kobj,
                                struct kobj_attribute *attr, char *buf,
                                enum transparent_hugepage_flag flag)
 {
-       if (test_bit(flag, &transparent_hugepage_flags))
-               return sprintf(buf, "[yes] no\n");
-       else
-               return sprintf(buf, "yes [no]\n");
+       return sprintf(buf, "%d\n",
+                      !!test_bit(flag, &transparent_hugepage_flags));
 }
+
 static ssize_t single_flag_store(struct kobject *kobj,
                                 struct kobj_attribute *attr,
                                 const char *buf, size_t count,
                                 enum transparent_hugepage_flag flag)
 {
-       if (!memcmp("yes", buf,
-                   min(sizeof("yes")-1, count))) {
+       unsigned long value;
+       int ret;
+
+       ret = kstrtoul(buf, 10, &value);
+       if (ret < 0)
+               return ret;
+       if (value > 1)
+               return -EINVAL;
+
+       if (value)
                set_bit(flag, &transparent_hugepage_flags);
-       } else if (!memcmp("no", buf,
-                          min(sizeof("no")-1, count))) {
+       else
                clear_bit(flag, &transparent_hugepage_flags);
-       } else
-               return -EINVAL;
 
        return count;
 }
@@ -680,8 +684,11 @@ int do_huge_pmd_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
                        return VM_FAULT_OOM;
                page = alloc_hugepage_vma(transparent_hugepage_defrag(vma),
                                          vma, haddr, numa_node_id(), 0);
-               if (unlikely(!page))
+               if (unlikely(!page)) {
+                       count_vm_event(THP_FAULT_FALLBACK);
                        goto out;
+               }
+               count_vm_event(THP_FAULT_ALLOC);
                if (unlikely(mem_cgroup_newpage_charge(page, mm, GFP_KERNEL))) {
                        put_page(page);
                        goto out;
@@ -909,11 +916,13 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
                new_page = NULL;
 
        if (unlikely(!new_page)) {
+               count_vm_event(THP_FAULT_FALLBACK);
                ret = do_huge_pmd_wp_page_fallback(mm, vma, address,
                                                   pmd, orig_pmd, page, haddr);
                put_page(page);
                goto out;
        }
+       count_vm_event(THP_FAULT_ALLOC);
 
        if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) {
                put_page(new_page);
@@ -1390,6 +1399,7 @@ int split_huge_page(struct page *page)
 
        BUG_ON(!PageSwapBacked(page));
        __split_huge_page(page, anon_vma);
+       count_vm_event(THP_SPLIT);
 
        BUG_ON(PageCompound(page));
 out_unlock:
@@ -1784,9 +1794,11 @@ static void collapse_huge_page(struct mm_struct *mm,
                                      node, __GFP_OTHER_NODE);
        if (unlikely(!new_page)) {
                up_read(&mm->mmap_sem);
+               count_vm_event(THP_COLLAPSE_ALLOC_FAILED);
                *hpage = ERR_PTR(-ENOMEM);
                return;
        }
+       count_vm_event(THP_COLLAPSE_ALLOC);
        if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) {
                up_read(&mm->mmap_sem);
                put_page(new_page);
@@ -2151,8 +2163,11 @@ static void khugepaged_do_scan(struct page **hpage)
 #ifndef CONFIG_NUMA
                if (!*hpage) {
                        *hpage = alloc_hugepage(khugepaged_defrag());
-                       if (unlikely(!*hpage))
+                       if (unlikely(!*hpage)) {
+                               count_vm_event(THP_COLLAPSE_ALLOC_FAILED);
                                break;
+                       }
+                       count_vm_event(THP_COLLAPSE_ALLOC);
                }
 #else
                if (IS_ERR(*hpage))
@@ -2192,8 +2207,11 @@ static struct page *khugepaged_alloc_hugepage(void)
 
        do {
                hpage = alloc_hugepage(khugepaged_defrag());
-               if (!hpage)
+               if (!hpage) {
+                       count_vm_event(THP_COLLAPSE_ALLOC_FAILED);
                        khugepaged_alloc_sleep();
+               } else
+                       count_vm_event(THP_COLLAPSE_ALLOC);
        } while (unlikely(!hpage) &&
                 likely(khugepaged_enabled()));
        return hpage;
@@ -2210,8 +2228,11 @@ static void khugepaged_loop(void)
        while (likely(khugepaged_enabled())) {
 #ifndef CONFIG_NUMA
                hpage = khugepaged_alloc_hugepage();
-               if (unlikely(!hpage))
+               if (unlikely(!hpage)) {
+                       count_vm_event(THP_COLLAPSE_ALLOC_FAILED);
                        break;
+               }
+               count_vm_event(THP_COLLAPSE_ALLOC);
 #else
                if (IS_ERR(hpage)) {
                        khugepaged_alloc_sleep();
index 9da8cab1b1b0abceae9569a794447f3ddb0c1134..ce22a250926f59711f51e634a565cb90256d969c 100644 (file)
@@ -1410,6 +1410,13 @@ no_page_table:
        return page;
 }
 
+static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr)
+{
+       return (vma->vm_flags & VM_GROWSDOWN) &&
+               (vma->vm_start == addr) &&
+               !vma_stack_continue(vma->vm_prev, addr);
+}
+
 /**
  * __get_user_pages() - pin user pages in memory
  * @tsk:       task_struct of target task
@@ -1488,7 +1495,6 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                vma = find_extend_vma(mm, start);
                if (!vma && in_gate_area(mm, start)) {
                        unsigned long pg = start & PAGE_MASK;
-                       struct vm_area_struct *gate_vma = get_gate_vma(mm);
                        pgd_t *pgd;
                        pud_t *pud;
                        pmd_t *pmd;
@@ -1513,10 +1519,11 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                                pte_unmap(pte);
                                return i ? : -EFAULT;
                        }
+                       vma = get_gate_vma(mm);
                        if (pages) {
                                struct page *page;
 
-                               page = vm_normal_page(gate_vma, start, *pte);
+                               page = vm_normal_page(vma, start, *pte);
                                if (!page) {
                                        if (!(gup_flags & FOLL_DUMP) &&
                                             is_zero_pfn(pte_pfn(*pte)))
@@ -1530,12 +1537,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                                get_page(page);
                        }
                        pte_unmap(pte);
-                       if (vmas)
-                               vmas[i] = gate_vma;
-                       i++;
-                       start += PAGE_SIZE;
-                       nr_pages--;
-                       continue;
+                       goto next_page;
                }
 
                if (!vma ||
@@ -1549,6 +1551,13 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                        continue;
                }
 
+               /*
+                * If we don't actually want the page itself,
+                * and it's the stack guard page, just skip it.
+                */
+               if (!pages && stack_guard_page(vma, start))
+                       goto next_page;
+
                do {
                        struct page *page;
                        unsigned int foll_flags = gup_flags;
@@ -1631,6 +1640,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                                flush_anon_page(vma, page, start);
                                flush_dcache_page(page);
                        }
+next_page:
                        if (vmas)
                                vmas[i] = vma;
                        i++;
@@ -3678,7 +3688,7 @@ static int __access_remote_vm(struct task_struct *tsk, struct mm_struct *mm,
                         */
 #ifdef CONFIG_HAVE_IOREMAP_PROT
                        vma = find_vma(mm, addr);
-                       if (!vma)
+                       if (!vma || vma->vm_start > addr)
                                break;
                        if (vma->vm_ops && vma->vm_ops->access)
                                ret = vma->vm_ops->access(vma, addr, buf,
index a2acaf820fe518a98a5e6008690967453fbef7d0..9ca1d604f7cd74aab7a897de22e0784a8c0bcb45 100644 (file)
@@ -375,7 +375,7 @@ void online_page(struct page *page)
 #endif
 
 #ifdef CONFIG_FLATMEM
-       max_mapnr = max(page_to_pfn(page), max_mapnr);
+       max_mapnr = max(pfn, max_mapnr);
 #endif
 
        ClearPageReserved(page);
index 2689a08c79affabda1e46b65271c60e3ba653ab7..6b55e3efe0df4ebd9aafd71e9317bc664956006f 100644 (file)
@@ -135,13 +135,6 @@ void munlock_vma_page(struct page *page)
        }
 }
 
-static inline int stack_guard_page(struct vm_area_struct *vma, unsigned long addr)
-{
-       return (vma->vm_flags & VM_GROWSDOWN) &&
-               (vma->vm_start == addr) &&
-               !vma_stack_continue(vma->vm_prev, addr);
-}
-
 /**
  * __mlock_vma_pages_range() -  mlock a range of pages in the vma.
  * @vma:   target vma
@@ -188,12 +181,6 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma,
        if (vma->vm_flags & VM_LOCKED)
                gup_flags |= FOLL_MLOCK;
 
-       /* We don't try to access the guard page of a stack vma */
-       if (stack_guard_page(vma, start)) {
-               addr += PAGE_SIZE;
-               nr_pages--;
-       }
-
        return __get_user_pages(current, mm, addr, nr_pages, gup_flags,
                                NULL, NULL, nonblocking);
 }
index 2ec8eb5a9cdd0b4ae2e20471858bd4e09d83af00..e27e0cf0de03ccb81b252953932fc356c3499c10 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -259,7 +259,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk)
         * randomize_va_space to 2, which will still cause mm->start_brk
         * to be arbitrarily shifted
         */
-       if (mm->start_brk > PAGE_ALIGN(mm->end_data))
+       if (current->brk_randomized)
                min_brk = mm->start_brk;
        else
                min_brk = mm->end_data;
@@ -1814,11 +1814,14 @@ static int expand_downwards(struct vm_area_struct *vma,
                size = vma->vm_end - address;
                grow = (vma->vm_start - address) >> PAGE_SHIFT;
 
-               error = acct_stack_growth(vma, size, grow);
-               if (!error) {
-                       vma->vm_start = address;
-                       vma->vm_pgoff -= grow;
-                       perf_event_mmap(vma);
+               error = -ENOMEM;
+               if (grow <= vma->vm_pgoff) {
+                       error = acct_stack_growth(vma, size, grow);
+                       if (!error) {
+                               vma->vm_start = address;
+                               vma->vm_pgoff -= grow;
+                               perf_event_mmap(vma);
+                       }
                }
        }
        vma_unlock_anon_vma(vma);
index 6a819d1b2c7dd70015b9fadff8f28d70f3b6f422..83fb72c108b7947a7b18989455607e14ead0084f 100644 (file)
@@ -83,24 +83,6 @@ static bool has_intersects_mems_allowed(struct task_struct *tsk,
 }
 #endif /* CONFIG_NUMA */
 
-/*
- * If this is a system OOM (not a memcg OOM) and the task selected to be
- * killed is not already running at high (RT) priorities, speed up the
- * recovery by boosting the dying task to the lowest FIFO priority.
- * That helps with the recovery and avoids interfering with RT tasks.
- */
-static void boost_dying_task_prio(struct task_struct *p,
-                                 struct mem_cgroup *mem)
-{
-       struct sched_param param = { .sched_priority = 1 };
-
-       if (mem)
-               return;
-
-       if (!rt_task(p))
-               sched_setscheduler_nocheck(p, SCHED_FIFO, &param);
-}
-
 /*
  * The process p may have detached its own ->mm while exiting or through
  * use_mm(), but one or more of its subthreads may still have a valid
@@ -452,13 +434,6 @@ static int oom_kill_task(struct task_struct *p, struct mem_cgroup *mem)
        set_tsk_thread_flag(p, TIF_MEMDIE);
        force_sig(SIGKILL, p);
 
-       /*
-        * We give our sacrificial lamb high priority and access to
-        * all the memory it needs. That way it should be able to
-        * exit() and clear out its resources quickly...
-        */
-       boost_dying_task_prio(p, mem);
-
        return 0;
 }
 #undef K
@@ -482,7 +457,6 @@ static int oom_kill_process(struct task_struct *p, gfp_t gfp_mask, int order,
         */
        if (p->flags & PF_EXITING) {
                set_tsk_thread_flag(p, TIF_MEMDIE);
-               boost_dying_task_prio(p, mem);
                return 0;
        }
 
@@ -556,7 +530,6 @@ void mem_cgroup_out_of_memory(struct mem_cgroup *mem, gfp_t gfp_mask)
         */
        if (fatal_signal_pending(current)) {
                set_thread_flag(TIF_MEMDIE);
-               boost_dying_task_prio(current, NULL);
                return;
        }
 
@@ -712,7 +685,6 @@ void out_of_memory(struct zonelist *zonelist, gfp_t gfp_mask,
         */
        if (fatal_signal_pending(current)) {
                set_thread_flag(TIF_MEMDIE);
-               boost_dying_task_prio(current, NULL);
                return;
        }
 
index 2747f5e5abc15f9d56472d2b73b823e9e091e7cd..9f8a97b9a350d17ec070d5e741c04f8d9998e7a8 100644 (file)
@@ -3176,7 +3176,7 @@ static __init_refok int __build_all_zonelists(void *data)
  * Called with zonelists_mutex held always
  * unless system_state == SYSTEM_BOOTING.
  */
-void build_all_zonelists(void *data)
+void __ref build_all_zonelists(void *data)
 {
        set_zonelist_order();
 
index 58da7c150ba6d7b4132f423663ff920345038d7c..8fa27e4e582a236886eba7d875e6c612130468fc 100644 (file)
@@ -421,7 +421,8 @@ static swp_entry_t *shmem_swp_alloc(struct shmem_inode_info *info, unsigned long
                 * a waste to allocate index if we cannot allocate data.
                 */
                if (sbinfo->max_blocks) {
-                       if (percpu_counter_compare(&sbinfo->used_blocks, (sbinfo->max_blocks - 1)) > 0)
+                       if (percpu_counter_compare(&sbinfo->used_blocks,
+                                               sbinfo->max_blocks - 1) >= 0)
                                return ERR_PTR(-ENOSPC);
                        percpu_counter_inc(&sbinfo->used_blocks);
                        spin_lock(&inode->i_lock);
@@ -1397,7 +1398,8 @@ repeat:
                shmem_swp_unmap(entry);
                sbinfo = SHMEM_SB(inode->i_sb);
                if (sbinfo->max_blocks) {
-                       if ((percpu_counter_compare(&sbinfo->used_blocks, sbinfo->max_blocks) > 0) ||
+                       if (percpu_counter_compare(&sbinfo->used_blocks,
+                                               sbinfo->max_blocks) >= 0 ||
                            shmem_acct_block(info->flags)) {
                                spin_unlock(&info->lock);
                                error = -ENOSPC;
index c7f5a6d4b75bfff6cc10d7e9b91a79590cd3aea6..f6b435c80079337489b17122f0d0ab1b829e12c3 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/memcontrol.h>
 #include <linux/delayacct.h>
 #include <linux/sysctl.h>
+#include <linux/oom.h>
 
 #include <asm/tlbflush.h>
 #include <asm/div64.h>
@@ -1988,17 +1989,12 @@ static bool zone_reclaimable(struct zone *zone)
        return zone->pages_scanned < zone_reclaimable_pages(zone) * 6;
 }
 
-/*
- * As hibernation is going on, kswapd is freezed so that it can't mark
- * the zone into all_unreclaimable. It can't handle OOM during hibernation.
- * So let's check zone's unreclaimable in direct reclaim as well as kswapd.
- */
+/* All zones in zonelist are unreclaimable? */
 static bool all_unreclaimable(struct zonelist *zonelist,
                struct scan_control *sc)
 {
        struct zoneref *z;
        struct zone *zone;
-       bool all_unreclaimable = true;
 
        for_each_zone_zonelist_nodemask(zone, z, zonelist,
                        gfp_zone(sc->gfp_mask), sc->nodemask) {
@@ -2006,13 +2002,11 @@ static bool all_unreclaimable(struct zonelist *zonelist,
                        continue;
                if (!cpuset_zone_allowed_hardwall(zone, GFP_KERNEL))
                        continue;
-               if (zone_reclaimable(zone)) {
-                       all_unreclaimable = false;
-                       break;
-               }
+               if (!zone->all_unreclaimable)
+                       return false;
        }
 
-       return all_unreclaimable;
+       return true;
 }
 
 /*
@@ -2108,6 +2102,14 @@ out:
        if (sc->nr_reclaimed)
                return sc->nr_reclaimed;
 
+       /*
+        * As hibernation is going on, kswapd is freezed so that it can't mark
+        * the zone into all_unreclaimable. Thus bypassing all_unreclaimable
+        * check.
+        */
+       if (oom_killer_disabled)
+               return 0;
+
        /* top priority shrink_zones still had more to do? don't OOM, then */
        if (scanning_global_lru(sc) && !all_unreclaimable(zonelist, sc))
                return 1;
index 772b39b87d955078b4f0d7a1b7114751e0ef9a74..897ea9e88238d1a9ffd99c4f35124988bbc85ef0 100644 (file)
@@ -321,9 +321,12 @@ static inline void mod_state(struct zone *zone,
                /*
                 * The fetching of the stat_threshold is racy. We may apply
                 * a counter threshold to the wrong the cpu if we get
-                * rescheduled while executing here. However, the following
-                * will apply the threshold again and therefore bring the
-                * counter under the threshold.
+                * rescheduled while executing here. However, the next
+                * counter update will apply the threshold again and
+                * therefore bring the counter under the threshold again.
+                *
+                * Most of the time the thresholds are the same anyways
+                * for all cpus in a zone.
                 */
                t = this_cpu_read(pcp->stat_threshold);
 
@@ -945,7 +948,16 @@ static const char * const vmstat_text[] = {
        "unevictable_pgs_cleared",
        "unevictable_pgs_stranded",
        "unevictable_pgs_mlockfreed",
+
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+       "thp_fault_alloc",
+       "thp_fault_fallback",
+       "thp_collapse_alloc",
+       "thp_collapse_alloc_failed",
+       "thp_split",
 #endif
+
+#endif /* CONFIG_VM_EVENTS_COUNTERS */
 };
 
 static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat,
index 48b8e084e710c30aa2984307aeaff94ed8571152..77367745be9bd4d03c3b7100c8108d71c8536d98 100644 (file)
@@ -929,15 +929,15 @@ error:
 }
 EXPORT_SYMBOL(p9_client_attach);
 
-struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
-       int clone)
+struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
+               char **wnames, int clone)
 {
        int err;
        struct p9_client *clnt;
        struct p9_fid *fid;
        struct p9_qid *wqids;
        struct p9_req_t *req;
-       int16_t nwqids, count;
+       uint16_t nwqids, count;
 
        err = 0;
        wqids = NULL;
@@ -955,7 +955,7 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
                fid = oldfid;
 
 
-       P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %d wname[0] %s\n",
+       P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %ud wname[0] %s\n",
                oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL);
 
        req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid,
@@ -1220,27 +1220,6 @@ error:
 }
 EXPORT_SYMBOL(p9_client_fsync);
 
-int p9_client_sync_fs(struct p9_fid *fid)
-{
-       int err = 0;
-       struct p9_req_t *req;
-       struct p9_client *clnt;
-
-       P9_DPRINTK(P9_DEBUG_9P, ">>> TSYNC_FS fid %d\n", fid->fid);
-
-       clnt = fid->clnt;
-       req = p9_client_rpc(clnt, P9_TSYNCFS, "d", fid->fid);
-       if (IS_ERR(req)) {
-               err = PTR_ERR(req);
-               goto error;
-       }
-       P9_DPRINTK(P9_DEBUG_9P, "<<< RSYNCFS fid %d\n", fid->fid);
-       p9_free_req(clnt, req);
-error:
-       return err;
-}
-EXPORT_SYMBOL(p9_client_sync_fs);
-
 int p9_client_clunk(struct p9_fid *fid)
 {
        int err;
index 8a4084fa8b5a907df17db9b023c215d1bb7da772..b58a501cf3d124a06939d266002bf48a92863ee1 100644 (file)
@@ -265,7 +265,7 @@ p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
                        }
                        break;
                case 'T':{
-                               int16_t *nwname = va_arg(ap, int16_t *);
+                               uint16_t *nwname = va_arg(ap, uint16_t *);
                                char ***wnames = va_arg(ap, char ***);
 
                                errcode = p9pdu_readf(pdu, proto_version,
@@ -468,7 +468,8 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
                case 'E':{
                                 int32_t cnt = va_arg(ap, int32_t);
                                 const char *k = va_arg(ap, const void *);
-                                const char *u = va_arg(ap, const void *);
+                                const char __user *u = va_arg(ap,
+                                                       const void __user *);
                                 errcode = p9pdu_writef(pdu, proto_version, "d",
                                                 cnt);
                                 if (!errcode && pdu_write_urw(pdu, k, u, cnt))
@@ -495,7 +496,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
                        }
                        break;
                case 'T':{
-                               int16_t nwname = va_arg(ap, int);
+                               uint16_t nwname = va_arg(ap, int);
                                const char **wnames = va_arg(ap, const char **);
 
                                errcode = p9pdu_writef(pdu, proto_version, "w",
index d47880e971dd534ec92d3fecbed8a50d35649ab7..e883172f9aa2c1096d363483f252a603bba7f108 100644 (file)
@@ -66,7 +66,7 @@ p9_payload_gup(struct p9_req_t *req, size_t *pdata_off, int *pdata_len,
        uint32_t pdata_mapped_pages;
        struct trans_rpage_info  *rpinfo;
 
-       *pdata_off = (size_t)req->tc->pubuf & (PAGE_SIZE-1);
+       *pdata_off = (__force size_t)req->tc->pubuf & (PAGE_SIZE-1);
 
        if (*pdata_off)
                first_page_bytes = min(((size_t)PAGE_SIZE - *pdata_off),
index e8f046b071821636daf99ae9ef79e88f28ef7a09..244e70742183dd689c347166885905baa1584e43 100644 (file)
@@ -326,8 +326,11 @@ req_retry_pinned:
                        outp = pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM,
                                        pdata_off, rpinfo->rp_data, pdata_len);
                } else {
-                       char *pbuf = req->tc->pubuf ? req->tc->pubuf :
-                                                               req->tc->pkbuf;
+                       char *pbuf;
+                       if (req->tc->pubuf)
+                               pbuf = (__force char *) req->tc->pubuf;
+                       else
+                               pbuf = req->tc->pkbuf;
                        outp = pack_sg_list(chan->sg, out, VIRTQUEUE_NUM, pbuf,
                                        req->tc->pbuf_size);
                }
@@ -352,8 +355,12 @@ req_retry_pinned:
                        in = pack_sg_list_p(chan->sg, out+inp, VIRTQUEUE_NUM,
                                        pdata_off, rpinfo->rp_data, pdata_len);
                } else {
-                       char *pbuf = req->tc->pubuf ? req->tc->pubuf :
-                                                               req->tc->pkbuf;
+                       char *pbuf;
+                       if (req->tc->pubuf)
+                               pbuf = (__force char *) req->tc->pubuf;
+                       else
+                               pbuf = req->tc->pkbuf;
+
                        in = pack_sg_list(chan->sg, out+inp, VIRTQUEUE_NUM,
                                        pbuf, req->tc->pbuf_size);
                }
index 008ff6c4eecf3da16c55901afd9e9fbde9f5ee2f..f3bc322c589128d14d6367368597f6da66958bcb 100644 (file)
@@ -249,11 +249,9 @@ static int br_parse_ip_options(struct sk_buff *skb)
                goto drop;
        }
 
-       /* Zero out the CB buffer if no options present */
-       if (iph->ihl == 5) {
-               memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+       memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+       if (iph->ihl == 5)
                return 0;
-       }
 
        opt->optlen = iph->ihl*4 - sizeof(struct iphdr);
        if (ip_options_compile(dev_net(dev), opt, skb))
index 27dab26ad3b84ff213497bcd9029b7af75688560..054fdb5aeb88073d89293a424fcf7c6458f4bd51 100644 (file)
@@ -13,6 +13,7 @@
 #include <net/caif/cfsrvl.h>
 #include <net/caif/cfpkt.h>
 
+
 #define container_obj(layr) ((struct cfsrvl *) layr)
 
 #define DGM_CMD_BIT  0x80
@@ -83,6 +84,7 @@ static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt)
 
 static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt)
 {
+       u8 packet_type;
        u32 zero = 0;
        struct caif_payload_info *info;
        struct cfsrvl *service = container_obj(layr);
@@ -94,7 +96,9 @@ static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt)
        if (cfpkt_getlen(pkt) > DGM_MTU)
                return -EMSGSIZE;
 
-       cfpkt_add_head(pkt, &zero, 4);
+       cfpkt_add_head(pkt, &zero, 3);
+       packet_type = 0x08; /* B9 set - UNCLASSIFIED */
+       cfpkt_add_head(pkt, &packet_type, 1);
 
        /* Add info for MUX-layer to route the packet out. */
        info = cfpkt_info(pkt);
index 46f34b2e04784d8fd379384851c3d5b19377ddee..24f1ffa74b06dbc17a751eef251f1c73f111d064 100644 (file)
@@ -244,9 +244,9 @@ static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
                                int phyid)
 {
        struct cfmuxl *muxl = container_obj(layr);
-       struct list_head *node;
+       struct list_head *node, *next;
        struct cflayer *layer;
-       list_for_each(node, &muxl->srvl_list) {
+       list_for_each_safe(node, next, &muxl->srvl_list) {
                layer = list_entry(node, struct cflayer, node);
                if (cfsrvl_phyid_match(layer, phyid))
                        layer->ctrlcmd(layer, ctrl, phyid);
index 50af02737a3d216e0b66c23003172163fbd71bbd..5a80f41c0cbaf207cf71310161856b5a31e65b4a 100644 (file)
@@ -579,9 +579,15 @@ static void __kick_osd_requests(struct ceph_osd_client *osdc,
 
        list_for_each_entry_safe(req, nreq, &osd->o_linger_requests,
                                 r_linger_osd) {
-               __unregister_linger_request(osdc, req);
+               /*
+                * reregister request prior to unregistering linger so
+                * that r_osd is preserved.
+                */
+               BUG_ON(!list_empty(&req->r_req_lru_item));
                __register_request(osdc, req);
-               list_move(&req->r_req_lru_item, &osdc->req_unsent);
+               list_add(&req->r_req_lru_item, &osdc->req_unsent);
+               list_add(&req->r_osd_item, &req->r_osd->o_requests);
+               __unregister_linger_request(osdc, req);
                dout("requeued lingering %p tid %llu osd%d\n", req, req->r_tid,
                     osd->o_osd);
        }
@@ -798,7 +804,7 @@ static void __register_request(struct ceph_osd_client *osdc,
        req->r_request->hdr.tid = cpu_to_le64(req->r_tid);
        INIT_LIST_HEAD(&req->r_req_lru_item);
 
-       dout("register_request %p tid %lld\n", req, req->r_tid);
+       dout("__register_request %p tid %lld\n", req, req->r_tid);
        __insert_request(osdc, req);
        ceph_osdc_get_request(req);
        osdc->num_requests++;
index 956d3b006e8b96598acb655c383de5d964167697..c2ac599fa0f642f368025ababaa6c95476874c24 100644 (file)
@@ -5203,11 +5203,15 @@ u32 netdev_fix_features(struct net_device *dev, u32 features)
        }
 
        /* TSO requires that SG is present as well. */
-       if ((features & NETIF_F_TSO) && !(features & NETIF_F_SG)) {
-               netdev_info(dev, "Dropping NETIF_F_TSO since no SG feature.\n");
-               features &= ~NETIF_F_TSO;
+       if ((features & NETIF_F_ALL_TSO) && !(features & NETIF_F_SG)) {
+               netdev_info(dev, "Dropping TSO features since no SG feature.\n");
+               features &= ~NETIF_F_ALL_TSO;
        }
 
+       /* TSO ECN requires that TSO is present as well. */
+       if ((features & NETIF_F_ALL_TSO) == NETIF_F_TSO_ECN)
+               features &= ~NETIF_F_TSO_ECN;
+
        /* Software GSO depends on SG. */
        if ((features & NETIF_F_GSO) && !(features & NETIF_F_SG)) {
                netdev_info(dev, "Dropping NETIF_F_GSO since no SG feature.\n");
index d951f93644bf754fcb40ea9319d1d8f5262e7d72..3da418894efcc715ceca776061028c7e7ce4d551 100644 (file)
 #include "dsa_priv.h"
 #include "mv88e6xxx.h"
 
+/*
+ * Switch product IDs
+ */
+#define ID_6085                0x04a0
+#define ID_6095                0x0950
+#define ID_6131                0x1060
+
 static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr)
 {
        int ret;
@@ -21,9 +28,11 @@ static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr)
        ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03);
        if (ret >= 0) {
                ret &= 0xfff0;
-               if (ret == 0x0950)
+               if (ret == ID_6085)
+                       return "Marvell 88E6085";
+               if (ret == ID_6095)
                        return "Marvell 88E6095/88E6095F";
-               if (ret == 0x1060)
+               if (ret == ID_6131)
                        return "Marvell 88E6131";
        }
 
@@ -164,6 +173,7 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
 
 static int mv88e6131_setup_port(struct dsa_switch *ds, int p)
 {
+       struct mv88e6xxx_priv_state *ps = (void *)(ds + 1);
        int addr = REG_PORT(p);
        u16 val;
 
@@ -171,10 +181,13 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p)
         * MAC Forcing register: don't force link, speed, duplex
         * or flow control state to any particular values on physical
         * ports, but force the CPU port and all DSA ports to 1000 Mb/s
-        * full duplex.
+        * (100 Mb/s on 6085) full duplex.
         */
        if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p))
-               REG_WRITE(addr, 0x01, 0x003e);
+               if (ps->id == ID_6085)
+                       REG_WRITE(addr, 0x01, 0x003d); /* 100 Mb/s */
+               else
+                       REG_WRITE(addr, 0x01, 0x003e); /* 1000 Mb/s */
        else
                REG_WRITE(addr, 0x01, 0x0003);
 
@@ -286,6 +299,8 @@ static int mv88e6131_setup(struct dsa_switch *ds)
        mv88e6xxx_ppu_state_init(ds);
        mutex_init(&ps->stats_mutex);
 
+       ps->id = REG_READ(REG_PORT(0), 0x03) & 0xfff0;
+
        ret = mv88e6131_switch_reset(ds);
        if (ret < 0)
                return ret;
index eb0e0aaa9f1b586e12031d3ed355fc1dce67c16c..61156ca26a0da3d17e7be6bc70bc7c11de4c6489 100644 (file)
@@ -39,6 +39,8 @@ struct mv88e6xxx_priv_state {
         * Hold this mutex over snapshot + dump sequences.
         */
        struct mutex    stats_mutex;
+
+       int             id; /* switch product id */
 };
 
 struct mv88e6xxx_hw_stat {
index ce2d33582859df2dd139941f79a70340c4775edc..5761185f884e8d72d32257476e94b273da0190d0 100644 (file)
@@ -1,5 +1,3 @@
 obj-$(CONFIG_IEEE802154) +=    ieee802154.o af_802154.o
 ieee802154-y           := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o
 af_802154-y            := af_ieee802154.o raw.o dgram.o
-
-ccflags-y += -Wall -DDEBUG
index 6c0b7f4a3d7d3c97e83a197e16809e6fdb071234..38f23e721b80108d0a9ae3716fca5212cf8f737d 100644 (file)
@@ -73,7 +73,7 @@ int inet_csk_bind_conflict(const struct sock *sk,
                     !sk2->sk_bound_dev_if ||
                     sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) {
                        if (!reuse || !sk2->sk_reuse ||
-                           ((1 << sk2->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) {
+                           sk2->sk_state == TCP_LISTEN) {
                                const __be32 sk2_rcv_saddr = sk_rcv_saddr(sk2);
                                if (!sk2_rcv_saddr || !sk_rcv_saddr(sk) ||
                                    sk2_rcv_saddr == sk_rcv_saddr(sk))
@@ -122,8 +122,7 @@ again:
                                            (tb->num_owners < smallest_size || smallest_size == -1)) {
                                                smallest_size = tb->num_owners;
                                                smallest_rover = rover;
-                                               if (atomic_read(&hashinfo->bsockets) > (high - low) + 1 &&
-                                                   !inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) {
+                                               if (atomic_read(&hashinfo->bsockets) > (high - low) + 1) {
                                                        spin_unlock(&head->lock);
                                                        snum = smallest_rover;
                                                        goto have_snum;
index dd1b20eca1a25fd845e03ecc077a1e0f43412eff..9df4e635fb5fe5d4a0c92526ad68b845094aa39d 100644 (file)
@@ -354,7 +354,8 @@ static void inetpeer_free_rcu(struct rcu_head *head)
 }
 
 /* May be called with local BH enabled. */
-static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base)
+static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base,
+                            struct inet_peer __rcu **stack[PEER_MAXDEPTH])
 {
        int do_free;
 
@@ -368,7 +369,6 @@ static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base)
         * We use refcnt=-1 to alert lockless readers this entry is deleted.
         */
        if (atomic_cmpxchg(&p->refcnt, 1, -1) == 1) {
-               struct inet_peer __rcu **stack[PEER_MAXDEPTH];
                struct inet_peer __rcu ***stackptr, ***delp;
                if (lookup(&p->daddr, stack, base) != p)
                        BUG();
@@ -422,7 +422,7 @@ static struct inet_peer_base *peer_to_base(struct inet_peer *p)
 }
 
 /* May be called with local BH enabled. */
-static int cleanup_once(unsigned long ttl)
+static int cleanup_once(unsigned long ttl, struct inet_peer __rcu **stack[PEER_MAXDEPTH])
 {
        struct inet_peer *p = NULL;
 
@@ -454,7 +454,7 @@ static int cleanup_once(unsigned long ttl)
                 * happen because of entry limits in route cache. */
                return -1;
 
-       unlink_from_pool(p, peer_to_base(p));
+       unlink_from_pool(p, peer_to_base(p), stack);
        return 0;
 }
 
@@ -524,7 +524,7 @@ struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create)
 
        if (base->total >= inet_peer_threshold)
                /* Remove one less-recently-used entry. */
-               cleanup_once(0);
+               cleanup_once(0, stack);
 
        return p;
 }
@@ -540,6 +540,7 @@ static void peer_check_expire(unsigned long dummy)
 {
        unsigned long now = jiffies;
        int ttl, total;
+       struct inet_peer __rcu **stack[PEER_MAXDEPTH];
 
        total = compute_total();
        if (total >= inet_peer_threshold)
@@ -548,7 +549,7 @@ static void peer_check_expire(unsigned long dummy)
                ttl = inet_peer_maxttl
                                - (inet_peer_maxttl - inet_peer_minttl) / HZ *
                                        total / inet_peer_threshold * HZ;
-       while (!cleanup_once(ttl)) {
+       while (!cleanup_once(ttl, stack)) {
                if (jiffies != now)
                        break;
        }
index 28a736f3442f456c1abd7b7d56eb2e9c4ffdb493..2391b24e8251e62e2c71eadad172a673a1e76c2f 100644 (file)
@@ -329,7 +329,7 @@ int ip_options_compile(struct net *net,
                                        pp_ptr = optptr + 2;
                                        goto error;
                                }
-                               if (skb) {
+                               if (rt) {
                                        memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
                                        opt->is_changed = 1;
                                }
@@ -371,7 +371,7 @@ int ip_options_compile(struct net *net,
                                                goto error;
                                        }
                                        opt->ts = optptr - iph;
-                                       if (skb) {
+                                       if (rt)  {
                                                memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
                                                timeptr = (__be32*)&optptr[optptr[2]+3];
                                        }
@@ -603,7 +603,7 @@ int ip_options_rcv_srr(struct sk_buff *skb)
        unsigned long orefdst;
        int err;
 
-       if (!opt->srr)
+       if (!opt->srr || !rt)
                return 0;
 
        if (skb->pkt_type != PACKET_HOST)
index f3c0b549b8e18fefb7797b4a69570f6e681ef13e..4614babdc45fec0a2c5dbf553576267ba78d79b8 100644 (file)
@@ -221,9 +221,10 @@ static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
        return csum;
 }
 
-static int nf_ip_route(struct dst_entry **dst, struct flowi *fl)
+static int nf_ip_route(struct net *net, struct dst_entry **dst,
+                      struct flowi *fl, bool strict __always_unused)
 {
-       struct rtable *rt = ip_route_output_key(&init_net, &fl->u.ip4);
+       struct rtable *rt = ip_route_output_key(net, &fl->u.ip4);
        if (IS_ERR(rt))
                return PTR_ERR(rt);
        *dst = &rt->dst;
index ea107515c53ee5aa7faeb9a955b1f6331add56af..c1acf69858fd722e6a755c8bf029a56039605b67 100644 (file)
@@ -1891,6 +1891,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
 #ifdef CONFIG_IP_ROUTE_CLASSID
        rth->dst.tclassid = itag;
 #endif
+       rth->rt_route_iif = dev->ifindex;
        rth->rt_iif     = dev->ifindex;
        rth->dst.dev    = init_net.loopback_dev;
        dev_hold(rth->dst.dev);
@@ -2026,6 +2027,7 @@ static int __mkroute_input(struct sk_buff *skb,
        rth->rt_key_src = saddr;
        rth->rt_src     = saddr;
        rth->rt_gateway = daddr;
+       rth->rt_route_iif = in_dev->dev->ifindex;
        rth->rt_iif     = in_dev->dev->ifindex;
        rth->dst.dev    = (out_dev)->dev;
        dev_hold(rth->dst.dev);
@@ -2202,6 +2204,7 @@ local_input:
 #ifdef CONFIG_IP_ROUTE_CLASSID
        rth->dst.tclassid = itag;
 #endif
+       rth->rt_route_iif = dev->ifindex;
        rth->rt_iif     = dev->ifindex;
        rth->dst.dev    = net->loopback_dev;
        dev_hold(rth->dst.dev);
@@ -2401,7 +2404,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res,
        rth->rt_mark    = oldflp4->flowi4_mark;
        rth->rt_dst     = fl4->daddr;
        rth->rt_src     = fl4->saddr;
-       rth->rt_iif     = 0;
+       rth->rt_route_iif = 0;
+       rth->rt_iif     = oldflp4->flowi4_oif ? : dev_out->ifindex;
        /* get references to the devices that are to be hold by the routing
           cache entry */
        rth->dst.dev    = dev_out;
@@ -2716,6 +2720,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
                rt->rt_key_dst = ort->rt_key_dst;
                rt->rt_key_src = ort->rt_key_src;
                rt->rt_tos = ort->rt_tos;
+               rt->rt_route_iif = ort->rt_route_iif;
                rt->rt_iif = ort->rt_iif;
                rt->rt_oif = ort->rt_oif;
                rt->rt_mark = ort->rt_mark;
@@ -2725,7 +2730,6 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or
                rt->rt_type = ort->rt_type;
                rt->rt_dst = ort->rt_dst;
                rt->rt_src = ort->rt_src;
-               rt->rt_iif = ort->rt_iif;
                rt->rt_gateway = ort->rt_gateway;
                rt->rt_spec_dst = ort->rt_spec_dst;
                rt->peer = ort->peer;
index 1a456652086b7b4837b8e1035f0a96bb12eb6700..321e6e84dbccb93e08741263815aaae82610b0a8 100644 (file)
@@ -311,7 +311,6 @@ static struct ctl_table ipv4_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_do_large_bitmap,
        },
-#ifdef CONFIG_IP_MULTICAST
        {
                .procname       = "igmp_max_memberships",
                .data           = &sysctl_igmp_max_memberships,
@@ -319,8 +318,6 @@ static struct ctl_table ipv4_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec
        },
-
-#endif
        {
                .procname       = "igmp_max_msf",
                .data           = &sysctl_igmp_max_msf,
index 13e0e7f659ffa7ef57e611548fc77f5920600f82..d20a05e970d83fc76df80c3170515e6d06272ed9 100644 (file)
@@ -74,6 +74,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
        rt->rt_key_dst = fl4->daddr;
        rt->rt_key_src = fl4->saddr;
        rt->rt_tos = fl4->flowi4_tos;
+       rt->rt_route_iif = fl4->flowi4_iif;
        rt->rt_iif = fl4->flowi4_iif;
        rt->rt_oif = fl4->flowi4_oif;
        rt->rt_mark = fl4->flowi4_mark;
index 1660546504668a1c0378e23fec57112cc9710826..f2c5b0fc0f218a0294b1c4308a46374bc3410d99 100644 (file)
@@ -44,7 +44,7 @@ int inet6_csk_bind_conflict(const struct sock *sk,
                     !sk2->sk_bound_dev_if ||
                     sk->sk_bound_dev_if == sk2->sk_bound_dev_if) &&
                    (!sk->sk_reuse || !sk2->sk_reuse ||
-                    ((1 << sk2->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) &&
+                    sk2->sk_state == TCP_LISTEN) &&
                     ipv6_rcv_saddr_equal(sk, sk2))
                        break;
        }
index 39aaca2b4fd2db98d7463110107ecc0ec70b2097..28bc1f644b7b3158470620a9a8ca2b9c0c1f44e8 100644 (file)
@@ -90,9 +90,18 @@ static int nf_ip6_reroute(struct sk_buff *skb,
        return 0;
 }
 
-static int nf_ip6_route(struct dst_entry **dst, struct flowi *fl)
+static int nf_ip6_route(struct net *net, struct dst_entry **dst,
+                       struct flowi *fl, bool strict)
 {
-       *dst = ip6_route_output(&init_net, NULL, &fl->u.ip6);
+       static const struct ipv6_pinfo fake_pinfo;
+       static const struct inet_sock fake_sk = {
+               /* makes ip6_route_output set RT6_LOOKUP_F_IFACE: */
+               .sk.sk_bound_dev_if = 1,
+               .pinet6 = (struct ipv6_pinfo *) &fake_pinfo,
+       };
+       const void *sk = strict ? &fake_sk : NULL;
+
+       *dst = ip6_route_output(net, sk, &fl->u.ip6);
        return (*dst)->error;
 }
 
index 56fa12538d4505b40e9ec762d00f38d1048b163e..4f49e5dd41bbb2681111cc992b91409e33b68c0f 100644 (file)
@@ -1622,6 +1622,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
                opt_skb = skb_clone(skb, GFP_ATOMIC);
 
        if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */
+               sock_rps_save_rxhash(sk, skb->rxhash);
                if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len))
                        goto reset;
                if (opt_skb)
@@ -1649,7 +1650,8 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
                                __kfree_skb(opt_skb);
                        return 0;
                }
-       }
+       } else
+               sock_rps_save_rxhash(sk, skb->rxhash);
 
        if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len))
                goto reset;
index d7037c006e1321923d654bbb2b45f457994662cd..15c37746845ed1ad678866756b4057421b7f3f0a 100644 (file)
@@ -505,6 +505,9 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
        int rc;
        int is_udplite = IS_UDPLITE(sk);
 
+       if (!ipv6_addr_any(&inet6_sk(sk)->daddr))
+               sock_rps_save_rxhash(sk, skb->rxhash);
+
        if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
                goto drop;
 
index c9890e25cd4c9681b14f838976a97ed4db560ac7..cc616974a447d582a66c837a09c8c95b1fb8900a 100644 (file)
@@ -1297,8 +1297,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
        /* Note : socket.c set MSG_EOR on SEQPACKET sockets */
        if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT |
                               MSG_NOSIGNAL)) {
-               err = -EINVAL;
-               goto out;
+               return -EINVAL;
        }
 
        lock_sock(sk);
index 058f1e9a91281859bf39501619da6eb5ece8d16a..903242111317f14438bc84881358875729e21948 100644 (file)
@@ -121,8 +121,7 @@ static inline int llc_fixup_skb(struct sk_buff *skb)
                s32 data_size = ntohs(pdulen) - llc_len;
 
                if (data_size < 0 ||
-                   ((skb_tail_pointer(skb) -
-                     (u8 *)pdu) - llc_len) < data_size)
+                   !pskb_may_pull(skb, data_size))
                        return 0;
                if (unlikely(pskb_trim_rcsum(skb, data_size)))
                        return 0;
index 9d192d665ff5bf263fda180150c4aec7df986ad0..c5d4530d8284e59f07b44af1ce904fea5fc26018 100644 (file)
@@ -2541,7 +2541,6 @@ static void ieee80211_rx_handlers(struct ieee80211_rx_data *rx)
                 * same TID from the same station
                 */
                rx->skb = skb;
-               rx->flags = 0;
 
                CALL_RXH(ieee80211_rx_h_decrypt)
                CALL_RXH(ieee80211_rx_h_check_more_data)
@@ -2612,6 +2611,7 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
                .sdata = sta->sdata,
                .local = sta->local,
                .queue = tid,
+               .flags = 0,
        };
        struct tid_ampdu_rx *tid_agg_rx;
 
index c3f988aa1152ece13b58fa4d75e13263577aaf61..32bff6d86cb24911c6f7206c31668dc4c8e0c36e 100644 (file)
@@ -652,7 +652,6 @@ comment "Xtables matches"
 config NETFILTER_XT_MATCH_ADDRTYPE
        tristate '"addrtype" address type match support'
        depends on NETFILTER_ADVANCED
-       depends on (IPV6 || IPV6=n)
        ---help---
          This option allows you to match what routing thinks of an address,
          eg. UNICAST, LOCAL, BROADCAST, ...
index bca96990218dedeb2791d9df35727a9f47b20ea7..a113ff066928445902ce5a4e43f51c115586c894 100644 (file)
@@ -338,8 +338,7 @@ bitmap_ip_head(struct ip_set *set, struct sk_buff *skb)
        NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
        if (map->netmask != 32)
                NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask);
-       NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
-                     htonl(atomic_read(&set->ref) - 1));
+       NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
        NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
                      htonl(sizeof(*map) + map->memsize));
        if (with_timeout(map->timeout))
index 5e790172deffb36638c8cbf5a0bdfe54067f820d..a274300b6a566faee28c3e10d31fdba1bbd212c0 100644 (file)
@@ -343,6 +343,10 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb,
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct ipmac data;
 
+       /* MAC can be src only */
+       if (!(flags & IPSET_DIM_TWO_SRC))
+               return 0;
+
        data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC));
        if (data.id < map->first_ip || data.id > map->last_ip)
                return -IPSET_ERR_BITMAP_RANGE;
@@ -434,8 +438,7 @@ bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb)
                goto nla_put_failure;
        NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip));
        NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip));
-       NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
-                     htonl(atomic_read(&set->ref) - 1));
+       NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
        NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
                      htonl(sizeof(*map)
                            + (map->last_ip - map->first_ip + 1) * map->dsize));
index 165f09b1a9cb22cad3f3db40f2a13ed905eefd9c..6b38eb8f6ed823fc42ca7d0443349b506b8623f3 100644 (file)
@@ -320,8 +320,7 @@ bitmap_port_head(struct ip_set *set, struct sk_buff *skb)
                goto nla_put_failure;
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port));
        NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port));
-       NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
-                     htonl(atomic_read(&set->ref) - 1));
+       NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
        NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
                      htonl(sizeof(*map) + map->memsize));
        if (with_timeout(map->timeout))
index 253326e8d99070805430c84a62fa55ca14f34237..72d1ac611fdc8e70124c6fca29686ffa416e9cd3 100644 (file)
@@ -26,6 +26,7 @@
 
 static LIST_HEAD(ip_set_type_list);            /* all registered set types */
 static DEFINE_MUTEX(ip_set_type_mutex);                /* protects ip_set_type_list */
+static DEFINE_RWLOCK(ip_set_ref_lock);         /* protects the set refs */
 
 static struct ip_set **ip_set_list;            /* all individual sets */
 static ip_set_id_t ip_set_max = CONFIG_IP_SET_MAX; /* max number of sets */
@@ -301,13 +302,18 @@ EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6);
 static inline void
 __ip_set_get(ip_set_id_t index)
 {
-       atomic_inc(&ip_set_list[index]->ref);
+       write_lock_bh(&ip_set_ref_lock);
+       ip_set_list[index]->ref++;
+       write_unlock_bh(&ip_set_ref_lock);
 }
 
 static inline void
 __ip_set_put(ip_set_id_t index)
 {
-       atomic_dec(&ip_set_list[index]->ref);
+       write_lock_bh(&ip_set_ref_lock);
+       BUG_ON(ip_set_list[index]->ref == 0);
+       ip_set_list[index]->ref--;
+       write_unlock_bh(&ip_set_ref_lock);
 }
 
 /*
@@ -324,7 +330,7 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb,
        struct ip_set *set = ip_set_list[index];
        int ret = 0;
 
-       BUG_ON(set == NULL || atomic_read(&set->ref) == 0);
+       BUG_ON(set == NULL);
        pr_debug("set %s, index %u\n", set->name, index);
 
        if (dim < set->type->dimension ||
@@ -356,7 +362,7 @@ ip_set_add(ip_set_id_t index, const struct sk_buff *skb,
        struct ip_set *set = ip_set_list[index];
        int ret;
 
-       BUG_ON(set == NULL || atomic_read(&set->ref) == 0);
+       BUG_ON(set == NULL);
        pr_debug("set %s, index %u\n", set->name, index);
 
        if (dim < set->type->dimension ||
@@ -378,7 +384,7 @@ ip_set_del(ip_set_id_t index, const struct sk_buff *skb,
        struct ip_set *set = ip_set_list[index];
        int ret = 0;
 
-       BUG_ON(set == NULL || atomic_read(&set->ref) == 0);
+       BUG_ON(set == NULL);
        pr_debug("set %s, index %u\n", set->name, index);
 
        if (dim < set->type->dimension ||
@@ -397,7 +403,6 @@ EXPORT_SYMBOL_GPL(ip_set_del);
  * Find set by name, reference it once. The reference makes sure the
  * thing pointed to, does not go away under our feet.
  *
- * The nfnl mutex must already be activated.
  */
 ip_set_id_t
 ip_set_get_byname(const char *name, struct ip_set **set)
@@ -423,15 +428,12 @@ EXPORT_SYMBOL_GPL(ip_set_get_byname);
  * reference count by 1. The caller shall not assume the index
  * to be valid, after calling this function.
  *
- * The nfnl mutex must already be activated.
  */
 void
 ip_set_put_byindex(ip_set_id_t index)
 {
-       if (ip_set_list[index] != NULL) {
-               BUG_ON(atomic_read(&ip_set_list[index]->ref) == 0);
+       if (ip_set_list[index] != NULL)
                __ip_set_put(index);
-       }
 }
 EXPORT_SYMBOL_GPL(ip_set_put_byindex);
 
@@ -441,7 +443,6 @@ EXPORT_SYMBOL_GPL(ip_set_put_byindex);
  * can't be destroyed. The set cannot be renamed due to
  * the referencing either.
  *
- * The nfnl mutex must already be activated.
  */
 const char *
 ip_set_name_byindex(ip_set_id_t index)
@@ -449,7 +450,7 @@ ip_set_name_byindex(ip_set_id_t index)
        const struct ip_set *set = ip_set_list[index];
 
        BUG_ON(set == NULL);
-       BUG_ON(atomic_read(&set->ref) == 0);
+       BUG_ON(set->ref == 0);
 
        /* Referenced, so it's safe */
        return set->name;
@@ -515,10 +516,7 @@ void
 ip_set_nfnl_put(ip_set_id_t index)
 {
        nfnl_lock();
-       if (ip_set_list[index] != NULL) {
-               BUG_ON(atomic_read(&ip_set_list[index]->ref) == 0);
-               __ip_set_put(index);
-       }
+       ip_set_put_byindex(index);
        nfnl_unlock();
 }
 EXPORT_SYMBOL_GPL(ip_set_nfnl_put);
@@ -526,7 +524,7 @@ EXPORT_SYMBOL_GPL(ip_set_nfnl_put);
 /*
  * Communication protocol with userspace over netlink.
  *
- * We already locked by nfnl_lock.
+ * The commands are serialized by the nfnl mutex.
  */
 
 static inline bool
@@ -657,7 +655,6 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
                return -ENOMEM;
        rwlock_init(&set->lock);
        strlcpy(set->name, name, IPSET_MAXNAMELEN);
-       atomic_set(&set->ref, 0);
        set->family = family;
 
        /*
@@ -690,8 +687,8 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb,
 
        /*
         * Here, we have a valid, constructed set and we are protected
-        * by nfnl_lock. Find the first free index in ip_set_list and
-        * check clashing.
+        * by the nfnl mutex. Find the first free index in ip_set_list
+        * and check clashing.
         */
        if ((ret = find_free_id(set->name, &index, &clash)) != 0) {
                /* If this is the same set and requested, ignore error */
@@ -751,31 +748,51 @@ ip_set_destroy(struct sock *ctnl, struct sk_buff *skb,
               const struct nlattr * const attr[])
 {
        ip_set_id_t i;
+       int ret = 0;
 
        if (unlikely(protocol_failed(attr)))
                return -IPSET_ERR_PROTOCOL;
 
-       /* References are protected by the nfnl mutex */
+       /* Commands are serialized and references are
+        * protected by the ip_set_ref_lock.
+        * External systems (i.e. xt_set) must call
+        * ip_set_put|get_nfnl_* functions, that way we
+        * can safely check references here.
+        *
+        * list:set timer can only decrement the reference
+        * counter, so if it's already zero, we can proceed
+        * without holding the lock.
+        */
+       read_lock_bh(&ip_set_ref_lock);
        if (!attr[IPSET_ATTR_SETNAME]) {
                for (i = 0; i < ip_set_max; i++) {
-                       if (ip_set_list[i] != NULL &&
-                           (atomic_read(&ip_set_list[i]->ref)))
-                               return -IPSET_ERR_BUSY;
+                       if (ip_set_list[i] != NULL && ip_set_list[i]->ref) {
+                               ret = IPSET_ERR_BUSY;
+                               goto out;
+                       }
                }
+               read_unlock_bh(&ip_set_ref_lock);
                for (i = 0; i < ip_set_max; i++) {
                        if (ip_set_list[i] != NULL)
                                ip_set_destroy_set(i);
                }
        } else {
                i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME]));
-               if (i == IPSET_INVALID_ID)
-                       return -ENOENT;
-               else if (atomic_read(&ip_set_list[i]->ref))
-                       return -IPSET_ERR_BUSY;
+               if (i == IPSET_INVALID_ID) {
+                       ret = -ENOENT;
+                       goto out;
+               } else if (ip_set_list[i]->ref) {
+                       ret = -IPSET_ERR_BUSY;
+                       goto out;
+               }
+               read_unlock_bh(&ip_set_ref_lock);
 
                ip_set_destroy_set(i);
        }
        return 0;
+out:
+       read_unlock_bh(&ip_set_ref_lock);
+       return ret;
 }
 
 /* Flush sets */
@@ -834,6 +851,7 @@ ip_set_rename(struct sock *ctnl, struct sk_buff *skb,
        struct ip_set *set;
        const char *name2;
        ip_set_id_t i;
+       int ret = 0;
 
        if (unlikely(protocol_failed(attr) ||
                     attr[IPSET_ATTR_SETNAME] == NULL ||
@@ -843,25 +861,33 @@ ip_set_rename(struct sock *ctnl, struct sk_buff *skb,
        set = find_set(nla_data(attr[IPSET_ATTR_SETNAME]));
        if (set == NULL)
                return -ENOENT;
-       if (atomic_read(&set->ref) != 0)
-               return -IPSET_ERR_REFERENCED;
+
+       read_lock_bh(&ip_set_ref_lock);
+       if (set->ref != 0) {
+               ret = -IPSET_ERR_REFERENCED;
+               goto out;
+       }
 
        name2 = nla_data(attr[IPSET_ATTR_SETNAME2]);
        for (i = 0; i < ip_set_max; i++) {
                if (ip_set_list[i] != NULL &&
-                   STREQ(ip_set_list[i]->name, name2))
-                       return -IPSET_ERR_EXIST_SETNAME2;
+                   STREQ(ip_set_list[i]->name, name2)) {
+                       ret = -IPSET_ERR_EXIST_SETNAME2;
+                       goto out;
+               }
        }
        strncpy(set->name, name2, IPSET_MAXNAMELEN);
 
-       return 0;
+out:
+       read_unlock_bh(&ip_set_ref_lock);
+       return ret;
 }
 
 /* Swap two sets so that name/index points to the other.
  * References and set names are also swapped.
  *
- * We are protected by the nfnl mutex and references are
- * manipulated only by holding the mutex. The kernel interfaces
+ * The commands are serialized by the nfnl mutex and references are
+ * protected by the ip_set_ref_lock. The kernel interfaces
  * do not hold the mutex but the pointer settings are atomic
  * so the ip_set_list always contains valid pointers to the sets.
  */
@@ -874,7 +900,6 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
        struct ip_set *from, *to;
        ip_set_id_t from_id, to_id;
        char from_name[IPSET_MAXNAMELEN];
-       u32 from_ref;
 
        if (unlikely(protocol_failed(attr) ||
                     attr[IPSET_ATTR_SETNAME] == NULL ||
@@ -899,17 +924,15 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb,
              from->type->family == to->type->family))
                return -IPSET_ERR_TYPE_MISMATCH;
 
-       /* No magic here: ref munging protected by the nfnl_lock */
        strncpy(from_name, from->name, IPSET_MAXNAMELEN);
-       from_ref = atomic_read(&from->ref);
-
        strncpy(from->name, to->name, IPSET_MAXNAMELEN);
-       atomic_set(&from->ref, atomic_read(&to->ref));
        strncpy(to->name, from_name, IPSET_MAXNAMELEN);
-       atomic_set(&to->ref, from_ref);
 
+       write_lock_bh(&ip_set_ref_lock);
+       swap(from->ref, to->ref);
        ip_set_list[from_id] = to;
        ip_set_list[to_id] = from;
+       write_unlock_bh(&ip_set_ref_lock);
 
        return 0;
 }
@@ -926,7 +949,7 @@ ip_set_dump_done(struct netlink_callback *cb)
 {
        if (cb->args[2]) {
                pr_debug("release set %s\n", ip_set_list[cb->args[1]]->name);
-               __ip_set_put((ip_set_id_t) cb->args[1]);
+               ip_set_put_byindex((ip_set_id_t) cb->args[1]);
        }
        return 0;
 }
@@ -999,8 +1022,9 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
        if (cb->args[1] >= ip_set_max)
                goto out;
 
-       pr_debug("args[0]: %ld args[1]: %ld\n", cb->args[0], cb->args[1]);
        max = cb->args[0] == DUMP_ONE ? cb->args[1] + 1 : ip_set_max;
+dump_last:
+       pr_debug("args[0]: %ld args[1]: %ld\n", cb->args[0], cb->args[1]);
        for (; cb->args[1] < max; cb->args[1]++) {
                index = (ip_set_id_t) cb->args[1];
                set = ip_set_list[index];
@@ -1015,8 +1039,8 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
                 * so that lists (unions of sets) are dumped last.
                 */
                if (cb->args[0] != DUMP_ONE &&
-                   !((cb->args[0] == DUMP_ALL) ^
-                     (set->type->features & IPSET_DUMP_LAST)))
+                   ((cb->args[0] == DUMP_ALL) ==
+                    !!(set->type->features & IPSET_DUMP_LAST)))
                        continue;
                pr_debug("List set: %s\n", set->name);
                if (!cb->args[2]) {
@@ -1060,6 +1084,12 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb)
                        goto release_refcount;
                }
        }
+       /* If we dump all sets, continue with dumping last ones */
+       if (cb->args[0] == DUMP_ALL) {
+               cb->args[0] = DUMP_LAST;
+               cb->args[1] = 0;
+               goto dump_last;
+       }
        goto out;
 
 nla_put_failure:
@@ -1068,13 +1098,8 @@ release_refcount:
        /* If there was an error or set is done, release set */
        if (ret || !cb->args[2]) {
                pr_debug("release set %s\n", ip_set_list[index]->name);
-               __ip_set_put(index);
+               ip_set_put_byindex(index);
        }
-
-       /* If we dump all sets, continue with dumping last ones */
-       if (cb->args[0] == DUMP_ALL && cb->args[1] >= max && !cb->args[2])
-               cb->args[0] = DUMP_LAST;
-
 out:
        if (nlh) {
                nlmsg_end(skb, nlh);
index a47c32982f06233b48b37c386b32842cdf122614..e9159e99fc4bd491f2e0d11cecabed5172b1bd27 100644 (file)
@@ -43,14 +43,19 @@ struct list_set {
 static inline struct set_elem *
 list_set_elem(const struct list_set *map, u32 id)
 {
-       return (struct set_elem *)((char *)map->members + id * map->dsize);
+       return (struct set_elem *)((void *)map->members + id * map->dsize);
+}
+
+static inline struct set_telem *
+list_set_telem(const struct list_set *map, u32 id)
+{
+       return (struct set_telem *)((void *)map->members + id * map->dsize);
 }
 
 static inline bool
 list_set_timeout(const struct list_set *map, u32 id)
 {
-       const struct set_telem *elem =
-               (const struct set_telem *) list_set_elem(map, id);
+       const struct set_telem *elem = list_set_telem(map, id);
 
        return ip_set_timeout_test(elem->timeout);
 }
@@ -58,19 +63,11 @@ list_set_timeout(const struct list_set *map, u32 id)
 static inline bool
 list_set_expired(const struct list_set *map, u32 id)
 {
-       const struct set_telem *elem =
-               (const struct set_telem *) list_set_elem(map, id);
+       const struct set_telem *elem = list_set_telem(map, id);
 
        return ip_set_timeout_expired(elem->timeout);
 }
 
-static inline int
-list_set_exist(const struct set_telem *elem)
-{
-       return elem->id != IPSET_INVALID_ID &&
-              !ip_set_timeout_expired(elem->timeout);
-}
-
 /* Set list without and with timeout */
 
 static int
@@ -146,11 +143,11 @@ list_elem_tadd(struct list_set *map, u32 i, ip_set_id_t id,
        struct set_telem *e;
 
        for (; i < map->size; i++) {
-               e = (struct set_telem *)list_set_elem(map, i);
+               e = list_set_telem(map, i);
                swap(e->id, id);
+               swap(e->timeout, timeout);
                if (e->id == IPSET_INVALID_ID)
                        break;
-               swap(e->timeout, timeout);
        }
 }
 
@@ -164,7 +161,7 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id,
                /* Last element replaced: e.g. add new,before,last */
                ip_set_put_byindex(e->id);
        if (with_timeout(map->timeout))
-               list_elem_tadd(map, i, id, timeout);
+               list_elem_tadd(map, i, id, ip_set_timeout_set(timeout));
        else
                list_elem_add(map, i, id);
 
@@ -172,11 +169,11 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id,
 }
 
 static int
-list_set_del(struct list_set *map, ip_set_id_t id, u32 i)
+list_set_del(struct list_set *map, u32 i)
 {
        struct set_elem *a = list_set_elem(map, i), *b;
 
-       ip_set_put_byindex(id);
+       ip_set_put_byindex(a->id);
 
        for (; i < map->size - 1; i++) {
                b = list_set_elem(map, i + 1);
@@ -308,11 +305,11 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
                                 (before == 0 ||
                                  (before > 0 &&
                                   next_id_eq(map, i, refid))))
-                               ret = list_set_del(map, id, i);
+                               ret = list_set_del(map, i);
                        else if (before < 0 &&
                                 elem->id == refid &&
                                 next_id_eq(map, i, id))
-                               ret = list_set_del(map, id, i + 1);
+                               ret = list_set_del(map, i + 1);
                }
                break;
        default:
@@ -369,8 +366,7 @@ list_set_head(struct ip_set *set, struct sk_buff *skb)
        NLA_PUT_NET32(skb, IPSET_ATTR_SIZE, htonl(map->size));
        if (with_timeout(map->timeout))
                NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout));
-       NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES,
-                     htonl(atomic_read(&set->ref) - 1));
+       NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1));
        NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE,
                      htonl(sizeof(*map) + map->size * map->dsize));
        ipset_nest_end(skb, nested);
@@ -461,16 +457,13 @@ list_set_gc(unsigned long ul_set)
        struct set_telem *e;
        u32 i;
 
-       /* We run parallel with other readers (test element)
-        * but adding/deleting new entries is locked out */
-       read_lock_bh(&set->lock);
-       for (i = map->size - 1; i >= 0; i--) {
-               e = (struct set_telem *) list_set_elem(map, i);
-               if (e->id != IPSET_INVALID_ID &&
-                   list_set_expired(map, i))
-                       list_set_del(map, e->id, i);
+       write_lock_bh(&set->lock);
+       for (i = 0; i < map->size; i++) {
+               e = list_set_telem(map, i);
+               if (e->id != IPSET_INVALID_ID && list_set_expired(map, i))
+                       list_set_del(map, i);
        }
-       read_unlock_bh(&set->lock);
+       write_unlock_bh(&set->lock);
 
        map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ;
        add_timer(&map->gc);
index 33733c8872e70230587b7d1ef7f34147a3058374..ae47090bf45fe1fdfbf99192950aacb951cb1af1 100644 (file)
@@ -3120,7 +3120,7 @@ nla_put_failure:
 static int ip_vs_genl_dump_daemons(struct sk_buff *skb,
                                   struct netlink_callback *cb)
 {
-       struct net *net = skb_net(skb);
+       struct net *net = skb_sknet(skb);
        struct netns_ipvs *ipvs = net_ipvs(net);
 
        mutex_lock(&__ip_vs_mutex);
index 867882313e499931b9e89416326937398a655ccb..bcd5ed6b713048e781f73f91e80a0e055eafb6d5 100644 (file)
@@ -631,7 +631,7 @@ static int decode_seqof(bitstr_t *bs, const struct field_t *f,
                CHECK_BOUND(bs, 2);
                count = *bs->cur++;
                count <<= 8;
-               count = *bs->cur++;
+               count += *bs->cur++;
                break;
        case SEMI:
                BYTE_ALIGN(bs);
index 533a183e666108eff291f7072e5d4b4a27a0c4fe..18b2ce5c8ced1c82f5f4e3f41af1ed1e659079f9 100644 (file)
@@ -731,10 +731,10 @@ static int callforward_do_filter(const union nf_inet_addr *src,
 
                memset(&fl2, 0, sizeof(fl2));
                fl2.daddr = dst->ip;
-               if (!afinfo->route((struct dst_entry **)&rt1,
-                                  flowi4_to_flowi(&fl1))) {
-                       if (!afinfo->route((struct dst_entry **)&rt2,
-                                          flowi4_to_flowi(&fl2))) {
+               if (!afinfo->route(&init_net, (struct dst_entry **)&rt1,
+                                  flowi4_to_flowi(&fl1), false)) {
+                       if (!afinfo->route(&init_net, (struct dst_entry **)&rt2,
+                                          flowi4_to_flowi(&fl2), false)) {
                                if (rt1->rt_gateway == rt2->rt_gateway &&
                                    rt1->dst.dev  == rt2->dst.dev)
                                        ret = 1;
@@ -755,10 +755,10 @@ static int callforward_do_filter(const union nf_inet_addr *src,
 
                memset(&fl2, 0, sizeof(fl2));
                ipv6_addr_copy(&fl2.daddr, &dst->in6);
-               if (!afinfo->route((struct dst_entry **)&rt1,
-                                  flowi6_to_flowi(&fl1))) {
-                       if (!afinfo->route((struct dst_entry **)&rt2,
-                                          flowi6_to_flowi(&fl2))) {
+               if (!afinfo->route(&init_net, (struct dst_entry **)&rt1,
+                                  flowi6_to_flowi(&fl1), false)) {
+                       if (!afinfo->route(&init_net, (struct dst_entry **)&rt2,
+                                          flowi6_to_flowi(&fl2), false)) {
                                if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway,
                                            sizeof(rt1->rt6i_gateway)) &&
                                    rt1->dst.dev == rt2->dst.dev)
index 6e6b46cb1db9ba6c75c98bf742ef02e3022fe0cd..9e63b43faeed030b5b51118f54722bc68cd2997d 100644 (file)
@@ -166,7 +166,7 @@ static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb,
        rcu_read_lock();
        ai = nf_get_afinfo(family);
        if (ai != NULL)
-               ai->route((struct dst_entry **)&rt, &fl);
+               ai->route(&init_net, (struct dst_entry **)&rt, &fl, false);
        rcu_read_unlock();
 
        if (rt != NULL) {
index 2220b85e95190794aa69d2cf292410c5b2a6b41c..b77d383cec7818387d3703ba01b79b0c74bf5f52 100644 (file)
@@ -32,11 +32,32 @@ MODULE_ALIAS("ipt_addrtype");
 MODULE_ALIAS("ip6t_addrtype");
 
 #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
-static u32 xt_addrtype_rt6_to_type(const struct rt6_info *rt)
+static u32 match_lookup_rt6(struct net *net, const struct net_device *dev,
+                           const struct in6_addr *addr)
 {
+       const struct nf_afinfo *afinfo;
+       struct flowi6 flow;
+       struct rt6_info *rt;
        u32 ret;
+       int route_err;
 
-       if (!rt)
+       memset(&flow, 0, sizeof(flow));
+       ipv6_addr_copy(&flow.daddr, addr);
+       if (dev)
+               flow.flowi6_oif = dev->ifindex;
+
+       rcu_read_lock();
+
+       afinfo = nf_get_afinfo(NFPROTO_IPV6);
+       if (afinfo != NULL)
+               route_err = afinfo->route(net, (struct dst_entry **)&rt,
+                                       flowi6_to_flowi(&flow), !!dev);
+       else
+               route_err = 1;
+
+       rcu_read_unlock();
+
+       if (route_err)
                return XT_ADDRTYPE_UNREACHABLE;
 
        if (rt->rt6i_flags & RTF_REJECT)
@@ -48,6 +69,9 @@ static u32 xt_addrtype_rt6_to_type(const struct rt6_info *rt)
                ret |= XT_ADDRTYPE_LOCAL;
        if (rt->rt6i_flags & RTF_ANYCAST)
                ret |= XT_ADDRTYPE_ANYCAST;
+
+
+       dst_release(&rt->dst);
        return ret;
 }
 
@@ -65,18 +89,8 @@ static bool match_type6(struct net *net, const struct net_device *dev,
                return false;
 
        if ((XT_ADDRTYPE_LOCAL | XT_ADDRTYPE_ANYCAST |
-            XT_ADDRTYPE_UNREACHABLE) & mask) {
-               struct rt6_info *rt;
-               u32 type;
-               int ifindex = dev ? dev->ifindex : 0;
-
-               rt = rt6_lookup(net, addr, NULL, ifindex, !!dev);
-
-               type = xt_addrtype_rt6_to_type(rt);
-
-               dst_release(&rt->dst);
-               return !!(mask & type);
-       }
+            XT_ADDRTYPE_UNREACHABLE) & mask)
+               return !!(mask & match_lookup_rt6(net, dev, addr));
        return true;
 }
 
index 2c0086a4751e3a846d517236869d52a5ae6f548a..481a86fdc40973bb43f62cfd2a36b0d4746f8a63 100644 (file)
@@ -195,7 +195,7 @@ conntrack_mt(const struct sk_buff *skb, struct xt_action_param *par,
                return info->match_flags & XT_CONNTRACK_STATE;
        if ((info->match_flags & XT_CONNTRACK_DIRECTION) &&
            (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) ^
-           !!(info->invert_flags & XT_CONNTRACK_DIRECTION))
+           !(info->invert_flags & XT_CONNTRACK_DIRECTION))
                return false;
 
        if (info->match_flags & XT_CONNTRACK_ORIGSRC)
index 061d48cec137e3a88a3a98153d6d5cbd9d1c3464..b3babaed7719b770e02d478091885e7692eac68a 100644 (file)
@@ -81,6 +81,7 @@ set_match_v0_checkentry(const struct xt_mtchk_param *par)
        if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) {
                pr_warning("Protocol error: set match dimension "
                           "is over the limit!\n");
+               ip_set_nfnl_put(info->match_set.index);
                return -ERANGE;
        }
 
@@ -135,6 +136,8 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
                if (index == IPSET_INVALID_ID) {
                        pr_warning("Cannot find del_set index %u as target\n",
                                   info->del_set.index);
+                       if (info->add_set.index != IPSET_INVALID_ID)
+                               ip_set_nfnl_put(info->add_set.index);
                        return -ENOENT;
                }
        }
@@ -142,6 +145,10 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par)
            info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) {
                pr_warning("Protocol error: SET target dimension "
                           "is over the limit!\n");
+               if (info->add_set.index != IPSET_INVALID_ID)
+                       ip_set_nfnl_put(info->add_set.index);
+               if (info->del_set.index != IPSET_INVALID_ID)
+                       ip_set_nfnl_put(info->del_set.index);
                return -ERANGE;
        }
 
@@ -192,6 +199,7 @@ set_match_checkentry(const struct xt_mtchk_param *par)
        if (info->match_set.dim > IPSET_DIM_MAX) {
                pr_warning("Protocol error: set match dimension "
                           "is over the limit!\n");
+               ip_set_nfnl_put(info->match_set.index);
                return -ERANGE;
        }
 
@@ -219,7 +227,7 @@ set_target(struct sk_buff *skb, const struct xt_action_param *par)
        if (info->del_set.index != IPSET_INVALID_ID)
                ip_set_del(info->del_set.index,
                           skb, par->family,
-                          info->add_set.dim,
+                          info->del_set.dim,
                           info->del_set.flags);
 
        return XT_CONTINUE;
@@ -245,13 +253,19 @@ set_target_checkentry(const struct xt_tgchk_param *par)
                if (index == IPSET_INVALID_ID) {
                        pr_warning("Cannot find del_set index %u as target\n",
                                   info->del_set.index);
+                       if (info->add_set.index != IPSET_INVALID_ID)
+                               ip_set_nfnl_put(info->add_set.index);
                        return -ENOENT;
                }
        }
        if (info->add_set.dim > IPSET_DIM_MAX ||
-           info->del_set.flags > IPSET_DIM_MAX) {
+           info->del_set.dim > IPSET_DIM_MAX) {
                pr_warning("Protocol error: SET target dimension "
                           "is over the limit!\n");
+               if (info->add_set.index != IPSET_INVALID_ID)
+                       ip_set_nfnl_put(info->add_set.index);
+               if (info->del_set.index != IPSET_INVALID_ID)
+                       ip_set_nfnl_put(info->del_set.index);
                return -ERANGE;
        }
 
index 0698cad6176367c5a0ad6dffefcf07133304e9fb..1a21c571aa034fc90db2a38d4606681af03f0669 100644 (file)
@@ -569,6 +569,8 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
                sctp_assoc_set_primary(asoc, transport);
        if (asoc->peer.active_path == peer)
                asoc->peer.active_path = transport;
+       if (asoc->peer.retran_path == peer)
+               asoc->peer.retran_path = transport;
        if (asoc->peer.last_data_from == peer)
                asoc->peer.last_data_from = transport;
 
@@ -1323,6 +1325,8 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
 
        if (t)
                asoc->peer.retran_path = t;
+       else
+               t = asoc->peer.retran_path;
 
        SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association"
                                 " %p addr: ",
index 8808b82311b1eb207a2fb3306548666ad6dd6a8b..76e0d56950751a8a60074d5a9a7df6232a1ee472 100644 (file)
@@ -140,6 +140,9 @@ int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
        if (!prtd || !prtd->params)
                return 0;
 
+       if (prtd->dma_ch == -1)
+               return -EINVAL;
+
        DCSR(prtd->dma_ch) &= ~DCSR_RUN;
        DCSR(prtd->dma_ch) = 0;
        DCMD(prtd->dma_ch) = 0;
index 69e33869a53e509d37c86ee1d34364cb822f3f6c..ad97d937d3a8d92d362a108c8285a99c4dbdfc76 100644 (file)
@@ -3035,6 +3035,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD),
+       SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD),
        SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
        SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */
        {}
index 251773e45f61bf0a252ed5c1e888c9853e6b14b9..715615a88a8d4ce7e68adacd4202eaa7a5ab9d56 100644 (file)
@@ -1280,6 +1280,39 @@ static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
                                             stream_tag, format, substream);
 }
 
+static void nvhdmi_8ch_7x_set_info_frame_parameters(struct hda_codec *codec,
+                                                   int channels)
+{
+       unsigned int chanmask;
+       int chan = channels ? (channels - 1) : 1;
+
+       switch (channels) {
+       default:
+       case 0:
+       case 2:
+               chanmask = 0x00;
+               break;
+       case 4:
+               chanmask = 0x08;
+               break;
+       case 6:
+               chanmask = 0x0b;
+               break;
+       case 8:
+               chanmask = 0x13;
+               break;
+       }
+
+       /* Set the audio infoframe channel allocation and checksum fields.  The
+        * channel count is computed implicitly by the hardware. */
+       snd_hda_codec_write(codec, 0x1, 0,
+                       Nv_VERB_SET_Channel_Allocation, chanmask);
+
+       snd_hda_codec_write(codec, 0x1, 0,
+                       Nv_VERB_SET_Info_Frame_Checksum,
+                       (0x71 - chan - chanmask));
+}
+
 static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo,
                                   struct hda_codec *codec,
                                   struct snd_pcm_substream *substream)
@@ -1298,6 +1331,10 @@ static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo,
                                AC_VERB_SET_STREAM_FORMAT, 0);
        }
 
+       /* The audio hardware sends a channel count of 0x7 (8ch) when all the
+        * streams are disabled. */
+       nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8);
+
        return snd_hda_multi_out_dig_close(codec, &spec->multiout);
 }
 
@@ -1308,37 +1345,16 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
                                     struct snd_pcm_substream *substream)
 {
        int chs;
-       unsigned int dataDCC1, dataDCC2, chan, chanmask, channel_id;
+       unsigned int dataDCC1, dataDCC2, channel_id;
        int i;
 
        mutex_lock(&codec->spdif_mutex);
 
        chs = substream->runtime->channels;
-       chan = chs ? (chs - 1) : 1;
 
-       switch (chs) {
-       default:
-       case 0:
-       case 2:
-               chanmask = 0x00;
-               break;
-       case 4:
-               chanmask = 0x08;
-               break;
-       case 6:
-               chanmask = 0x0b;
-               break;
-       case 8:
-               chanmask = 0x13;
-               break;
-       }
        dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT;
        dataDCC2 = 0x2;
 
-       /* set the Audio InforFrame Channel Allocation */
-       snd_hda_codec_write(codec, 0x1, 0,
-                       Nv_VERB_SET_Channel_Allocation, chanmask);
-
        /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
        if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE))
                snd_hda_codec_write(codec,
@@ -1413,10 +1429,7 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
                }
        }
 
-       /* set the Audio Info Frame Checksum */
-       snd_hda_codec_write(codec, 0x1, 0,
-                       Nv_VERB_SET_Info_Frame_Checksum,
-                       (0x71 - chan - chanmask));
+       nvhdmi_8ch_7x_set_info_frame_parameters(codec, chs);
 
        mutex_unlock(&codec->spdif_mutex);
        return 0;
@@ -1512,6 +1525,11 @@ static int patch_nvhdmi_8ch_7x(struct hda_codec *codec)
        spec->multiout.max_channels = 8;
        spec->pcm_playback = &nvhdmi_pcm_playback_8ch_7x;
        codec->patch_ops = nvhdmi_patch_ops_8ch_7x;
+
+       /* Initialize the audio infoframe channel mask and checksum to something
+        * valid */
+       nvhdmi_8ch_7x_set_info_frame_parameters(codec, 8);
+
        return 0;
 }
 
index 7e28a64884f6927a8cf00df442890a1e69af5542..52928d9a72dacf3dfc42636212a523f658df5e95 100644 (file)
@@ -14124,7 +14124,7 @@ static hda_nid_t alc269vb_capsrc_nids[1] = {
 };
 
 static hda_nid_t alc269_adc_candidates[] = {
-       0x08, 0x09, 0x07,
+       0x08, 0x09, 0x07, 0x11,
 };
 
 #define alc269_modes           alc260_modes
index 1395991c39f2634fbf6620c5c0a662dfe924a1c9..94d19c03a7f4f728bf3ddb394c77ba431f52b9b2 100644 (file)
@@ -3408,6 +3408,9 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux,
        hda_nid_t conn[HDA_MAX_NUM_INPUTS];
        int i, nums;
 
+       if (!(get_wcaps(codec, mux) & AC_WCAP_CONN_LIST))
+               return -1;
+
        nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn));
        for (i = 0; i < nums; i++)
                if (conn[i] == nid)
index 02fb66416ddc894c7abdfd2fa52cddc3eb717225..2ce0b2d891d5081df50ed6c677ef835eab845b94 100644 (file)
@@ -65,6 +65,7 @@ static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
        if (prtd->dma_ch >= 0) {
                pxa_free_dma(prtd->dma_ch);
                prtd->dma_ch = -1;
+               prtd->params = NULL;
        }
 
        return 0;
index ac577263b3e3dd7205b7243ae7e434f0aef21575..b6445757fc547d953ca23a0da5dd7a3ff1ab8ccf 100644 (file)
@@ -167,7 +167,7 @@ static struct snd_soc_dai_link zylonite_dai[] = {
        .codec_name = "wm9713-codec",
        .platform_name = "pxa-pcm-audio",
        .cpu_dai_name = "pxa2xx-ac97",
-       .codec_name = "wm9713-hifi",
+       .codec_dai_name = "wm9713-hifi",
        .init = zylonite_wm9713_init,
 },
 {
@@ -176,7 +176,7 @@ static struct snd_soc_dai_link zylonite_dai[] = {
        .codec_name = "wm9713-codec",
        .platform_name = "pxa-pcm-audio",
        .cpu_dai_name = "pxa2xx-ac97-aux",
-       .codec_name = "wm9713-aux",
+       .codec_dai_name = "wm9713-aux",
 },
 {
        .name = "WM9713 Voice",
@@ -184,7 +184,7 @@ static struct snd_soc_dai_link zylonite_dai[] = {
        .codec_name = "wm9713-codec",
        .platform_name = "pxa-pcm-audio",
        .cpu_dai_name = "pxa-ssp-dai.2",
-       .codec_name = "wm9713-voice",
+       .codec_dai_name = "wm9713-voice",
        .ops = &zylonite_voice_ops,
 },
 };
index 4dda58926bc52c282d29b769b40d6f546a3230fe..b76b74db0968d18d360e02aeb59ebc6e802c99fe 100644 (file)
@@ -92,8 +92,8 @@ static int min_bytes_needed(unsigned long val)
 static int format_register_str(struct snd_soc_codec *codec,
                               unsigned int reg, char *buf, size_t len)
 {
-       int wordsize = codec->driver->reg_word_size * 2;
-       int regsize = min_bytes_needed(codec->driver->reg_cache_size) * 2;
+       int wordsize = min_bytes_needed(codec->driver->reg_cache_size) * 2;
+       int regsize = codec->driver->reg_word_size * 2;
        int ret;
        char tmpbuf[len + 1];
        char regbuf[regsize + 1];
@@ -132,8 +132,8 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf,
        size_t total = 0;
        loff_t p = 0;
 
-       wordsize = codec->driver->reg_word_size * 2;
-       regsize = min_bytes_needed(codec->driver->reg_cache_size) * 2;
+       wordsize = min_bytes_needed(codec->driver->reg_cache_size) * 2;
+       regsize = codec->driver->reg_word_size * 2;
 
        len = wordsize + regsize + 2 + 1;
 
index b4b39c0b6c9ed8b1e698213a88ceb9637a082cef..f9289102886ad890987a0d27739a19f1e48afdd4 100644 (file)
@@ -1301,6 +1301,7 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi* umidi,
        case USB_ID(0x15ca, 0x0101): /* Textech USB Midi Cable */
        case USB_ID(0x15ca, 0x1806): /* Textech USB Midi Cable */
        case USB_ID(0x1a86, 0x752d): /* QinHeng CH345 "USB2.0-MIDI" */
+       case USB_ID(0xfc08, 0x0101): /* Unknown vendor Cable */
                ep->max_transfer = 4;
                break;
                /*
index 17d1dcb3c66771cb1d7603cff6a5ed981d44ca69..416538248a4bb04eaf2e28a1a2f58f062e6372fc 100644 (file)
@@ -163,6 +163,7 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
        struct perf_event_attr *attr = &evsel->attr;
        int track = !evsel->idx; /* only the first counter needs these */
 
+       attr->inherit           = !no_inherit;
        attr->read_format       = PERF_FORMAT_TOTAL_TIME_ENABLED |
                                  PERF_FORMAT_TOTAL_TIME_RUNNING |
                                  PERF_FORMAT_ID;
@@ -251,6 +252,9 @@ static void open_counters(struct perf_evlist *evlist)
 {
        struct perf_evsel *pos;
 
+       if (evlist->cpus->map[0] < 0)
+               no_inherit = true;
+
        list_for_each_entry(pos, &evlist->entries, node) {
                struct perf_event_attr *attr = &pos->attr;
                /*
@@ -271,8 +275,7 @@ static void open_counters(struct perf_evlist *evlist)
 retry_sample_id:
                attr->sample_id_all = sample_id_all_avail ? 1 : 0;
 try_again:
-               if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group,
-                                    !no_inherit) < 0) {
+               if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
                        int err = errno;
 
                        if (err == EPERM || err == EACCES) {
index e2109f9b43eb3ed99a5239805087277b229739d3..03f0e45f1479c2fab31de2624d69d95458886157 100644 (file)
@@ -167,16 +167,17 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
                attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
                                    PERF_FORMAT_TOTAL_TIME_RUNNING;
 
+       attr->inherit = !no_inherit;
+
        if (system_wide)
-               return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false, false);
+               return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false);
 
-       attr->inherit = !no_inherit;
        if (target_pid == -1 && target_tid == -1) {
                attr->disabled = 1;
                attr->enable_on_exec = 1;
        }
 
-       return perf_evsel__open_per_thread(evsel, evsel_list->threads, false, false);
+       return perf_evsel__open_per_thread(evsel, evsel_list->threads, false);
 }
 
 /*
index 1b2106c58f660c83a858636df0862c458d127eb8..11e3c84583622bac20ed799cfab29e7066c6d6eb 100644 (file)
@@ -290,7 +290,7 @@ static int test__open_syscall_event(void)
                goto out_thread_map_delete;
        }
 
-       if (perf_evsel__open_per_thread(evsel, threads, false, false) < 0) {
+       if (perf_evsel__open_per_thread(evsel, threads, false) < 0) {
                pr_debug("failed to open counter: %s, "
                         "tweak /proc/sys/kernel/perf_event_paranoid?\n",
                         strerror(errno));
@@ -303,7 +303,7 @@ static int test__open_syscall_event(void)
        }
 
        if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) {
-               pr_debug("perf_evsel__open_read_on_cpu\n");
+               pr_debug("perf_evsel__read_on_cpu\n");
                goto out_close_fd;
        }
 
@@ -365,7 +365,7 @@ static int test__open_syscall_event_on_all_cpus(void)
                goto out_thread_map_delete;
        }
 
-       if (perf_evsel__open(evsel, cpus, threads, false, false) < 0) {
+       if (perf_evsel__open(evsel, cpus, threads, false) < 0) {
                pr_debug("failed to open counter: %s, "
                         "tweak /proc/sys/kernel/perf_event_paranoid?\n",
                         strerror(errno));
@@ -418,7 +418,7 @@ static int test__open_syscall_event_on_all_cpus(void)
                        continue;
 
                if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) {
-                       pr_debug("perf_evsel__open_read_on_cpu\n");
+                       pr_debug("perf_evsel__read_on_cpu\n");
                        err = -1;
                        break;
                }
@@ -529,7 +529,7 @@ static int test__basic_mmap(void)
 
                perf_evlist__add(evlist, evsels[i]);
 
-               if (perf_evsel__open(evsels[i], cpus, threads, false, false) < 0) {
+               if (perf_evsel__open(evsels[i], cpus, threads, false) < 0) {
                        pr_debug("failed to open counter: %s, "
                                 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
                                 strerror(errno));
index fc1273e976c58f4c25d6321abf578392ba1126ad..7e3d6e310bf839f09e5d6afed39c8c1530a13807 100644 (file)
@@ -845,9 +845,10 @@ static void start_counters(struct perf_evlist *evlist)
                }
 
                attr->mmap = 1;
+               attr->inherit = inherit;
 try_again:
                if (perf_evsel__open(counter, top.evlist->cpus,
-                                    top.evlist->threads, group, inherit) < 0) {
+                                    top.evlist->threads, group) < 0) {
                        int err = errno;
 
                        if (err == EPERM || err == EACCES) {
index 9fea75535221a256aea8dcd344f85e463779a80f..96bee5c46008450519a67785c21e4f0481d1e6c4 100644 (file)
@@ -13,7 +13,7 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
 {
        FILE *fp;
        char mountpoint[MAX_PATH+1], tokens[MAX_PATH+1], type[MAX_PATH+1];
-       char *token, *saved_ptr;
+       char *token, *saved_ptr = NULL;
        int found = 0;
 
        fp = fopen("/proc/mounts", "r");
index d852cefa20def5ff48665e7ef44bc842093f6f49..45da8d186b492d4f82512862aef867acd4649f09 100644 (file)
@@ -12,6 +12,7 @@
 #include "evlist.h"
 #include "evsel.h"
 #include "util.h"
+#include "debug.h"
 
 #include <sys/mman.h>
 
@@ -250,15 +251,19 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
        return evlist->mmap != NULL ? 0 : -ENOMEM;
 }
 
-static int __perf_evlist__mmap(struct perf_evlist *evlist, int cpu, int prot,
-                              int mask, int fd)
+static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *evsel,
+                              int cpu, int prot, int mask, int fd)
 {
        evlist->mmap[cpu].prev = 0;
        evlist->mmap[cpu].mask = mask;
        evlist->mmap[cpu].base = mmap(NULL, evlist->mmap_len, prot,
                                      MAP_SHARED, fd, 0);
-       if (evlist->mmap[cpu].base == MAP_FAILED)
+       if (evlist->mmap[cpu].base == MAP_FAILED) {
+               if (evlist->cpus->map[cpu] == -1 && evsel->attr.inherit)
+                       ui__warning("Inherit is not allowed on per-task "
+                                   "events using mmap.\n");
                return -1;
+       }
 
        perf_evlist__add_pollfd(evlist, fd);
        return 0;
@@ -312,7 +317,8 @@ int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite)
                                        if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT,
                                                  FD(first_evsel, cpu, 0)) != 0)
                                                goto out_unmap;
-                               } else if (__perf_evlist__mmap(evlist, cpu, prot, mask, fd) < 0)
+                               } else if (__perf_evlist__mmap(evlist, evsel, cpu,
+                                                              prot, mask, fd) < 0)
                                        goto out_unmap;
 
                                if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
index 662596afd7f1d49fccaeb8c95ee7c8c64748b8c9..d6fd59beb860739aea40e1b4052f6eda1a741996 100644 (file)
@@ -175,7 +175,7 @@ int __perf_evsel__read(struct perf_evsel *evsel,
 }
 
 static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
-                             struct thread_map *threads, bool group, bool inherit)
+                             struct thread_map *threads, bool group)
 {
        int cpu, thread;
        unsigned long flags = 0;
@@ -192,19 +192,6 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
 
        for (cpu = 0; cpu < cpus->nr; cpu++) {
                int group_fd = -1;
-               /*
-                * Don't allow mmap() of inherited per-task counters. This
-                * would create a performance issue due to all children writing
-                * to the same buffer.
-                *
-                * FIXME:
-                * Proper fix is not to pass 'inherit' to perf_evsel__open*,
-                * but a 'flags' parameter, with 'group' folded there as well,
-                * then introduce a PERF_O_{MMAP,GROUP,INHERIT} enum, and if
-                * O_MMAP is set, emit a warning if cpu < 0 and O_INHERIT is
-                * set. Lets go for the minimal fix first tho.
-                */
-               evsel->attr.inherit = (cpus->map[cpu] >= 0) && inherit;
 
                for (thread = 0; thread < threads->nr; thread++) {
 
@@ -253,7 +240,7 @@ static struct {
 };
 
 int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
-                    struct thread_map *threads, bool group, bool inherit)
+                    struct thread_map *threads, bool group)
 {
        if (cpus == NULL) {
                /* Work around old compiler warnings about strict aliasing */
@@ -263,19 +250,19 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
        if (threads == NULL)
                threads = &empty_thread_map.map;
 
-       return __perf_evsel__open(evsel, cpus, threads, group, inherit);
+       return __perf_evsel__open(evsel, cpus, threads, group);
 }
 
 int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
-                            struct cpu_map *cpus, bool group, bool inherit)
+                            struct cpu_map *cpus, bool group)
 {
-       return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group, inherit);
+       return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group);
 }
 
 int perf_evsel__open_per_thread(struct perf_evsel *evsel,
-                               struct thread_map *threads, bool group, bool inherit)
+                               struct thread_map *threads, bool group)
 {
-       return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, inherit);
+       return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group);
 }
 
 static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
index 6710ab538342fe1d5970c812423908ddec3ee5a7..f79bb2c09a6cbea510e31d260a1fabb778e13950 100644 (file)
@@ -81,11 +81,11 @@ void perf_evsel__free_id(struct perf_evsel *evsel);
 void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
 
 int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
-                            struct cpu_map *cpus, bool group, bool inherit);
+                            struct cpu_map *cpus, bool group);
 int perf_evsel__open_per_thread(struct perf_evsel *evsel,
-                               struct thread_map *threads, bool group, bool inherit);
+                               struct thread_map *threads, bool group);
 int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
-                    struct thread_map *threads, bool group, bool inherit);
+                    struct thread_map *threads, bool group);
 
 #define perf_evsel__match(evsel, t, c)         \
        (evsel->attr.type == PERF_TYPE_##t &&   \
index a9f2d7e1204d1655b14b99cafb06d08d5046d8a6..f5e38451fdc505e329ac77415e9e8aba5fbe7ebb 100644 (file)
@@ -498,11 +498,11 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
        struct cpu_map *cpus = NULL;
        struct thread_map *threads = NULL;
        PyObject *pcpus = NULL, *pthreads = NULL;
-       int group = 0, overwrite = 0;
-       static char *kwlist[] = {"cpus", "threads", "group", "overwrite", NULL, NULL};
+       int group = 0, inherit = 0;
+       static char *kwlist[] = {"cpus", "threads", "group", "inherit", NULL, NULL};
 
        if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
-                                        &pcpus, &pthreads, &group, &overwrite))
+                                        &pcpus, &pthreads, &group, &inherit))
                return NULL;
 
        if (pthreads != NULL)
@@ -511,7 +511,8 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
        if (pcpus != NULL)
                cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
 
-       if (perf_evsel__open(evsel, cpus, threads, group, overwrite) < 0) {
+       evsel->attr.inherit = inherit;
+       if (perf_evsel__open(evsel, cpus, threads, group) < 0) {
                PyErr_SetFromErrno(PyExc_OSError);
                return NULL;
        }
index 8c17a8730e4a36a9923537f79466c3793fd06559..15633d6081332f0204acc978974ff6deec8d2375 100644 (file)
@@ -256,10 +256,9 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
                         int refresh)
 {
        struct objdump_line *pos, *n;
-       struct annotation *notes = symbol__annotation(sym);
+       struct annotation *notes;
        struct annotate_browser browser = {
                .b = {
-                       .entries = &notes->src->source,
                        .refresh = ui_browser__list_head_refresh,
                        .seek    = ui_browser__list_head_seek,
                        .write   = annotate_browser__write,
@@ -281,6 +280,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
 
        ui_helpline__push("Press <- or ESC to exit");
 
+       notes = symbol__annotation(sym);
+
        list_for_each_entry(pos, &notes->src->source, node) {
                struct objdump_line_rb_node *rbpos;
                size_t line_len = strlen(pos->line);
@@ -291,6 +292,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
                rbpos->idx = browser.b.nr_entries++;
        }
 
+       browser.b.entries = &notes->src->source,
        browser.b.width += 18; /* Percentage */
        ret = annotate_browser__run(&browser, evidx, refresh);
        list_for_each_entry_safe(pos, n, &notes->src->source, node) {
index 798efdca3eadd9fe89b84157ceba5c56a8d5dcb2..5d767c622dfc1f862fb747ababa610e9031944c8 100644 (file)
@@ -851,7 +851,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel,
                        goto out_free_stack;
                case 'a':
                        if (browser->selection == NULL ||
-                           browser->selection->map == NULL ||
+                           browser->selection->sym == NULL ||
                            browser->selection->map->dso->annotate_warned)
                                continue;
                        goto do_annotate;