Merge branch 'for-linus' of git://github.com/at91linux/linux-2.6-at91
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 6 May 2011 04:27:57 +0000 (21:27 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 6 May 2011 04:27:57 +0000 (21:27 -0700)
* 'for-linus' of git://github.com/at91linux/linux-2.6-at91:
  at91: Add ARCH_ID and basic cpu macros definition for 5series chips family.
  arm: at91: fix compiler warning for eb01 board build
  arm: at91: minimal defconfig for at91x40 SoC
  ARM: at91: AT91CAP9 has a macb device

348 files changed:
Documentation/DocBook/media-entities.tmpl
Documentation/DocBook/v4l/media-ioc-setup-link.xml
Documentation/DocBook/v4l/pixfmt-y12.xml [new file with mode: 0644]
Documentation/DocBook/v4l/pixfmt.xml
Documentation/DocBook/v4l/subdev-formats.xml
Documentation/cgroups/memory.txt
Documentation/flexible-arrays.txt
Documentation/hwmon/adm1021
Documentation/hwmon/lm90
Documentation/video4linux/sh_mobile_ceu_camera.txt
Documentation/workqueue.txt
MAINTAINERS
Makefile
arch/arm/include/asm/kprobes.h
arch/arm/kernel/kprobes-decode.c
arch/arm/kernel/kprobes.c
arch/arm/kernel/perf_event.c
arch/arm/kernel/smp.c
arch/arm/kernel/sys_oabi-compat.c
arch/arm/mach-davinci/Kconfig
arch/arm/mach-davinci/board-mityomapl138.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/dm355.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-davinci/include/mach/debug-macro.S
arch/arm/mach-davinci/include/mach/serial.h
arch/arm/mach-mx3/mach-vpr200.c
arch/arm/mach-mx5/board-mx53_loco.c
arch/arm/mach-mxs/clock-mx28.c
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-rx51.c
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/cm2xxx_3xxx.c
arch/arm/mach-omap2/control.c
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_l3_smx.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/voltage.c
arch/arm/mach-pxa/hx4700.c
arch/arm/mach-pxa/magician.c
arch/arm/mach-ux500/board-mop500.c
arch/arm/mm/proc-xscale.S
arch/arm/plat-mxc/gpio.c
arch/arm/plat-mxc/ssi-fiq.S
arch/m68k/mm/motorola.c
arch/parisc/mm/init.c
arch/powerpc/include/asm/8xx_immap.h
arch/powerpc/include/asm/uninorth.h
arch/s390/crypto/prng.c
arch/s390/kvm/sie64a.S
arch/s390/mm/fault.c
arch/s390/mm/pageattr.c
arch/um/Kconfig.um
arch/um/include/asm/thread_info.h
arch/um/sys-i386/Makefile
arch/um/sys-i386/atomic64_cx8_32.S [new file with mode: 0644]
arch/x86/boot/memory.c
arch/x86/include/asm/io_apic.h
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apm_32.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_p4.c
arch/x86/kernel/devicetree.c
arch/x86/kernel/reboot_32.S
arch/x86/mm/numa_64.c
arch/x86/platform/ce4100/falconfalls.dts
arch/x86/xen/mmu.c
drivers/acpi/scan.c
drivers/ata/ahci.c
drivers/ata/ahci.h
drivers/ata/ata_piix.c
drivers/ata/libahci.c
drivers/ata/libata-core.c
drivers/ata/libata-eh.c
drivers/ata/pata_at91.c
drivers/base/power/main.c
drivers/base/power/wakeup.c
drivers/base/syscore.c
drivers/block/rbd.c
drivers/clk/clkdev.c
drivers/edac/amd64_edac.c
drivers/edac/amd64_edac.h
drivers/edac/edac_mc_sysfs.c
drivers/firewire/ohci.c
drivers/gpu/drm/Kconfig
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/drm_irq.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_fb.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/evergreend.h
drivers/gpu/drm/radeon/radeon_atombios.c
drivers/gpu/drm/radeon/radeon_kms.c
drivers/gpu/drm/radeon/reg_srcs/r600
drivers/hwmon/Kconfig
drivers/hwmon/lm85.c
drivers/hwmon/lm90.c
drivers/hwmon/twl4030-madc-hwmon.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-parport.c
drivers/infiniband/hw/qib/qib_iba6120.c
drivers/infiniband/hw/qib/qib_iba7220.c
drivers/infiniband/hw/qib/qib_iba7322.c
drivers/input/touchscreen/wm831x-ts.c
drivers/media/common/tuners/tda18271-common.c
drivers/media/common/tuners/tda18271-fe.c
drivers/media/common/tuners/tda18271-maps.c
drivers/media/dvb/b2c2/flexcop-pci.c
drivers/media/dvb/dvb-usb/Kconfig
drivers/media/dvb/dvb-usb/dib0700_devices.c
drivers/media/dvb/ngene/ngene-core.c
drivers/media/media-entity.c
drivers/media/radio/radio-sf16fmr2.c
drivers/media/radio/saa7706h.c
drivers/media/radio/tef6862.c
drivers/media/rc/imon.c
drivers/media/rc/ite-cir.c
drivers/media/rc/mceusb.c
drivers/media/rc/rc-main.c
drivers/media/video/Kconfig
drivers/media/video/cx18/cx18-streams.c
drivers/media/video/cx23885/Kconfig
drivers/media/video/imx074.c
drivers/media/video/m52790.c
drivers/media/video/omap3isp/isp.c
drivers/media/video/omap3isp/isp.h
drivers/media/video/omap3isp/ispccdc.c
drivers/media/video/omap3isp/isppreview.c
drivers/media/video/omap3isp/ispqueue.c
drivers/media/video/omap3isp/ispresizer.c
drivers/media/video/omap3isp/ispstat.h
drivers/media/video/omap3isp/ispvideo.c
drivers/media/video/omap3isp/ispvideo.h
drivers/media/video/s5p-fimc/fimc-capture.c
drivers/media/video/s5p-fimc/fimc-core.c
drivers/media/video/sh_mobile_ceu_camera.c
drivers/media/video/sh_mobile_csi2.c
drivers/media/video/soc_camera.c
drivers/media/video/tda9840.c
drivers/media/video/tea6415c.c
drivers/media/video/tea6420.c
drivers/media/video/upd64031a.c
drivers/media/video/upd64083.c
drivers/media/video/v4l2-dev.c
drivers/media/video/videobuf2-core.c
drivers/media/video/videobuf2-dma-contig.c
drivers/mfd/omap-usb-host.c
drivers/mmc/core/bus.c
drivers/mmc/core/host.c
drivers/mmc/host/omap.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/tmio_mmc_pio.c
drivers/mtd/nand/diskonchip.c
drivers/net/amd8111e.c
drivers/net/atl1c/atl1c.h
drivers/net/atl1c/atl1c_main.c
drivers/net/benet/be_main.c
drivers/net/bnx2.c
drivers/net/bnx2x/bnx2x_cmn.c
drivers/net/bonding/bond_3ad.c
drivers/net/ehea/ehea_main.c
drivers/net/fs_enet/mac-fec.c
drivers/net/ftmac100.c
drivers/net/mii.c
drivers/net/netconsole.c
drivers/net/r8169.c
drivers/net/tg3.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/smsc95xx.c
drivers/net/usb/usbnet.c
drivers/net/veth.c
drivers/net/wireless/ath/ath9k/recv.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/iwlegacy/iwl-4965-tx.c
drivers/net/wireless/iwlegacy/iwl-led.c
drivers/net/wireless/iwlegacy/iwl4965-base.c
drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
drivers/net/wireless/iwlwifi/iwl-agn-tx.c
drivers/pcmcia/pcmcia_resource.c
drivers/rtc/rtc-coh901331.c
drivers/rtc/rtc-max8925.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_devmap.c
drivers/s390/block/dasd_diag.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_genhd.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dasd_ioctl.c
drivers/s390/cio/qdio_main.c
drivers/s390/kvm/kvm_virtio.c
drivers/scsi/device_handler/scsi_dh.c
drivers/scsi/mpt2sas/mpt2sas_ctl.c
drivers/scsi/pmcraid.c
drivers/scsi/scsi_sysfs.c
drivers/staging/ft1000/ft1000-pcmcia/ft1000_hw.c
drivers/staging/ft1000/ft1000-pcmcia/ft1000_proc.c
drivers/staging/gma500/Kconfig
drivers/staging/intel_sst/intelmid_v1_control.c
drivers/staging/intel_sst/intelmid_v2_control.c
drivers/staging/olpc_dcon/olpc_dcon_xo_1.c
drivers/staging/rt2860/common/cmm_data_pci.c
drivers/staging/rt2860/common/cmm_data_usb.c
drivers/staging/rts_pstor/debug.h
drivers/staging/rts_pstor/ms.c
drivers/staging/rts_pstor/rtsx_chip.c
drivers/staging/rts_pstor/rtsx_scsi.c
drivers/staging/rts_pstor/sd.c
drivers/staging/rts_pstor/trace.h
drivers/staging/rts_pstor/xd.c
drivers/staging/solo6x10/Kconfig
drivers/staging/spectra/ffsport.c
drivers/staging/tidspbridge/dynload/cload.c
drivers/staging/tty/specialix.c
drivers/staging/usbip/vhci_hcd.c
drivers/staging/usbip/vhci_sysfs.c
drivers/staging/wlan-ng/cfg80211.c
drivers/usb/host/ehci-omap.c
drivers/usb/host/isp1760-hcd.c
drivers/usb/host/xhci-hub.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/omap2430.c
drivers/watchdog/iTCO_wdt.c
drivers/xen/manage.c
fs/btrfs/ctree.h
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/free-space-cache.c
fs/btrfs/inode.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/ceph/addr.c
fs/ceph/caps.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/super.h
fs/ceph/xattr.c
fs/cifs/connect.c
fs/dcache.c
fs/ecryptfs/crypto.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ecryptfs/kthread.c
fs/ecryptfs/main.c
fs/ecryptfs/super.c
fs/file.c
fs/gfs2/glock.c
fs/logfs/super.c
fs/nfs/namespace.c
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
fs/nfs/pnfs.c
fs/nfs/super.c
fs/nfs/write.c
fs/ocfs2/ocfs2_fs.h
fs/ubifs/log.c
fs/ubifs/recovery.c
fs/ubifs/replay.c
fs/ubifs/super.c
include/drm/drm_fb_helper.h
include/drm/drm_pciids.h
include/drm/radeon_drm.h
include/linux/bit_spinlock.h
include/linux/dcache.h
include/linux/flex_array.h
include/linux/huge_mm.h
include/linux/libata.h
include/linux/list_bl.h
include/linux/mfd/wm831x/pdata.h
include/linux/mm.h
include/linux/mmc/host.h
include/linux/nfs_fs_sb.h
include/linux/nfs_xdr.h
include/linux/pci_ids.h
include/linux/percpu.h
include/linux/sunrpc/sched.h
include/linux/usb/usbnet.h
include/linux/v4l2-mediabus.h
include/linux/videodev2.h
include/media/v4l2-device.h
init/Kconfig
kernel/hrtimer.c
kernel/irq/proc.c
kernel/kexec.c
kernel/power/hibernate.c
kernel/power/suspend.c
kernel/trace/Kconfig
kernel/watchdog.c
kernel/workqueue.c
lib/flex_array.c
lib/xz/xz_dec_lzma2.c
mm/huge_memory.c
mm/memory.c
mm/mlock.c
mm/oom_kill.c
mm/slub.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/l2cap_core.c
net/bluetooth/sco.c
net/bridge/br_input.c
net/can/bcm.c
net/can/raw.c
net/ceph/messenger.c
net/ceph/osd_client.c
net/core/dev.c
net/dsa/Kconfig
net/dsa/mv88e6131.c
net/ipv4/devinet.c
net/ipv4/fib_trie.c
net/ipv4/route.c
net/ipv6/addrconf.c
net/ipv6/esp6.c
net/ipv6/route.c
net/ipv6/udp.c
net/l2tp/l2tp_ip.c
net/mac80211/cfg.c
net/mac80211/debugfs_netdev.c
net/sctp/ulpevent.c
net/sunrpc/Kconfig
net/sunrpc/auth_gss/auth_gss.c
net/sunrpc/clnt.c
net/sunrpc/xprt.c
net/unix/af_unix.c
net/xfrm/xfrm_replay.c
net/xfrm/xfrm_user.c
scripts/kconfig/conf.c
security/selinux/avc.c
security/selinux/hooks.c
security/selinux/include/avc.h
security/selinux/ss/policydb.c
sound/aoa/codecs/tas.c
sound/pci/au88x0/au88x0_pcm.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_via.c
sound/usb/format.c
sound/usb/quirks.c

index 5d259c6..fea63b4 100644 (file)
 <!ENTITY sub-srggb10 SYSTEM "v4l/pixfmt-srggb10.xml">
 <!ENTITY sub-srggb8 SYSTEM "v4l/pixfmt-srggb8.xml">
 <!ENTITY sub-y10 SYSTEM "v4l/pixfmt-y10.xml">
+<!ENTITY sub-y12 SYSTEM "v4l/pixfmt-y12.xml">
 <!ENTITY sub-pixfmt SYSTEM "v4l/pixfmt.xml">
 <!ENTITY sub-cropcap SYSTEM "v4l/vidioc-cropcap.xml">
 <!ENTITY sub-dbg-g-register SYSTEM "v4l/vidioc-dbg-g-register.xml">
index 2331e76..cec97af 100644 (file)
@@ -34,7 +34,7 @@
       <varlistentry>
        <term><parameter>request</parameter></term>
        <listitem>
-         <para>MEDIA_IOC_ENUM_LINKS</para>
+         <para>MEDIA_IOC_SETUP_LINK</para>
        </listitem>
       </varlistentry>
       <varlistentry>
diff --git a/Documentation/DocBook/v4l/pixfmt-y12.xml b/Documentation/DocBook/v4l/pixfmt-y12.xml
new file mode 100644 (file)
index 0000000..ff417b8
--- /dev/null
@@ -0,0 +1,79 @@
+<refentry id="V4L2-PIX-FMT-Y12">
+  <refmeta>
+    <refentrytitle>V4L2_PIX_FMT_Y12 ('Y12 ')</refentrytitle>
+    &manvol;
+  </refmeta>
+  <refnamediv>
+    <refname><constant>V4L2_PIX_FMT_Y12</constant></refname>
+    <refpurpose>Grey-scale image</refpurpose>
+  </refnamediv>
+  <refsect1>
+    <title>Description</title>
+
+    <para>This is a grey-scale image with a depth of 12 bits per pixel. Pixels
+are stored in 16-bit words with unused high bits padded with 0. The least
+significant byte is stored at lower memory addresses (little-endian).</para>
+
+    <example>
+      <title><constant>V4L2_PIX_FMT_Y12</constant> 4 &times; 4
+pixel image</title>
+
+      <formalpara>
+       <title>Byte Order.</title>
+       <para>Each cell is one byte.
+         <informaltable frame="none">
+           <tgroup cols="9" align="center">
+             <colspec align="left" colwidth="2*" />
+             <tbody valign="top">
+               <row>
+                 <entry>start&nbsp;+&nbsp;0:</entry>
+                 <entry>Y'<subscript>00low</subscript></entry>
+                 <entry>Y'<subscript>00high</subscript></entry>
+                 <entry>Y'<subscript>01low</subscript></entry>
+                 <entry>Y'<subscript>01high</subscript></entry>
+                 <entry>Y'<subscript>02low</subscript></entry>
+                 <entry>Y'<subscript>02high</subscript></entry>
+                 <entry>Y'<subscript>03low</subscript></entry>
+                 <entry>Y'<subscript>03high</subscript></entry>
+               </row>
+               <row>
+                 <entry>start&nbsp;+&nbsp;8:</entry>
+                 <entry>Y'<subscript>10low</subscript></entry>
+                 <entry>Y'<subscript>10high</subscript></entry>
+                 <entry>Y'<subscript>11low</subscript></entry>
+                 <entry>Y'<subscript>11high</subscript></entry>
+                 <entry>Y'<subscript>12low</subscript></entry>
+                 <entry>Y'<subscript>12high</subscript></entry>
+                 <entry>Y'<subscript>13low</subscript></entry>
+                 <entry>Y'<subscript>13high</subscript></entry>
+               </row>
+               <row>
+                 <entry>start&nbsp;+&nbsp;16:</entry>
+                 <entry>Y'<subscript>20low</subscript></entry>
+                 <entry>Y'<subscript>20high</subscript></entry>
+                 <entry>Y'<subscript>21low</subscript></entry>
+                 <entry>Y'<subscript>21high</subscript></entry>
+                 <entry>Y'<subscript>22low</subscript></entry>
+                 <entry>Y'<subscript>22high</subscript></entry>
+                 <entry>Y'<subscript>23low</subscript></entry>
+                 <entry>Y'<subscript>23high</subscript></entry>
+               </row>
+               <row>
+                 <entry>start&nbsp;+&nbsp;24:</entry>
+                 <entry>Y'<subscript>30low</subscript></entry>
+                 <entry>Y'<subscript>30high</subscript></entry>
+                 <entry>Y'<subscript>31low</subscript></entry>
+                 <entry>Y'<subscript>31high</subscript></entry>
+                 <entry>Y'<subscript>32low</subscript></entry>
+                 <entry>Y'<subscript>32high</subscript></entry>
+                 <entry>Y'<subscript>33low</subscript></entry>
+                 <entry>Y'<subscript>33high</subscript></entry>
+               </row>
+             </tbody>
+           </tgroup>
+         </informaltable>
+       </para>
+      </formalpara>
+    </example>
+  </refsect1>
+</refentry>
index c6fdcbb..40af4be 100644 (file)
@@ -696,6 +696,7 @@ information.</para>
     &sub-packed-yuv;
     &sub-grey;
     &sub-y10;
+    &sub-y12;
     &sub-y16;
     &sub-yuyv;
     &sub-uyvy;
index 7041127..d7ccd25 100644 (file)
              <entry>b<subscript>1</subscript></entry>
              <entry>b<subscript>0</subscript></entry>
            </row>
+           <row id="V4L2-MBUS-FMT-SGBRG8-1X8">
+             <entry>V4L2_MBUS_FMT_SGBRG8_1X8</entry>
+             <entry>0x3013</entry>
+             <entry></entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>g<subscript>7</subscript></entry>
+             <entry>g<subscript>6</subscript></entry>
+             <entry>g<subscript>5</subscript></entry>
+             <entry>g<subscript>4</subscript></entry>
+             <entry>g<subscript>3</subscript></entry>
+             <entry>g<subscript>2</subscript></entry>
+             <entry>g<subscript>1</subscript></entry>
+             <entry>g<subscript>0</subscript></entry>
+           </row>
            <row id="V4L2-MBUS-FMT-SGRBG8-1X8">
              <entry>V4L2_MBUS_FMT_SGRBG8_1X8</entry>
              <entry>0x3002</entry>
              <entry>g<subscript>1</subscript></entry>
              <entry>g<subscript>0</subscript></entry>
            </row>
+           <row id="V4L2-MBUS-FMT-SRGGB8-1X8">
+             <entry>V4L2_MBUS_FMT_SRGGB8_1X8</entry>
+             <entry>0x3014</entry>
+             <entry></entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>r<subscript>7</subscript></entry>
+             <entry>r<subscript>6</subscript></entry>
+             <entry>r<subscript>5</subscript></entry>
+             <entry>r<subscript>4</subscript></entry>
+             <entry>r<subscript>3</subscript></entry>
+             <entry>r<subscript>2</subscript></entry>
+             <entry>r<subscript>1</subscript></entry>
+             <entry>r<subscript>0</subscript></entry>
+           </row>
            <row id="V4L2-MBUS-FMT-SBGGR10-DPCM8-1X8">
              <entry>V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8</entry>
              <entry>0x300b</entry>
              <entry>u<subscript>1</subscript></entry>
              <entry>u<subscript>0</subscript></entry>
            </row>
+           <row id="V4L2-MBUS-FMT-Y12-1X12">
+             <entry>V4L2_MBUS_FMT_Y12_1X12</entry>
+             <entry>0x2013</entry>
+             <entry></entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>-</entry>
+             <entry>y<subscript>11</subscript></entry>
+             <entry>y<subscript>10</subscript></entry>
+             <entry>y<subscript>9</subscript></entry>
+             <entry>y<subscript>8</subscript></entry>
+             <entry>y<subscript>7</subscript></entry>
+             <entry>y<subscript>6</subscript></entry>
+             <entry>y<subscript>5</subscript></entry>
+             <entry>y<subscript>4</subscript></entry>
+             <entry>y<subscript>3</subscript></entry>
+             <entry>y<subscript>2</subscript></entry>
+             <entry>y<subscript>1</subscript></entry>
+             <entry>y<subscript>0</subscript></entry>
+           </row>
            <row id="V4L2-MBUS-FMT-UYVY8-1X16">
              <entry>V4L2_MBUS_FMT_UYVY8_1X16</entry>
              <entry>0x200f</entry>
index b6ed61c..7c16347 100644 (file)
@@ -52,8 +52,10 @@ Brief summary of control files.
  tasks                          # attach a task(thread) and show list of threads
  cgroup.procs                   # show list of processes
  cgroup.event_control           # an interface for event_fd()
- memory.usage_in_bytes          # show current memory(RSS+Cache) usage.
- memory.memsw.usage_in_bytes    # show current memory+Swap usage
+ memory.usage_in_bytes          # show current res_counter usage for memory
+                                (See 5.5 for details)
+ memory.memsw.usage_in_bytes    # show current res_counter usage for memory+Swap
+                                (See 5.5 for details)
  memory.limit_in_bytes          # set/show limit of memory usage
  memory.memsw.limit_in_bytes    # set/show limit of memory+Swap usage
  memory.failcnt                         # show the number of memory usage hits limits
@@ -453,6 +455,15 @@ memory under it will be reclaimed.
 You can reset failcnt by writing 0 to failcnt file.
 # echo 0 > .../memory.failcnt
 
+5.5 usage_in_bytes
+
+For efficiency, as other kernel components, memory cgroup uses some optimization
+to avoid unnecessary cacheline false sharing. usage_in_bytes is affected by the
+method and doesn't show 'exact' value of memory(and swap) usage, it's an fuzz
+value for efficient access. (Of course, when necessary, it's synchronized.)
+If you want to know more exact memory usage, you should use RSS+CACHE(+SWAP)
+value in memory.stat(see 5.2).
+
 6. Hierarchy support
 
 The memory controller supports a deep hierarchy and hierarchical accounting.
index cb8a3a0..df904ae 100644 (file)
@@ -66,10 +66,10 @@ trick is to ensure that any needed memory allocations are done before
 entering atomic context, using:
 
     int flex_array_prealloc(struct flex_array *array, unsigned int start,
-                           unsigned int end, gfp_t flags);
+                           unsigned int nr_elements, gfp_t flags);
 
 This function will ensure that memory for the elements indexed in the range
-defined by start and end has been allocated.  Thereafter, a
+defined by start and nr_elements has been allocated.  Thereafter, a
 flex_array_put() call on an element in that range is guaranteed not to
 block.
 
index 03d02bf..02ad96c 100644 (file)
@@ -14,10 +14,6 @@ Supported chips:
     Prefix: 'gl523sm'
     Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
     Datasheet:
-  * Intel Xeon Processor
-    Prefix: - any other - may require 'force_adm1021' parameter
-    Addresses scanned: none
-    Datasheet: Publicly available at Intel website
   * Maxim MAX1617
     Prefix: 'max1617'
     Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
@@ -91,21 +87,27 @@ will do no harm, but will return 'old' values. It is possible to make
 ADM1021-clones do faster measurements, but there is really no good reason
 for that.
 
-Xeon support
-------------
 
-Some Xeon processors have real max1617, adm1021, or compatible chips
-within them, with two temperature sensors.
+Netburst-based Xeon support
+---------------------------
 
-Other Xeons have chips with only one sensor.
+Some Xeon processors based on the Netburst (early Pentium 4, from 2001 to
+2003) microarchitecture had real MAX1617, ADM1021, or compatible chips
+within them, with two temperature sensors. Other Xeon processors of this
+era (with 400 MHz FSB) had chips with only one temperature sensor.
 
-If you have a Xeon, and the adm1021 module loads, and both temperatures
-appear valid, then things are good.
+If you have such an old Xeon, and you get two valid temperatures when
+loading the adm1021 module, then things are good.
 
-If the adm1021 module doesn't load, you should try this:
-       modprobe adm1021 force_adm1021=BUS,ADDRESS
-       ADDRESS can only be 0x18, 0x1a, 0x29, 0x2b, 0x4c, or 0x4e.
+If nothing happens when loading the adm1021 module, and you are certain
+that your specific Xeon processor model includes compatible sensors, you
+will have to explicitly instantiate the sensor chips from user-space. See
+method 4 in Documentation/i2c/instantiating-devices. Possible slave
+addresses are 0x18, 0x1a, 0x29, 0x2b, 0x4c, or 0x4e. It is likely that
+only temp2 will be correct and temp1 will have to be ignored.
 
-If you have dual Xeons you may have appear to have two separate
-adm1021-compatible chips, or two single-temperature sensors, at distinct
-addresses.
+Previous generations of the Xeon processor (based on Pentium II/III)
+didn't have these sensors. Next generations of Xeon processors (533 MHz
+FSB and faster) lost them, until the Core-based generation which
+introduced integrated digital thermal sensors. These are supported by
+the coretemp driver.
index fa475c0..f3efd18 100644 (file)
@@ -32,6 +32,16 @@ Supported chips:
     Addresses scanned: I2C 0x4c and 0x4d
     Datasheet: Publicly available at the ON Semiconductor website
                http://www.onsemi.com/PowerSolutions/product.do?id=ADT7461
+  * Analog Devices ADT7461A
+    Prefix: 'adt7461a'
+    Addresses scanned: I2C 0x4c and 0x4d
+    Datasheet: Publicly available at the ON Semiconductor website
+               http://www.onsemi.com/PowerSolutions/product.do?id=ADT7461A
+  * ON Semiconductor NCT1008
+    Prefix: 'nct1008'
+    Addresses scanned: I2C 0x4c and 0x4d
+    Datasheet: Publicly available at the ON Semiconductor website
+               http://www.onsemi.com/PowerSolutions/product.do?id=NCT1008
   * Maxim MAX6646
     Prefix: 'max6646'
     Addresses scanned: I2C 0x4d
@@ -149,7 +159,7 @@ ADM1032:
   * ALERT is triggered by open remote sensor.
   * SMBus PEC support for Write Byte and Receive Byte transactions.
 
-ADT7461:
+ADT7461, ADT7461A, NCT1008:
   * Extended temperature range (breaks compatibility)
   * Lower resolution for remote temperature
 
@@ -195,9 +205,9 @@ are exported, one for each channel, but these values are of course linked.
 Only the local hysteresis can be set from user-space, and the same delta
 applies to the remote hysteresis.
 
-The lm90 driver will not update its values more frequently than every
-other second; reading them more often will do no harm, but will return
-'old' values.
+The lm90 driver will not update its values more frequently than configured with
+the update_interval attribute; reading them more often will do no harm, but will
+return 'old' values.
 
 SMBus Alert Support
 -------------------
@@ -205,11 +215,12 @@ SMBus Alert Support
 This driver has basic support for SMBus alert. When an alert is received,
 the status register is read and the faulty temperature channel is logged.
 
-The Analog Devices chips (ADM1032 and ADT7461) do not implement the SMBus
-alert protocol properly so additional care is needed: the ALERT output is
-disabled when an alert is received, and is re-enabled only when the alarm
-is gone. Otherwise the chip would block alerts from other chips in the bus
-as long as the alarm is active.
+The Analog Devices chips (ADM1032, ADT7461 and ADT7461A) and ON
+Semiconductor chips (NCT1008) do not implement the SMBus alert protocol
+properly so additional care is needed: the ALERT output is disabled when
+an alert is received, and is re-enabled only when the alarm is gone.
+Otherwise the chip would block alerts from other chips in the bus as long
+as the alarm is active.
 
 PEC Support
 -----------
index cb47e72..1e96ce6 100644 (file)
@@ -37,7 +37,7 @@ Generic scaling / cropping scheme
 -1'-
 
 In the above chart minuses and slashes represent "real" data amounts, points and
-accents represent "useful" data, basically, CEU scaled amd cropped output,
+accents represent "useful" data, basically, CEU scaled and cropped output,
 mapped back onto the client's source plane.
 
 Such a configuration can be produced by user requests:
@@ -65,7 +65,7 @@ Do not touch input rectangle - it is already optimal.
 
 1. Calculate current sensor scales:
 
-       scale_s = ((3') - (3)) / ((2') - (2))
+       scale_s = ((2') - (2)) / ((3') - (3))
 
 2. Calculate "effective" input crop (sensor subwindow) - CEU crop scaled back at
 current sensor scales onto input window - this is user S_CROP:
@@ -80,7 +80,7 @@ window:
 4. Calculate sensor output window by applying combined scales to real input
 window:
 
-       width_s_out = ((2') - (2)) / scale_comb
+       width_s_out = ((7') - (7)) = ((2') - (2)) / scale_comb
 
 5. Apply iterative sensor S_FMT for sensor output window.
 
index 01c513f..a0b577d 100644 (file)
@@ -12,6 +12,7 @@ CONTENTS
 4. Application Programming Interface (API)
 5. Example Execution Scenarios
 6. Guidelines
+7. Debugging
 
 
 1. Introduction
@@ -379,3 +380,42 @@ If q1 has WQ_CPU_INTENSIVE set,
 * Unless work items are expected to consume a huge amount of CPU
   cycles, using a bound wq is usually beneficial due to the increased
   level of locality in wq operations and work item execution.
+
+
+7. Debugging
+
+Because the work functions are executed by generic worker threads
+there are a few tricks needed to shed some light on misbehaving
+workqueue users.
+
+Worker threads show up in the process list as:
+
+root      5671  0.0  0.0      0     0 ?        S    12:07   0:00 [kworker/0:1]
+root      5672  0.0  0.0      0     0 ?        S    12:07   0:00 [kworker/1:2]
+root      5673  0.0  0.0      0     0 ?        S    12:12   0:00 [kworker/0:0]
+root      5674  0.0  0.0      0     0 ?        S    12:13   0:00 [kworker/1:0]
+
+If kworkers are going crazy (using too much cpu), there are two types
+of possible problems:
+
+       1. Something beeing scheduled in rapid succession
+       2. A single work item that consumes lots of cpu cycles
+
+The first one can be tracked using tracing:
+
+       $ echo workqueue:workqueue_queue_work > /sys/kernel/debug/tracing/set_event
+       $ cat /sys/kernel/debug/tracing/trace_pipe > out.txt
+       (wait a few secs)
+       ^C
+
+If something is busy looping on work queueing, it would be dominating
+the output and the offender can be determined with the work item
+function.
+
+For the second type of problems it should be possible to just check
+the stack trace of the offending worker thread.
+
+       $ cat /proc/THE_OFFENDING_KWORKER/stack
+
+The work item's function should be trivially visible in the stack
+trace.
index 1380312..16a5c5f 100644 (file)
@@ -1032,12 +1032,13 @@ W:      http://www.fluff.org/ben/linux/
 S:     Maintained
 F:     arch/arm/mach-s3c64xx/
 
-ARM/S5P ARM ARCHITECTURES
+ARM/S5P EXYNOS ARM ARCHITECTURES
 M:     Kukjin Kim <kgene.kim@samsung.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
 S:     Maintained
 F:     arch/arm/mach-s5p*/
+F:     arch/arm/mach-exynos*/
 
 ARM/SAMSUNG MOBILE MACHINE SUPPORT
 M:     Kyungmin Park <kyungmin.park@samsung.com>
@@ -2808,7 +2809,7 @@ GPIO SUBSYSTEM
 M:     Grant Likely <grant.likely@secretlab.ca>
 S:     Maintained
 T:     git git://git.secretlab.ca/git/linux-2.6.git
-F:     Documentation/gpio/gpio.txt
+F:     Documentation/gpio.txt
 F:     drivers/gpio/
 F:     include/linux/gpio*
 
@@ -6555,7 +6556,7 @@ S:        Maintained
 F:     drivers/usb/host/uhci*
 
 USB "USBNET" DRIVER FRAMEWORK
-M:     David Brownell <dbrownell@users.sourceforge.net>
+M:     Oliver Neukum <oneukum@suse.de>
 L:     netdev@vger.kernel.org
 W:     http://www.linux-usb.org/usbnet
 S:     Maintained
@@ -6921,6 +6922,18 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.
 S:     Maintained
 F:     drivers/platform/x86
 
+XEN HYPERVISOR INTERFACE
+M:     Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
+M:     Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+L:     xen-devel@lists.xensource.com (moderated for non-subscribers)
+L:     virtualization@lists.linux-foundation.org
+S:     Supported
+F:     arch/x86/xen/
+F:     drivers/*/xen-*front.c
+F:     drivers/xen/
+F:     arch/x86/include/asm/xen/
+F:     include/xen/
+
 XEN NETWORK BACKEND DRIVER
 M:     Ian Campbell <ian.campbell@citrix.com>
 L:     xen-devel@lists.xensource.com (moderated for non-subscribers)
@@ -6942,18 +6955,6 @@ S:       Supported
 F:     arch/x86/xen/*swiotlb*
 F:     drivers/xen/*swiotlb*
 
-XEN HYPERVISOR INTERFACE
-M:     Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
-M:     Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
-L:     xen-devel@lists.xensource.com (moderated for non-subscribers)
-L:     virtualization@lists.linux-foundation.org
-S:     Supported
-F:     arch/x86/xen/
-F:     drivers/*/xen-*front.c
-F:     drivers/xen/
-F:     arch/x86/include/asm/xen/
-F:     include/xen/
-
 XFS FILESYSTEM
 P:     Silicon Graphics Inc
 M:     Alex Elder <aelder@sgi.com>
index b967b96..28820f7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 39
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc6
 NAME = Flesh-Eating Bats with Fangs
 
 # *DOCUMENTATION*
index bb8a19b..e46bdd0 100644 (file)
@@ -39,10 +39,13 @@ typedef u32 kprobe_opcode_t;
 struct kprobe;
 typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *);
 
+typedef unsigned long (kprobe_check_cc)(unsigned long);
+
 /* Architecture specific copy of original instruction. */
 struct arch_specific_insn {
        kprobe_opcode_t         *insn;
        kprobe_insn_handler_t   *insn_handler;
+       kprobe_check_cc         *insn_check_cc;
 };
 
 struct prev_kprobe {
index 2389131..15eeff6 100644 (file)
@@ -34,9 +34,6 @@
  *
  *   *) If the PC is written to by the instruction, the
  *      instruction must be fully simulated in software.
- *      If it is a conditional instruction, the handler
- *      will use insn[0] to copy its condition code to
- *     set r0 to 1 and insn[1] to "mov pc, lr" to return.
  *
  *   *) Otherwise, a modified form of the instruction is
  *      directly executed.  Its handler calls the
 
 #define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
 
+#define is_r15(insn, bitpos) (((insn) & (0xf << bitpos)) == (0xf << bitpos))
+
+/*
+ * Test if load/store instructions writeback the address register.
+ * if P (bit 24) == 0 or W (bit 21) == 1
+ */
+#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)
+
 #define PSR_fs (PSR_f|PSR_s)
 
 #define KPROBE_RETURN_INSTRUCTION      0xe1a0f00e      /* mov pc, lr */
-#define SET_R0_TRUE_INSTRUCTION                0xe3a00001      /* mov  r0, #1 */
-
-#define        truecc_insn(insn)       (((insn) & 0xf0000000) | \
-                                (SET_R0_TRUE_INSTRUCTION & 0x0fffffff))
 
 typedef long (insn_0arg_fn_t)(void);
 typedef long (insn_1arg_fn_t)(long);
@@ -419,14 +420,10 @@ insnslot_llret_4arg_rwflags(long r0, long r1, long r2, long r3, long *cpsr,
 
 static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
 {
-       insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
        kprobe_opcode_t insn = p->opcode;
        long iaddr = (long)p->addr;
        int disp  = branch_displacement(insn);
 
-       if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
-               return;
-
        if (insn & (1 << 24))
                regs->ARM_lr = iaddr + 4;
 
@@ -446,14 +443,10 @@ static void __kprobes simulate_blx1(struct kprobe *p, struct pt_regs *regs)
 
 static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
 {
-       insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
        kprobe_opcode_t insn = p->opcode;
        int rm = insn & 0xf;
        long rmv = regs->uregs[rm];
 
-       if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
-               return;
-
        if (insn & (1 << 5))
                regs->ARM_lr = (long)p->addr + 4;
 
@@ -463,9 +456,16 @@ static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
                regs->ARM_cpsr |= PSR_T_BIT;
 }
 
+static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
+{
+       kprobe_opcode_t insn = p->opcode;
+       int rd = (insn >> 12) & 0xf;
+       unsigned long mask = 0xf8ff03df; /* Mask out execution state */
+       regs->uregs[rd] = regs->ARM_cpsr & mask;
+}
+
 static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
 {
-       insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
        kprobe_opcode_t insn = p->opcode;
        int rn = (insn >> 16) & 0xf;
        int lbit = insn & (1 << 20);
@@ -476,9 +476,6 @@ static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
        int reg_bit_vector;
        int reg_count;
 
-       if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
-               return;
-
        reg_count = 0;
        reg_bit_vector = insn & 0xffff;
        while (reg_bit_vector) {
@@ -510,11 +507,6 @@ static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
 
 static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
 {
-       insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
-
-       if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
-               return;
-
        regs->ARM_pc = (long)p->addr + str_pc_offset;
        simulate_ldm1stm1(p, regs);
        regs->ARM_pc = (long)p->addr + 4;
@@ -525,24 +517,16 @@ static void __kprobes simulate_mov_ipsp(struct kprobe *p, struct pt_regs *regs)
        regs->uregs[12] = regs->uregs[13];
 }
 
-static void __kprobes emulate_ldcstc(struct kprobe *p, struct pt_regs *regs)
-{
-       insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
-       kprobe_opcode_t insn = p->opcode;
-       int rn = (insn >> 16) & 0xf;
-       long rnv = regs->uregs[rn];
-
-       /* Save Rn in case of writeback. */
-       regs->uregs[rn] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
-}
-
 static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
 {
        insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
        kprobe_opcode_t insn = p->opcode;
+       long ppc = (long)p->addr + 8;
        int rd = (insn >> 12) & 0xf;
        int rn = (insn >> 16) & 0xf;
        int rm = insn & 0xf;  /* rm may be invalid, don't care. */
+       long rmv = (rm == 15) ? ppc : regs->uregs[rm];
+       long rnv = (rn == 15) ? ppc : regs->uregs[rn];
 
        /* Not following the C calling convention here, so need asm(). */
        __asm__ __volatile__ (
@@ -554,29 +538,36 @@ static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
                "str    r0, %[rn]       \n\t"   /* in case of writeback */
                "str    r2, %[rd0]      \n\t"
                "str    r3, %[rd1]      \n\t"
-               : [rn]  "+m" (regs->uregs[rn]),
+               : [rn]  "+m" (rnv),
                  [rd0] "=m" (regs->uregs[rd]),
                  [rd1] "=m" (regs->uregs[rd+1])
-               : [rm]   "m" (regs->uregs[rm]),
+               : [rm]   "m" (rmv),
                  [cpsr] "r" (regs->ARM_cpsr),
                  [i_fn] "r" (i_fn)
                : "r0", "r1", "r2", "r3", "lr", "cc"
        );
+       if (is_writeback(insn))
+               regs->uregs[rn] = rnv;
 }
 
 static void __kprobes emulate_strd(struct kprobe *p, struct pt_regs *regs)
 {
        insn_4arg_fn_t *i_fn = (insn_4arg_fn_t *)&p->ainsn.insn[0];
        kprobe_opcode_t insn = p->opcode;
+       long ppc = (long)p->addr + 8;
        int rd = (insn >> 12) & 0xf;
        int rn = (insn >> 16) & 0xf;
        int rm  = insn & 0xf;
-       long rnv = regs->uregs[rn];
-       long rmv = regs->uregs[rm];  /* rm/rmv may be invalid, don't care. */
+       long rnv = (rn == 15) ? ppc : regs->uregs[rn];
+       /* rm/rmv may be invalid, don't care. */
+       long rmv = (rm == 15) ? ppc : regs->uregs[rm];
+       long rnv_wb;
 
-       regs->uregs[rn] = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd],
+       rnv_wb = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd],
                                               regs->uregs[rd+1],
                                               regs->ARM_cpsr, i_fn);
+       if (is_writeback(insn))
+               regs->uregs[rn] = rnv_wb;
 }
 
 static void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs)
@@ -630,31 +621,6 @@ static void __kprobes emulate_str(struct kprobe *p, struct pt_regs *regs)
                regs->uregs[rn] = rnv_wb;  /* Save Rn in case of writeback. */
 }
 
-static void __kprobes emulate_mrrc(struct kprobe *p, struct pt_regs *regs)
-{
-       insn_llret_0arg_fn_t *i_fn = (insn_llret_0arg_fn_t *)&p->ainsn.insn[0];
-       kprobe_opcode_t insn = p->opcode;
-       union reg_pair fnr;
-       int rd = (insn >> 12) & 0xf;
-       int rn = (insn >> 16) & 0xf;
-
-       fnr.dr = insnslot_llret_0arg_rflags(regs->ARM_cpsr, i_fn);
-       regs->uregs[rn] = fnr.r0;
-       regs->uregs[rd] = fnr.r1;
-}
-
-static void __kprobes emulate_mcrr(struct kprobe *p, struct pt_regs *regs)
-{
-       insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
-       kprobe_opcode_t insn = p->opcode;
-       int rd = (insn >> 12) & 0xf;
-       int rn = (insn >> 16) & 0xf;
-       long rnv = regs->uregs[rn];
-       long rdv = regs->uregs[rd];
-
-       insnslot_2arg_rflags(rnv, rdv, regs->ARM_cpsr, i_fn);
-}
-
 static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs)
 {
        insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
@@ -688,32 +654,32 @@ static void __kprobes emulate_none(struct kprobe *p, struct pt_regs *regs)
        insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
 }
 
-static void __kprobes emulate_rd12(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes emulate_nop(struct kprobe *p, struct pt_regs *regs)
 {
-       insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0];
-       kprobe_opcode_t insn = p->opcode;
-       int rd = (insn >> 12) & 0xf;
-
-       regs->uregs[rd] = insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
 }
 
-static void __kprobes emulate_ird12(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+emulate_rd12_modify(struct kprobe *p, struct pt_regs *regs)
 {
        insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
        kprobe_opcode_t insn = p->opcode;
-       int ird = (insn >> 12) & 0xf;
+       int rd = (insn >> 12) & 0xf;
+       long rdv = regs->uregs[rd];
 
-       insnslot_1arg_rflags(regs->uregs[ird], regs->ARM_cpsr, i_fn);
+       regs->uregs[rd] = insnslot_1arg_rflags(rdv, regs->ARM_cpsr, i_fn);
 }
 
-static void __kprobes emulate_rn16(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+emulate_rd12rn0_modify(struct kprobe *p, struct pt_regs *regs)
 {
-       insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
+       insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
        kprobe_opcode_t insn = p->opcode;
-       int rn = (insn >> 16) & 0xf;
+       int rd = (insn >> 12) & 0xf;
+       int rn = insn & 0xf;
+       long rdv = regs->uregs[rd];
        long rnv = regs->uregs[rn];
 
-       insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
+       regs->uregs[rd] = insnslot_2arg_rflags(rdv, rnv, regs->ARM_cpsr, i_fn);
 }
 
 static void __kprobes emulate_rd12rm0(struct kprobe *p, struct pt_regs *regs)
@@ -818,6 +784,17 @@ emulate_alu_imm_rwflags(struct kprobe *p, struct pt_regs *regs)
        regs->uregs[rd] = insnslot_1arg_rwflags(rnv, &regs->ARM_cpsr, i_fn);
 }
 
+static void __kprobes
+emulate_alu_tests_imm(struct kprobe *p, struct pt_regs *regs)
+{
+       insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
+       kprobe_opcode_t insn = p->opcode;
+       int rn = (insn >> 16) & 0xf;
+       long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
+
+       insnslot_1arg_rwflags(rnv, &regs->ARM_cpsr, i_fn);
+}
+
 static void __kprobes
 emulate_alu_rflags(struct kprobe *p, struct pt_regs *regs)
 {
@@ -854,14 +831,34 @@ emulate_alu_rwflags(struct kprobe *p, struct pt_regs *regs)
                insnslot_3arg_rwflags(rnv, rmv, rsv, &regs->ARM_cpsr, i_fn);
 }
 
+static void __kprobes
+emulate_alu_tests(struct kprobe *p, struct pt_regs *regs)
+{
+       insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
+       kprobe_opcode_t insn = p->opcode;
+       long ppc = (long)p->addr + 8;
+       int rn = (insn >> 16) & 0xf;
+       int rs = (insn >> 8) & 0xf;     /* rs/rsv may be invalid, don't care. */
+       int rm = insn & 0xf;
+       long rnv = (rn == 15) ? ppc : regs->uregs[rn];
+       long rmv = (rm == 15) ? ppc : regs->uregs[rm];
+       long rsv = regs->uregs[rs];
+
+       insnslot_3arg_rwflags(rnv, rmv, rsv, &regs->ARM_cpsr, i_fn);
+}
+
 static enum kprobe_insn __kprobes
 prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
-       int ibit = (insn & (1 << 26)) ? 25 : 22;
+       int not_imm = (insn & (1 << 26)) ? (insn & (1 << 25))
+                                        : (~insn & (1 << 22));
+
+       if (is_writeback(insn) && is_r15(insn, 16))
+               return INSN_REJECTED;   /* Writeback to PC */
 
        insn &= 0xfff00fff;
        insn |= 0x00001000;     /* Rn = r0, Rd = r1 */
-       if (insn & (1 << ibit)) {
+       if (not_imm) {
                insn &= ~0xf;
                insn |= 2;      /* Rm = r2 */
        }
@@ -871,20 +868,40 @@ prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 }
 
 static enum kprobe_insn __kprobes
-prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+prep_emulate_rd12_modify(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
-       insn &= 0xffff0ff0;     /* Rd = r0, Rm = r0 */
+       if (is_r15(insn, 12))
+               return INSN_REJECTED;   /* Rd is PC */
+
+       insn &= 0xffff0fff;     /* Rd = r0 */
        asi->insn[0] = insn;
-       asi->insn_handler = emulate_rd12rm0;
+       asi->insn_handler = emulate_rd12_modify;
        return INSN_GOOD;
 }
 
 static enum kprobe_insn __kprobes
-prep_emulate_rd12(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+prep_emulate_rd12rn0_modify(kprobe_opcode_t insn,
+                           struct arch_specific_insn *asi)
 {
-       insn &= 0xffff0fff;     /* Rd = r0 */
+       if (is_r15(insn, 12))
+               return INSN_REJECTED;   /* Rd is PC */
+
+       insn &= 0xffff0ff0;     /* Rd = r0 */
+       insn |= 0x00000001;     /* Rn = r1 */
+       asi->insn[0] = insn;
+       asi->insn_handler = emulate_rd12rn0_modify;
+       return INSN_GOOD;
+}
+
+static enum kprobe_insn __kprobes
+prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+       if (is_r15(insn, 12))
+               return INSN_REJECTED;   /* Rd is PC */
+
+       insn &= 0xffff0ff0;     /* Rd = r0, Rm = r0 */
        asi->insn[0] = insn;
-       asi->insn_handler = emulate_rd12;
+       asi->insn_handler = emulate_rd12rm0;
        return INSN_GOOD;
 }
 
@@ -892,6 +909,9 @@ static enum kprobe_insn __kprobes
 prep_emulate_rd12rn16rm0_wflags(kprobe_opcode_t insn,
                                struct arch_specific_insn *asi)
 {
+       if (is_r15(insn, 12))
+               return INSN_REJECTED;   /* Rd is PC */
+
        insn &= 0xfff00ff0;     /* Rd = r0, Rn = r0 */
        insn |= 0x00000001;     /* Rm = r1 */
        asi->insn[0] = insn;
@@ -903,6 +923,9 @@ static enum kprobe_insn __kprobes
 prep_emulate_rd16rs8rm0_wflags(kprobe_opcode_t insn,
                               struct arch_specific_insn *asi)
 {
+       if (is_r15(insn, 16))
+               return INSN_REJECTED;   /* Rd is PC */
+
        insn &= 0xfff0f0f0;     /* Rd = r0, Rs = r0 */
        insn |= 0x00000001;     /* Rm = r1          */
        asi->insn[0] = insn;
@@ -914,6 +937,9 @@ static enum kprobe_insn __kprobes
 prep_emulate_rd16rn12rs8rm0_wflags(kprobe_opcode_t insn,
                                   struct arch_specific_insn *asi)
 {
+       if (is_r15(insn, 16))
+               return INSN_REJECTED;   /* Rd is PC */
+
        insn &= 0xfff000f0;     /* Rd = r0, Rn = r0 */
        insn |= 0x00000102;     /* Rs = r1, Rm = r2 */
        asi->insn[0] = insn;
@@ -925,6 +951,9 @@ static enum kprobe_insn __kprobes
 prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn,
                                       struct arch_specific_insn *asi)
 {
+       if (is_r15(insn, 16) || is_r15(insn, 12))
+               return INSN_REJECTED;   /* RdHi or RdLo is PC */
+
        insn &= 0xfff000f0;     /* RdHi = r0, RdLo = r1 */
        insn |= 0x00001203;     /* Rs = r2, Rm = r3 */
        asi->insn[0] = insn;
@@ -945,20 +974,13 @@ prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn,
 static enum kprobe_insn __kprobes
 space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
-       /* CPS mmod == 1 : 1111 0001 0000 xx10 xxxx xxxx xx0x xxxx */
-       /* RFE           : 1111 100x x0x1 xxxx xxxx 1010 xxxx xxxx */
-       /* SRS           : 1111 100x x1x0 1101 xxxx 0101 xxxx xxxx */
-       if ((insn & 0xfff30020) == 0xf1020000 ||
-           (insn & 0xfe500f00) == 0xf8100a00 ||
-           (insn & 0xfe5f0f00) == 0xf84d0500)
-               return INSN_REJECTED;
-
-       /* PLD : 1111 01x1 x101 xxxx xxxx xxxx xxxx xxxx : */
-       if ((insn & 0xfd700000) == 0xf4500000) {
-               insn &= 0xfff0ffff;     /* Rn = r0 */
-               asi->insn[0] = insn;
-               asi->insn_handler = emulate_rn16;
-               return INSN_GOOD;
+       /* memory hint : 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx : */
+       /* PLDI        : 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx : */
+       /* PLDW        : 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx : */
+       /* PLD         : 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx : */
+       if ((insn & 0xfe300000) == 0xf4100000) {
+               asi->insn_handler = emulate_nop;
+               return INSN_GOOD_NO_SLOT;
        }
 
        /* BLX(1) : 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx : */
@@ -967,41 +989,22 @@ space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi)
                return INSN_GOOD_NO_SLOT;
        }
 
-       /* SETEND : 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
-       /* CDP2   : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
-       if ((insn & 0xffff00f0) == 0xf1010000 ||
-           (insn & 0xff000010) == 0xfe000000) {
-               asi->insn[0] = insn;
-               asi->insn_handler = emulate_none;
-               return INSN_GOOD;
-       }
+       /* CPS   : 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */
+       /* SETEND: 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
 
+       /* SRS   : 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
+       /* RFE   : 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
+
+       /* Coprocessor instructions... */
        /* MCRR2 : 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
        /* MRRC2 : 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
-       if ((insn & 0xffe00000) == 0xfc400000) {
-               insn &= 0xfff00fff;     /* Rn = r0 */
-               insn |= 0x00001000;     /* Rd = r1 */
-               asi->insn[0] = insn;
-               asi->insn_handler =
-                       (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr;
-               return INSN_GOOD;
-       }
+       /* LDC2  : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
+       /* STC2  : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
+       /* CDP2  : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
+       /* MCR2  : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
+       /* MRC2  : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
 
-       /* LDC2 : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
-       /* STC2 : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
-       if ((insn & 0xfe000000) == 0xfc000000) {
-               insn &= 0xfff0ffff;      /* Rn = r0 */
-               asi->insn[0] = insn;
-               asi->insn_handler = emulate_ldcstc;
-               return INSN_GOOD;
-       }
-
-       /* MCR2 : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
-       /* MRC2 : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
-       insn &= 0xffff0fff;     /* Rd = r0 */
-       asi->insn[0]      = insn;
-       asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12;
-       return INSN_GOOD;
+       return INSN_REJECTED;
 }
 
 static enum kprobe_insn __kprobes
@@ -1010,19 +1013,18 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
        /* cccc 0001 0xx0 xxxx xxxx xxxx xxxx xxx0 xxxx */
        if ((insn & 0x0f900010) == 0x01000000) {
 
-               /* BXJ  : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
-               /* MSR  : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
-               if ((insn & 0x0ff000f0) == 0x01200020 ||
-                   (insn & 0x0fb000f0) == 0x01200000)
-                       return INSN_REJECTED;
-
-               /* MRS : cccc 0001 0x00 xxxx xxxx xxxx 0000 xxxx */
-               if ((insn & 0x0fb00010) == 0x01000000)
-                       return prep_emulate_rd12(insn, asi);
+               /* MRS cpsr : cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
+               if ((insn & 0x0ff000f0) == 0x01000000) {
+                       if (is_r15(insn, 12))
+                               return INSN_REJECTED;   /* Rd is PC */
+                       asi->insn_handler = simulate_mrs;
+                       return INSN_GOOD_NO_SLOT;
+               }
 
                /* SMLALxy : cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
                if ((insn & 0x0ff00090) == 0x01400080)
-                       return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
+                       return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn,
+                                                                       asi);
 
                /* SMULWy : cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
                /* SMULxy : cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
@@ -1031,24 +1033,29 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
                        return prep_emulate_rd16rs8rm0_wflags(insn, asi);
 
                /* SMLAxy : cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx : Q */
-               /* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 0x00 xxxx : Q */
-               return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
+               /* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx : Q */
+               if ((insn & 0x0ff00090) == 0x01000080 ||
+                   (insn & 0x0ff000b0) == 0x01200080)
+                       return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
+
+               /* BXJ      : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
+               /* MSR      : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
+               /* MRS spsr : cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */
 
+               /* Other instruction encodings aren't yet defined */
+               return INSN_REJECTED;
        }
 
        /* cccc 0001 0xx0 xxxx xxxx xxxx xxxx 0xx1 xxxx */
        else if ((insn & 0x0f900090) == 0x01000010) {
 
-               /* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
-               if ((insn & 0xfff000f0) == 0xe1200070)
-                       return INSN_REJECTED;
-
                /* BLX(2) : cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
                /* BX     : cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
                if ((insn & 0x0ff000d0) == 0x01200010) {
-                       asi->insn[0] = truecc_insn(insn);
+                       if ((insn & 0x0ff000ff) == 0x0120003f)
+                               return INSN_REJECTED; /* BLX pc */
                        asi->insn_handler = simulate_blx2bx;
-                       return INSN_GOOD;
+                       return INSN_GOOD_NO_SLOT;
                }
 
                /* CLZ : cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
@@ -1059,17 +1066,27 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
                /* QSUB    : cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx :Q */
                /* QDADD   : cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx :Q */
                /* QDSUB   : cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx :Q */
-               return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+               if ((insn & 0x0f9000f0) == 0x01000050)
+                       return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+
+               /* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
+               /* SMC  : cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */
+
+               /* Other instruction encodings aren't yet defined */
+               return INSN_REJECTED;
        }
 
        /* cccc 0000 xxxx xxxx xxxx xxxx xxxx 1001 xxxx */
-       else if ((insn & 0x0f000090) == 0x00000090) {
+       else if ((insn & 0x0f0000f0) == 0x00000090) {
 
                /* MUL    : cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx :   */
                /* MULS   : cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx :cc */
                /* MLA    : cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx :   */
                /* MLAS   : cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx :cc */
                /* UMAAL  : cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx :   */
+               /* undef  : cccc 0000 0101 xxxx xxxx xxxx 1001 xxxx :   */
+               /* MLS    : cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx :   */
+               /* undef  : cccc 0000 0111 xxxx xxxx xxxx 1001 xxxx :   */
                /* UMULL  : cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx :   */
                /* UMULLS : cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx :cc */
                /* UMLAL  : cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx :   */
@@ -1078,13 +1095,15 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
                /* SMULLS : cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx :cc */
                /* SMLAL  : cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx :   */
                /* SMLALS : cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx :cc */
-               if ((insn & 0x0fe000f0) == 0x00000090) {
-                      return prep_emulate_rd16rs8rm0_wflags(insn, asi);
-               } else if  ((insn & 0x0fe000f0) == 0x00200090) {
-                      return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
-               } else {
-                      return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
-               }
+               if ((insn & 0x00d00000) == 0x00500000)
+                       return INSN_REJECTED;
+               else if ((insn & 0x00e00000) == 0x00000000)
+                       return prep_emulate_rd16rs8rm0_wflags(insn, asi);
+               else if ((insn & 0x00a00000) == 0x00200000)
+                       return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
+               else
+                       return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn,
+                                                                       asi);
        }
 
        /* cccc 000x xxxx xxxx xxxx xxxx xxxx 1xx1 xxxx */
@@ -1092,23 +1111,45 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 
                /* SWP   : cccc 0001 0000 xxxx xxxx xxxx 1001 xxxx */
                /* SWPB  : cccc 0001 0100 xxxx xxxx xxxx 1001 xxxx */
-               /* LDRD  : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */
-               /* STRD  : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */
+               /* ???   : cccc 0001 0x01 xxxx xxxx xxxx 1001 xxxx */
+               /* ???   : cccc 0001 0x10 xxxx xxxx xxxx 1001 xxxx */
+               /* ???   : cccc 0001 0x11 xxxx xxxx xxxx 1001 xxxx */
                /* STREX : cccc 0001 1000 xxxx xxxx xxxx 1001 xxxx */
                /* LDREX : cccc 0001 1001 xxxx xxxx xxxx 1001 xxxx */
+               /* STREXD: cccc 0001 1010 xxxx xxxx xxxx 1001 xxxx */
+               /* LDREXD: cccc 0001 1011 xxxx xxxx xxxx 1001 xxxx */
+               /* STREXB: cccc 0001 1100 xxxx xxxx xxxx 1001 xxxx */
+               /* LDREXB: cccc 0001 1101 xxxx xxxx xxxx 1001 xxxx */
+               /* STREXH: cccc 0001 1110 xxxx xxxx xxxx 1001 xxxx */
+               /* LDREXH: cccc 0001 1111 xxxx xxxx xxxx 1001 xxxx */
+
+               /* LDRD  : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */
+               /* STRD  : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */
                /* LDRH  : cccc 000x xxx1 xxxx xxxx xxxx 1011 xxxx */
                /* STRH  : cccc 000x xxx0 xxxx xxxx xxxx 1011 xxxx */
                /* LDRSB : cccc 000x xxx1 xxxx xxxx xxxx 1101 xxxx */
                /* LDRSH : cccc 000x xxx1 xxxx xxxx xxxx 1111 xxxx */
-               if ((insn & 0x0fb000f0) == 0x01000090) {
-                       /* SWP/SWPB */
-                       return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+               if ((insn & 0x0f0000f0) == 0x01000090) {
+                       if ((insn & 0x0fb000f0) == 0x01000090) {
+                               /* SWP/SWPB */
+                               return prep_emulate_rd12rn16rm0_wflags(insn,
+                                                                       asi);
+                       } else {
+                               /* STREX/LDREX variants and unallocaed space */
+                               return INSN_REJECTED;
+                       }
+
                } else if ((insn & 0x0e1000d0) == 0x00000d0) {
                        /* STRD/LDRD */
+                       if ((insn & 0x0000e000) == 0x0000e000)
+                               return INSN_REJECTED;   /* Rd is LR or PC */
+                       if (is_writeback(insn) && is_r15(insn, 16))
+                               return INSN_REJECTED;   /* Writeback to PC */
+
                        insn &= 0xfff00fff;
                        insn |= 0x00002000;     /* Rn = r0, Rd = r2 */
-                       if (insn & (1 << 22)) {
-                               /* I bit */
+                       if (!(insn & (1 << 22))) {
+                               /* Register index */
                                insn &= ~0xf;
                                insn |= 1;      /* Rm = r1 */
                        }
@@ -1118,6 +1159,9 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
                        return INSN_GOOD;
                }
 
+               /* LDRH/STRH/LDRSB/LDRSH */
+               if (is_r15(insn, 12))
+                       return INSN_REJECTED;   /* Rd is PC */
                return prep_emulate_ldr_str(insn, asi);
        }
 
@@ -1125,7 +1169,7 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 
        /*
         * ALU op with S bit and Rd == 15 :
-        *      cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx
+        *      cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx
         */
        if ((insn & 0x0e10f000) == 0x0010f000)
                return INSN_REJECTED;
@@ -1154,22 +1198,61 @@ space_cccc_000x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
                insn |= 0x00000200;     /* Rs = r2 */
        }
        asi->insn[0] = insn;
-       asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
+
+       if ((insn & 0x0f900000) == 0x01100000) {
+               /*
+                * TST : cccc 0001 0001 xxxx xxxx xxxx xxxx xxxx
+                * TEQ : cccc 0001 0011 xxxx xxxx xxxx xxxx xxxx
+                * CMP : cccc 0001 0101 xxxx xxxx xxxx xxxx xxxx
+                * CMN : cccc 0001 0111 xxxx xxxx xxxx xxxx xxxx
+                */
+               asi->insn_handler = emulate_alu_tests;
+       } else {
+               /* ALU ops which write to Rd */
+               asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
                                emulate_alu_rwflags : emulate_alu_rflags;
+       }
        return INSN_GOOD;
 }
 
 static enum kprobe_insn __kprobes
 space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
+       /* MOVW  : cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */
+       /* MOVT  : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */
+       if ((insn & 0x0fb00000) == 0x03000000)
+               return prep_emulate_rd12_modify(insn, asi);
+
+       /* hints : cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */
+       if ((insn & 0x0fff0000) == 0x03200000) {
+               unsigned op2 = insn & 0x000000ff;
+               if (op2 == 0x01 || op2 == 0x04) {
+                       /* YIELD : cccc 0011 0010 0000 xxxx xxxx 0000 0001 */
+                       /* SEV   : cccc 0011 0010 0000 xxxx xxxx 0000 0100 */
+                       asi->insn[0] = insn;
+                       asi->insn_handler = emulate_none;
+                       return INSN_GOOD;
+               } else if (op2 <= 0x03) {
+                       /* NOP   : cccc 0011 0010 0000 xxxx xxxx 0000 0000 */
+                       /* WFE   : cccc 0011 0010 0000 xxxx xxxx 0000 0010 */
+                       /* WFI   : cccc 0011 0010 0000 xxxx xxxx 0000 0011 */
+                       /*
+                        * We make WFE and WFI true NOPs to avoid stalls due
+                        * to missing events whilst processing the probe.
+                        */
+                       asi->insn_handler = emulate_nop;
+                       return INSN_GOOD_NO_SLOT;
+               }
+               /* For DBG and unallocated hints it's safest to reject them */
+               return INSN_REJECTED;
+       }
+
        /*
         * MSR   : cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx
-        * Undef : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx
         * ALU op with S bit and Rd == 15 :
         *         cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx
         */
        if ((insn & 0x0fb00000) == 0x03200000 ||        /* MSR */
-           (insn & 0x0ff00000) == 0x03400000 ||        /* Undef */
            (insn & 0x0e10f000) == 0x0210f000)          /* ALU s-bit, R15  */
                return INSN_REJECTED;
 
@@ -1180,10 +1263,22 @@ space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
         * *S (bit 20) updates condition codes
         * ADC/SBC/RSC reads the C flag
         */
-       insn &= 0xffff0fff;     /* Rd = r0 */
+       insn &= 0xfff00fff;     /* Rn = r0 and Rd = r0 */
        asi->insn[0] = insn;
-       asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
+
+       if ((insn & 0x0f900000) == 0x03100000) {
+               /*
+                * TST : cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx
+                * TEQ : cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx
+                * CMP : cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx
+                * CMN : cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx
+                */
+               asi->insn_handler = emulate_alu_tests_imm;
+       } else {
+               /* ALU ops which write to Rd */
+               asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
                        emulate_alu_imm_rwflags : emulate_alu_imm_rflags;
+       }
        return INSN_GOOD;
 }
 
@@ -1192,6 +1287,8 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
        /* SEL : cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx GE: !!! */
        if ((insn & 0x0ff000f0) == 0x068000b0) {
+               if (is_r15(insn, 12))
+                       return INSN_REJECTED;   /* Rd is PC */
                insn &= 0xfff00ff0;     /* Rd = r0, Rn = r0 */
                insn |= 0x00000001;     /* Rm = r1 */
                asi->insn[0] = insn;
@@ -1205,6 +1302,8 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
        /* USAT16 : cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx :Q */
        if ((insn & 0x0fa00030) == 0x06a00010 ||
            (insn & 0x0fb000f0) == 0x06a00030) {
+               if (is_r15(insn, 12))
+                       return INSN_REJECTED;   /* Rd is PC */
                insn &= 0xffff0ff0;     /* Rd = r0, Rm = r0 */
                asi->insn[0] = insn;
                asi->insn_handler = emulate_sat;
@@ -1213,57 +1312,101 @@ space_cccc_0110__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 
        /* REV    : cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */
        /* REV16  : cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */
+       /* RBIT   : cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */
        /* REVSH  : cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */
        if ((insn & 0x0ff00070) == 0x06b00030 ||
-           (insn & 0x0ff000f0) == 0x06f000b0)
+           (insn & 0x0ff00070) == 0x06f00030)
                return prep_emulate_rd12rm0(insn, asi);
 
+       /* ???       : cccc 0110 0000 xxxx xxxx xxxx xxx1 xxxx :   */
        /* SADD16    : cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx :GE */
        /* SADDSUBX  : cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx :GE */
        /* SSUBADDX  : cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx :GE */
        /* SSUB16    : cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx :GE */
        /* SADD8     : cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx :GE */
+       /* ???       : cccc 0110 0001 xxxx xxxx xxxx 1011 xxxx :   */
+       /* ???       : cccc 0110 0001 xxxx xxxx xxxx 1101 xxxx :   */
        /* SSUB8     : cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx :GE */
        /* QADD16    : cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx :   */
        /* QADDSUBX  : cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx :   */
        /* QSUBADDX  : cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx :   */
        /* QSUB16    : cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx :   */
        /* QADD8     : cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx :   */
+       /* ???       : cccc 0110 0010 xxxx xxxx xxxx 1011 xxxx :   */
+       /* ???       : cccc 0110 0010 xxxx xxxx xxxx 1101 xxxx :   */
        /* QSUB8     : cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx :   */
        /* SHADD16   : cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx :   */
        /* SHADDSUBX : cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx :   */
        /* SHSUBADDX : cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx :   */
        /* SHSUB16   : cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx :   */
        /* SHADD8    : cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx :   */
+       /* ???       : cccc 0110 0011 xxxx xxxx xxxx 1011 xxxx :   */
+       /* ???       : cccc 0110 0011 xxxx xxxx xxxx 1101 xxxx :   */
        /* SHSUB8    : cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx :   */
+       /* ???       : cccc 0110 0100 xxxx xxxx xxxx xxx1 xxxx :   */
        /* UADD16    : cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx :GE */
        /* UADDSUBX  : cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx :GE */
        /* USUBADDX  : cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx :GE */
        /* USUB16    : cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx :GE */
        /* UADD8     : cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx :GE */
+       /* ???       : cccc 0110 0101 xxxx xxxx xxxx 1011 xxxx :   */
+       /* ???       : cccc 0110 0101 xxxx xxxx xxxx 1101 xxxx :   */
        /* USUB8     : cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx :GE */
        /* UQADD16   : cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx :   */
        /* UQADDSUBX : cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx :   */
        /* UQSUBADDX : cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx :   */
        /* UQSUB16   : cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx :   */
        /* UQADD8    : cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx :   */
+       /* ???       : cccc 0110 0110 xxxx xxxx xxxx 1011 xxxx :   */
+       /* ???       : cccc 0110 0110 xxxx xxxx xxxx 1101 xxxx :   */
        /* UQSUB8    : cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx :   */
        /* UHADD16   : cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx :   */
        /* UHADDSUBX : cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx :   */
        /* UHSUBADDX : cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx :   */
        /* UHSUB16   : cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx :   */
        /* UHADD8    : cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx :   */
+       /* ???       : cccc 0110 0111 xxxx xxxx xxxx 1011 xxxx :   */
+       /* ???       : cccc 0110 0111 xxxx xxxx xxxx 1101 xxxx :   */
        /* UHSUB8    : cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx :   */
+       if ((insn & 0x0f800010) == 0x06000010) {
+               if ((insn & 0x00300000) == 0x00000000 ||
+                   (insn & 0x000000e0) == 0x000000a0 ||
+                   (insn & 0x000000e0) == 0x000000c0)
+                       return INSN_REJECTED;   /* Unallocated space */
+               return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+       }
+
        /* PKHBT     : cccc 0110 1000 xxxx xxxx xxxx x001 xxxx :   */
        /* PKHTB     : cccc 0110 1000 xxxx xxxx xxxx x101 xxxx :   */
+       if ((insn & 0x0ff00030) == 0x06800010)
+               return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+
        /* SXTAB16   : cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx :   */
-       /* SXTB      : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx :   */
+       /* SXTB16    : cccc 0110 1000 1111 xxxx xxxx 0111 xxxx :   */
+       /* ???       : cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx :   */
        /* SXTAB     : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx :   */
+       /* SXTB      : cccc 0110 1010 1111 xxxx xxxx 0111 xxxx :   */
        /* SXTAH     : cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx :   */
+       /* SXTH      : cccc 0110 1011 1111 xxxx xxxx 0111 xxxx :   */
        /* UXTAB16   : cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx :   */
+       /* UXTB16    : cccc 0110 1100 1111 xxxx xxxx 0111 xxxx :   */
+       /* ???       : cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx :   */
        /* UXTAB     : cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx :   */
+       /* UXTB      : cccc 0110 1110 1111 xxxx xxxx 0111 xxxx :   */
        /* UXTAH     : cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx :   */
-       return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+       /* UXTH      : cccc 0110 1111 1111 xxxx xxxx 0111 xxxx :   */
+       if ((insn & 0x0f8000f0) == 0x06800070) {
+               if ((insn & 0x00300000) == 0x00100000)
+                       return INSN_REJECTED;   /* Unallocated space */
+
+               if ((insn & 0x000f0000) == 0x000f0000)
+                       return prep_emulate_rd12rm0(insn, asi);
+               else
+                       return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+       }
+
+       /* Other instruction encodings aren't yet defined */
+       return INSN_REJECTED;
 }
 
 static enum kprobe_insn __kprobes
@@ -1273,29 +1416,49 @@ space_cccc_0111__1(kprobe_opcode_t insn, struct arch_specific_insn *asi)
        if ((insn & 0x0ff000f0) == 0x03f000f0)
                return INSN_REJECTED;
 
-       /* USADA8 : cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */
-       /* USAD8  : cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */
-       if ((insn & 0x0ff000f0) == 0x07800010)
-                return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
-
        /* SMLALD : cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */
        /* SMLSLD : cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */
        if ((insn & 0x0ff00090) == 0x07400010)
                return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
 
        /* SMLAD  : cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx :Q */
+       /* SMUAD  : cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx :Q */
        /* SMLSD  : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx :Q */
+       /* SMUSD  : cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx :  */
        /* SMMLA  : cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx :  */
-       /* SMMLS  : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx :  */
+       /* SMMUL  : cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx :  */
+       /* USADA8 : cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx :  */
+       /* USAD8  : cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx :  */
        if ((insn & 0x0ff00090) == 0x07000010 ||
            (insn & 0x0ff000d0) == 0x07500010 ||
-           (insn & 0x0ff000d0) == 0x075000d0)
+           (insn & 0x0ff000f0) == 0x07800010) {
+
+               if ((insn & 0x0000f000) == 0x0000f000)
+                       return prep_emulate_rd16rs8rm0_wflags(insn, asi);
+               else
+                       return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
+       }
+
+       /* SMMLS  : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx :  */
+       if ((insn & 0x0ff000d0) == 0x075000d0)
                return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
 
-       /* SMUSD  : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx :  */
-       /* SMUAD  : cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx :Q */
-       /* SMMUL  : cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx :  */
-       return prep_emulate_rd16rs8rm0_wflags(insn, asi);
+       /* SBFX   : cccc 0111 101x xxxx xxxx xxxx x101 xxxx :  */
+       /* UBFX   : cccc 0111 111x xxxx xxxx xxxx x101 xxxx :  */
+       if ((insn & 0x0fa00070) == 0x07a00050)
+               return prep_emulate_rd12rm0(insn, asi);
+
+       /* BFI    : cccc 0111 110x xxxx xxxx xxxx x001 xxxx :  */
+       /* BFC    : cccc 0111 110x xxxx xxxx xxxx x001 1111 :  */
+       if ((insn & 0x0fe00070) == 0x07c00010) {
+
+               if ((insn & 0x0000000f) == 0x0000000f)
+                       return prep_emulate_rd12_modify(insn, asi);
+               else
+                       return prep_emulate_rd12rn0_modify(insn, asi);
+       }
+
+       return INSN_REJECTED;
 }
 
 static enum kprobe_insn __kprobes
@@ -1309,6 +1472,10 @@ space_cccc_01xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
        /* STRB  : cccc 01xx x1x0 xxxx xxxx xxxx xxxx xxxx */
        /* STRBT : cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */
        /* STRT  : cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */
+
+       if ((insn & 0x00500000) == 0x00500000 && is_r15(insn, 12))
+               return INSN_REJECTED;   /* LDRB into PC */
+
        return prep_emulate_ldr_str(insn, asi);
 }
 
@@ -1323,10 +1490,9 @@ space_cccc_100x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 
        /* LDM(1) : cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
        /* STM(1) : cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
-       asi->insn[0] = truecc_insn(insn);
        asi->insn_handler = ((insn & 0x108000) == 0x008000) ? /* STM & R15 */
                                simulate_stm1_pc : simulate_ldm1stm1;
-       return INSN_GOOD;
+       return INSN_GOOD_NO_SLOT;
 }
 
 static enum kprobe_insn __kprobes
@@ -1334,58 +1500,117 @@ space_cccc_101x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
        /* B  : cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */
        /* BL : cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */
-       asi->insn[0] = truecc_insn(insn);
        asi->insn_handler = simulate_bbl;
-       return INSN_GOOD;
+       return INSN_GOOD_NO_SLOT;
 }
 
 static enum kprobe_insn __kprobes
-space_cccc_1100_010x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
+       /* Coprocessor instructions... */
        /* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
        /* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
-       insn &= 0xfff00fff;
-       insn |= 0x00001000;     /* Rn = r0, Rd = r1 */
-       asi->insn[0] = insn;
-       asi->insn_handler = (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr;
-       return INSN_GOOD;
+       /* LDC  : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
+       /* STC  : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
+       /* CDP  : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
+       /* MCR  : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
+       /* MRC  : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
+
+       /* SVC  : cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
+
+       return INSN_REJECTED;
 }
 
-static enum kprobe_insn __kprobes
-space_cccc_110x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+static unsigned long __kprobes __check_eq(unsigned long cpsr)
 {
-       /* LDC : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
-       /* STC : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
-       insn &= 0xfff0ffff;     /* Rn = r0 */
-       asi->insn[0] = insn;
-       asi->insn_handler = emulate_ldcstc;
-       return INSN_GOOD;
+       return cpsr & PSR_Z_BIT;
 }
 
-static enum kprobe_insn __kprobes
-space_cccc_111x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+static unsigned long __kprobes __check_ne(unsigned long cpsr)
 {
-       /* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
-       /* SWI  : cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
-       if ((insn & 0xfff000f0) == 0xe1200070 ||
-           (insn & 0x0f000000) == 0x0f000000)
-               return INSN_REJECTED;
+       return (~cpsr) & PSR_Z_BIT;
+}
 
-       /* CDP : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
-       if ((insn & 0x0f000010) == 0x0e000000) {
-               asi->insn[0] = insn;
-               asi->insn_handler = emulate_none;
-               return INSN_GOOD;
-       }
+static unsigned long __kprobes __check_cs(unsigned long cpsr)
+{
+       return cpsr & PSR_C_BIT;
+}
 
-       /* MCR : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
-       /* MRC : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
-       insn &= 0xffff0fff;     /* Rd = r0 */
-       asi->insn[0] = insn;
-       asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12;
-       return INSN_GOOD;
+static unsigned long __kprobes __check_cc(unsigned long cpsr)
+{
+       return (~cpsr) & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_mi(unsigned long cpsr)
+{
+       return cpsr & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_pl(unsigned long cpsr)
+{
+       return (~cpsr) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_vs(unsigned long cpsr)
+{
+       return cpsr & PSR_V_BIT;
+}
+
+static unsigned long __kprobes __check_vc(unsigned long cpsr)
+{
+       return (~cpsr) & PSR_V_BIT;
+}
+
+static unsigned long __kprobes __check_hi(unsigned long cpsr)
+{
+       cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+       return cpsr & PSR_C_BIT;
 }
 
+static unsigned long __kprobes __check_ls(unsigned long cpsr)
+{
+       cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+       return (~cpsr) & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_ge(unsigned long cpsr)
+{
+       cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+       return (~cpsr) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_lt(unsigned long cpsr)
+{
+       cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+       return cpsr & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_gt(unsigned long cpsr)
+{
+       unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+       temp |= (cpsr << 1);                     /* PSR_N_BIT |= PSR_Z_BIT */
+       return (~temp) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_le(unsigned long cpsr)
+{
+       unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+       temp |= (cpsr << 1);                     /* PSR_N_BIT |= PSR_Z_BIT */
+       return temp & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_al(unsigned long cpsr)
+{
+       return true;
+}
+
+static kprobe_check_cc * const condition_checks[16] = {
+       &__check_eq, &__check_ne, &__check_cs, &__check_cc,
+       &__check_mi, &__check_pl, &__check_vs, &__check_vc,
+       &__check_hi, &__check_ls, &__check_ge, &__check_lt,
+       &__check_gt, &__check_le, &__check_al, &__check_al
+};
+
 /* Return:
  *   INSN_REJECTED     If instruction is one not allowed to kprobe,
  *   INSN_GOOD         If instruction is supported and uses instruction slot,
@@ -1401,133 +1626,45 @@ space_cccc_111x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 enum kprobe_insn __kprobes
 arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
+       asi->insn_check_cc = condition_checks[insn>>28];
        asi->insn[1] = KPROBE_RETURN_INSTRUCTION;
 
-       if ((insn & 0xf0000000) == 0xf0000000) {
+       if ((insn & 0xf0000000) == 0xf0000000)
 
                return space_1111(insn, asi);
 
-       } else if ((insn & 0x0e000000) == 0x00000000) {
+       else if ((insn & 0x0e000000) == 0x00000000)
 
                return space_cccc_000x(insn, asi);
 
-       } else if ((insn & 0x0e000000) == 0x02000000) {
+       else if ((insn & 0x0e000000) == 0x02000000)
 
                return space_cccc_001x(insn, asi);
 
-       } else if ((insn & 0x0f000010) == 0x06000010) {
+       else if ((insn & 0x0f000010) == 0x06000010)
 
                return space_cccc_0110__1(insn, asi);
 
-       } else if ((insn & 0x0f000010) == 0x07000010) {
+       else if ((insn & 0x0f000010) == 0x07000010)
 
                return space_cccc_0111__1(insn, asi);
 
-       } else if ((insn & 0x0c000000) == 0x04000000) {
+       else if ((insn & 0x0c000000) == 0x04000000)
 
                return space_cccc_01xx(insn, asi);
 
-       } else if ((insn & 0x0e000000) == 0x08000000) {
+       else if ((insn & 0x0e000000) == 0x08000000)
 
                return space_cccc_100x(insn, asi);
 
-       } else if ((insn & 0x0e000000) == 0x0a000000) {
+       else if ((insn & 0x0e000000) == 0x0a000000)
 
                return space_cccc_101x(insn, asi);
 
-       } else if ((insn & 0x0fe00000) == 0x0c400000) {
-
-               return space_cccc_1100_010x(insn, asi);
-
-       } else if ((insn & 0x0e000000) == 0x0c000000) {
-
-               return space_cccc_110x(insn, asi);
-
-       }
-
-       return space_cccc_111x(insn, asi);
+       return space_cccc_11xx(insn, asi);
 }
 
 void __init arm_kprobe_decode_init(void)
 {
        find_str_pc_offset();
 }
-
-
-/*
- * All ARM instructions listed below.
- *
- * Instructions and their general purpose registers are given.
- * If a particular register may not use R15, it is prefixed with a "!".
- * If marked with a "*" means the value returned by reading R15
- * is implementation defined.
- *
- * ADC/ADD/AND/BIC/CMN/CMP/EOR/MOV/MVN/ORR/RSB/RSC/SBC/SUB/TEQ
- *     TST: Rd, Rn, Rm, !Rs
- * BX: Rm
- * BLX(2): !Rm
- * BX: Rm (R15 legal, but discouraged)
- * BXJ: !Rm,
- * CLZ: !Rd, !Rm
- * CPY: Rd, Rm
- * LDC/2,STC/2 immediate offset & unindex: Rn
- * LDC/2,STC/2 immediate pre/post-indexed: !Rn
- * LDM(1/3): !Rn, register_list
- * LDM(2): !Rn, !register_list
- * LDR,STR,PLD immediate offset: Rd, Rn
- * LDR,STR,PLD register offset: Rd, Rn, !Rm
- * LDR,STR,PLD scaled register offset: Rd, !Rn, !Rm
- * LDR,STR immediate pre/post-indexed: Rd, !Rn
- * LDR,STR register pre/post-indexed: Rd, !Rn, !Rm
- * LDR,STR scaled register pre/post-indexed: Rd, !Rn, !Rm
- * LDRB,STRB immediate offset: !Rd, Rn
- * LDRB,STRB register offset: !Rd, Rn, !Rm
- * LDRB,STRB scaled register offset: !Rd, !Rn, !Rm
- * LDRB,STRB immediate pre/post-indexed: !Rd, !Rn
- * LDRB,STRB register pre/post-indexed: !Rd, !Rn, !Rm
- * LDRB,STRB scaled register pre/post-indexed: !Rd, !Rn, !Rm
- * LDRT,LDRBT,STRBT immediate pre/post-indexed: !Rd, !Rn
- * LDRT,LDRBT,STRBT register pre/post-indexed: !Rd, !Rn, !Rm
- * LDRT,LDRBT,STRBT scaled register pre/post-indexed: !Rd, !Rn, !Rm
- * LDRH/SH/SB/D,STRH/SH/SB/D immediate offset: !Rd, Rn
- * LDRH/SH/SB/D,STRH/SH/SB/D register offset: !Rd, Rn, !Rm
- * LDRH/SH/SB/D,STRH/SH/SB/D immediate pre/post-indexed: !Rd, !Rn
- * LDRH/SH/SB/D,STRH/SH/SB/D register pre/post-indexed: !Rd, !Rn, !Rm
- * LDREX: !Rd, !Rn
- * MCR/2: !Rd
- * MCRR/2,MRRC/2: !Rd, !Rn
- * MLA: !Rd, !Rn, !Rm, !Rs
- * MOV: Rd
- * MRC/2: !Rd (if Rd==15, only changes cond codes, not the register)
- * MRS,MSR: !Rd
- * MUL: !Rd, !Rm, !Rs
- * PKH{BT,TB}: !Rd, !Rn, !Rm
- * QDADD,[U]QADD/16/8/SUBX: !Rd, !Rm, !Rn
- * QDSUB,[U]QSUB/16/8/ADDX: !Rd, !Rm, !Rn
- * REV/16/SH: !Rd, !Rm
- * RFE: !Rn
- * {S,U}[H]ADD{16,8,SUBX},{S,U}[H]SUB{16,8,ADDX}: !Rd, !Rn, !Rm
- * SEL: !Rd, !Rn, !Rm
- * SMLA<x><y>,SMLA{D,W<y>},SMLSD,SMML{A,S}: !Rd, !Rn, !Rm, !Rs
- * SMLAL<x><y>,SMLA{D,LD},SMLSLD,SMMULL,SMULW<y>: !RdHi, !RdLo, !Rm, !Rs
- * SMMUL,SMUAD,SMUL<x><y>,SMUSD: !Rd, !Rm, !Rs
- * SSAT/16: !Rd, !Rm
- * STM(1/2): !Rn, register_list* (R15 in reg list not recommended)
- * STRT immediate pre/post-indexed: Rd*, !Rn
- * STRT register pre/post-indexed: Rd*, !Rn, !Rm
- * STRT scaled register pre/post-indexed: Rd*, !Rn, !Rm
- * STREX: !Rd, !Rn, !Rm
- * SWP/B: !Rd, !Rn, !Rm
- * {S,U}XTA{B,B16,H}: !Rd, !Rn, !Rm
- * {S,U}XT{B,B16,H}: !Rd, !Rm
- * UM{AA,LA,UL}L: !RdHi, !RdLo, !Rm, !Rs
- * USA{D8,A8,T,T16}: !Rd, !Rm, !Rs
- *
- * May transfer control by writing R15 (possible mode changes or alternate
- * mode accesses marked by "*"):
- * ALU op (* with s-bit), B, BL, BKPT, BLX(1/2), BX, BXJ, CPS*, CPY,
- * LDM(1), LDM(2/3)*, LDR, MOV, RFE*, SWI*
- *
- * Instructions that do not take general registers, nor transfer control:
- * CDP/2, SETEND, SRS*
- */
index 2ba7deb..1656c87 100644 (file)
@@ -134,7 +134,8 @@ static void __kprobes singlestep(struct kprobe *p, struct pt_regs *regs,
                                 struct kprobe_ctlblk *kcb)
 {
        regs->ARM_pc += 4;
-       p->ainsn.insn_handler(p, regs);
+       if (p->ainsn.insn_check_cc(regs->ARM_cpsr))
+               p->ainsn.insn_handler(p, regs);
 }
 
 /*
index 979da39..139e3c8 100644 (file)
@@ -746,7 +746,8 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs)
 
        tail = (struct frame_tail __user *)regs->ARM_fp - 1;
 
-       while (tail && !((unsigned long)tail & 0x3))
+       while ((entry->nr < PERF_MAX_STACK_DEPTH) &&
+              tail && !((unsigned long)tail & 0x3))
                tail = user_backtrace(tail, entry);
 }
 
index 8fe05ad..f29b8a2 100644 (file)
@@ -479,7 +479,7 @@ static void broadcast_timer_set_mode(enum clock_event_mode mode,
 {
 }
 
-static void broadcast_timer_setup(struct clock_event_device *evt)
+static void __cpuinit broadcast_timer_setup(struct clock_event_device *evt)
 {
        evt->name       = "dummy_timer";
        evt->features   = CLOCK_EVT_FEAT_ONESHOT |
index 4ad8da1..af0aaeb 100644 (file)
@@ -311,7 +311,7 @@ asmlinkage long sys_oabi_semtimedop(int semid,
        long err;
        int i;
 
-       if (nsops < 1)
+       if (nsops < 1 || nsops > SEMOPM)
                return -EINVAL;
        sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL);
        if (!sops)
index 32f1479..c0deaca 100644 (file)
@@ -63,6 +63,7 @@ config MACH_DAVINCI_EVM
        depends on ARCH_DAVINCI_DM644x
        select MISC_DEVICES
        select EEPROM_AT24
+       select I2C
        help
          Configure this option to specify the whether the board used
          for development is a DM644x EVM
@@ -72,6 +73,7 @@ config MACH_SFFSDR
        depends on ARCH_DAVINCI_DM644x
        select MISC_DEVICES
        select EEPROM_AT24
+       select I2C
        help
          Say Y here to select the Lyrtech Small Form Factor
          Software Defined Radio (SFFSDR) board.
@@ -105,6 +107,7 @@ config MACH_DAVINCI_DM6467_EVM
        select MACH_DAVINCI_DM6467TEVM
        select MISC_DEVICES
        select EEPROM_AT24
+       select I2C
        help
          Configure this option to specify the whether the board used
          for development is a DM6467 EVM
@@ -118,6 +121,7 @@ config MACH_DAVINCI_DM365_EVM
        depends on ARCH_DAVINCI_DM365
        select MISC_DEVICES
        select EEPROM_AT24
+       select I2C
        help
          Configure this option to specify whether the board used
          for development is a DM365 EVM
@@ -129,6 +133,7 @@ config MACH_DAVINCI_DA830_EVM
        select GPIO_PCF857X
        select MISC_DEVICES
        select EEPROM_AT24
+       select I2C
        help
          Say Y here to select the TI DA830/OMAP-L137/AM17x Evaluation Module.
 
@@ -205,6 +210,7 @@ config MACH_MITYOMAPL138
        depends on ARCH_DAVINCI_DA850
        select MISC_DEVICES
        select EEPROM_AT24
+       select I2C
        help
          Say Y here to select the Critical Link MityDSP-L138/MityARM-1808
          System on Module.  Information on this SoM may be found at
index 2aa79c5..606a6f2 100644 (file)
@@ -29,7 +29,7 @@
 #include <mach/mux.h>
 #include <mach/spi.h>
 
-#define MITYOMAPL138_PHY_ID            "0:03"
+#define MITYOMAPL138_PHY_ID            ""
 
 #define FACTORY_CONFIG_MAGIC   0x012C0138
 #define FACTORY_CONFIG_VERSION 0x00010001
@@ -414,7 +414,7 @@ static struct resource mityomapl138_nandflash_resource[] = {
 
 static struct platform_device mityomapl138_nandflash_device = {
        .name           = "davinci_nand",
-       .id             = 0,
+       .id             = 1,
        .dev            = {
                .platform_data  = &mityomapl138_nandflash_data,
        },
index 625d4b6..58a02dc 100644 (file)
@@ -39,7 +39,8 @@
 #define DA8XX_GPIO_BASE                        0x01e26000
 #define DA8XX_I2C1_BASE                        0x01e28000
 #define DA8XX_SPI0_BASE                        0x01c41000
-#define DA8XX_SPI1_BASE                        0x01f0e000
+#define DA830_SPI1_BASE                        0x01e12000
+#define DA850_SPI1_BASE                        0x01f0e000
 
 #define DA8XX_EMAC_CTRL_REG_OFFSET     0x3000
 #define DA8XX_EMAC_MOD_REG_OFFSET      0x2000
@@ -762,8 +763,8 @@ static struct resource da8xx_spi0_resources[] = {
 
 static struct resource da8xx_spi1_resources[] = {
        [0] = {
-               .start  = DA8XX_SPI1_BASE,
-               .end    = DA8XX_SPI1_BASE + SZ_4K - 1,
+               .start  = DA830_SPI1_BASE,
+               .end    = DA830_SPI1_BASE + SZ_4K - 1,
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
@@ -832,5 +833,10 @@ int __init da8xx_register_spi(int instance, struct spi_board_info *info,
 
        da8xx_spi_pdata[instance].num_chipselect = len;
 
+       if (instance == 1 && cpu_is_davinci_da850()) {
+               da8xx_spi1_resources[0].start = DA850_SPI1_BASE;
+               da8xx_spi1_resources[0].end = DA850_SPI1_BASE + SZ_4K - 1;
+       }
+
        return platform_device_register(&da8xx_spi_device[instance]);
 }
index f680122..a3a94e9 100644 (file)
@@ -314,7 +314,7 @@ static struct clk timer2_clk = {
        .name = "timer2",
        .parent = &pll1_aux_clk,
        .lpsc = DAVINCI_LPSC_TIMER2,
-       .usecount = 1,              /* REVISIT: why can't' this be disabled? */
+       .usecount = 1,              /* REVISIT: why can't this be disabled? */
 };
 
 static struct clk timer3_clk = {
index 5f8a654..4c82c27 100644 (file)
@@ -274,7 +274,7 @@ static struct clk timer2_clk = {
        .name = "timer2",
        .parent = &pll1_aux_clk,
        .lpsc = DAVINCI_LPSC_TIMER2,
-       .usecount = 1,              /* REVISIT: why can't' this be disabled? */
+       .usecount = 1,              /* REVISIT: why can't this be disabled? */
 };
 
 static struct clk_lookup dm644x_clks[] = {
index 9f1befc..f8b7ea4 100644 (file)
@@ -24,6 +24,9 @@
 
 #define UART_SHIFT     2
 
+#define davinci_uart_v2p(x)    ((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)
+#define davinci_uart_p2v(x)    ((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)
+
                .pushsection .data
 davinci_uart_phys:     .word   0
 davinci_uart_virt:     .word   0
@@ -34,7 +37,7 @@ davinci_uart_virt:    .word   0
                /* Use davinci_uart_phys/virt if already configured */
 10:            mrc     p15, 0, \rp, c1, c0
                tst     \rp, #1                 @ MMU enabled?
-               ldreq   \rp, =__virt_to_phys(davinci_uart_phys)
+               ldreq   \rp, =davinci_uart_v2p(davinci_uart_phys)
                ldrne   \rp, =davinci_uart_phys
                add     \rv, \rp, #4            @ davinci_uart_virt
                ldr     \rp, [\rp, #0]
@@ -48,18 +51,18 @@ davinci_uart_virt:  .word   0
                tst     \rp, #1                 @ MMU enabled?
 
                /* Copy uart phys address from decompressor uart info */
-               ldreq   \rv, =__virt_to_phys(davinci_uart_phys)
+               ldreq   \rv, =davinci_uart_v2p(davinci_uart_phys)
                ldrne   \rv, =davinci_uart_phys
                ldreq   \rp, =DAVINCI_UART_INFO
-               ldrne   \rp, =__phys_to_virt(DAVINCI_UART_INFO)
+               ldrne   \rp, =davinci_uart_p2v(DAVINCI_UART_INFO)
                ldr     \rp, [\rp, #0]
                str     \rp, [\rv]
 
                /* Copy uart virt address from decompressor uart info */
-               ldreq   \rv, =__virt_to_phys(davinci_uart_virt)
+               ldreq   \rv, =davinci_uart_v2p(davinci_uart_virt)
                ldrne   \rv, =davinci_uart_virt
                ldreq   \rp, =DAVINCI_UART_INFO
-               ldrne   \rp, =__phys_to_virt(DAVINCI_UART_INFO)
+               ldrne   \rp, =davinci_uart_p2v(DAVINCI_UART_INFO)
                ldr     \rp, [\rp, #4]
                str     \rp, [\rv]
 
index 8051110..c9e6ce1 100644 (file)
@@ -22,7 +22,7 @@
  *
  * This area sits just below the page tables (see arch/arm/kernel/head.S).
  */
-#define DAVINCI_UART_INFO      (PHYS_OFFSET + 0x3ff8)
+#define DAVINCI_UART_INFO      (PLAT_PHYS_OFFSET + 0x3ff8)
 
 #define DAVINCI_UART0_BASE     (IO_PHYS + 0x20000)
 #define DAVINCI_UART1_BASE     (IO_PHYS + 0x20400)
index 2cf390f..47a69cb 100644 (file)
@@ -257,11 +257,16 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
        .workaround     = FLS_USB2_WORKAROUND_ENGCM09152,
 };
 
+static int vpr200_usbh_init(struct platform_device *pdev)
+{
+       return mx35_initialize_usb_hw(pdev->id,
+                       MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY);
+}
+
 /* USB HOST config */
 static const struct mxc_usbh_platform_data usb_host_pdata __initconst = {
-       .portsc         = MXC_EHCI_MODE_SERIAL,
-       .flags          = MXC_EHCI_INTERFACE_SINGLE_UNI |
-                         MXC_EHCI_INTERNAL_PHY,
+       .init = vpr200_usbh_init,
+       .portsc = MXC_EHCI_MODE_SERIAL,
 };
 
 static struct platform_device *devices[] __initdata = {
index 10a1bea..6206b11 100644 (file)
@@ -193,7 +193,7 @@ static iomux_v3_cfg_t mx53_loco_pads[] = {
        .wakeup         = wake,                                 \
 }
 
-static const struct gpio_keys_button loco_buttons[] __initconst = {
+static struct gpio_keys_button loco_buttons[] = {
        GPIO_BUTTON(MX53_LOCO_POWER, KEY_POWER, 1, "power", 0),
        GPIO_BUTTON(MX53_LOCO_UI1, KEY_VOLUMEUP, 1, "volume-up", 0),
        GPIO_BUTTON(MX53_LOCO_UI2, KEY_VOLUMEDOWN, 1, "volume-down", 0),
index 1ad97fe..5dcc59d 100644 (file)
@@ -295,11 +295,11 @@ static int name##_set_rate(struct clk *clk, unsigned long rate)           \
        unsigned long diff, parent_rate, calc_rate;                     \
        int i;                                                          \
                                                                        \
-       parent_rate = clk_get_rate(clk->parent);                        \
        div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV;       \
        bm_busy = BM_CLKCTRL_##dr##_BUSY;                               \
                                                                        \
        if (clk->parent == &ref_xtal_clk) {                             \
+               parent_rate = clk_get_rate(clk->parent);                \
                div = DIV_ROUND_UP(parent_rate, rate);                  \
                if (clk == &cpu_clk) {                                  \
                        div_max = BM_CLKCTRL_CPU_DIV_XTAL >>            \
@@ -309,6 +309,11 @@ static int name##_set_rate(struct clk *clk, unsigned long rate)            \
                if (div == 0 || div > div_max)                          \
                        return -EINVAL;                                 \
        } else {                                                        \
+               /*                                                      \
+                * hack alert: this block modifies clk->parent, too,    \
+                * so the base to use it the grand parent.              \
+                */                                                     \
+               parent_rate = clk_get_rate(clk->parent->parent);        \
                rate >>= PARENT_RATE_SHIFT;                             \
                parent_rate >>= PARENT_RATE_SHIFT;                      \
                diff = parent_rate;                                     \
index a45cd64..512b152 100644 (file)
@@ -68,7 +68,7 @@ obj-$(CONFIG_OMAP_SMARTREFLEX)          += sr_device.o smartreflex.o
 obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3)  += smartreflex-class3.o
 
 AFLAGS_sleep24xx.o                     :=-Wa,-march=armv6
-AFLAGS_sleep34xx.o                     :=-Wa,-march=armv7-a
+AFLAGS_sleep34xx.o                     :=-Wa,-march=armv7-a$(plus_sec)
 
 ifeq ($(CONFIG_PM_VERBOSE),y)
 CFLAGS_pm_bus.o                                += -DDEBUG
index e964895..f8ba20a 100644 (file)
@@ -141,14 +141,19 @@ static void __init rx51_init(void)
 static void __init rx51_map_io(void)
 {
        omap2_set_globals_3xxx();
-       rx51_video_mem_init();
        omap34xx_map_common_io();
 }
 
+static void __init rx51_reserve(void)
+{
+       rx51_video_mem_init();
+       omap_reserve();
+}
+
 MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
        /* Maintainer: Lauri Leukkunen <lauri.leukkunen@nokia.com> */
        .boot_params    = 0x80000100,
-       .reserve        = omap_reserve,
+       .reserve        = rx51_reserve,
        .map_io         = rx51_map_io,
        .init_early     = rx51_init_early,
        .init_irq       = omap_init_irq,
index 276992d..8c96567 100644 (file)
@@ -3116,14 +3116,9 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "dsp_fck",                      &dsp_fck,       CK_443X),
        CLK("omapdss_dss",      "sys_clk",                      &dss_sys_clk,   CK_443X),
        CLK("omapdss_dss",      "tv_clk",                       &dss_tv_clk,    CK_443X),
-       CLK("omapdss_dss",      "dss_clk",                      &dss_dss_clk,   CK_443X),
        CLK("omapdss_dss",      "video_clk",                    &dss_48mhz_clk, CK_443X),
-       CLK("omapdss_dss",      "fck",                          &dss_fck,       CK_443X),
-       /*
-        * On OMAP4, DSS ick is a dummy clock; this is needed for compatibility
-        * with OMAP2/3.
-        */
-       CLK("omapdss_dss",      "ick",                          &dummy_ck,      CK_443X),
+       CLK("omapdss_dss",      "fck",                          &dss_dss_clk,   CK_443X),
+       CLK("omapdss_dss",      "ick",                          &dss_fck,       CK_443X),
        CLK(NULL,       "efuse_ctrl_cust_fck",          &efuse_ctrl_cust_fck,   CK_443X),
        CLK(NULL,       "emif1_fck",                    &emif1_fck,     CK_443X),
        CLK(NULL,       "emif2_fck",                    &emif2_fck,     CK_443X),
index 9d0dec8..38830d8 100644 (file)
@@ -247,6 +247,7 @@ struct omap3_cm_regs {
        u32 per_cm_clksel;
        u32 emu_cm_clksel;
        u32 emu_cm_clkstctrl;
+       u32 pll_cm_autoidle;
        u32 pll_cm_autoidle2;
        u32 pll_cm_clksel4;
        u32 pll_cm_clksel5;
@@ -319,6 +320,15 @@ void omap3_cm_save_context(void)
                omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
        cm_context.emu_cm_clkstctrl =
                omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
+       /*
+        * As per erratum i671, ROM code does not respect the PER DPLL
+        * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
+        * In this case, even though this register has been saved in
+        * scratchpad contents, we need to restore AUTO_PERIPH_DPLL
+        * by ourselves. So, we need to save it anyway.
+        */
+       cm_context.pll_cm_autoidle =
+               omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
        cm_context.pll_cm_autoidle2 =
                omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
        cm_context.pll_cm_clksel4 =
@@ -441,6 +451,13 @@ void omap3_cm_restore_context(void)
                               CM_CLKSEL1);
        omap2_cm_write_mod_reg(cm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD,
                               OMAP2_CM_CLKSTCTRL);
+       /*
+        * As per erratum i671, ROM code does not respect the PER DPLL
+        * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
+        * In this case, we need to restore AUTO_PERIPH_DPLL by ourselves.
+        */
+       omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle, PLL_MOD,
+                              CM_AUTOIDLE);
        omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle2, PLL_MOD,
                               CM_AUTOIDLE2);
        omap2_cm_write_mod_reg(cm_context.pll_cm_clksel4, PLL_MOD,
index 6952794..da53ba3 100644 (file)
@@ -316,8 +316,14 @@ void omap3_save_scratchpad_contents(void)
                        omap2_cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
        prcm_block_contents.cm_clken_pll =
                        omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
+       /*
+        * As per erratum i671, ROM code does not respect the PER DPLL
+        * programming scheme if CM_AUTOIDLE_PLL..AUTO_PERIPH_DPLL == 1.
+        * Then,  in anycase, clear these bits to avoid extra latencies.
+        */
        prcm_block_contents.cm_autoidle_pll =
-                       omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_AUTOIDLE_PLL);
+                       omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE) &
+                       ~OMAP3430_AUTO_PERIPH_DPLL_MASK;
        prcm_block_contents.cm_clksel1_pll =
                        omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL);
        prcm_block_contents.cm_clksel2_pll =
index 8eb3ce1..c4d0ae8 100644 (file)
@@ -1639,6 +1639,7 @@ static struct omap_hwmod_ocp_if *omap2420_gpio1_slaves[] = {
 
 static struct omap_hwmod omap2420_gpio1_hwmod = {
        .name           = "gpio1",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap242x_gpio1_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap242x_gpio1_irqs),
        .main_clk       = "gpios_fck",
@@ -1669,6 +1670,7 @@ static struct omap_hwmod_ocp_if *omap2420_gpio2_slaves[] = {
 
 static struct omap_hwmod omap2420_gpio2_hwmod = {
        .name           = "gpio2",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap242x_gpio2_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap242x_gpio2_irqs),
        .main_clk       = "gpios_fck",
@@ -1699,6 +1701,7 @@ static struct omap_hwmod_ocp_if *omap2420_gpio3_slaves[] = {
 
 static struct omap_hwmod omap2420_gpio3_hwmod = {
        .name           = "gpio3",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap242x_gpio3_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap242x_gpio3_irqs),
        .main_clk       = "gpios_fck",
@@ -1729,6 +1732,7 @@ static struct omap_hwmod_ocp_if *omap2420_gpio4_slaves[] = {
 
 static struct omap_hwmod omap2420_gpio4_hwmod = {
        .name           = "gpio4",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap242x_gpio4_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap242x_gpio4_irqs),
        .main_clk       = "gpios_fck",
@@ -1782,7 +1786,7 @@ static struct omap_hwmod_irq_info omap2420_dma_system_irqs[] = {
 static struct omap_hwmod_addr_space omap2420_dma_system_addrs[] = {
        {
                .pa_start       = 0x48056000,
-               .pa_end         = 0x4a0560ff,
+               .pa_end         = 0x48056fff,
                .flags          = ADDR_TYPE_RT
        },
 };
index e6e3810..9682dd5 100644 (file)
@@ -1742,6 +1742,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio1_slaves[] = {
 
 static struct omap_hwmod omap2430_gpio1_hwmod = {
        .name           = "gpio1",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap243x_gpio1_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap243x_gpio1_irqs),
        .main_clk       = "gpios_fck",
@@ -1772,6 +1773,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio2_slaves[] = {
 
 static struct omap_hwmod omap2430_gpio2_hwmod = {
        .name           = "gpio2",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap243x_gpio2_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap243x_gpio2_irqs),
        .main_clk       = "gpios_fck",
@@ -1802,6 +1804,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio3_slaves[] = {
 
 static struct omap_hwmod omap2430_gpio3_hwmod = {
        .name           = "gpio3",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap243x_gpio3_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap243x_gpio3_irqs),
        .main_clk       = "gpios_fck",
@@ -1832,6 +1835,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio4_slaves[] = {
 
 static struct omap_hwmod omap2430_gpio4_hwmod = {
        .name           = "gpio4",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap243x_gpio4_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap243x_gpio4_irqs),
        .main_clk       = "gpios_fck",
@@ -1862,6 +1866,7 @@ static struct omap_hwmod_ocp_if *omap2430_gpio5_slaves[] = {
 
 static struct omap_hwmod omap2430_gpio5_hwmod = {
        .name           = "gpio5",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap243x_gpio5_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap243x_gpio5_irqs),
        .main_clk       = "gpio5_fck",
@@ -1915,7 +1920,7 @@ static struct omap_hwmod_irq_info omap2430_dma_system_irqs[] = {
 static struct omap_hwmod_addr_space omap2430_dma_system_addrs[] = {
        {
                .pa_start       = 0x48056000,
-               .pa_end         = 0x4a0560ff,
+               .pa_end         = 0x48056fff,
                .flags          = ADDR_TYPE_RT
        },
 };
index b98e2df..909a84d 100644 (file)
@@ -2141,6 +2141,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio1_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio1_hwmod = {
        .name           = "gpio1",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap3xxx_gpio1_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_gpio1_irqs),
        .main_clk       = "gpio1_ick",
@@ -2177,6 +2178,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio2_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio2_hwmod = {
        .name           = "gpio2",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap3xxx_gpio2_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_gpio2_irqs),
        .main_clk       = "gpio2_ick",
@@ -2213,6 +2215,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio3_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio3_hwmod = {
        .name           = "gpio3",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap3xxx_gpio3_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_gpio3_irqs),
        .main_clk       = "gpio3_ick",
@@ -2249,6 +2252,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio4_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio4_hwmod = {
        .name           = "gpio4",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap3xxx_gpio4_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_gpio4_irqs),
        .main_clk       = "gpio4_ick",
@@ -2285,6 +2289,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio5_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio5_hwmod = {
        .name           = "gpio5",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap3xxx_gpio5_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_gpio5_irqs),
        .main_clk       = "gpio5_ick",
@@ -2321,6 +2326,7 @@ static struct omap_hwmod_ocp_if *omap3xxx_gpio6_slaves[] = {
 
 static struct omap_hwmod omap3xxx_gpio6_hwmod = {
        .name           = "gpio6",
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .mpu_irqs       = omap3xxx_gpio6_irqs,
        .mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_gpio6_irqs),
        .main_clk       = "gpio6_ick",
@@ -2386,7 +2392,7 @@ static struct omap_hwmod_irq_info omap3xxx_dma_system_irqs[] = {
 static struct omap_hwmod_addr_space omap3xxx_dma_system_addrs[] = {
        {
                .pa_start       = 0x48056000,
-               .pa_end         = 0x4a0560ff,
+               .pa_end         = 0x48056fff,
                .flags          = ADDR_TYPE_RT
        },
 };
index 3e88dd3..abc548a 100644 (file)
@@ -885,7 +885,7 @@ static struct omap_hwmod_ocp_if *omap44xx_dma_system_masters[] = {
 static struct omap_hwmod_addr_space omap44xx_dma_system_addrs[] = {
        {
                .pa_start       = 0x4a056000,
-               .pa_end         = 0x4a0560ff,
+               .pa_end         = 0x4a056fff,
                .flags          = ADDR_TYPE_RT
        },
 };
index 5f2da75..4321e79 100644 (file)
@@ -196,11 +196,11 @@ static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
                /* No timeout error for debug sources */
        }
 
-       base = ((l3->rt) + (*(omap3_l3_bases[int_type] + err_source)));
-
        /* identify the error source */
        for (err_source = 0; !(status & (1 << err_source)); err_source++)
                                                                        ;
+
+       base = l3->rt + *(omap3_l3_bases[int_type] + err_source);
        error = omap3_l3_readll(base, L3_ERROR_LOG);
 
        if (error) {
index 30af335..49486f5 100644 (file)
@@ -89,6 +89,7 @@ static void omap2_init_processor_devices(void)
        if (cpu_is_omap44xx()) {
                _init_omap_device("l3_main_1", &l3_dev);
                _init_omap_device("dsp", &dsp_dev);
+               _init_omap_device("iva", &iva_dev);
        } else {
                _init_omap_device("l3_main", &l3_dev);
        }
index 6fb5209..0c1552d 100644 (file)
@@ -114,7 +114,6 @@ static int __init _config_common_vdd_data(struct omap_vdd_info *vdd)
        sys_clk_speed /= 1000;
 
        /* Generic voltage parameters */
-       vdd->curr_volt = 1200000;
        vdd->volt_scale = vp_forceupdate_scale_voltage;
        vdd->vp_enabled = false;
 
index 6de0ad0..9cdcca5 100644 (file)
@@ -711,7 +711,7 @@ static struct regulator_consumer_supply bq24022_consumers[] = {
 static struct regulator_init_data bq24022_init_data = {
        .constraints = {
                .max_uA         = 500000,
-               .valid_ops_mask = REGULATOR_CHANGE_CURRENT,
+               .valid_ops_mask = REGULATOR_CHANGE_CURRENT|REGULATOR_CHANGE_STATUS,
        },
        .num_consumer_supplies  = ARRAY_SIZE(bq24022_consumers),
        .consumer_supplies      = bq24022_consumers,
index a72993d..9984ef7 100644 (file)
@@ -599,7 +599,7 @@ static struct regulator_consumer_supply bq24022_consumers[] = {
 static struct regulator_init_data bq24022_init_data = {
        .constraints = {
                .max_uA         = 500000,
-               .valid_ops_mask = REGULATOR_CHANGE_CURRENT,
+               .valid_ops_mask = REGULATOR_CHANGE_CURRENT | REGULATOR_CHANGE_STATUS,
        },
        .num_consumer_supplies  = ARRAY_SIZE(bq24022_consumers),
        .consumer_supplies      = bq24022_consumers,
index af91374..6e1907f 100644 (file)
@@ -178,16 +178,15 @@ static struct i2c_board_info __initdata mop500_i2c0_devices[] = {
                .irq            = NOMADIK_GPIO_TO_IRQ(217),
                .platform_data  = &mop500_tc35892_data,
        },
-};
-
-/* I2C0 devices only available prior to HREFv60 */
-static struct i2c_board_info __initdata mop500_i2c0_old_devices[] = {
+       /* I2C0 devices only available prior to HREFv60 */
        {
                I2C_BOARD_INFO("tps61052", 0x33),
                .platform_data  = &mop500_tps61052_data,
        },
 };
 
+#define NUM_PRE_V60_I2C0_DEVICES 1
+
 static struct i2c_board_info __initdata mop500_i2c2_devices[] = {
        {
                /* lp5521 LED driver, 1st device */
@@ -425,6 +424,8 @@ static void __init mop500_uart_init(void)
 
 static void __init mop500_init_machine(void)
 {
+       int i2c0_devs;
+
        /*
         * The HREFv60 board removed a GPIO expander and routed
         * all these GPIO pins to the internal GPIO controller
@@ -448,11 +449,11 @@ static void __init mop500_init_machine(void)
 
        platform_device_register(&ab8500_device);
 
-       i2c_register_board_info(0, mop500_i2c0_devices,
-                               ARRAY_SIZE(mop500_i2c0_devices));
-       if (!machine_is_hrefv60())
-               i2c_register_board_info(0, mop500_i2c0_old_devices,
-                                       ARRAY_SIZE(mop500_i2c0_old_devices));
+       i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
+       if (machine_is_hrefv60())
+               i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
+
+       i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
        i2c_register_board_info(2, mop500_i2c2_devices,
                                ARRAY_SIZE(mop500_i2c2_devices));
 }
index ce233bc..42af976 100644 (file)
@@ -395,7 +395,7 @@ ENTRY(xscale_dma_a0_map_area)
        teq     r2, #DMA_TO_DEVICE
        beq     xscale_dma_clean_range
        b       xscale_dma_flush_range
-ENDPROC(xscsale_dma_a0_map_area)
+ENDPROC(xscale_dma_a0_map_area)
 
 /*
  *     dma_unmap_area(start, size, dir)
index 7a10724..6cd6d7f 100644 (file)
@@ -295,6 +295,12 @@ static int mxc_gpio_direction_output(struct gpio_chip *chip,
        return 0;
 }
 
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
 int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
 {
        int i, j;
@@ -311,6 +317,7 @@ int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
                __raw_writel(~0, port[i].base + GPIO_ISR);
                for (j = port[i].virtual_irq_start;
                        j < port[i].virtual_irq_start + 32; j++) {
+                       irq_set_lockdep_class(j, &gpio_lock_class);
                        irq_set_chip_and_handler(j, &gpio_irq_chip,
                                                 handle_level_irq);
                        set_irq_flags(j, IRQF_VALID);
index 4ddce56..8397a2d 100644 (file)
@@ -124,6 +124,8 @@ imx_ssi_fiq_start:
 1:
                @ return from FIQ
                subs    pc, lr, #4
+
+               .align
 imx_ssi_fiq_base:
                .word 0x0
 imx_ssi_fiq_rx_buffer:
index 02b7a03..8b3db1c 100644 (file)
@@ -300,6 +300,8 @@ void __init paging_init(void)
                zones_size[ZONE_DMA] = m68k_memory[i].size >> PAGE_SHIFT;
                free_area_init_node(i, zones_size,
                                    m68k_memory[i].addr >> PAGE_SHIFT, NULL);
+               if (node_present_pages(i))
+                       node_set_state(i, N_NORMAL_MEMORY);
        }
 }
 
index b7ed8d7..b1d1262 100644 (file)
@@ -266,8 +266,10 @@ static void __init setup_bootmem(void)
        }
        memset(pfnnid_map, 0xff, sizeof(pfnnid_map));
 
-       for (i = 0; i < npmem_ranges; i++)
+       for (i = 0; i < npmem_ranges; i++) {
+               node_set_state(i, N_NORMAL_MEMORY);
                node_set_online(i);
+       }
 #endif
 
        /*
index 6b6dc20..bdf0563 100644 (file)
@@ -393,8 +393,8 @@ typedef struct fec {
        uint    fec_addr_low;           /* lower 32 bits of station address     */
        ushort  fec_addr_high;          /* upper 16 bits of station address     */
        ushort  res1;                   /* reserved                             */
-       uint    fec_hash_table_high;    /* upper 32-bits of hash table          */
-       uint    fec_hash_table_low;     /* lower 32-bits of hash table          */
+       uint    fec_grp_hash_table_high;        /* upper 32-bits of hash table          */
+       uint    fec_grp_hash_table_low; /* lower 32-bits of hash table          */
        uint    fec_r_des_start;        /* beginning of Rx descriptor ring      */
        uint    fec_x_des_start;        /* beginning of Tx descriptor ring      */
        uint    fec_r_buff_size;        /* Rx buffer size                       */
index ae9c899..d12b11d 100644 (file)
@@ -60,7 +60,7 @@
  *
  * Obviously, the GART is not cache coherent and so any change to it
  * must be flushed to memory (or maybe just make the GART space non
- * cachable). AGP memory itself does't seem to be cache coherent neither.
+ * cachable). AGP memory itself doesn't seem to be cache coherent neither.
  *
  * In order to invalidate the GART (which is probably necessary to inval
  * the bridge internal TLBs), the following sequence has to be written,
index 975e3ab..8b16c47 100644 (file)
@@ -76,7 +76,7 @@ static void prng_seed(int nbytes)
 
        /* Add the entropy */
        while (nbytes >= 8) {
-               *((__u64 *)parm_block) ^= *((__u64 *)buf+i*8);
+               *((__u64 *)parm_block) ^= *((__u64 *)(buf+i));
                prng_add_entropy();
                i += 8;
                nbytes -= 8;
index 7e9d30d..ab0e041 100644 (file)
@@ -48,10 +48,10 @@ sie_irq_handler:
        tm      __TI_flags+7(%r2),_TIF_EXIT_SIE
        jz      0f
        larl    %r2,sie_exit                    # work pending, leave sie
-       stg     %r2,__LC_RETURN_PSW+8
+       stg     %r2,SPI_PSW+8(0,%r15)
        br      %r14
 0:     larl    %r2,sie_reenter                 # re-enter with guest id
-       stg     %r2,__LC_RETURN_PSW+8
+       stg     %r2,SPI_PSW+8(0,%r15)
 1:     br      %r14
 
 /*
index 9217e33..ab98813 100644 (file)
@@ -543,7 +543,6 @@ static void pfault_interrupt(unsigned int ext_int_code,
        struct task_struct *tsk;
        __u16 subcode;
 
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++;
        /*
         * Get the external interruption subcode & pfault
         * initial/completion signal bit. VM stores this 
@@ -553,14 +552,15 @@ static void pfault_interrupt(unsigned int ext_int_code,
        subcode = ext_int_code >> 16;
        if ((subcode & 0xff00) != __SUBCODE_MASK)
                return;
+       kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++;
 
        /*
         * Get the token (= address of the task structure of the affected task).
         */
 #ifdef CONFIG_64BIT
-       tsk = *(struct task_struct **) param64;
+       tsk = (struct task_struct *) param64;
 #else
-       tsk = *(struct task_struct **) param32;
+       tsk = (struct task_struct *) param32;
 #endif
 
        if (subcode & 0x0080) {
index 122ffbd..0607e4b 100644 (file)
@@ -24,12 +24,13 @@ static void change_page_attr(unsigned long addr, int numpages,
                        WARN_ON_ONCE(1);
                        continue;
                }
-               ptep = pte_offset_kernel(pmdp, addr + i * PAGE_SIZE);
+               ptep = pte_offset_kernel(pmdp, addr);
 
                pte = *ptep;
                pte = set(pte);
-               ptep_invalidate(&init_mm, addr + i * PAGE_SIZE, ptep);
+               ptep_invalidate(&init_mm, addr, ptep);
                *ptep = pte;
+               addr += PAGE_SIZE;
        }
 }
 
index 90a438a..b5e675e 100644 (file)
@@ -47,7 +47,7 @@ config HOSTFS
 
 config HPPFS
        tristate "HoneyPot ProcFS (EXPERIMENTAL)"
-       depends on EXPERIMENTAL
+       depends on EXPERIMENTAL && PROC_FS
        help
          hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
          entries to be overridden, removed, or fabricated from the host.
index e2cf786..5bd1bad 100644 (file)
@@ -49,7 +49,10 @@ static inline struct thread_info *current_thread_info(void)
 {
        struct thread_info *ti;
        unsigned long mask = THREAD_SIZE - 1;
-       ti = (struct thread_info *) (((unsigned long) &ti) & ~mask);
+       void *p;
+
+       asm volatile ("" : "=r" (p) : "0" (&ti));
+       ti = (struct thread_info *) (((unsigned long)p) & ~mask);
        return ti;
 }
 
index 804b28d..b1da91c 100644 (file)
@@ -4,7 +4,7 @@
 
 obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
        ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
-       sys_call_table.o tls.o
+       sys_call_table.o tls.o atomic64_cx8_32.o
 
 obj-$(CONFIG_BINFMT_ELF) += elfcore.o
 
diff --git a/arch/um/sys-i386/atomic64_cx8_32.S b/arch/um/sys-i386/atomic64_cx8_32.S
new file mode 100644 (file)
index 0000000..1e901d3
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+ * atomic64_t for 586+
+ *
+ * Copied from arch/x86/lib/atomic64_cx8_32.S
+ *
+ * Copyright Â© 2010  Luca Barbieri
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/alternative-asm.h>
+#include <asm/dwarf2.h>
+
+.macro SAVE reg
+       pushl_cfi %\reg
+       CFI_REL_OFFSET \reg, 0
+.endm
+
+.macro RESTORE reg
+       popl_cfi %\reg
+       CFI_RESTORE \reg
+.endm
+
+.macro read64 reg
+       movl %ebx, %eax
+       movl %ecx, %edx
+/* we need LOCK_PREFIX since otherwise cmpxchg8b always does the write */
+       LOCK_PREFIX
+       cmpxchg8b (\reg)
+.endm
+
+ENTRY(atomic64_read_cx8)
+       CFI_STARTPROC
+
+       read64 %ecx
+       ret
+       CFI_ENDPROC
+ENDPROC(atomic64_read_cx8)
+
+ENTRY(atomic64_set_cx8)
+       CFI_STARTPROC
+
+1:
+/* we don't need LOCK_PREFIX since aligned 64-bit writes
+ * are atomic on 586 and newer */
+       cmpxchg8b (%esi)
+       jne 1b
+
+       ret
+       CFI_ENDPROC
+ENDPROC(atomic64_set_cx8)
+
+ENTRY(atomic64_xchg_cx8)
+       CFI_STARTPROC
+
+       movl %ebx, %eax
+       movl %ecx, %edx
+1:
+       LOCK_PREFIX
+       cmpxchg8b (%esi)
+       jne 1b
+
+       ret
+       CFI_ENDPROC
+ENDPROC(atomic64_xchg_cx8)
+
+.macro addsub_return func ins insc
+ENTRY(atomic64_\func\()_return_cx8)
+       CFI_STARTPROC
+       SAVE ebp
+       SAVE ebx
+       SAVE esi
+       SAVE edi
+
+       movl %eax, %esi
+       movl %edx, %edi
+       movl %ecx, %ebp
+
+       read64 %ebp
+1:
+       movl %eax, %ebx
+       movl %edx, %ecx
+       \ins\()l %esi, %ebx
+       \insc\()l %edi, %ecx
+       LOCK_PREFIX
+       cmpxchg8b (%ebp)
+       jne 1b
+
+10:
+       movl %ebx, %eax
+       movl %ecx, %edx
+       RESTORE edi
+       RESTORE esi
+       RESTORE ebx
+       RESTORE ebp
+       ret
+       CFI_ENDPROC
+ENDPROC(atomic64_\func\()_return_cx8)
+.endm
+
+addsub_return add add adc
+addsub_return sub sub sbb
+
+.macro incdec_return func ins insc
+ENTRY(atomic64_\func\()_return_cx8)
+       CFI_STARTPROC
+       SAVE ebx
+
+       read64 %esi
+1:
+       movl %eax, %ebx
+       movl %edx, %ecx
+       \ins\()l $1, %ebx
+       \insc\()l $0, %ecx
+       LOCK_PREFIX
+       cmpxchg8b (%esi)
+       jne 1b
+
+10:
+       movl %ebx, %eax
+       movl %ecx, %edx
+       RESTORE ebx
+       ret
+       CFI_ENDPROC
+ENDPROC(atomic64_\func\()_return_cx8)
+.endm
+
+incdec_return inc add adc
+incdec_return dec sub sbb
+
+ENTRY(atomic64_dec_if_positive_cx8)
+       CFI_STARTPROC
+       SAVE ebx
+
+       read64 %esi
+1:
+       movl %eax, %ebx
+       movl %edx, %ecx
+       subl $1, %ebx
+       sbb $0, %ecx
+       js 2f
+       LOCK_PREFIX
+       cmpxchg8b (%esi)
+       jne 1b
+
+2:
+       movl %ebx, %eax
+       movl %ecx, %edx
+       RESTORE ebx
+       ret
+       CFI_ENDPROC
+ENDPROC(atomic64_dec_if_positive_cx8)
+
+ENTRY(atomic64_add_unless_cx8)
+       CFI_STARTPROC
+       SAVE ebp
+       SAVE ebx
+/* these just push these two parameters on the stack */
+       SAVE edi
+       SAVE esi
+
+       movl %ecx, %ebp
+       movl %eax, %esi
+       movl %edx, %edi
+
+       read64 %ebp
+1:
+       cmpl %eax, 0(%esp)
+       je 4f
+2:
+       movl %eax, %ebx
+       movl %edx, %ecx
+       addl %esi, %ebx
+       adcl %edi, %ecx
+       LOCK_PREFIX
+       cmpxchg8b (%ebp)
+       jne 1b
+
+       movl $1, %eax
+3:
+       addl $8, %esp
+       CFI_ADJUST_CFA_OFFSET -8
+       RESTORE ebx
+       RESTORE ebp
+       ret
+4:
+       cmpl %edx, 4(%esp)
+       jne 2b
+       xorl %eax, %eax
+       jmp 3b
+       CFI_ENDPROC
+ENDPROC(atomic64_add_unless_cx8)
+
+ENTRY(atomic64_inc_not_zero_cx8)
+       CFI_STARTPROC
+       SAVE ebx
+
+       read64 %esi
+1:
+       testl %eax, %eax
+       je 4f
+2:
+       movl %eax, %ebx
+       movl %edx, %ecx
+       addl $1, %ebx
+       adcl $0, %ecx
+       LOCK_PREFIX
+       cmpxchg8b (%esi)
+       jne 1b
+
+       movl $1, %eax
+3:
+       RESTORE ebx
+       ret
+4:
+       testl %edx, %edx
+       jne 2b
+       jmp 3b
+       CFI_ENDPROC
+ENDPROC(atomic64_inc_not_zero_cx8)
index cae3feb..db75d07 100644 (file)
@@ -91,7 +91,7 @@ static int detect_memory_e801(void)
        if (oreg.ax > 15*1024) {
                return -1;      /* Bogus! */
        } else if (oreg.ax == 15*1024) {
-               boot_params.alt_mem_k = (oreg.dx << 6) + oreg.ax;
+               boot_params.alt_mem_k = (oreg.bx << 6) + oreg.ax;
        } else {
                /*
                 * This ignores memory above 16MB if we have a memory
index c4bd267..a97a240 100644 (file)
@@ -150,7 +150,7 @@ void setup_IO_APIC_irq_extra(u32 gsi);
 extern void ioapic_and_gsi_init(void);
 extern void ioapic_insert_resources(void);
 
-int io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr);
+int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr);
 
 extern struct IO_APIC_route_entry **alloc_ioapic_entries(void);
 extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
index 68df09b..45fd33d 100644 (file)
@@ -128,8 +128,8 @@ static int __init parse_noapic(char *str)
 }
 early_param("noapic", parse_noapic);
 
-static int io_apic_setup_irq_pin_once(unsigned int irq, int node,
-                                     struct io_apic_irq_attr *attr);
+static int io_apic_setup_irq_pin(unsigned int irq, int node,
+                                struct io_apic_irq_attr *attr);
 
 /* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
 void mp_save_irq(struct mpc_intsrc *m)
@@ -3570,7 +3570,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 }
 #endif /* CONFIG_HT_IRQ */
 
-int
+static int
 io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
 {
        struct irq_cfg *cfg = alloc_irq_and_cfg_at(irq, node);
@@ -3585,8 +3585,8 @@ io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
        return ret;
 }
 
-static int io_apic_setup_irq_pin_once(unsigned int irq, int node,
-                                     struct io_apic_irq_attr *attr)
+int io_apic_setup_irq_pin_once(unsigned int irq, int node,
+                              struct io_apic_irq_attr *attr)
 {
        unsigned int id = attr->ioapic, pin = attr->ioapic_pin;
        int ret;
index 0b4be43..adee12e 100644 (file)
 #include <linux/kthread.h>
 #include <linux/jiffies.h>
 #include <linux/acpi.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -1238,6 +1239,7 @@ static int suspend(int vetoable)
 
        local_irq_disable();
        sysdev_suspend(PMSG_SUSPEND);
+       syscore_suspend();
 
        local_irq_enable();
 
@@ -1255,6 +1257,7 @@ static int suspend(int vetoable)
                apm_error("suspend", err);
        err = (err == APM_SUCCESS) ? 0 : -EIO;
 
+       syscore_resume();
        sysdev_resume();
        local_irq_enable();
 
@@ -1280,6 +1283,7 @@ static void standby(void)
 
        local_irq_disable();
        sysdev_suspend(PMSG_SUSPEND);
+       syscore_suspend();
        local_irq_enable();
 
        err = set_system_power_state(APM_STATE_STANDBY);
@@ -1287,6 +1291,7 @@ static void standby(void)
                apm_error("standby", err);
 
        local_irq_disable();
+       syscore_resume();
        sysdev_resume();
        local_irq_enable();
 
index 3532d3b..bb9eb29 100644 (file)
@@ -698,7 +698,7 @@ cpu_dev_register(amd_cpu_dev);
  */
 
 const int amd_erratum_400[] =
-       AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf),
+       AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0x0f, 0x4, 0x2, 0xff, 0xf),
                            AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf));
 EXPORT_SYMBOL_GPL(amd_erratum_400);
 
index 632e5dc..e638689 100644 (file)
@@ -613,8 +613,8 @@ static int x86_setup_perfctr(struct perf_event *event)
        /*
         * Branch tracing:
         */
-       if ((attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
-           (hwc->sample_period == 1)) {
+       if (attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS &&
+           !attr->freq && hwc->sample_period == 1) {
                /* BTS is not supported by this architecture. */
                if (!x86_pmu.bts_active)
                        return -EOPNOTSUPP;
@@ -1288,6 +1288,16 @@ static int x86_pmu_handle_irq(struct pt_regs *regs)
 
        cpuc = &__get_cpu_var(cpu_hw_events);
 
+       /*
+        * Some chipsets need to unmask the LVTPC in a particular spot
+        * inside the nmi handler.  As a result, the unmasking was pushed
+        * into all the nmi handlers.
+        *
+        * This generic handler doesn't seem to have any issues where the
+        * unmasking occurs so it was left at the top.
+        */
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+
        for (idx = 0; idx < x86_pmu.num_counters; idx++) {
                if (!test_bit(idx, cpuc->active_mask)) {
                        /*
@@ -1374,8 +1384,6 @@ perf_event_nmi_handler(struct notifier_block *self,
                return NOTIFY_DONE;
        }
 
-       apic_write(APIC_LVTPC, APIC_DM_NMI);
-
        handled = x86_pmu.handle_irq(args->regs);
        if (!handled)
                return NOTIFY_DONE;
index 43fa20b..e61539b 100644 (file)
@@ -25,7 +25,7 @@ struct intel_percore {
 /*
  * Intel PerfMon, used on Core and later.
  */
-static const u64 intel_perfmon_event_map[] =
+static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly =
 {
   [PERF_COUNT_HW_CPU_CYCLES]           = 0x003c,
   [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,
@@ -933,6 +933,16 @@ static int intel_pmu_handle_irq(struct pt_regs *regs)
 
        cpuc = &__get_cpu_var(cpu_hw_events);
 
+       /*
+        * Some chipsets need to unmask the LVTPC in a particular spot
+        * inside the nmi handler.  As a result, the unmasking was pushed
+        * into all the nmi handlers.
+        *
+        * This handler doesn't seem to have any issues with the unmasking
+        * so it was left at the top.
+        */
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
+
        intel_pmu_disable_all();
        handled = intel_pmu_drain_bts_buffer();
        status = intel_pmu_get_status();
@@ -998,6 +1008,9 @@ intel_bts_constraints(struct perf_event *event)
        struct hw_perf_event *hwc = &event->hw;
        unsigned int hw_event, bts_event;
 
+       if (event->attr.freq)
+               return NULL;
+
        hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;
        bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
 
@@ -1305,7 +1318,7 @@ static void intel_clovertown_quirks(void)
         * AJ106 could possibly be worked around by not allowing LBR
         *       usage from PEBS, including the fixup.
         * AJ68  could possibly be worked around by always programming
-        *       a pebs_event_reset[0] value and coping with the lost events.
+        *       a pebs_event_reset[0] value and coping with the lost events.
         *
         * But taken together it might just make sense to not enable PEBS on
         * these chips.
@@ -1409,6 +1422,18 @@ static __init int intel_pmu_init(void)
                x86_pmu.percore_constraints = intel_nehalem_percore_constraints;
                x86_pmu.enable_all = intel_pmu_nhm_enable_all;
                x86_pmu.extra_regs = intel_nehalem_extra_regs;
+
+               if (ebx & 0x40) {
+                       /*
+                        * Erratum AAJ80 detected, we work it around by using
+                        * the BR_MISP_EXEC.ANY event. This will over-count
+                        * branch-misses, but it's still much better than the
+                        * architectural event which is often completely bogus:
+                        */
+                       intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89;
+
+                       pr_cont("erratum AAJ80 worked around, ");
+               }
                pr_cont("Nehalem events, ");
                break;
 
index d1f77e2..e93fcd5 100644 (file)
@@ -950,11 +950,20 @@ static int p4_pmu_handle_irq(struct pt_regs *regs)
                        x86_pmu_stop(event, 0);
        }
 
-       if (handled) {
-               /* p4 quirk: unmask it again */
-               apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
+       if (handled)
                inc_irq_stat(apic_perf_irqs);
-       }
+
+       /*
+        * When dealing with the unmasking of the LVTPC on P4 perf hw, it has
+        * been observed that the OVF bit flag has to be cleared first _before_
+        * the LVTPC can be unmasked.
+        *
+        * The reason is the NMI line will continue to be asserted while the OVF
+        * bit is set.  This causes a second NMI to generate if the LVTPC is
+        * unmasked before the OVF bit is cleared, leading to unknown NMI
+        * messages.
+        */
+       apic_write(APIC_LVTPC, APIC_DM_NMI);
 
        return handled;
 }
index 706a9fb..e90f084 100644 (file)
@@ -391,7 +391,7 @@ static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize,
 
        set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
 
-       return io_apic_setup_irq_pin(*out_hwirq, cpu_to_node(0), &attr);
+       return io_apic_setup_irq_pin_once(*out_hwirq, cpu_to_node(0), &attr);
 }
 
 static void __init ioapic_add_ofnode(struct device_node *np)
index 29092b3..1d5c46d 100644 (file)
@@ -21,26 +21,26 @@ r_base = .
        /* Get our own relocated address */
        call    1f
 1:     popl    %ebx
-       subl    $1b, %ebx
+       subl    $(1b - r_base), %ebx
 
        /* Compute the equivalent real-mode segment */
        movl    %ebx, %ecx
        shrl    $4, %ecx
        
        /* Patch post-real-mode segment jump */
-       movw    dispatch_table(%ebx,%eax,2),%ax
-       movw    %ax, 101f(%ebx)
-       movw    %cx, 102f(%ebx)
+       movw    (dispatch_table - r_base)(%ebx,%eax,2),%ax
+       movw    %ax, (101f - r_base)(%ebx)
+       movw    %cx, (102f - r_base)(%ebx)
 
        /* Set up the IDT for real mode. */
-       lidtl   machine_real_restart_idt(%ebx)
+       lidtl   (machine_real_restart_idt - r_base)(%ebx)
 
        /*
         * Set up a GDT from which we can load segment descriptors for real
         * mode.  The GDT is not used in real mode; it is just needed here to
         * prepare the descriptors.
         */
-       lgdtl   machine_real_restart_gdt(%ebx)
+       lgdtl   (machine_real_restart_gdt - r_base)(%ebx)
 
        /*
         * Load the data segment registers with 16-bit compatible values
index e8c00cc..85b52fc 100644 (file)
@@ -306,7 +306,7 @@ int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
                bi->end = min(bi->end, high);
 
                /* and there's no empty block */
-               if (bi->start == bi->end) {
+               if (bi->start >= bi->end) {
                        numa_remove_memblk_from(i--, mi);
                        continue;
                }
index 2d6d226..e70be38 100644 (file)
                                                   "pciclass0c03";
 
                                        reg = <0x16800 0x0 0x0 0x0 0x0>;
-                                       interrupts = <22 3>;
+                                       interrupts = <22 1>;
                                };
 
                                usb@d,1 {
                                                   "pciclass0c03";
 
                                        reg = <0x16900 0x0 0x0 0x0 0x0>;
-                                       interrupts = <22 3>;
+                                       interrupts = <22 1>;
                                };
 
                                sata@e,0 {
                                                   "pciclass0106";
 
                                        reg = <0x17000 0x0 0x0 0x0 0x0>;
-                                       interrupts = <23 3>;
+                                       interrupts = <23 1>;
                                };
 
                                flash@f,0 {
index aef7af9..55c965b 100644 (file)
@@ -1463,6 +1463,119 @@ static int xen_pgd_alloc(struct mm_struct *mm)
        return ret;
 }
 
+#ifdef CONFIG_X86_64
+static __initdata u64 __last_pgt_set_rw = 0;
+static __initdata u64 __pgt_buf_start = 0;
+static __initdata u64 __pgt_buf_end = 0;
+static __initdata u64 __pgt_buf_top = 0;
+/*
+ * As a consequence of the commit:
+ * 
+ * commit 4b239f458c229de044d6905c2b0f9fe16ed9e01e
+ * Author: Yinghai Lu <yinghai@kernel.org>
+ * Date:   Fri Dec 17 16:58:28 2010 -0800
+ * 
+ *     x86-64, mm: Put early page table high
+ * 
+ * at some point init_memory_mapping is going to reach the pagetable pages
+ * area and map those pages too (mapping them as normal memory that falls
+ * in the range of addresses passed to init_memory_mapping as argument).
+ * Some of those pages are already pagetable pages (they are in the range
+ * pgt_buf_start-pgt_buf_end) therefore they are going to be mapped RO and
+ * everything is fine.
+ * Some of these pages are not pagetable pages yet (they fall in the range
+ * pgt_buf_end-pgt_buf_top; for example the page at pgt_buf_end) so they
+ * are going to be mapped RW.  When these pages become pagetable pages and
+ * are hooked into the pagetable, xen will find that the guest has already
+ * a RW mapping of them somewhere and fail the operation.
+ * The reason Xen requires pagetables to be RO is that the hypervisor needs
+ * to verify that the pagetables are valid before using them. The validation
+ * operations are called "pinning".
+ * 
+ * In order to fix the issue we mark all the pages in the entire range
+ * pgt_buf_start-pgt_buf_top as RO, however when the pagetable allocation
+ * is completed only the range pgt_buf_start-pgt_buf_end is reserved by
+ * init_memory_mapping. Hence the kernel is going to crash as soon as one
+ * of the pages in the range pgt_buf_end-pgt_buf_top is reused (b/c those
+ * ranges are RO).
+ * 
+ * For this reason, 'mark_rw_past_pgt' is introduced which is called _after_
+ * the init_memory_mapping has completed (in a perfect world we would
+ * call this function from init_memory_mapping, but lets ignore that).
+ * 
+ * Because we are called _after_ init_memory_mapping the pgt_buf_[start,
+ * end,top] have all changed to new values (b/c init_memory_mapping
+ * is called and setting up another new page-table). Hence, the first time
+ * we enter this function, we save away the pgt_buf_start value and update
+ * the pgt_buf_[end,top].
+ * 
+ * When we detect that the "old" pgt_buf_start through pgt_buf_end
+ * PFNs have been reserved (so memblock_x86_reserve_range has been called),
+ * we immediately set out to RW the "old" pgt_buf_end through pgt_buf_top.
+ * 
+ * And then we update those "old" pgt_buf_[end|top] with the new ones
+ * so that we can redo this on the next pagetable.
+ */
+static __init void mark_rw_past_pgt(void) {
+
+       if (pgt_buf_end > pgt_buf_start) {
+               u64 addr, size;
+
+               /* Save it away. */
+               if (!__pgt_buf_start) {
+                       __pgt_buf_start = pgt_buf_start;
+                       __pgt_buf_end = pgt_buf_end;
+                       __pgt_buf_top = pgt_buf_top;
+                       return;
+               }
+               /* If we get the range that starts at __pgt_buf_end that means
+                * the range is reserved, and that in 'init_memory_mapping'
+                * the 'memblock_x86_reserve_range' has been called with the
+                * outdated __pgt_buf_start, __pgt_buf_end (the "new"
+                * pgt_buf_[start|end|top] refer now to a new pagetable.
+                * Note: we are called _after_ the pgt_buf_[..] have been
+                * updated.*/
+
+               addr = memblock_x86_find_in_range_size(PFN_PHYS(__pgt_buf_start),
+                                                      &size, PAGE_SIZE);
+
+               /* Still not reserved, meaning 'memblock_x86_reserve_range'
+                * hasn't been called yet. Update the _end and _top.*/
+               if (addr == PFN_PHYS(__pgt_buf_start)) {
+                       __pgt_buf_end = pgt_buf_end;
+                       __pgt_buf_top = pgt_buf_top;
+                       return;
+               }
+
+               /* OK, the area is reserved, meaning it is time for us to
+                * set RW for the old end->top PFNs. */
+
+               /* ..unless we had already done this. */
+               if (__pgt_buf_end == __last_pgt_set_rw)
+                       return;
+
+               addr = PFN_PHYS(__pgt_buf_end);
+               
+               /* set as RW the rest */
+               printk(KERN_DEBUG "xen: setting RW the range %llx - %llx\n",
+                       PFN_PHYS(__pgt_buf_end), PFN_PHYS(__pgt_buf_top));
+               
+               while (addr < PFN_PHYS(__pgt_buf_top)) {
+                       make_lowmem_page_readwrite(__va(addr));
+                       addr += PAGE_SIZE;
+               }
+               /* And update everything so that we are ready for the next
+                * pagetable (the one created for regions past 4GB) */
+               __last_pgt_set_rw = __pgt_buf_end;
+               __pgt_buf_start = pgt_buf_start;
+               __pgt_buf_end = pgt_buf_end;
+               __pgt_buf_top = pgt_buf_top;
+       }
+       return;
+}
+#else
+static __init void mark_rw_past_pgt(void) { }
+#endif
 static void xen_pgd_free(struct mm_struct *mm, pgd_t *pgd)
 {
 #ifdef CONFIG_X86_64
@@ -1488,6 +1601,14 @@ static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
 {
        unsigned long pfn = pte_pfn(pte);
 
+       /*
+        * A bit of optimization. We do not need to call the workaround
+        * when xen_set_pte_init is called with a PTE with 0 as PFN.
+        * That is b/c the pagetable at that point are just being populated
+        * with empty values and we can save some cycles by not calling
+        * the 'memblock' code.*/
+       if (pfn)
+               mark_rw_past_pgt();
        /*
         * If the new pfn is within the range of the newly allocated
         * kernel pagetable, and it isn't being mapped into an
@@ -1495,7 +1616,7 @@ static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
         * it is RO.
         */
        if (((!is_early_ioremap_ptep(ptep) &&
-                       pfn >= pgt_buf_start && pfn < pgt_buf_end)) ||
+                       pfn >= pgt_buf_start && pfn < pgt_buf_top)) ||
                        (is_early_ioremap_ptep(ptep) && pfn != (pgt_buf_end - 1)))
                pte = pte_wrprotect(pte);
 
@@ -1997,6 +2118,8 @@ __init void xen_ident_map_ISA(void)
 
 static __init void xen_post_allocator_init(void)
 {
+       mark_rw_past_pgt();
+
 #ifdef CONFIG_XEN_DEBUG
        pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte_debug);
 #endif
index b136c9c..449c556 100644 (file)
@@ -943,6 +943,10 @@ static int acpi_bus_get_flags(struct acpi_device *device)
        if (ACPI_SUCCESS(status))
                device->flags.lockable = 1;
 
+       /* Power resources cannot be power manageable. */
+       if (device->device_type == ACPI_BUS_TYPE_POWER)
+               return 0;
+
        /* Presence of _PS0|_PR0 indicates 'power manageable' */
        status = acpi_get_handle(device->handle, "_PS0", &temp);
        if (ACPI_FAILURE(status))
index 39d829c..71afe03 100644 (file)
@@ -150,7 +150,7 @@ static const struct ata_port_info ahci_port_info[] = {
        {
                AHCI_HFLAGS     (AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
                                 AHCI_HFLAG_YES_NCQ),
-               .flags          = AHCI_FLAG_COMMON,
+               .flags          = AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
                .pio_mask       = ATA_PIO4,
                .udma_mask      = ATA_UDMA6,
                .port_ops       = &ahci_ops,
@@ -261,6 +261,12 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
        { PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */
        { PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
+       { PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */
+       { PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */
+       { PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */
+       { PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
+       { PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
+       { PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */
 
        /* JMicron 360/1/3/5/6, match class to avoid IDE function */
        { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
index 3986500..12c5282 100644 (file)
@@ -229,6 +229,10 @@ enum {
        EM_CTL_ALHD             = (1 << 26), /* Activity LED */
        EM_CTL_XMT              = (1 << 25), /* Transmit Only */
        EM_CTL_SMB              = (1 << 24), /* Single Message Buffer */
+       EM_CTL_SGPIO            = (1 << 19), /* SGPIO messages supported */
+       EM_CTL_SES              = (1 << 18), /* SES-2 messages supported */
+       EM_CTL_SAFTE            = (1 << 17), /* SAF-TE messages supported */
+       EM_CTL_LED              = (1 << 16), /* LED messages supported */
 
        /* em message type */
        EM_MSG_TYPE_LED         = (1 << 0), /* LED */
index 0bc3fd6..6f6e771 100644 (file)
@@ -309,6 +309,14 @@ static const struct pci_device_id piix_pci_tbl[] = {
        { 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
        /* SATA Controller IDE (PBG) */
        { 0x8086, 0x1d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+       /* SATA Controller IDE (Panther Point) */
+       { 0x8086, 0x1e00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+       /* SATA Controller IDE (Panther Point) */
+       { 0x8086, 0x1e01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+       /* SATA Controller IDE (Panther Point) */
+       { 0x8086, 0x1e08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+       /* SATA Controller IDE (Panther Point) */
+       { 0x8086, 0x1e09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
        { }     /* terminate list */
 };
 
index 26d4523..ff9d832 100644 (file)
@@ -109,6 +109,8 @@ static ssize_t ahci_read_em_buffer(struct device *dev,
 static ssize_t ahci_store_em_buffer(struct device *dev,
                                    struct device_attribute *attr,
                                    const char *buf, size_t size);
+static ssize_t ahci_show_em_supported(struct device *dev,
+                                     struct device_attribute *attr, char *buf);
 
 static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
 static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
@@ -116,6 +118,7 @@ static DEVICE_ATTR(ahci_host_version, S_IRUGO, ahci_show_host_version, NULL);
 static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
 static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO,
                   ahci_read_em_buffer, ahci_store_em_buffer);
+static DEVICE_ATTR(em_message_supported, S_IRUGO, ahci_show_em_supported, NULL);
 
 struct device_attribute *ahci_shost_attrs[] = {
        &dev_attr_link_power_management_policy,
@@ -126,6 +129,7 @@ struct device_attribute *ahci_shost_attrs[] = {
        &dev_attr_ahci_host_version,
        &dev_attr_ahci_port_cmd,
        &dev_attr_em_buffer,
+       &dev_attr_em_message_supported,
        NULL
 };
 EXPORT_SYMBOL_GPL(ahci_shost_attrs);
@@ -343,6 +347,24 @@ static ssize_t ahci_store_em_buffer(struct device *dev,
        return size;
 }
 
+static ssize_t ahci_show_em_supported(struct device *dev,
+                                     struct device_attribute *attr, char *buf)
+{
+       struct Scsi_Host *shost = class_to_shost(dev);
+       struct ata_port *ap = ata_shost_to_port(shost);
+       struct ahci_host_priv *hpriv = ap->host->private_data;
+       void __iomem *mmio = hpriv->mmio;
+       u32 em_ctl;
+
+       em_ctl = readl(mmio + HOST_EM_CTL);
+
+       return sprintf(buf, "%s%s%s%s\n",
+                      em_ctl & EM_CTL_LED ? "led " : "",
+                      em_ctl & EM_CTL_SAFTE ? "saf-te " : "",
+                      em_ctl & EM_CTL_SES ? "ses-2 " : "",
+                      em_ctl & EM_CTL_SGPIO ? "sgpio " : "");
+}
+
 /**
  *     ahci_save_initial_config - Save and fixup initial config values
  *     @dev: target AHCI device
@@ -539,6 +561,27 @@ void ahci_start_engine(struct ata_port *ap)
 {
        void __iomem *port_mmio = ahci_port_base(ap);
        u32 tmp;
+       u8 status;
+
+       status = readl(port_mmio + PORT_TFDATA) & 0xFF;
+
+       /*
+        * At end of section 10.1 of AHCI spec (rev 1.3), it states
+        * Software shall not set PxCMD.ST to 1 until it is determined
+        * that a functoinal device is present on the port as determined by
+        * PxTFD.STS.BSY=0, PxTFD.STS.DRQ=0 and PxSSTS.DET=3h
+        *
+        * Even though most AHCI host controllers work without this check,
+        * specific controller will fail under this condition
+        */
+       if (status & (ATA_BUSY | ATA_DRQ))
+               return;
+       else {
+               ahci_scr_read(&ap->link, SCR_STATUS, &tmp);
+
+               if ((tmp & 0xf) != 0x3)
+                       return;
+       }
 
        /* start DMA */
        tmp = readl(port_mmio + PORT_CMD);
@@ -1897,7 +1940,17 @@ static void ahci_pmp_attach(struct ata_port *ap)
        ahci_enable_fbs(ap);
 
        pp->intr_mask |= PORT_IRQ_BAD_PMP;
-       writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+       /*
+        * We must not change the port interrupt mask register if the
+        * port is marked frozen, the value in pp->intr_mask will be
+        * restored later when the port is thawed.
+        *
+        * Note that during initialization, the port is marked as
+        * frozen since the irq handler is not yet registered.
+        */
+       if (!(ap->pflags & ATA_PFLAG_FROZEN))
+               writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
 }
 
 static void ahci_pmp_detach(struct ata_port *ap)
@@ -1913,7 +1966,10 @@ static void ahci_pmp_detach(struct ata_port *ap)
        writel(cmd, port_mmio + PORT_CMD);
 
        pp->intr_mask &= ~PORT_IRQ_BAD_PMP;
-       writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+       /* see comment above in ahci_pmp_attach() */
+       if (!(ap->pflags & ATA_PFLAG_FROZEN))
+               writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
 }
 
 int ahci_port_resume(struct ata_port *ap)
index 423c0a6..76c3c15 100644 (file)
@@ -4139,6 +4139,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
         */
        { "PIONEER DVD-RW  DVRTD08",    "1.00", ATA_HORKAGE_NOSETXFER },
        { "PIONEER DVD-RW  DVR-212D",   "1.28", ATA_HORKAGE_NOSETXFER },
+       { "PIONEER DVD-RW  DVR-216D",   "1.08", ATA_HORKAGE_NOSETXFER },
 
        /* End Marker */
        { }
@@ -5480,7 +5481,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
        if (!ap)
                return NULL;
 
-       ap->pflags |= ATA_PFLAG_INITIALIZING;
+       ap->pflags |= ATA_PFLAG_INITIALIZING | ATA_PFLAG_FROZEN;
        ap->lock = &host->lock;
        ap->print_id = -1;
        ap->host = host;
index 88cd22f..f26f2fe 100644 (file)
@@ -3316,6 +3316,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
        struct ata_eh_context *ehc = &link->eh_context;
        struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL;
        enum ata_lpm_policy old_policy = link->lpm_policy;
+       bool no_dipm = ap->flags & ATA_FLAG_NO_DIPM;
        unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;
        unsigned int err_mask;
        int rc;
@@ -3332,7 +3333,7 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
         */
        ata_for_each_dev(dev, link, ENABLED) {
                bool hipm = ata_id_has_hipm(dev->id);
-               bool dipm = ata_id_has_dipm(dev->id);
+               bool dipm = ata_id_has_dipm(dev->id) && !no_dipm;
 
                /* find the first enabled and LPM enabled devices */
                if (!link_dev)
@@ -3389,7 +3390,8 @@ static int ata_eh_set_lpm(struct ata_link *link, enum ata_lpm_policy policy,
 
        /* host config updated, enable DIPM if transitioning to MIN_POWER */
        ata_for_each_dev(dev, link, ENABLED) {
-               if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) {
+               if (policy == ATA_LPM_MIN_POWER && !no_dipm &&
+                   ata_id_has_dipm(dev->id)) {
                        err_mask = ata_dev_set_feature(dev,
                                        SETFEATURES_SATA_ENABLE, SATA_DIPM);
                        if (err_mask && err_mask != AC_ERR_DEV) {
index 0da0dcc..a5fdbdc 100644 (file)
 
 
 #define DRV_NAME "pata_at91"
-#define DRV_VERSION "0.1"
+#define DRV_VERSION "0.2"
 
 #define CF_IDE_OFFSET      0x00c00000
 #define CF_ALT_IDE_OFFSET   0x00e00000
 #define CF_IDE_RES_SIZE     0x08
+#define NCS_RD_PULSE_LIMIT  0x3f /* maximal value for pulse bitfields */
 
 struct at91_ide_info {
        unsigned long mode;
@@ -49,8 +50,18 @@ struct at91_ide_info {
        void __iomem *alt_addr;
 };
 
-static const struct ata_timing initial_timing =
-       {XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0};
+static const struct ata_timing initial_timing = {
+       .mode           = XFER_PIO_0,
+       .setup          = 70,
+       .act8b          = 290,
+       .rec8b          = 240,
+       .cyc8b          = 600,
+       .active         = 165,
+       .recover        = 150,
+       .dmack_hold     = 0,
+       .cycle          = 600,
+       .udma           = 0
+};
 
 static unsigned long calc_mck_cycles(unsigned long ns, unsigned long mck_hz)
 {
@@ -109,6 +120,11 @@ static void set_smc_timing(struct device *dev,
        /* (CS0, CS1, DIR, OE) <= (CFCE1, CFCE2, CFRNW, NCSX) timings */
        ncs_read_setup = 1;
        ncs_read_pulse = read_cycle - 2;
+       if (ncs_read_pulse > NCS_RD_PULSE_LIMIT) {
+               ncs_read_pulse = NCS_RD_PULSE_LIMIT;
+               dev_warn(dev, "ncs_read_pulse limited to maximal value %lu\n",
+                       ncs_read_pulse);
+       }
 
        /* Write timings same as read timings */
        write_cycle = read_cycle;
index fbc5b6e..abe3ab7 100644 (file)
@@ -63,6 +63,7 @@ void device_pm_init(struct device *dev)
        dev->power.wakeup = NULL;
        spin_lock_init(&dev->power.lock);
        pm_runtime_init(dev);
+       INIT_LIST_HEAD(&dev->power.entry);
 }
 
 /**
index 4573c83..abbbd33 100644 (file)
@@ -258,7 +258,7 @@ void device_set_wakeup_capable(struct device *dev, bool capable)
        if (!!dev->power.can_wakeup == !!capable)
                return;
 
-       if (device_is_registered(dev)) {
+       if (device_is_registered(dev) && !list_empty(&dev->power.entry)) {
                if (capable) {
                        if (wakeup_sysfs_add(dev))
                                return;
index 90af294..c126db3 100644 (file)
@@ -73,6 +73,7 @@ int syscore_suspend(void)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(syscore_suspend);
 
 /**
  * syscore_resume - Execute all the registered system core resume callbacks.
@@ -95,6 +96,7 @@ void syscore_resume(void)
                                "Interrupts enabled after %pF\n", ops->resume);
                }
 }
+EXPORT_SYMBOL_GPL(syscore_resume);
 #endif /* CONFIG_PM_SLEEP */
 
 /**
index 16dc364..3e90471 100644 (file)
@@ -777,9 +777,9 @@ static int rbd_do_request(struct request *rq,
                                      ops,
                                      false,
                                      GFP_NOIO, pages, bio);
-       if (IS_ERR(req)) {
+       if (!req) {
                up_read(&header->snap_rwsem);
-               ret = PTR_ERR(req);
+               ret = -ENOMEM;
                goto done_pages;
        }
 
index 0fc0a79..6db161f 100644 (file)
@@ -32,10 +32,9 @@ static DEFINE_MUTEX(clocks_mutex);
  * Then we take the most specific entry - with the following
  * order of precedence: dev+con > dev only > con only.
  */
-static struct clk *clk_find(const char *dev_id, const char *con_id)
+static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
 {
-       struct clk_lookup *p;
-       struct clk *clk = NULL;
+       struct clk_lookup *p, *cl = NULL;
        int match, best = 0;
 
        list_for_each_entry(p, &clocks, node) {
@@ -52,27 +51,27 @@ static struct clk *clk_find(const char *dev_id, const char *con_id)
                }
 
                if (match > best) {
-                       clk = p->clk;
+                       cl = p;
                        if (match != 3)
                                best = match;
                        else
                                break;
                }
        }
-       return clk;
+       return cl;
 }
 
 struct clk *clk_get_sys(const char *dev_id, const char *con_id)
 {
-       struct clk *clk;
+       struct clk_lookup *cl;
 
        mutex_lock(&clocks_mutex);
-       clk = clk_find(dev_id, con_id);
-       if (clk && !__clk_get(clk))
-               clk = NULL;
+       cl = clk_find(dev_id, con_id);
+       if (cl && !__clk_get(cl->clk))
+               cl = NULL;
        mutex_unlock(&clocks_mutex);
 
-       return clk ? clk : ERR_PTR(-ENOENT);
+       return cl ? cl->clk : ERR_PTR(-ENOENT);
 }
 EXPORT_SYMBOL(clk_get_sys);
 
index 31e71c4..9a8bebc 100644 (file)
@@ -211,8 +211,6 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci)
 
        scrubval = scrubval & 0x001F;
 
-       amd64_debug("pci-read, sdram scrub control value: %d\n", scrubval);
-
        for (i = 0; i < ARRAY_SIZE(scrubrates); i++) {
                if (scrubrates[i].scrubval == scrubval) {
                        retval = scrubrates[i].bandwidth;
@@ -933,25 +931,74 @@ static int k8_early_channel_count(struct amd64_pvt *pvt)
 /* On F10h and later ErrAddr is MC4_ADDR[47:1] */
 static u64 get_error_address(struct mce *m)
 {
+       struct cpuinfo_x86 *c = &boot_cpu_data;
+       u64 addr;
        u8 start_bit = 1;
        u8 end_bit   = 47;
 
-       if (boot_cpu_data.x86 == 0xf) {
+       if (c->x86 == 0xf) {
                start_bit = 3;
                end_bit   = 39;
        }
 
-       return m->addr & GENMASK(start_bit, end_bit);
+       addr = m->addr & GENMASK(start_bit, end_bit);
+
+       /*
+        * Erratum 637 workaround
+        */
+       if (c->x86 == 0x15) {
+               struct amd64_pvt *pvt;
+               u64 cc6_base, tmp_addr;
+               u32 tmp;
+               u8 mce_nid, intlv_en;
+
+               if ((addr & GENMASK(24, 47)) >> 24 != 0x00fdf7)
+                       return addr;
+
+               mce_nid = amd_get_nb_id(m->extcpu);
+               pvt     = mcis[mce_nid]->pvt_info;
+
+               amd64_read_pci_cfg(pvt->F1, DRAM_LOCAL_NODE_LIM, &tmp);
+               intlv_en = tmp >> 21 & 0x7;
+
+               /* add [47:27] + 3 trailing bits */
+               cc6_base  = (tmp & GENMASK(0, 20)) << 3;
+
+               /* reverse and add DramIntlvEn */
+               cc6_base |= intlv_en ^ 0x7;
+
+               /* pin at [47:24] */
+               cc6_base <<= 24;
+
+               if (!intlv_en)
+                       return cc6_base | (addr & GENMASK(0, 23));
+
+               amd64_read_pci_cfg(pvt->F1, DRAM_LOCAL_NODE_BASE, &tmp);
+
+                                                       /* faster log2 */
+               tmp_addr  = (addr & GENMASK(12, 23)) << __fls(intlv_en + 1);
+
+               /* OR DramIntlvSel into bits [14:12] */
+               tmp_addr |= (tmp & GENMASK(21, 23)) >> 9;
+
+               /* add remaining [11:0] bits from original MC4_ADDR */
+               tmp_addr |= addr & GENMASK(0, 11);
+
+               return cc6_base | tmp_addr;
+       }
+
+       return addr;
 }
 
 static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range)
 {
+       struct cpuinfo_x86 *c = &boot_cpu_data;
        int off = range << 3;
 
        amd64_read_pci_cfg(pvt->F1, DRAM_BASE_LO + off,  &pvt->ranges[range].base.lo);
        amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_LO + off, &pvt->ranges[range].lim.lo);
 
-       if (boot_cpu_data.x86 == 0xf)
+       if (c->x86 == 0xf)
                return;
 
        if (!dram_rw(pvt, range))
@@ -959,6 +1006,31 @@ static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range)
 
        amd64_read_pci_cfg(pvt->F1, DRAM_BASE_HI + off,  &pvt->ranges[range].base.hi);
        amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_HI + off, &pvt->ranges[range].lim.hi);
+
+       /* Factor in CC6 save area by reading dst node's limit reg */
+       if (c->x86 == 0x15) {
+               struct pci_dev *f1 = NULL;
+               u8 nid = dram_dst_node(pvt, range);
+               u32 llim;
+
+               f1 = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0x18 + nid, 1));
+               if (WARN_ON(!f1))
+                       return;
+
+               amd64_read_pci_cfg(f1, DRAM_LOCAL_NODE_LIM, &llim);
+
+               pvt->ranges[range].lim.lo &= GENMASK(0, 15);
+
+                                           /* {[39:27],111b} */
+               pvt->ranges[range].lim.lo |= ((llim & 0x1fff) << 3 | 0x7) << 16;
+
+               pvt->ranges[range].lim.hi &= GENMASK(0, 7);
+
+                                           /* [47:40] */
+               pvt->ranges[range].lim.hi |= llim >> 13;
+
+               pci_dev_put(f1);
+       }
 }
 
 static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
@@ -1403,12 +1475,8 @@ static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range,
                return -EINVAL;
        }
 
-       if (intlv_en &&
-           (intlv_sel != ((sys_addr >> 12) & intlv_en))) {
-               amd64_warn("Botched intlv bits, en: 0x%x, sel: 0x%x\n",
-                          intlv_en, intlv_sel);
+       if (intlv_en && (intlv_sel != ((sys_addr >> 12) & intlv_en)))
                return -EINVAL;
-       }
 
        sys_addr = f1x_swap_interleaved_region(pvt, sys_addr);
 
index 11be36a..9a666cb 100644 (file)
 
 #define DCT_CFG_SEL                    0x10C
 
+#define DRAM_LOCAL_NODE_BASE           0x120
+#define DRAM_LOCAL_NODE_LIM            0x124
+
 #define DRAM_BASE_HI                   0x140
 #define DRAM_LIMIT_HI                  0x144
 
index 26343fd..29ffa35 100644 (file)
@@ -458,13 +458,13 @@ static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci,
                return -EINVAL;
 
        new_bw = mci->set_sdram_scrub_rate(mci, bandwidth);
-       if (new_bw >= 0) {
-               edac_printk(KERN_DEBUG, EDAC_MC, "Scrub rate set to %d\n", new_bw);
-               return count;
+       if (new_bw < 0) {
+               edac_printk(KERN_WARNING, EDAC_MC,
+                           "Error setting scrub rate to: %lu\n", bandwidth);
+               return -EINVAL;
        }
 
-       edac_printk(KERN_DEBUG, EDAC_MC, "Error setting scrub rate to: %lu\n", bandwidth);
-       return -EINVAL;
+       return count;
 }
 
 /*
@@ -483,7 +483,6 @@ static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data)
                return bandwidth;
        }
 
-       edac_printk(KERN_DEBUG, EDAC_MC, "Read scrub rate: %d\n", bandwidth);
        return sprintf(data, "%d\n", bandwidth);
 }
 
index f903d7b..23d1468 100644 (file)
@@ -2199,7 +2199,6 @@ static int ohci_set_config_rom(struct fw_card *card,
 {
        struct fw_ohci *ohci;
        unsigned long flags;
-       int ret = -EBUSY;
        __be32 *next_config_rom;
        dma_addr_t uninitialized_var(next_config_rom_bus);
 
@@ -2240,22 +2239,37 @@ static int ohci_set_config_rom(struct fw_card *card,
 
        spin_lock_irqsave(&ohci->lock, flags);
 
+       /*
+        * If there is not an already pending config_rom update,
+        * push our new allocation into the ohci->next_config_rom
+        * and then mark the local variable as null so that we
+        * won't deallocate the new buffer.
+        *
+        * OTOH, if there is a pending config_rom update, just
+        * use that buffer with the new config_rom data, and
+        * let this routine free the unused DMA allocation.
+        */
+
        if (ohci->next_config_rom == NULL) {
                ohci->next_config_rom = next_config_rom;
                ohci->next_config_rom_bus = next_config_rom_bus;
+               next_config_rom = NULL;
+       }
 
-               copy_config_rom(ohci->next_config_rom, config_rom, length);
+       copy_config_rom(ohci->next_config_rom, config_rom, length);
 
-               ohci->next_header = config_rom[0];
-               ohci->next_config_rom[0] = 0;
+       ohci->next_header = config_rom[0];
+       ohci->next_config_rom[0] = 0;
 
-               reg_write(ohci, OHCI1394_ConfigROMmap,
-                         ohci->next_config_rom_bus);
-               ret = 0;
-       }
+       reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus);
 
        spin_unlock_irqrestore(&ohci->lock, flags);
 
+       /* If we didn't use the DMA allocation, delete it. */
+       if (next_config_rom != NULL)
+               dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+                                 next_config_rom, next_config_rom_bus);
+
        /*
         * Now initiate a bus reset to have the changes take
         * effect. We clean up the old config rom memory and DMA
@@ -2263,13 +2277,10 @@ static int ohci_set_config_rom(struct fw_card *card,
         * controller could need to access it before the bus reset
         * takes effect.
         */
-       if (ret == 0)
-               fw_schedule_bus_reset(&ohci->card, true, true);
-       else
-               dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
-                                 next_config_rom, next_config_rom_bus);
 
-       return ret;
+       fw_schedule_bus_reset(&ohci->card, true, true);
+
+       return 0;
 }
 
 static void ohci_send_request(struct fw_card *card, struct fw_packet *packet)
index c58f691..b493663 100644 (file)
@@ -24,6 +24,7 @@ config DRM_KMS_HELPER
        depends on DRM
        select FB
        select FRAMEBUFFER_CONSOLE if !EXPERT
+       select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if FRAMEBUFFER_CONSOLE
        help
          FB and CRTC helpers for KMS drivers.
 
index 9507204..11d7a72 100644 (file)
@@ -342,9 +342,22 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
 }
 EXPORT_SYMBOL(drm_fb_helper_debug_leave);
 
+bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
+{
+       bool error = false;
+       int i, ret;
+       for (i = 0; i < fb_helper->crtc_count; i++) {
+               struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
+               ret = drm_crtc_helper_set_config(mode_set);
+               if (ret)
+                       error = true;
+       }
+       return error;
+}
+EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode);
+
 bool drm_fb_helper_force_kernel_mode(void)
 {
-       int i = 0;
        bool ret, error = false;
        struct drm_fb_helper *helper;
 
@@ -352,12 +365,12 @@ bool drm_fb_helper_force_kernel_mode(void)
                return false;
 
        list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
-               for (i = 0; i < helper->crtc_count; i++) {
-                       struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
-                       ret = drm_crtc_helper_set_config(mode_set);
-                       if (ret)
-                               error = true;
-               }
+               if (helper->dev->switch_power_state == DRM_SWITCH_POWER_OFF)
+                       continue;
+
+               ret = drm_fb_helper_restore_fbdev_mode(helper);
+               if (ret)
+                       error = true;
        }
        return error;
 }
index 741457b..a1f12cb 100644 (file)
@@ -932,11 +932,34 @@ EXPORT_SYMBOL(drm_vblank_put);
 
 void drm_vblank_off(struct drm_device *dev, int crtc)
 {
+       struct drm_pending_vblank_event *e, *t;
+       struct timeval now;
        unsigned long irqflags;
+       unsigned int seq;
 
        spin_lock_irqsave(&dev->vbl_lock, irqflags);
        vblank_disable_and_save(dev, crtc);
        DRM_WAKEUP(&dev->vbl_queue[crtc]);
+
+       /* Send any queued vblank events, lest the natives grow disquiet */
+       seq = drm_vblank_count_and_time(dev, crtc, &now);
+       list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
+               if (e->pipe != crtc)
+                       continue;
+               DRM_DEBUG("Sending premature vblank event on disable: \
+                         wanted %d, current %d\n",
+                         e->event.sequence, seq);
+
+               e->event.sequence = seq;
+               e->event.tv_sec = now.tv_sec;
+               e->event.tv_usec = now.tv_usec;
+               drm_vblank_put(dev, e->pipe);
+               list_move_tail(&e->base.link, &e->base.file_priv->event_list);
+               wake_up_interruptible(&e->base.file_priv->event_wait);
+               trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
+                                                e->event.sequence);
+       }
+
        spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 }
 EXPORT_SYMBOL(drm_vblank_off);
index 7273037..12876f2 100644 (file)
@@ -2207,7 +2207,7 @@ void i915_driver_lastclose(struct drm_device * dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
 
        if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) {
-               drm_fb_helper_restore();
+               intel_fb_restore_mode(dev);
                vga_switcheroo_process_delayed_switch();
                return;
        }
index f5b0d83..1d20712 100644 (file)
@@ -338,4 +338,5 @@ extern int intel_overlay_attrs(struct drm_device *dev, void *data,
                               struct drm_file *file_priv);
 
 extern void intel_fb_output_poll_changed(struct drm_device *dev);
+extern void intel_fb_restore_mode(struct drm_device *dev);
 #endif /* __INTEL_DRV_H__ */
index 5127827..ec49bae 100644 (file)
@@ -264,3 +264,13 @@ void intel_fb_output_poll_changed(struct drm_device *dev)
        drm_i915_private_t *dev_priv = dev->dev_private;
        drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
 }
+
+void intel_fb_restore_mode(struct drm_device *dev)
+{
+       int ret;
+       drm_i915_private_t *dev_priv = dev->dev_private;
+
+       ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
+       if (ret)
+               DRM_DEBUG("failed to restore crtc mode\n");
+}
index e9bc135..c20eac3 100644 (file)
@@ -862,9 +862,15 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev)
                SYSTEM_ACCESS_MODE_NOT_IN_SYS |
                SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU |
                EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5);
-       WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
-       WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
-       WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+       if (rdev->flags & RADEON_IS_IGP) {
+               WREG32(FUS_MC_VM_MD_L1_TLB0_CNTL, tmp);
+               WREG32(FUS_MC_VM_MD_L1_TLB1_CNTL, tmp);
+               WREG32(FUS_MC_VM_MD_L1_TLB2_CNTL, tmp);
+       } else {
+               WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
+               WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
+               WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+       }
        WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
        WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
        WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
@@ -2923,11 +2929,6 @@ static int evergreen_startup(struct radeon_device *rdev)
                rdev->asic->copy = NULL;
                dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
        }
-       /* XXX: ontario has problems blitting to gart at the moment */
-       if (rdev->family == CHIP_PALM) {
-               rdev->asic->copy = NULL;
-               radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
-       }
 
        /* allocate wb buffer */
        r = radeon_wb_init(rdev);
index 9aaa3f0..9453384 100644 (file)
 #define        MC_VM_MD_L1_TLB0_CNTL                           0x2654
 #define        MC_VM_MD_L1_TLB1_CNTL                           0x2658
 #define        MC_VM_MD_L1_TLB2_CNTL                           0x265C
+
+#define        FUS_MC_VM_MD_L1_TLB0_CNTL                       0x265C
+#define        FUS_MC_VM_MD_L1_TLB1_CNTL                       0x2660
+#define        FUS_MC_VM_MD_L1_TLB2_CNTL                       0x2664
+
 #define        MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR              0x203C
 #define        MC_VM_SYSTEM_APERTURE_HIGH_ADDR                 0x2038
 #define        MC_VM_SYSTEM_APERTURE_LOW_ADDR                  0x2034
index f5d12fb..f116516 100644 (file)
@@ -1599,9 +1599,10 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
                                                        memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0],
                                                               fake_edid_record->ucFakeEDIDLength);
 
-                                                       if (drm_edid_is_valid(edid))
+                                                       if (drm_edid_is_valid(edid)) {
                                                                rdev->mode_info.bios_hardcoded_edid = edid;
-                                                       else
+                                                               rdev->mode_info.bios_hardcoded_edid_size = edid_size;
+                                                       } else
                                                                kfree(edid);
                                                }
                                        }
index bf7d4c0..bd58af6 100644 (file)
@@ -221,6 +221,22 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                        return -EINVAL;
                }
                break;
+       case RADEON_INFO_NUM_TILE_PIPES:
+               if (rdev->family >= CHIP_CAYMAN)
+                       value = rdev->config.cayman.max_tile_pipes;
+               else if (rdev->family >= CHIP_CEDAR)
+                       value = rdev->config.evergreen.max_tile_pipes;
+               else if (rdev->family >= CHIP_RV770)
+                       value = rdev->config.rv770.max_tile_pipes;
+               else if (rdev->family >= CHIP_R600)
+                       value = rdev->config.r600.max_tile_pipes;
+               else {
+                       return -EINVAL;
+               }
+               break;
+       case RADEON_INFO_FUSION_GART_WORKING:
+               value = 1;
+               break;
        default:
                DRM_DEBUG_KMS("Invalid request %d\n", info->request);
                return -EINVAL;
index af0da4a..92f1900 100644 (file)
@@ -708,6 +708,7 @@ r600 0x9400
 0x00028D0C DB_RENDER_CONTROL
 0x00028D10 DB_RENDER_OVERRIDE
 0x0002880C DB_SHADER_CONTROL
+0x00028D28 DB_SRESULTS_COMPARE_STATE0
 0x00028D2C DB_SRESULTS_COMPARE_STATE1
 0x00028430 DB_STENCILREFMASK
 0x00028434 DB_STENCILREFMASK_BF
index 060ef63..50e40db 100644 (file)
@@ -110,8 +110,7 @@ config SENSORS_ADM1021
        help
          If you say yes here you get support for Analog Devices ADM1021
          and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
-         Genesys Logic GL523SM, National Semiconductor LM84, TI THMC10,
-         and the XEON processor built-in sensor.
+         Genesys Logic GL523SM, National Semiconductor LM84 and TI THMC10.
 
          This driver can also be built as a module.  If so, the module
          will be called adm1021.
@@ -618,10 +617,10 @@ config SENSORS_LM90
        depends on I2C
        help
          If you say yes here you get support for National Semiconductor LM90,
-         LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, Maxim
-         MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659,
-         MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, and Winbond/Nuvoton
-         W83L771W/G/AWG/ASG sensor chips.
+         LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A,
+         Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659,
+         MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008,
+         and Winbond/Nuvoton W83L771W/G/AWG/ASG sensor chips.
 
          This driver can also be built as a module.  If so, the module
          will be called lm90.
index 250d099..da72dc1 100644 (file)
@@ -1094,6 +1094,7 @@ static struct attribute *lm85_attributes_minctl[] = {
        &sensor_dev_attr_pwm1_auto_pwm_minctl.dev_attr.attr,
        &sensor_dev_attr_pwm2_auto_pwm_minctl.dev_attr.attr,
        &sensor_dev_attr_pwm3_auto_pwm_minctl.dev_attr.attr,
+       NULL
 };
 
 static const struct attribute_group lm85_group_minctl = {
@@ -1104,6 +1105,7 @@ static struct attribute *lm85_attributes_temp_off[] = {
        &sensor_dev_attr_temp1_auto_temp_off.dev_attr.attr,
        &sensor_dev_attr_temp2_auto_temp_off.dev_attr.attr,
        &sensor_dev_attr_temp3_auto_temp_off.dev_attr.attr,
+       NULL
 };
 
 static const struct attribute_group lm85_group_temp_off = {
@@ -1329,11 +1331,11 @@ static int lm85_probe(struct i2c_client *client,
        if (data->type != emc6d103s) {
                err = sysfs_create_group(&client->dev.kobj, &lm85_group_minctl);
                if (err)
-                       goto err_kfree;
+                       goto err_remove_files;
                err = sysfs_create_group(&client->dev.kobj,
                                         &lm85_group_temp_off);
                if (err)
-                       goto err_kfree;
+                       goto err_remove_files;
        }
 
        /* The ADT7463/68 have an optional VRM 10 mode where pin 21 is used
index c43b4e9..2f94f95 100644 (file)
  * chips, but support three temperature sensors instead of two. MAX6695
  * and MAX6696 only differ in the pinout so they can be treated identically.
  *
- * This driver also supports the ADT7461 chip from Analog Devices.
- * It's supported in both compatibility and extended mode. It is mostly
- * compatible with LM90 except for a data format difference for the
- * temperature value registers.
+ * This driver also supports ADT7461 and ADT7461A from Analog Devices as well as
+ * NCT1008 from ON Semiconductor. The chips are supported in both compatibility
+ * and extended mode. They are mostly compatible with LM90 except for a data
+ * format difference for the temperature value registers.
  *
  * Since the LM90 was the first chipset supported by this driver, most
  * comments will refer to this chipset, but are actually general and
  * Addresses to scan
  * Address is fully defined internally and cannot be changed except for
  * MAX6659, MAX6680 and MAX6681.
- * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6649, MAX6657,
- * MAX6658 and W83L771 have address 0x4c.
- * ADM1032-2, ADT7461-2, LM89-1, LM99-1 and MAX6646 have address 0x4d.
+ * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, ADT7461A, MAX6649,
+ * MAX6657, MAX6658, NCT1008 and W83L771 have address 0x4c.
+ * ADM1032-2, ADT7461-2, ADT7461A-2, LM89-1, LM99-1, MAX6646, and NCT1008D
+ * have address 0x4d.
  * MAX6647 has address 0x4e.
  * MAX6659 can have address 0x4c, 0x4d or 0x4e.
  * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b,
@@ -174,6 +175,7 @@ enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680,
 static const struct i2c_device_id lm90_id[] = {
        { "adm1032", adm1032 },
        { "adt7461", adt7461 },
+       { "adt7461a", adt7461 },
        { "lm90", lm90 },
        { "lm86", lm86 },
        { "lm89", lm86 },
@@ -188,6 +190,7 @@ static const struct i2c_device_id lm90_id[] = {
        { "max6681", max6680 },
        { "max6695", max6696 },
        { "max6696", max6696 },
+       { "nct1008", adt7461 },
        { "w83l771", w83l771 },
        { }
 };
@@ -1153,6 +1156,11 @@ static int lm90_detect(struct i2c_client *new_client,
                 && (reg_config1 & 0x1B) == 0x00
                 && reg_convrate <= 0x0A) {
                        name = "adt7461";
+               } else
+               if (chip_id == 0x57 /* ADT7461A, NCT1008 */
+                && (reg_config1 & 0x1B) == 0x00
+                && reg_convrate <= 0x0A) {
+                       name = "adt7461a";
                }
        } else
        if (man_id == 0x4D) { /* Maxim */
index de58191..5724074 100644 (file)
@@ -98,7 +98,6 @@ static const struct attribute_group twl4030_madc_group = {
 static int __devinit twl4030_madc_hwmon_probe(struct platform_device *pdev)
 {
        int ret;
-       int status;
        struct device *hwmon;
 
        ret = sysfs_create_group(&pdev->dev.kobj, &twl4030_madc_group);
@@ -107,7 +106,7 @@ static int __devinit twl4030_madc_hwmon_probe(struct platform_device *pdev)
        hwmon = hwmon_device_register(&pdev->dev);
        if (IS_ERR(hwmon)) {
                dev_err(&pdev->dev, "hwmon_device_register failed.\n");
-               status = PTR_ERR(hwmon);
+               ret = PTR_ERR(hwmon);
                goto err_reg;
        }
 
index 72c0415..455e909 100644 (file)
                                 SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \
                                 SMBHSTSTS_INTR)
 
+/* Older devices have their ID defined in <linux/pci_ids.h> */
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS  0x1c22
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS     0x1d22
 /* Patsburg also has three 'Integrated Device Function' SMBus controllers */
 #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0        0x1d70
 #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1        0x1d71
 #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2        0x1d72
+#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS     0x2330
+#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS        0x3b30
 
 struct i801_priv {
        struct i2c_adapter adapter;
index 0eb1515..2dbba16 100644 (file)
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------ *
  * i2c-parport.c I2C bus over parallel port                                 *
  * ------------------------------------------------------------------------ *
-   Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org>
+   Copyright (C) 2003-2011 Jean Delvare <khali@linux-fr.org>
    
    Based on older i2c-philips-par.c driver
    Copyright (C) 1995-2000 Simon G. Vogl
@@ -33,6 +33,8 @@
 #include <linux/i2c-algo-bit.h>
 #include <linux/i2c-smbus.h>
 #include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
 #include "i2c-parport.h"
 
 /* ----- Device list ------------------------------------------------------ */
@@ -43,10 +45,11 @@ struct i2c_par {
        struct i2c_algo_bit_data algo_data;
        struct i2c_smbus_alert_setup alert_data;
        struct i2c_client *ara;
-       struct i2c_par *next;
+       struct list_head node;
 };
 
-static struct i2c_par *adapter_list;
+static LIST_HEAD(adapter_list);
+static DEFINE_MUTEX(adapter_list_lock);
 
 /* ----- Low-level parallel port access ----------------------------------- */
 
@@ -228,8 +231,9 @@ static void i2c_parport_attach (struct parport *port)
        }
 
        /* Add the new adapter to the list */
-       adapter->next = adapter_list;
-       adapter_list = adapter;
+       mutex_lock(&adapter_list_lock);
+       list_add_tail(&adapter->node, &adapter_list);
+       mutex_unlock(&adapter_list_lock);
         return;
 
 ERROR1:
@@ -241,11 +245,11 @@ ERROR0:
 
 static void i2c_parport_detach (struct parport *port)
 {
-       struct i2c_par *adapter, *prev;
+       struct i2c_par *adapter, *_n;
 
        /* Walk the list */
-       for (prev = NULL, adapter = adapter_list; adapter;
-            prev = adapter, adapter = adapter->next) {
+       mutex_lock(&adapter_list_lock);
+       list_for_each_entry_safe(adapter, _n, &adapter_list, node) {
                if (adapter->pdev->port == port) {
                        if (adapter->ara) {
                                parport_disable_irq(port);
@@ -259,14 +263,11 @@ static void i2c_parport_detach (struct parport *port)
                                
                        parport_release(adapter->pdev);
                        parport_unregister_device(adapter->pdev);
-                       if (prev)
-                               prev->next = adapter->next;
-                       else
-                               adapter_list = adapter->next;
+                       list_del(&adapter->node);
                        kfree(adapter);
-                       return;
                }
        }
+       mutex_unlock(&adapter_list_lock);
 }
 
 static struct parport_driver i2c_parport_driver = {
index 7de4b7e..d8ca0a0 100644 (file)
@@ -1799,7 +1799,7 @@ static int qib_6120_setup_reset(struct qib_devdata *dd)
        /*
         * Keep chip from being accessed until we are ready.  Use
         * writeq() directly, to allow the write even though QIB_PRESENT
-        * isn't' set.
+        * isn't set.
         */
        dd->flags &= ~(QIB_INITTED | QIB_PRESENT);
        dd->int_counter = 0; /* so we check interrupts work again */
index 74fe036..c765a2e 100644 (file)
@@ -2111,7 +2111,7 @@ static int qib_setup_7220_reset(struct qib_devdata *dd)
        /*
         * Keep chip from being accessed until we are ready.  Use
         * writeq() directly, to allow the write even though QIB_PRESENT
-        * isn't' set.
+        * isn't set.
         */
        dd->flags &= ~(QIB_INITTED | QIB_PRESENT);
        dd->int_counter = 0; /* so we check interrupts work again */
index 55de3cf..6bab3ea 100644 (file)
@@ -3299,7 +3299,7 @@ static int qib_do_7322_reset(struct qib_devdata *dd)
        /*
         * Keep chip from being accessed until we are ready.  Use
         * writeq() directly, to allow the write even though QIB_PRESENT
-        * isn't' set.
+        * isn't set.
         */
        dd->flags &= ~(QIB_INITTED | QIB_PRESENT | QIB_BADINTR);
        dd->flags |= QIB_DOING_RESET;
index 6ae054f..9175d49 100644 (file)
@@ -68,8 +68,23 @@ struct wm831x_ts {
        unsigned int pd_irq;
        bool pressure;
        bool pen_down;
+       struct work_struct pd_data_work;
 };
 
+static void wm831x_pd_data_work(struct work_struct *work)
+{
+       struct wm831x_ts *wm831x_ts =
+               container_of(work, struct wm831x_ts, pd_data_work);
+
+       if (wm831x_ts->pen_down) {
+               enable_irq(wm831x_ts->data_irq);
+               dev_dbg(wm831x_ts->wm831x->dev, "IRQ PD->DATA done\n");
+       } else {
+               enable_irq(wm831x_ts->pd_irq);
+               dev_dbg(wm831x_ts->wm831x->dev, "IRQ DATA->PD done\n");
+       }
+}
+
 static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
 {
        struct wm831x_ts *wm831x_ts = irq_data;
@@ -110,6 +125,9 @@ static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
        }
 
        if (!wm831x_ts->pen_down) {
+               /* Switch from data to pen down */
+               dev_dbg(wm831x->dev, "IRQ DATA->PD\n");
+
                disable_irq_nosync(wm831x_ts->data_irq);
 
                /* Don't need data any more */
@@ -128,6 +146,10 @@ static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
                                         ABS_PRESSURE, 0);
 
                input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 0);
+
+               schedule_work(&wm831x_ts->pd_data_work);
+       } else {
+               input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 1);
        }
 
        input_sync(wm831x_ts->input_dev);
@@ -141,6 +163,11 @@ static irqreturn_t wm831x_ts_pen_down_irq(int irq, void *irq_data)
        struct wm831x *wm831x = wm831x_ts->wm831x;
        int ena = 0;
 
+       if (wm831x_ts->pen_down)
+               return IRQ_HANDLED;
+
+       disable_irq_nosync(wm831x_ts->pd_irq);
+
        /* Start collecting data */
        if (wm831x_ts->pressure)
                ena |= WM831X_TCH_Z_ENA;
@@ -149,14 +176,14 @@ static irqreturn_t wm831x_ts_pen_down_irq(int irq, void *irq_data)
                        WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA,
                        WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | ena);
 
-       input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 1);
-       input_sync(wm831x_ts->input_dev);
-
        wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
                        WM831X_TCHPD_EINT, WM831X_TCHPD_EINT);
 
        wm831x_ts->pen_down = true;
-       enable_irq(wm831x_ts->data_irq);
+
+       /* Switch from pen down to data */
+       dev_dbg(wm831x->dev, "IRQ PD->DATA\n");
+       schedule_work(&wm831x_ts->pd_data_work);
 
        return IRQ_HANDLED;
 }
@@ -182,13 +209,28 @@ static void wm831x_ts_input_close(struct input_dev *idev)
        struct wm831x_ts *wm831x_ts = input_get_drvdata(idev);
        struct wm831x *wm831x = wm831x_ts->wm831x;
 
+       /* Shut the controller down, disabling all other functionality too */
        wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
-                       WM831X_TCH_ENA | WM831X_TCH_CVT_ENA |
-                       WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA |
-                       WM831X_TCH_Z_ENA, 0);
+                       WM831X_TCH_ENA | WM831X_TCH_X_ENA |
+                       WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA, 0);
 
-       if (wm831x_ts->pen_down)
+       /* Make sure any pending IRQs are done, the above will prevent
+        * new ones firing.
+        */
+       synchronize_irq(wm831x_ts->data_irq);
+       synchronize_irq(wm831x_ts->pd_irq);
+
+       /* Make sure the IRQ completion work is quiesced */
+       flush_work_sync(&wm831x_ts->pd_data_work);
+
+       /* If we ended up with the pen down then make sure we revert back
+        * to pen detection state for the next time we start up.
+        */
+       if (wm831x_ts->pen_down) {
                disable_irq(wm831x_ts->data_irq);
+               enable_irq(wm831x_ts->pd_irq);
+               wm831x_ts->pen_down = false;
+       }
 }
 
 static __devinit int wm831x_ts_probe(struct platform_device *pdev)
@@ -198,7 +240,7 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev)
        struct wm831x_pdata *core_pdata = dev_get_platdata(pdev->dev.parent);
        struct wm831x_touch_pdata *pdata = NULL;
        struct input_dev *input_dev;
-       int error;
+       int error, irqf;
 
        if (core_pdata)
                pdata = core_pdata->touch;
@@ -212,6 +254,7 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev)
 
        wm831x_ts->wm831x = wm831x;
        wm831x_ts->input_dev = input_dev;
+       INIT_WORK(&wm831x_ts->pd_data_work, wm831x_pd_data_work);
 
        /*
         * If we have a direct IRQ use it, otherwise use the interrupt
@@ -270,9 +313,14 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev)
        wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
                        WM831X_TCH_RATE_MASK, 6);
 
+       if (pdata && pdata->data_irqf)
+               irqf = pdata->data_irqf;
+       else
+               irqf = IRQF_TRIGGER_HIGH;
+
        error = request_threaded_irq(wm831x_ts->data_irq,
                                     NULL, wm831x_ts_data_irq,
-                                    IRQF_ONESHOT,
+                                    irqf | IRQF_ONESHOT,
                                     "Touchscreen data", wm831x_ts);
        if (error) {
                dev_err(&pdev->dev, "Failed to request data IRQ %d: %d\n",
@@ -281,9 +329,14 @@ static __devinit int wm831x_ts_probe(struct platform_device *pdev)
        }
        disable_irq(wm831x_ts->data_irq);
 
+       if (pdata && pdata->pd_irqf)
+               irqf = pdata->pd_irqf;
+       else
+               irqf = IRQF_TRIGGER_HIGH;
+
        error = request_threaded_irq(wm831x_ts->pd_irq,
                                     NULL, wm831x_ts_pen_down_irq,
-                                    IRQF_ONESHOT,
+                                    irqf | IRQF_ONESHOT,
                                     "Touchscreen pen down", wm831x_ts);
        if (error) {
                dev_err(&pdev->dev, "Failed to request pen down IRQ %d: %d\n",
index 5466d47..aae40e5 100644 (file)
@@ -533,16 +533,7 @@ int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq)
        if (tda_fail(ret))
                goto fail;
 
-       regs[R_MPD]   = (0x77 & pd);
-
-       switch (priv->mode) {
-       case TDA18271_ANALOG:
-               regs[R_MPD]  &= ~0x08;
-               break;
-       case TDA18271_DIGITAL:
-               regs[R_MPD]  |=  0x08;
-               break;
-       }
+       regs[R_MPD]   = (0x7f & pd);
 
        div =  ((d * (freq / 1000)) << 7) / 125;
 
index 9ad4454..d884f5e 100644 (file)
@@ -579,8 +579,8 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq)
 #define RF3 2
        u32 rf_default[3];
        u32 rf_freq[3];
-       u8 prog_cal[3];
-       u8 prog_tab[3];
+       s32 prog_cal[3];
+       s32 prog_tab[3];
 
        i = tda18271_lookup_rf_band(fe, &freq, NULL);
 
@@ -602,32 +602,33 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq)
                        return bcal;
 
                tda18271_calc_rf_cal(fe, &rf_freq[rf]);
-               prog_tab[rf] = regs[R_EB14];
+               prog_tab[rf] = (s32)regs[R_EB14];
 
                if (1 == bcal)
-                       prog_cal[rf] = tda18271_calibrate_rf(fe, rf_freq[rf]);
+                       prog_cal[rf] =
+                               (s32)tda18271_calibrate_rf(fe, rf_freq[rf]);
                else
                        prog_cal[rf] = prog_tab[rf];
 
                switch (rf) {
                case RF1:
                        map[i].rf_a1 = 0;
-                       map[i].rf_b1 = (s32)(prog_cal[RF1] - prog_tab[RF1]);
+                       map[i].rf_b1 = (prog_cal[RF1] - prog_tab[RF1]);
                        map[i].rf1   = rf_freq[RF1] / 1000;
                        break;
                case RF2:
-                       dividend = (s32)(prog_cal[RF2] - prog_tab[RF2]) -
-                                  (s32)(prog_cal[RF1] + prog_tab[RF1]);
+                       dividend = (prog_cal[RF2] - prog_tab[RF2] -
+                                   prog_cal[RF1] + prog_tab[RF1]);
                        divisor = (s32)(rf_freq[RF2] - rf_freq[RF1]) / 1000;
                        map[i].rf_a1 = (dividend / divisor);
                        map[i].rf2   = rf_freq[RF2] / 1000;
                        break;
                case RF3:
-                       dividend = (s32)(prog_cal[RF3] - prog_tab[RF3]) -
-                                  (s32)(prog_cal[RF2] + prog_tab[RF2]);
+                       dividend = (prog_cal[RF3] - prog_tab[RF3] -
+                                   prog_cal[RF2] + prog_tab[RF2]);
                        divisor = (s32)(rf_freq[RF3] - rf_freq[RF2]) / 1000;
                        map[i].rf_a2 = (dividend / divisor);
-                       map[i].rf_b2 = (s32)(prog_cal[RF2] - prog_tab[RF2]);
+                       map[i].rf_b2 = (prog_cal[RF2] - prog_tab[RF2]);
                        map[i].rf3   = rf_freq[RF3] / 1000;
                        break;
                default:
index e7f84c7..3d5b6ab 100644 (file)
@@ -229,8 +229,7 @@ static struct tda18271_map tda18271c2_km[] = {
 static struct tda18271_map tda18271_rf_band[] = {
        { .rfmax =  47900, .val = 0x00 },
        { .rfmax =  61100, .val = 0x01 },
-/*     { .rfmax = 152600, .val = 0x02 }, */
-       { .rfmax = 121200, .val = 0x02 },
+       { .rfmax = 152600, .val = 0x02 },
        { .rfmax = 164700, .val = 0x03 },
        { .rfmax = 203500, .val = 0x04 },
        { .rfmax = 457800, .val = 0x05 },
@@ -448,7 +447,7 @@ static struct tda18271_map tda18271c2_rf_cal[] = {
        { .rfmax = 150000, .val = 0xb0 },
        { .rfmax = 151000, .val = 0xb1 },
        { .rfmax = 152000, .val = 0xb7 },
-       { .rfmax = 153000, .val = 0xbd },
+       { .rfmax = 152600, .val = 0xbd },
        { .rfmax = 154000, .val = 0x20 },
        { .rfmax = 155000, .val = 0x22 },
        { .rfmax = 156000, .val = 0x24 },
@@ -459,7 +458,7 @@ static struct tda18271_map tda18271c2_rf_cal[] = {
        { .rfmax = 161000, .val = 0x2d },
        { .rfmax = 163000, .val = 0x2e },
        { .rfmax = 164000, .val = 0x2f },
-       { .rfmax = 165000, .val = 0x30 },
+       { .rfmax = 164700, .val = 0x30 },
        { .rfmax = 166000, .val = 0x11 },
        { .rfmax = 167000, .val = 0x12 },
        { .rfmax = 168000, .val = 0x13 },
@@ -510,7 +509,8 @@ static struct tda18271_map tda18271c2_rf_cal[] = {
        { .rfmax = 236000, .val = 0x1b },
        { .rfmax = 237000, .val = 0x1c },
        { .rfmax = 240000, .val = 0x1d },
-       { .rfmax = 242000, .val = 0x1f },
+       { .rfmax = 242000, .val = 0x1e },
+       { .rfmax = 244000, .val = 0x1f },
        { .rfmax = 247000, .val = 0x20 },
        { .rfmax = 249000, .val = 0x21 },
        { .rfmax = 252000, .val = 0x22 },
@@ -624,7 +624,7 @@ static struct tda18271_map tda18271c2_rf_cal[] = {
        { .rfmax = 453000, .val = 0x93 },
        { .rfmax = 454000, .val = 0x94 },
        { .rfmax = 456000, .val = 0x96 },
-       { .rfmax = 457000, .val = 0x98 },
+       { .rfmax = 457800, .val = 0x98 },
        { .rfmax = 461000, .val = 0x11 },
        { .rfmax = 468000, .val = 0x12 },
        { .rfmax = 472000, .val = 0x13 },
index 9552540..03f96d6 100644 (file)
@@ -38,7 +38,7 @@ MODULE_PARM_DESC(debug,
        DEBSTATUS);
 
 #define DRIVER_VERSION "0.1"
-#define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver"
+#define DRIVER_NAME "flexcop-pci"
 #define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>"
 
 struct flexcop_pci {
index fe4f894..c545039 100644 (file)
@@ -356,13 +356,15 @@ config DVB_USB_LME2510
        select DVB_TDA826X if !DVB_FE_CUSTOMISE
        select DVB_STV0288 if !DVB_FE_CUSTOMISE
        select DVB_IX2505V if !DVB_FE_CUSTOMISE
+       select DVB_STV0299 if !DVB_FE_CUSTOMISE
+       select DVB_PLL if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 .
 
 config DVB_USB_TECHNISAT_USB2
        tristate "Technisat DVB-S/S2 USB2.0 support"
        depends on DVB_USB
-       select DVB_STB0899 if !DVB_FE_CUSTOMISE
-       select DVB_STB6100 if !DVB_FE_CUSTOMISE
+       select DVB_STV090x if !DVB_FE_CUSTOMISE
+       select DVB_STV6110x if !DVB_FE_CUSTOMISE
        help
          Say Y here to support the Technisat USB2 DVB-S/S2 device
index 97af266..65214af 100644 (file)
@@ -2162,7 +2162,7 @@ struct dibx000_agc_config dib7090_agc_config[2] = {
                .agc1_pt3       = 98,
                .agc1_slope1    = 0,
                .agc1_slope2    = 167,
-               .agc1_pt1       = 98,
+               .agc2_pt1       = 98,
                .agc2_pt2       = 255,
                .agc2_slope1    = 104,
                .agc2_slope2    = 0,
@@ -2440,11 +2440,11 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
        dib0700_set_i2c_speed(adap->dev, 340);
        adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
 
-       dib7090_slave_reset(adap->fe);
-
        if (adap->fe == NULL)
                return -ENODEV;
 
+       dib7090_slave_reset(adap->fe);
+
        return 0;
 }
 
index ccc2d1a..6927c72 100644 (file)
@@ -1520,6 +1520,7 @@ static int init_channel(struct ngene_channel *chan)
        if (dev->ci.en && (io & NGENE_IO_TSOUT)) {
                dvb_ca_en50221_init(adapter, dev->ci.en, 0, 1);
                set_transfer(chan, 1);
+               chan->dev->channel[2].DataFormatFlags = DF_SWAP32;
                set_transfer(&chan->dev->channel[2], 1);
                dvb_register_device(adapter, &chan->ci_dev,
                                    &ngene_dvbdev_ci, (void *) chan,
index 23640ed..056138f 100644 (file)
@@ -378,7 +378,6 @@ EXPORT_SYMBOL_GPL(media_entity_create_link);
 
 static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
 {
-       const u32 mask = MEDIA_LNK_FL_ENABLED;
        int ret;
 
        /* Notify both entities. */
@@ -395,7 +394,7 @@ static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
                return ret;
        }
 
-       link->flags = (link->flags & ~mask) | (flags & mask);
+       link->flags = flags;
        link->reverse->flags = link->flags;
 
        return 0;
@@ -417,6 +416,7 @@ static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
  */
 int __media_entity_setup_link(struct media_link *link, u32 flags)
 {
+       const u32 mask = MEDIA_LNK_FL_ENABLED;
        struct media_device *mdev;
        struct media_entity *source, *sink;
        int ret = -EBUSY;
@@ -424,6 +424,10 @@ int __media_entity_setup_link(struct media_link *link, u32 flags)
        if (link == NULL)
                return -EINVAL;
 
+       /* The non-modifiable link flags must not be modified. */
+       if ((link->flags & ~mask) != (flags & ~mask))
+               return -EINVAL;
+
        if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
                return link->flags == flags ? 0 : -EINVAL;
 
index dc3f04c..87bad76 100644 (file)
@@ -170,7 +170,7 @@ static int fmr2_setfreq(struct fmr2 *dev)
        return 0;
 }
 
-/* !!! not tested, in my card this does't work !!! */
+/* !!! not tested, in my card this doesn't work !!! */
 static int fmr2_setvolume(struct fmr2 *dev)
 {
        int vol[16] = { 0x021, 0x084, 0x090, 0x104,
index 585680f..b1193df 100644 (file)
@@ -376,7 +376,7 @@ static int __devinit saa7706h_probe(struct i2c_client *client,
        v4l_info(client, "chip found @ 0x%02x (%s)\n",
                        client->addr << 1, client->adapter->name);
 
-       state = kmalloc(sizeof(struct saa7706h_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct saa7706h_state), GFP_KERNEL);
        if (state == NULL)
                return -ENOMEM;
        sd = &state->sd;
index 7c0d777..0991e19 100644 (file)
@@ -176,7 +176,7 @@ static int __devinit tef6862_probe(struct i2c_client *client,
        v4l_info(client, "chip found @ 0x%02x (%s)\n",
                        client->addr << 1, client->adapter->name);
 
-       state = kmalloc(sizeof(struct tef6862_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct tef6862_state), GFP_KERNEL);
        if (state == NULL)
                return -ENOMEM;
        state->freq = TEF6862_LO_FREQ;
index ebd68ed..8fc0f08 100644 (file)
@@ -46,7 +46,7 @@
 #define MOD_AUTHOR     "Jarod Wilson <jarod@wilsonet.com>"
 #define MOD_DESC       "Driver for SoundGraph iMON MultiMedia IR/Display"
 #define MOD_NAME       "imon"
-#define MOD_VERSION    "0.9.2"
+#define MOD_VERSION    "0.9.3"
 
 #define DISPLAY_MINOR_BASE     144
 #define DEVICE_NAME    "lcd%d"
@@ -460,8 +460,9 @@ static int display_close(struct inode *inode, struct file *file)
 }
 
 /**
- * Sends a packet to the device -- this function must be called
- * with ictx->lock held.
+ * Sends a packet to the device -- this function must be called with
+ * ictx->lock held, or its unlock/lock sequence while waiting for tx
+ * to complete can/will lead to a deadlock.
  */
 static int send_packet(struct imon_context *ictx)
 {
@@ -991,12 +992,21 @@ static void imon_touch_display_timeout(unsigned long data)
  * the iMON remotes, and those used by the Windows MCE remotes (which is
  * really just RC-6), but only one or the other at a time, as the signals
  * are decoded onboard the receiver.
+ *
+ * This function gets called two different ways, one way is from
+ * rc_register_device, for initial protocol selection/setup, and the other is
+ * via a userspace-initiated protocol change request, either by direct sysfs
+ * prodding or by something like ir-keytable. In the rc_register_device case,
+ * the imon context lock is already held, but when initiated from userspace,
+ * it is not, so we must acquire it prior to calling send_packet, which
+ * requires that the lock is held.
  */
 static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
 {
        int retval;
        struct imon_context *ictx = rc->priv;
        struct device *dev = ictx->dev;
+       bool unlock = false;
        unsigned char ir_proto_packet[] = {
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
 
@@ -1029,6 +1039,11 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
 
        memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
 
+       if (!mutex_is_locked(&ictx->lock)) {
+               unlock = true;
+               mutex_lock(&ictx->lock);
+       }
+
        retval = send_packet(ictx);
        if (retval)
                goto out;
@@ -1037,6 +1052,9 @@ static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
        ictx->pad_mouse = false;
 
 out:
+       if (unlock)
+               mutex_unlock(&ictx->lock);
+
        return retval;
 }
 
@@ -2134,6 +2152,7 @@ static struct imon_context *imon_init_intf0(struct usb_interface *intf)
                goto rdev_setup_failed;
        }
 
+       mutex_unlock(&ictx->lock);
        return ictx;
 
 rdev_setup_failed:
@@ -2205,6 +2224,7 @@ static struct imon_context *imon_init_intf1(struct usb_interface *intf,
                goto urb_submit_failed;
        }
 
+       mutex_unlock(&ictx->lock);
        return ictx;
 
 urb_submit_failed:
@@ -2299,6 +2319,8 @@ static int __devinit imon_probe(struct usb_interface *interface,
        usb_set_intfdata(interface, ictx);
 
        if (ifnum == 0) {
+               mutex_lock(&ictx->lock);
+
                if (product == 0xffdc && ictx->rf_device) {
                        sysfs_err = sysfs_create_group(&interface->dev.kobj,
                                                       &imon_rf_attr_group);
@@ -2309,13 +2331,14 @@ static int __devinit imon_probe(struct usb_interface *interface,
 
                if (ictx->display_supported)
                        imon_init_display(ictx, interface);
+
+               mutex_unlock(&ictx->lock);
        }
 
        dev_info(dev, "iMON device (%04x:%04x, intf%d) on "
                 "usb<%d:%d> initialized\n", vendor, product, ifnum,
                 usbdev->bus->busnum, usbdev->devnum);
 
-       mutex_unlock(&ictx->lock);
        mutex_unlock(&driver_lock);
 
        return 0;
index accaf6c..43908a7 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/io.h>
 #include <linux/interrupt.h>
 #include <linux/sched.h>
+#include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/bitops.h>
index 044fb7a..0c273ec 100644 (file)
@@ -220,6 +220,8 @@ static struct usb_device_id mceusb_dev_table[] = {
        { USB_DEVICE(VENDOR_PHILIPS, 0x206c) },
        /* Philips/Spinel plus IR transceiver for ASUS */
        { USB_DEVICE(VENDOR_PHILIPS, 0x2088) },
+       /* Philips IR transceiver (Dell branded) */
+       { USB_DEVICE(VENDOR_PHILIPS, 0x2093) },
        /* Realtek MCE IR Receiver and card reader */
        { USB_DEVICE(VENDOR_REALTEK, 0x0161),
          .driver_info = MULTIFUNCTION },
index f53f9c6..a270664 100644 (file)
@@ -707,7 +707,8 @@ static void ir_close(struct input_dev *idev)
 {
        struct rc_dev *rdev = input_get_drvdata(idev);
 
-       rdev->close(rdev);
+        if (rdev)
+               rdev->close(rdev);
 }
 
 /* class for /sys/class/rc */
@@ -733,6 +734,7 @@ static struct {
        { RC_TYPE_SONY,         "sony"          },
        { RC_TYPE_RC5_SZ,       "rc-5-sz"       },
        { RC_TYPE_LIRC,         "lirc"          },
+       { RC_TYPE_OTHER,        "other"         },
 };
 
 #define PROTO_NONE     "none"
index 4498b94..00f51dd 100644 (file)
@@ -875,7 +875,7 @@ config MX3_VIDEO
 config VIDEO_MX3
        tristate "i.MX3x Camera Sensor Interface driver"
        depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA
-       select VIDEOBUF_DMA_CONTIG
+       select VIDEOBUF2_DMA_CONTIG
        select MX3_VIDEO
        ---help---
          This is a v4l2 driver for the i.MX3x Camera Sensor Interface
index c6e2ca3..6fbc356 100644 (file)
@@ -350,9 +350,17 @@ void cx18_streams_cleanup(struct cx18 *cx, int unregister)
 
                /* No struct video_device, but can have buffers allocated */
                if (type == CX18_ENC_STREAM_TYPE_IDX) {
+                       /* If the module params didn't inhibit IDX ... */
                        if (cx->stream_buffers[type] != 0) {
                                cx->stream_buffers[type] = 0;
-                               cx18_stream_free(&cx->streams[type]);
+                               /*
+                                * Before calling cx18_stream_free(),
+                                * check if the IDX stream was actually set up.
+                                * Needed, since the cx18_probe() error path
+                                * exits through here as well as normal clean up
+                                */
+                               if (cx->streams[type].buffers != 0)
+                                       cx18_stream_free(&cx->streams[type]);
                        }
                        continue;
                }
index 3b6e7f2..caab1bf 100644 (file)
@@ -22,6 +22,7 @@ config VIDEO_CX23885
        select DVB_CX24116 if !DVB_FE_CUSTOMISE
        select DVB_STV0900 if !DVB_FE_CUSTOMISE
        select DVB_DS3000 if !DVB_FE_CUSTOMISE
+       select DVB_STV0367 if !DVB_FE_CUSTOMISE
        select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
        select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
index 1a11691..0382ea7 100644 (file)
@@ -298,7 +298,7 @@ static unsigned long imx074_query_bus_param(struct soc_camera_device *icd)
 static int imx074_set_bus_param(struct soc_camera_device *icd,
                                 unsigned long flags)
 {
-       return -1;
+       return -EINVAL;
 }
 
 static struct soc_camera_ops imx074_ops = {
index 5e1c9a8..303ffa7 100644 (file)
@@ -174,7 +174,7 @@ static int m52790_probe(struct i2c_client *client,
        v4l_info(client, "chip found @ 0x%x (%s)\n",
                        client->addr << 1, client->adapter->name);
 
-       state = kmalloc(sizeof(struct m52790_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct m52790_state), GFP_KERNEL);
        if (state == NULL)
                return -ENOMEM;
 
index 503bd79..472a693 100644 (file)
@@ -215,20 +215,21 @@ static u32 isp_set_xclk(struct isp_device *isp, u32 xclk, u8 xclksel)
        }
 
        switch (xclksel) {
-       case 0:
+       case ISP_XCLK_A:
                isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
                                ISPTCTRL_CTRL_DIVA_MASK,
                                divisor << ISPTCTRL_CTRL_DIVA_SHIFT);
                dev_dbg(isp->dev, "isp_set_xclk(): cam_xclka set to %d Hz\n",
                        currentxclk);
                break;
-       case 1:
+       case ISP_XCLK_B:
                isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
                                ISPTCTRL_CTRL_DIVB_MASK,
                                divisor << ISPTCTRL_CTRL_DIVB_SHIFT);
                dev_dbg(isp->dev, "isp_set_xclk(): cam_xclkb set to %d Hz\n",
                        currentxclk);
                break;
+       case ISP_XCLK_NONE:
        default:
                omap3isp_put(isp);
                dev_dbg(isp->dev, "ISP_ERR: isp_set_xclk(): Invalid requested "
@@ -237,13 +238,13 @@ static u32 isp_set_xclk(struct isp_device *isp, u32 xclk, u8 xclksel)
        }
 
        /* Do we go from stable whatever to clock? */
-       if (divisor >= 2 && isp->xclk_divisor[xclksel] < 2)
+       if (divisor >= 2 && isp->xclk_divisor[xclksel - 1] < 2)
                omap3isp_get(isp);
        /* Stopping the clock. */
-       else if (divisor < 2 && isp->xclk_divisor[xclksel] >= 2)
+       else if (divisor < 2 && isp->xclk_divisor[xclksel - 1] >= 2)
                omap3isp_put(isp);
 
-       isp->xclk_divisor[xclksel] = divisor;
+       isp->xclk_divisor[xclksel - 1] = divisor;
 
        omap3isp_put(isp);
 
@@ -285,7 +286,8 @@ static void isp_power_settings(struct isp_device *isp, int idle)
  */
 void omap3isp_configure_bridge(struct isp_device *isp,
                               enum ccdc_input_entity input,
-                              const struct isp_parallel_platform_data *pdata)
+                              const struct isp_parallel_platform_data *pdata,
+                              unsigned int shift)
 {
        u32 ispctrl_val;
 
@@ -298,9 +300,9 @@ void omap3isp_configure_bridge(struct isp_device *isp,
        switch (input) {
        case CCDC_INPUT_PARALLEL:
                ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL;
-               ispctrl_val |= pdata->data_lane_shift << ISPCTRL_SHIFT_SHIFT;
                ispctrl_val |= pdata->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT;
                ispctrl_val |= pdata->bridge << ISPCTRL_PAR_BRIDGE_SHIFT;
+               shift += pdata->data_lane_shift * 2;
                break;
 
        case CCDC_INPUT_CSI2A:
@@ -319,6 +321,8 @@ void omap3isp_configure_bridge(struct isp_device *isp,
                return;
        }
 
+       ispctrl_val |= ((shift/2) << ISPCTRL_SHIFT_SHIFT) & ISPCTRL_SHIFT_MASK;
+
        ispctrl_val &= ~ISPCTRL_SYNC_DETECT_MASK;
        ispctrl_val |= ISPCTRL_SYNC_DETECT_VSRISE;
 
@@ -658,6 +662,8 @@ int omap3isp_pipeline_pm_use(struct media_entity *entity, int use)
 
        /* Apply power change to connected non-nodes. */
        ret = isp_pipeline_pm_power(entity, change);
+       if (ret < 0)
+               entity->use_count -= change;
 
        mutex_unlock(&entity->parent->graph_mutex);
 
@@ -872,6 +878,9 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
                }
        }
 
+       if (failure < 0)
+               isp->needs_reset = true;
+
        return failure;
 }
 
@@ -884,7 +893,8 @@ static int isp_pipeline_disable(struct isp_pipeline *pipe)
  * single-shot or continuous mode.
  *
  * Return 0 if successful, or the return value of the failed video::s_stream
- * operation otherwise.
+ * operation otherwise. The pipeline state is not updated when the operation
+ * fails, except when stopping the pipeline.
  */
 int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
                                 enum isp_pipeline_stream_state state)
@@ -895,7 +905,9 @@ int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
                ret = isp_pipeline_disable(pipe);
        else
                ret = isp_pipeline_enable(pipe, state);
-       pipe->stream_state = state;
+
+       if (ret == 0 || state == ISP_PIPELINE_STREAM_STOPPED)
+               pipe->stream_state = state;
 
        return ret;
 }
@@ -1481,6 +1493,10 @@ void omap3isp_put(struct isp_device *isp)
        if (--isp->ref_count == 0) {
                isp_disable_interrupts(isp);
                isp_save_ctx(isp);
+               if (isp->needs_reset) {
+                       isp_reset(isp);
+                       isp->needs_reset = false;
+               }
                isp_disable_clocks(isp);
        }
        mutex_unlock(&isp->isp_mutex);
index cf5214e..2620c40 100644 (file)
@@ -132,7 +132,6 @@ struct isp_reg {
 
 /**
  * struct isp_parallel_platform_data - Parallel interface platform data
- * @width: Parallel bus width in bits (8, 10, 11 or 12)
  * @data_lane_shift: Data lane shifter
  *             0 - CAMEXT[13:0] -> CAM[13:0]
  *             1 - CAMEXT[13:2] -> CAM[11:0]
@@ -146,7 +145,6 @@ struct isp_reg {
  *             ISPCTRL_PAR_BRIDGE_BENDIAN - Big endian
  */
 struct isp_parallel_platform_data {
-       unsigned int width;
        unsigned int data_lane_shift:2;
        unsigned int clk_pol:1;
        unsigned int bridge:4;
@@ -262,6 +260,7 @@ struct isp_device {
        /* ISP Obj */
        spinlock_t stat_lock;   /* common lock for statistic drivers */
        struct mutex isp_mutex; /* For handling ref_count field */
+       bool needs_reset;
        int has_context;
        int ref_count;
        unsigned int autoidle;
@@ -311,11 +310,12 @@ int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
                                 enum isp_pipeline_stream_state state);
 void omap3isp_configure_bridge(struct isp_device *isp,
                               enum ccdc_input_entity input,
-                              const struct isp_parallel_platform_data *pdata);
+                              const struct isp_parallel_platform_data *pdata,
+                              unsigned int shift);
 
-#define ISP_XCLK_NONE                  -1
-#define ISP_XCLK_A                     0
-#define ISP_XCLK_B                     1
+#define ISP_XCLK_NONE                  0
+#define ISP_XCLK_A                     1
+#define ISP_XCLK_B                     2
 
 struct isp_device *omap3isp_get(struct isp_device *isp);
 void omap3isp_put(struct isp_device *isp);
index 5ff9d14..39d501b 100644 (file)
@@ -43,6 +43,12 @@ __ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
 
 static const unsigned int ccdc_fmts[] = {
        V4L2_MBUS_FMT_Y8_1X8,
+       V4L2_MBUS_FMT_Y10_1X10,
+       V4L2_MBUS_FMT_Y12_1X12,
+       V4L2_MBUS_FMT_SGRBG8_1X8,
+       V4L2_MBUS_FMT_SRGGB8_1X8,
+       V4L2_MBUS_FMT_SBGGR8_1X8,
+       V4L2_MBUS_FMT_SGBRG8_1X8,
        V4L2_MBUS_FMT_SGRBG10_1X10,
        V4L2_MBUS_FMT_SRGGB10_1X10,
        V4L2_MBUS_FMT_SBGGR10_1X10,
@@ -1110,21 +1116,38 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
        struct isp_parallel_platform_data *pdata = NULL;
        struct v4l2_subdev *sensor;
        struct v4l2_mbus_framefmt *format;
+       const struct isp_format_info *fmt_info;
+       struct v4l2_subdev_format fmt_src;
+       unsigned int depth_out;
+       unsigned int depth_in = 0;
        struct media_pad *pad;
        unsigned long flags;
+       unsigned int shift;
        u32 syn_mode;
        u32 ccdc_pattern;
 
-       if (ccdc->input == CCDC_INPUT_PARALLEL) {
-               pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]);
-               sensor = media_entity_to_v4l2_subdev(pad->entity);
+       pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]);
+       sensor = media_entity_to_v4l2_subdev(pad->entity);
+       if (ccdc->input == CCDC_INPUT_PARALLEL)
                pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv)
                        ->bus.parallel;
+
+       /* Compute shift value for lane shifter to configure the bridge. */
+       fmt_src.pad = pad->index;
+       fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+       if (!v4l2_subdev_call(sensor, pad, get_fmt, NULL, &fmt_src)) {
+               fmt_info = omap3isp_video_format_info(fmt_src.format.code);
+               depth_in = fmt_info->bpp;
        }
 
-       omap3isp_configure_bridge(isp, ccdc->input, pdata);
+       fmt_info = omap3isp_video_format_info
+               (isp->isp_ccdc.formats[CCDC_PAD_SINK].code);
+       depth_out = fmt_info->bpp;
+
+       shift = depth_in - depth_out;
+       omap3isp_configure_bridge(isp, ccdc->input, pdata, shift);
 
-       ccdc->syncif.datsz = pdata ? pdata->width : 10;
+       ccdc->syncif.datsz = depth_out;
        ccdc_config_sync_if(ccdc, &ccdc->syncif);
 
        /* CCDC_PAD_SINK */
@@ -1338,7 +1361,7 @@ static int ccdc_sbl_wait_idle(struct isp_ccdc_device *ccdc,
  * @ccdc: Pointer to ISP CCDC device.
  * @event: Pointing which event trigger handler
  *
- * Return 1 when the event and stopping request combination is satisfyied,
+ * Return 1 when the event and stopping request combination is satisfied,
  * zero otherwise.
  */
 static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event)
@@ -1618,7 +1641,7 @@ static int ccdc_video_queue(struct isp_video *video, struct isp_buffer *buffer)
 
        ccdc_set_outaddr(ccdc, buffer->isp_addr);
 
-       /* We now have a buffer queued on the output, restart the pipeline in
+       /* We now have a buffer queued on the output, restart the pipeline
         * on the next CCDC interrupt if running in continuous mode (or when
         * starting the stream).
         */
index 2b16988..aba537a 100644 (file)
@@ -755,7 +755,7 @@ static struct preview_update update_attrs[] = {
  * @configs - pointer to update config structure.
  * @config - return pointer to appropriate structure field.
  * @bit - for which feature to return pointers.
- * Return size of coresponding prev_params member
+ * Return size of corresponding prev_params member
  */
 static u32
 __preview_get_ptrs(struct prev_params *params, void **param,
index 8fddc58..9c31714 100644 (file)
@@ -339,7 +339,7 @@ static int isp_video_buffer_prepare_user(struct isp_video_buffer *buf)
        up_read(&current->mm->mmap_sem);
 
        if (ret != buf->npages) {
-               buf->npages = ret;
+               buf->npages = ret < 0 ? 0 : ret;
                isp_video_buffer_cleanup(buf);
                return -EFAULT;
        }
@@ -408,8 +408,8 @@ done:
  * isp_video_buffer_prepare_vm_flags - Get VMA flags for a userspace address
  *
  * This function locates the VMAs for the buffer's userspace address and checks
- * that their flags match. The onlflag that we need to care for at the moment is
- * VM_PFNMAP.
+ * that their flags match. The only flag that we need to care for at the moment
+ * is VM_PFNMAP.
  *
  * The buffer vm_flags field is set to the first VMA flags.
  *
index 653f88b..0bb0f8c 100644 (file)
@@ -714,19 +714,50 @@ static void resizer_print_status(struct isp_res_device *res)
  * iw and ih are the input width and height after cropping. Those equations need
  * to be satisfied exactly for the resizer to work correctly.
  *
- * Reverting the equations, we can compute the resizing ratios with
+ * The equations can't be easily reverted, as the >> 8 operation is not linear.
+ * In addition, not all input sizes can be achieved for a given output size. To
+ * get the highest input size lower than or equal to the requested input size,
+ * we need to compute the highest resizing ratio that satisfies the following
+ * inequality (taking the 4-tap mode width equation as an example)
+ *
+ *     iw >= (32 * sph + (ow - 1) * hrsz + 16) >> 8 - 7
+ *
+ * (where iw is the requested input width) which can be rewritten as
+ *
+ *       iw - 7            >= (32 * sph + (ow - 1) * hrsz + 16) >> 8
+ *      (iw - 7) << 8      >=  32 * sph + (ow - 1) * hrsz + 16 - b
+ *     ((iw - 7) << 8) + b >=  32 * sph + (ow - 1) * hrsz + 16
+ *
+ * where b is the value of the 8 least significant bits of the right hand side
+ * expression of the last inequality. The highest resizing ratio value will be
+ * achieved when b is equal to its maximum value of 255. That resizing ratio
+ * value will still satisfy the original inequality, as b will disappear when
+ * the expression will be shifted right by 8.
+ *
+ * The reverted the equations thus become
  *
  * - 8-phase, 4-tap mode
- *     hrsz = ((iw - 7) * 256 - 16 - 32 * sph) / (ow - 1)
- *     vrsz = ((ih - 4) * 256 - 16 - 32 * spv) / (oh - 1)
+ *     hrsz = ((iw - 7) * 256 + 255 - 16 - 32 * sph) / (ow - 1)
+ *     vrsz = ((ih - 4) * 256 + 255 - 16 - 32 * spv) / (oh - 1)
  * - 4-phase, 7-tap mode
- *     hrsz = ((iw - 7) * 256 - 32 - 64 * sph) / (ow - 1)
- *     vrsz = ((ih - 7) * 256 - 32 - 64 * spv) / (oh - 1)
+ *     hrsz = ((iw - 7) * 256 + 255 - 32 - 64 * sph) / (ow - 1)
+ *     vrsz = ((ih - 7) * 256 + 255 - 32 - 64 * spv) / (oh - 1)
  *
- * The ratios are integer values, and must be rounded down to ensure that the
- * cropped input size is not bigger than the uncropped input size. As the ratio
- * in 7-tap mode is always smaller than the ratio in 4-tap mode, we can use the
- * 7-tap mode equations to compute a ratio approximation.
+ * The ratios are integer values, and are rounded down to ensure that the
+ * cropped input size is not bigger than the uncropped input size.
+ *
+ * As the number of phases/taps, used to select the correct equations to compute
+ * the ratio, depends on the ratio, we start with the 4-tap mode equations to
+ * compute an approximation of the ratio, and switch to the 7-tap mode equations
+ * if the approximation is higher than the ratio threshold.
+ *
+ * As the 7-tap mode equations will return a ratio smaller than or equal to the
+ * 4-tap mode equations, the resulting ratio could become lower than or equal to
+ * the ratio threshold. This 'equations loop' isn't an issue as long as the
+ * correct equations are used to compute the final input size. Starting with the
+ * 4-tap mode equations ensure that, in case of values resulting in a 'ratio
+ * loop', the smallest of the ratio values will be used, never exceeding the
+ * requested input size.
  *
  * We first clamp the output size according to the hardware capabilitie to avoid
  * auto-cropping the input more than required to satisfy the TRM equations. The
@@ -775,6 +806,8 @@ static void resizer_calc_ratios(struct isp_res_device *res,
        unsigned int max_width;
        unsigned int max_height;
        unsigned int width_alignment;
+       unsigned int width;
+       unsigned int height;
 
        /*
         * Clamp the output height based on the hardware capabilities and
@@ -786,19 +819,22 @@ static void resizer_calc_ratios(struct isp_res_device *res,
        max_height = min_t(unsigned int, max_height, MAX_OUT_HEIGHT);
        output->height = clamp(output->height, min_height, max_height);
 
-       ratio->vert = ((input->height - 7) * 256 - 32 - 64 * spv)
+       ratio->vert = ((input->height - 4) * 256 + 255 - 16 - 32 * spv)
                    / (output->height - 1);
+       if (ratio->vert > MID_RESIZE_VALUE)
+               ratio->vert = ((input->height - 7) * 256 + 255 - 32 - 64 * spv)
+                           / (output->height - 1);
        ratio->vert = clamp_t(unsigned int, ratio->vert,
                              MIN_RESIZE_VALUE, MAX_RESIZE_VALUE);
 
        if (ratio->vert <= MID_RESIZE_VALUE) {
                upscaled_height = (output->height - 1) * ratio->vert
                                + 32 * spv + 16;
-               input->height = (upscaled_height >> 8) + 4;
+               height = (upscaled_height >> 8) + 4;
        } else {
                upscaled_height = (output->height - 1) * ratio->vert
                                + 64 * spv + 32;
-               input->height = (upscaled_height >> 8) + 7;
+               height = (upscaled_height >> 8) + 7;
        }
 
        /*
@@ -854,20 +890,29 @@ static void resizer_calc_ratios(struct isp_res_device *res,
                              max_width & ~(width_alignment - 1));
        output->width = ALIGN(output->width, width_alignment);
 
-       ratio->horz = ((input->width - 7) * 256 - 32 - 64 * sph)
+       ratio->horz = ((input->width - 7) * 256 + 255 - 16 - 32 * sph)
                    / (output->width - 1);
+       if (ratio->horz > MID_RESIZE_VALUE)
+               ratio->horz = ((input->width - 7) * 256 + 255 - 32 - 64 * sph)
+                           / (output->width - 1);
        ratio->horz = clamp_t(unsigned int, ratio->horz,
                              MIN_RESIZE_VALUE, MAX_RESIZE_VALUE);
 
        if (ratio->horz <= MID_RESIZE_VALUE) {
                upscaled_width = (output->width - 1) * ratio->horz
                               + 32 * sph + 16;
-               input->width = (upscaled_width >> 8) + 7;
+               width = (upscaled_width >> 8) + 7;
        } else {
                upscaled_width = (output->width - 1) * ratio->horz
                               + 64 * sph + 32;
-               input->width = (upscaled_width >> 8) + 7;
+               width = (upscaled_width >> 8) + 7;
        }
+
+       /* Center the new crop rectangle. */
+       input->left += (input->width - width) / 2;
+       input->top += (input->height - height) / 2;
+       input->width = width;
+       input->height = height;
 }
 
 /*
index 820950c..d86da94 100644 (file)
@@ -131,9 +131,9 @@ struct ispstat {
 struct ispstat_generic_config {
        /*
         * Fields must be in the same order as in:
-        *  - isph3a_aewb_config
-        *  - isph3a_af_config
-        *  - isphist_config
+        *  - omap3isp_h3a_aewb_config
+        *  - omap3isp_h3a_af_config
+        *  - omap3isp_hist_config
         */
        u32 buf_size;
        u16 config_counter;
index 208a7ec..9cd8f1a 100644 (file)
 
 static struct isp_format_info formats[] = {
        { V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
-         V4L2_MBUS_FMT_Y8_1X8, V4L2_PIX_FMT_GREY, 8, },
+         V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
+         V4L2_PIX_FMT_GREY, 8, },
+       { V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10,
+         V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y8_1X8,
+         V4L2_PIX_FMT_Y10, 10, },
+       { V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y10_1X10,
+         V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y8_1X8,
+         V4L2_PIX_FMT_Y12, 12, },
+       { V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
+         V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
+         V4L2_PIX_FMT_SBGGR8, 8, },
+       { V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
+         V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
+         V4L2_PIX_FMT_SGBRG8, 8, },
+       { V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
+         V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
+         V4L2_PIX_FMT_SGRBG8, 8, },
+       { V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
+         V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
+         V4L2_PIX_FMT_SRGGB8, 8, },
        { V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
-         V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10DPCM8, 8, },
+         V4L2_MBUS_FMT_SGRBG10_1X10, 0,
+         V4L2_PIX_FMT_SGRBG10DPCM8, 8, },
        { V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10,
-         V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_PIX_FMT_SBGGR10, 10, },
+         V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8,
+         V4L2_PIX_FMT_SBGGR10, 10, },
        { V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10,
-         V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_PIX_FMT_SGBRG10, 10, },
+         V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8,
+         V4L2_PIX_FMT_SGBRG10, 10, },
        { V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10,
-         V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_PIX_FMT_SGRBG10, 10, },
+         V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8,
+         V4L2_PIX_FMT_SGRBG10, 10, },
        { V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10,
-         V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_PIX_FMT_SRGGB10, 10, },
+         V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8,
+         V4L2_PIX_FMT_SRGGB10, 10, },
        { V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10,
-         V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_PIX_FMT_SBGGR12, 12, },
+         V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8,
+         V4L2_PIX_FMT_SBGGR12, 12, },
        { V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10,
-         V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_PIX_FMT_SGBRG12, 12, },
+         V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8,
+         V4L2_PIX_FMT_SGBRG12, 12, },
        { V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10,
-         V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_PIX_FMT_SGRBG12, 12, },
+         V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8,
+         V4L2_PIX_FMT_SGRBG12, 12, },
        { V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10,
-         V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_PIX_FMT_SRGGB12, 12, },
+         V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8,
+         V4L2_PIX_FMT_SRGGB12, 12, },
        { V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16,
-         V4L2_MBUS_FMT_UYVY8_1X16, V4L2_PIX_FMT_UYVY, 16, },
+         V4L2_MBUS_FMT_UYVY8_1X16, 0,
+         V4L2_PIX_FMT_UYVY, 16, },
        { V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16,
-         V4L2_MBUS_FMT_YUYV8_1X16, V4L2_PIX_FMT_YUYV, 16, },
+         V4L2_MBUS_FMT_YUYV8_1X16, 0,
+         V4L2_PIX_FMT_YUYV, 16, },
 };
 
 const struct isp_format_info *
@@ -85,6 +115,37 @@ omap3isp_video_format_info(enum v4l2_mbus_pixelcode code)
        return NULL;
 }
 
+/*
+ * Decide whether desired output pixel code can be obtained with
+ * the lane shifter by shifting the input pixel code.
+ * @in: input pixelcode to shifter
+ * @out: output pixelcode from shifter
+ * @additional_shift: # of bits the sensor's LSB is offset from CAMEXT[0]
+ *
+ * return true if the combination is possible
+ * return false otherwise
+ */
+static bool isp_video_is_shiftable(enum v4l2_mbus_pixelcode in,
+               enum v4l2_mbus_pixelcode out,
+               unsigned int additional_shift)
+{
+       const struct isp_format_info *in_info, *out_info;
+
+       if (in == out)
+               return true;
+
+       in_info = omap3isp_video_format_info(in);
+       out_info = omap3isp_video_format_info(out);
+
+       if ((in_info->flavor == 0) || (out_info->flavor == 0))
+               return false;
+
+       if (in_info->flavor != out_info->flavor)
+               return false;
+
+       return in_info->bpp - out_info->bpp + additional_shift <= 6;
+}
+
 /*
  * isp_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format
  * @video: ISP video instance
@@ -235,6 +296,7 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
                return -EPIPE;
 
        while (1) {
+               unsigned int shifter_link;
                /* Retrieve the sink format */
                pad = &subdev->entity.pads[0];
                if (!(pad->flags & MEDIA_PAD_FL_SINK))
@@ -263,6 +325,10 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
                                return -ENOSPC;
                }
 
+               /* If sink pad is on CCDC, the link has the lane shifter
+                * in the middle of it. */
+               shifter_link = subdev == &isp->isp_ccdc.subdev;
+
                /* Retrieve the source format */
                pad = media_entity_remote_source(pad);
                if (pad == NULL ||
@@ -278,10 +344,24 @@ static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
                        return -EPIPE;
 
                /* Check if the two ends match */
-               if (fmt_source.format.code != fmt_sink.format.code ||
-                   fmt_source.format.width != fmt_sink.format.width ||
+               if (fmt_source.format.width != fmt_sink.format.width ||
                    fmt_source.format.height != fmt_sink.format.height)
                        return -EPIPE;
+
+               if (shifter_link) {
+                       unsigned int parallel_shift = 0;
+                       if (isp->isp_ccdc.input == CCDC_INPUT_PARALLEL) {
+                               struct isp_parallel_platform_data *pdata =
+                                       &((struct isp_v4l2_subdevs_group *)
+                                             subdev->host_priv)->bus.parallel;
+                               parallel_shift = pdata->data_lane_shift * 2;
+                       }
+                       if (!isp_video_is_shiftable(fmt_source.format.code,
+                                               fmt_sink.format.code,
+                                               parallel_shift))
+                               return -EPIPE;
+               } else if (fmt_source.format.code != fmt_sink.format.code)
+                       return -EPIPE;
        }
 
        return 0;
index 524a1ac..911bea6 100644 (file)
@@ -49,6 +49,8 @@ struct v4l2_pix_format;
  *     bits. Identical to @code if the format is 10 bits wide or less.
  * @uncompressed: V4L2 media bus format code for the corresponding uncompressed
  *     format. Identical to @code if the format is not DPCM compressed.
+ * @flavor: V4L2 media bus format code for the same pixel layout but
+ *     shifted to be 8 bits per pixel. =0 if format is not shiftable.
  * @pixelformat: V4L2 pixel format FCC identifier
  * @bpp: Bits per pixel
  */
@@ -56,6 +58,7 @@ struct isp_format_info {
        enum v4l2_mbus_pixelcode code;
        enum v4l2_mbus_pixelcode truncated;
        enum v4l2_mbus_pixelcode uncompressed;
+       enum v4l2_mbus_pixelcode flavor;
        u32 pixelformat;
        unsigned int bpp;
 };
index 95f8b4e..d142b40 100644 (file)
@@ -527,7 +527,7 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
        if (ret)
                return ret;
 
-       if (vb2_is_streaming(&fimc->vid_cap.vbq) || fimc_capture_active(fimc))
+       if (vb2_is_busy(&fimc->vid_cap.vbq) || fimc_capture_active(fimc))
                return -EBUSY;
 
        frame = &ctx->d_frame;
@@ -539,8 +539,10 @@ static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
                return -EINVAL;
        }
 
-       for (i = 0; i < frame->fmt->colplanes; i++)
-               frame->payload[i] = pix->plane_fmt[i].bytesperline * pix->height;
+       for (i = 0; i < frame->fmt->colplanes; i++) {
+               frame->payload[i] =
+                       (pix->width * pix->height * frame->fmt->depth[i]) >> 3;
+       }
 
        /* Output DMA frame pixel size and offsets. */
        frame->f_width = pix->plane_fmt[0].bytesperline * 8
index 6c919b3..dc91a85 100644 (file)
@@ -361,10 +361,20 @@ static void fimc_capture_irq_handler(struct fimc_dev *fimc)
 {
        struct fimc_vid_cap *cap = &fimc->vid_cap;
        struct fimc_vid_buffer *v_buf;
+       struct timeval *tv;
+       struct timespec ts;
 
        if (!list_empty(&cap->active_buf_q) &&
            test_bit(ST_CAPT_RUN, &fimc->state)) {
+               ktime_get_real_ts(&ts);
+
                v_buf = active_queue_pop(cap);
+
+               tv = &v_buf->vb.v4l2_buf.timestamp;
+               tv->tv_sec = ts.tv_sec;
+               tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+               v_buf->vb.v4l2_buf.sequence = cap->frame_count++;
+
                vb2_buffer_done(&v_buf->vb, VB2_BUF_STATE_DONE);
        }
 
@@ -758,7 +768,7 @@ static void fimc_unlock(struct vb2_queue *vq)
        mutex_unlock(&ctx->fimc_dev->lock);
 }
 
-struct vb2_ops fimc_qops = {
+static struct vb2_ops fimc_qops = {
        .queue_setup     = fimc_queue_setup,
        .buf_prepare     = fimc_buf_prepare,
        .buf_queue       = fimc_buf_queue,
@@ -927,23 +937,23 @@ int fimc_vidioc_try_fmt_mplane(struct file *file, void *priv,
        pix->num_planes = fmt->memplanes;
        pix->colorspace = V4L2_COLORSPACE_JPEG;
 
-       for (i = 0; i < pix->num_planes; ++i) {
-               int bpl = pix->plane_fmt[i].bytesperline;
 
-               dbg("[%d] bpl: %d, depth: %d, w: %d, h: %d",
-                   i, bpl, fmt->depth[i], pix->width, pix->height);
+       for (i = 0; i < pix->num_planes; ++i) {
+               u32 bpl = pix->plane_fmt[i].bytesperline;
+               u32 *sizeimage = &pix->plane_fmt[i].sizeimage;
 
-               if (!bpl || (bpl * 8 / fmt->depth[i]) > pix->width)
-                       bpl = (pix->width * fmt->depth[0]) >> 3;
+               if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width))
+                       bpl = pix->width; /* Planar */
 
-               if (!pix->plane_fmt[i].sizeimage)
-                       pix->plane_fmt[i].sizeimage = pix->height * bpl;
+               if (fmt->colplanes == 1 && /* Packed */
+                   (bpl == 0 || ((bpl * 8) / fmt->depth[i]) < pix->width))
+                       bpl = (pix->width * fmt->depth[0]) / 8;
 
-               pix->plane_fmt[i].bytesperline = bpl;
+               if (i == 0) /* Same bytesperline for each plane. */
+                       mod_x = bpl;
 
-               dbg("[%d]: bpl: %d, sizeimage: %d",
-                   i, pix->plane_fmt[i].bytesperline,
-                   pix->plane_fmt[i].sizeimage);
+               pix->plane_fmt[i].bytesperline = mod_x;
+               *sizeimage = (pix->width * pix->height * fmt->depth[i]) / 8;
        }
 
        return 0;
@@ -965,7 +975,7 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
 
        vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
 
-       if (vb2_is_streaming(vq)) {
+       if (vb2_is_busy(vq)) {
                v4l2_err(&fimc->m2m.v4l2_dev, "queue (%d) busy\n", f->type);
                return -EBUSY;
        }
@@ -985,8 +995,10 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
        if (!frame->fmt)
                return -EINVAL;
 
-       for (i = 0; i < frame->fmt->colplanes; i++)
-               frame->payload[i] = pix->plane_fmt[i].bytesperline * pix->height;
+       for (i = 0; i < frame->fmt->colplanes; i++) {
+               frame->payload[i] =
+                       (pix->width * pix->height * frame->fmt->depth[i]) / 8;
+       }
 
        frame->f_width  = pix->plane_fmt[0].bytesperline * 8 /
                frame->fmt->depth[0];
@@ -1750,7 +1762,7 @@ static int __devexit fimc_remove(struct platform_device *pdev)
 }
 
 /* Image pixel limits, similar across several FIMC HW revisions. */
-static struct fimc_pix_limit s5p_pix_limit[3] = {
+static struct fimc_pix_limit s5p_pix_limit[4] = {
        [0] = {
                .scaler_en_w    = 3264,
                .scaler_dis_w   = 8192,
@@ -1775,6 +1787,14 @@ static struct fimc_pix_limit s5p_pix_limit[3] = {
                .out_rot_en_w   = 1280,
                .out_rot_dis_w  = 1920,
        },
+       [3] = {
+               .scaler_en_w    = 1920,
+               .scaler_dis_w   = 8192,
+               .in_rot_en_h    = 1366,
+               .in_rot_dis_w   = 8192,
+               .out_rot_en_w   = 1366,
+               .out_rot_dis_w  = 1920,
+       },
 };
 
 static struct samsung_fimc_variant fimc0_variant_s5p = {
@@ -1827,7 +1847,7 @@ static struct samsung_fimc_variant fimc2_variant_s5pv210 = {
        .pix_limit       = &s5p_pix_limit[2],
 };
 
-static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
+static struct samsung_fimc_variant fimc0_variant_exynos4 = {
        .pix_hoff        = 1,
        .has_inp_rot     = 1,
        .has_out_rot     = 1,
@@ -1840,7 +1860,7 @@ static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
        .pix_limit       = &s5p_pix_limit[1],
 };
 
-static struct samsung_fimc_variant fimc2_variant_s5pv310 = {
+static struct samsung_fimc_variant fimc2_variant_exynos4 = {
        .pix_hoff        = 1,
        .has_cistatus2   = 1,
        .has_mainscaler_ext = 1,
@@ -1848,7 +1868,7 @@ static struct samsung_fimc_variant fimc2_variant_s5pv310 = {
        .min_out_pixsize = 16,
        .hor_offs_align  = 1,
        .out_buf_count   = 32,
-       .pix_limit       = &s5p_pix_limit[2],
+       .pix_limit       = &s5p_pix_limit[3],
 };
 
 /* S5PC100 */
@@ -1874,12 +1894,12 @@ static struct samsung_fimc_driverdata fimc_drvdata_s5pv210 = {
 };
 
 /* S5PV310, S5PC210 */
-static struct samsung_fimc_driverdata fimc_drvdata_s5pv310 = {
+static struct samsung_fimc_driverdata fimc_drvdata_exynos4 = {
        .variant = {
-               [0] = &fimc0_variant_s5pv310,
-               [1] = &fimc0_variant_s5pv310,
-               [2] = &fimc0_variant_s5pv310,
-               [3] = &fimc2_variant_s5pv310,
+               [0] = &fimc0_variant_exynos4,
+               [1] = &fimc0_variant_exynos4,
+               [2] = &fimc0_variant_exynos4,
+               [3] = &fimc2_variant_exynos4,
        },
        .num_entities = 4,
        .lclk_frequency = 166000000UL,
@@ -1893,8 +1913,8 @@ static struct platform_device_id fimc_driver_ids[] = {
                .name           = "s5pv210-fimc",
                .driver_data    = (unsigned long)&fimc_drvdata_s5pv210,
        }, {
-               .name           = "s5pv310-fimc",
-               .driver_data    = (unsigned long)&fimc_drvdata_s5pv310,
+               .name           = "exynos4-fimc",
+               .driver_data    = (unsigned long)&fimc_drvdata_exynos4,
        },
        {},
 };
index 3fe54bf..134e86b 100644 (file)
@@ -922,7 +922,7 @@ static int sh_mobile_ceu_get_formats(struct soc_camera_device *icd, unsigned int
                        /* Try 2560x1920, 1280x960, 640x480, 320x240 */
                        mf.width        = 2560 >> shift;
                        mf.height       = 1920 >> shift;
-                       ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
+                       ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
                                                         s_mbus_fmt, &mf);
                        if (ret < 0)
                                return ret;
@@ -1224,7 +1224,7 @@ static int client_s_fmt(struct soc_camera_device *icd,
        struct v4l2_cropcap cap;
        int ret;
 
-       ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
+       ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
                                         s_mbus_fmt, mf);
        if (ret < 0)
                return ret;
@@ -1254,7 +1254,7 @@ static int client_s_fmt(struct soc_camera_device *icd,
                tmp_h = min(2 * tmp_h, max_height);
                mf->width = tmp_w;
                mf->height = tmp_h;
-               ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
+               ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
                                                 s_mbus_fmt, mf);
                dev_geo(dev, "Camera scaled to %ux%u\n",
                        mf->width, mf->height);
@@ -1658,7 +1658,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
        mf.code         = xlate->code;
        mf.colorspace   = pix->colorspace;
 
-       ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video, try_mbus_fmt, &mf);
+       ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video, try_mbus_fmt, &mf);
        if (ret < 0)
                return ret;
 
@@ -1682,7 +1682,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd,
                         */
                        mf.width = 2560;
                        mf.height = 1920;
-                       ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
+                       ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
                                                         try_mbus_fmt, &mf);
                        if (ret < 0) {
                                /* Shouldn't actually happen... */
index dd1b81b..98b8748 100644 (file)
@@ -38,6 +38,8 @@ struct sh_csi2 {
        void __iomem                    *base;
        struct platform_device          *pdev;
        struct sh_csi2_client_config    *client;
+       unsigned long (*query_bus_param)(struct soc_camera_device *);
+       int (*set_bus_param)(struct soc_camera_device *, unsigned long);
 };
 
 static int sh_csi2_try_fmt(struct v4l2_subdev *sd,
@@ -208,6 +210,7 @@ static int sh_csi2_notify(struct notifier_block *nb,
        case BUS_NOTIFY_BOUND_DRIVER:
                snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "%s%s",
                         dev_name(v4l2_dev->dev), ".mipi-csi");
+               priv->subdev.grp_id = (long)icd;
                ret = v4l2_device_register_subdev(v4l2_dev, &priv->subdev);
                dev_dbg(dev, "%s(%p): ret(register_subdev) = %d\n", __func__, priv, ret);
                if (ret < 0)
@@ -215,6 +218,8 @@ static int sh_csi2_notify(struct notifier_block *nb,
 
                priv->client = pdata->clients + i;
 
+               priv->set_bus_param             = icd->ops->set_bus_param;
+               priv->query_bus_param           = icd->ops->query_bus_param;
                icd->ops->set_bus_param         = sh_csi2_set_bus_param;
                icd->ops->query_bus_param       = sh_csi2_query_bus_param;
 
@@ -226,8 +231,10 @@ static int sh_csi2_notify(struct notifier_block *nb,
                priv->client = NULL;
 
                /* Driver is about to be unbound */
-               icd->ops->set_bus_param         = NULL;
-               icd->ops->query_bus_param       = NULL;
+               icd->ops->set_bus_param         = priv->set_bus_param;
+               icd->ops->query_bus_param       = priv->query_bus_param;
+               priv->set_bus_param             = NULL;
+               priv->query_bus_param           = NULL;
 
                v4l2_device_unregister_subdev(&priv->subdev);
 
index 4628448..3973f9a 100644 (file)
@@ -996,10 +996,11 @@ static void soc_camera_free_i2c(struct soc_camera_device *icd)
 {
        struct i2c_client *client =
                to_i2c_client(to_soc_camera_control(icd));
+       struct i2c_adapter *adap = client->adapter;
        dev_set_drvdata(&icd->dev, NULL);
        v4l2_device_unregister_subdev(i2c_get_clientdata(client));
        i2c_unregister_device(client);
-       i2c_put_adapter(client->adapter);
+       i2c_put_adapter(adap);
 }
 #else
 #define soc_camera_init_i2c(icd, icl)  (-ENODEV)
@@ -1071,6 +1072,9 @@ static int soc_camera_probe(struct device *dev)
                }
        }
 
+       sd = soc_camera_to_subdev(icd);
+       sd->grp_id = (long)icd;
+
        /* At this point client .probe() should have run already */
        ret = soc_camera_init_user_formats(icd);
        if (ret < 0)
@@ -1092,7 +1096,6 @@ static int soc_camera_probe(struct device *dev)
                goto evidstart;
 
        /* Try to improve our guess of a reasonable window format */
-       sd = soc_camera_to_subdev(icd);
        if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) {
                icd->user_width         = mf.width;
                icd->user_height        = mf.height;
index 5d4cf3b..22fa820 100644 (file)
@@ -171,7 +171,7 @@ static int tda9840_probe(struct i2c_client *client,
        v4l_info(client, "chip found @ 0x%x (%s)\n",
                        client->addr << 1, client->adapter->name);
 
-       sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
        if (sd == NULL)
                return -ENOMEM;
        v4l2_i2c_subdev_init(sd, client, &tda9840_ops);
index 19621ed..827425c 100644 (file)
@@ -152,7 +152,7 @@ static int tea6415c_probe(struct i2c_client *client,
 
        v4l_info(client, "chip found @ 0x%x (%s)\n",
                        client->addr << 1, client->adapter->name);
-       sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
        if (sd == NULL)
                return -ENOMEM;
        v4l2_i2c_subdev_init(sd, client, &tea6415c_ops);
index 5ea8404..f350b6c 100644 (file)
@@ -125,7 +125,7 @@ static int tea6420_probe(struct i2c_client *client,
        v4l_info(client, "chip found @ 0x%x (%s)\n",
                        client->addr << 1, client->adapter->name);
 
-       sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+       sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
        if (sd == NULL)
                return -ENOMEM;
        v4l2_i2c_subdev_init(sd, client, &tea6420_ops);
index f8138c7..1aab96a 100644 (file)
@@ -230,7 +230,7 @@ static int upd64031a_probe(struct i2c_client *client,
        v4l_info(client, "chip found @ 0x%x (%s)\n",
                        client->addr << 1, client->adapter->name);
 
-       state = kmalloc(sizeof(struct upd64031a_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct upd64031a_state), GFP_KERNEL);
        if (state == NULL)
                return -ENOMEM;
        sd = &state->sd;
index 28e0e6b..9bbe617 100644 (file)
@@ -202,7 +202,7 @@ static int upd64083_probe(struct i2c_client *client,
        v4l_info(client, "chip found @ 0x%x (%s)\n",
                        client->addr << 1, client->adapter->name);
 
-       state = kmalloc(sizeof(struct upd64083_state), GFP_KERNEL);
+       state = kzalloc(sizeof(struct upd64083_state), GFP_KERNEL);
        if (state == NULL)
                return -ENOMEM;
        sd = &state->sd;
index 498e674..6dc7196 100644 (file)
@@ -389,7 +389,8 @@ static int v4l2_open(struct inode *inode, struct file *filp)
        video_get(vdev);
        mutex_unlock(&videodev_lock);
 #if defined(CONFIG_MEDIA_CONTROLLER)
-       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) {
+       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+           vdev->vfl_type != VFL_TYPE_SUBDEV) {
                entity = media_entity_get(&vdev->entity);
                if (!entity) {
                        ret = -EBUSY;
@@ -415,7 +416,8 @@ err:
        /* decrease the refcount in case of an error */
        if (ret) {
 #if defined(CONFIG_MEDIA_CONTROLLER)
-               if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
+               if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+                   vdev->vfl_type != VFL_TYPE_SUBDEV)
                        media_entity_put(entity);
 #endif
                video_put(vdev);
@@ -437,7 +439,8 @@ static int v4l2_release(struct inode *inode, struct file *filp)
                        mutex_unlock(vdev->lock);
        }
 #if defined(CONFIG_MEDIA_CONTROLLER)
-       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
+       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+           vdev->vfl_type != VFL_TYPE_SUBDEV)
                media_entity_put(&vdev->entity);
 #endif
        /* decrease the refcount unconditionally since the release()
@@ -686,7 +689,8 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
 
 #if defined(CONFIG_MEDIA_CONTROLLER)
        /* Part 5: Register the entity. */
-       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev) {
+       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+           vdev->vfl_type != VFL_TYPE_SUBDEV) {
                vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
                vdev->entity.name = vdev->name;
                vdev->entity.v4l.major = VIDEO_MAJOR;
@@ -733,7 +737,8 @@ void video_unregister_device(struct video_device *vdev)
                return;
 
 #if defined(CONFIG_MEDIA_CONTROLLER)
-       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev)
+       if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+           vdev->vfl_type != VFL_TYPE_SUBDEV)
                media_device_unregister_entity(&vdev->entity);
 #endif
 
index 6698c77..6ba1461 100644 (file)
@@ -37,6 +37,9 @@ module_param(debug, int, 0644);
 #define call_qop(q, op, args...)                                       \
        (((q)->ops->op) ? ((q)->ops->op(args)) : 0)
 
+#define V4L2_BUFFER_STATE_FLAGS        (V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
+                                V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR)
+
 /**
  * __vb2_buf_mem_alloc() - allocate video memory for the given buffer
  */
@@ -51,7 +54,7 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb,
        for (plane = 0; plane < vb->num_planes; ++plane) {
                mem_priv = call_memop(q, plane, alloc, q->alloc_ctx[plane],
                                        plane_sizes[plane]);
-               if (!mem_priv)
+               if (IS_ERR_OR_NULL(mem_priv))
                        goto free;
 
                /* Associate allocator private data with this plane */
@@ -284,7 +287,7 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
        struct vb2_queue *q = vb->vb2_queue;
        int ret = 0;
 
-       /* Copy back data such as timestamp, input, etc. */
+       /* Copy back data such as timestamp, flags, input, etc. */
        memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
        b->input = vb->v4l2_buf.input;
        b->reserved = vb->v4l2_buf.reserved;
@@ -313,7 +316,10 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
                        b->m.userptr = vb->v4l2_planes[0].m.userptr;
        }
 
-       b->flags = 0;
+       /*
+        * Clear any buffer state related flags.
+        */
+       b->flags &= ~V4L2_BUFFER_STATE_FLAGS;
 
        switch (vb->state) {
        case VB2_BUF_STATE_QUEUED:
@@ -519,6 +525,7 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
        num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME);
        memset(plane_sizes, 0, sizeof(plane_sizes));
        memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
+       q->memory = req->memory;
 
        /*
         * Ask the driver how many buffers and planes per buffer it requires.
@@ -560,8 +567,6 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
                ret = num_buffers;
        }
 
-       q->memory = req->memory;
-
        /*
         * Return the number of successfully allocated buffers
         * to the userspace.
@@ -715,6 +720,8 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b,
 
        vb->v4l2_buf.field = b->field;
        vb->v4l2_buf.timestamp = b->timestamp;
+       vb->v4l2_buf.input = b->input;
+       vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_STATE_FLAGS;
 
        return 0;
 }
index 58205d5..a790a5f 100644 (file)
@@ -46,7 +46,7 @@ static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
                                        GFP_KERNEL);
        if (!buf->vaddr) {
                dev_err(conf->dev, "dma_alloc_coherent of size %ld failed\n",
-                       buf->size);
+                       size);
                kfree(buf);
                return ERR_PTR(-ENOMEM);
        }
index 53450f4..2e16511 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/spinlock.h>
 #include <linux/gpio.h>
-#include <linux/regulator/consumer.h>
 #include <plat/usb.h>
 
 #define USBHS_DRIVER_NAME      "usbhs-omap"
@@ -700,8 +699,7 @@ static int usbhs_enable(struct device *dev)
        dev_dbg(dev, "starting TI HSUSB Controller\n");
        if (!pdata) {
                dev_dbg(dev, "missing platform_data\n");
-               ret =  -ENODEV;
-               goto end_enable;
+               return  -ENODEV;
        }
 
        spin_lock_irqsave(&omap->lock, flags);
@@ -915,7 +913,8 @@ static int usbhs_enable(struct device *dev)
 
 end_count:
        omap->count++;
-       goto end_enable;
+       spin_unlock_irqrestore(&omap->lock, flags);
+       return 0;
 
 err_tll:
        if (pdata->ehci_data->phy_reset) {
@@ -931,8 +930,6 @@ err_tll:
        clk_disable(omap->usbhost_fs_fck);
        clk_disable(omap->usbhost_hs_fck);
        clk_disable(omap->usbhost_ick);
-
-end_enable:
        spin_unlock_irqrestore(&omap->lock, flags);
        return ret;
 }
index 63667a8..d6d62fd 100644 (file)
@@ -284,6 +284,7 @@ int mmc_add_card(struct mmc_card *card)
                type = "SD-combo";
                if (mmc_card_blockaddr(card))
                        type = "SDHC-combo";
+               break;
        default:
                type = "?";
                break;
index 461e6a1..2b200c1 100644 (file)
@@ -94,7 +94,7 @@ static void mmc_host_clk_gate_delayed(struct mmc_host *host)
                spin_unlock_irqrestore(&host->clk_lock, flags);
                return;
        }
-       mutex_lock(&host->clk_gate_mutex);
+       mmc_claim_host(host);
        spin_lock_irqsave(&host->clk_lock, flags);
        if (!host->clk_requests) {
                spin_unlock_irqrestore(&host->clk_lock, flags);
@@ -104,7 +104,7 @@ static void mmc_host_clk_gate_delayed(struct mmc_host *host)
                pr_debug("%s: gated MCI clock\n", mmc_hostname(host));
        }
        spin_unlock_irqrestore(&host->clk_lock, flags);
-       mutex_unlock(&host->clk_gate_mutex);
+       mmc_release_host(host);
 }
 
 /*
@@ -130,7 +130,7 @@ void mmc_host_clk_ungate(struct mmc_host *host)
 {
        unsigned long flags;
 
-       mutex_lock(&host->clk_gate_mutex);
+       mmc_claim_host(host);
        spin_lock_irqsave(&host->clk_lock, flags);
        if (host->clk_gated) {
                spin_unlock_irqrestore(&host->clk_lock, flags);
@@ -140,7 +140,7 @@ void mmc_host_clk_ungate(struct mmc_host *host)
        }
        host->clk_requests++;
        spin_unlock_irqrestore(&host->clk_lock, flags);
-       mutex_unlock(&host->clk_gate_mutex);
+       mmc_release_host(host);
 }
 
 /**
@@ -215,7 +215,6 @@ static inline void mmc_host_clk_init(struct mmc_host *host)
        host->clk_gated = false;
        INIT_WORK(&host->clk_gate_work, mmc_host_clk_gate_work);
        spin_lock_init(&host->clk_lock);
-       mutex_init(&host->clk_gate_mutex);
 }
 
 /**
index 2e032f0..a6c3290 100644 (file)
@@ -832,7 +832,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
                return IRQ_HANDLED;
        }
 
-       if (end_command)
+       if (end_command && host->cmd)
                mmc_omap_cmd_done(host, host->cmd);
        if (host->data != NULL) {
                if (transfer_error)
index a136be7..f8b5f37 100644 (file)
@@ -957,6 +957,7 @@ static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
        host->ioaddr = pci_ioremap_bar(pdev, bar);
        if (!host->ioaddr) {
                dev_err(&pdev->dev, "failed to remap registers\n");
+               ret = -ENOMEM;
                goto release;
        }
 
index 9e15f41..5d20661 100644 (file)
@@ -1334,6 +1334,13 @@ static void sdhci_tasklet_finish(unsigned long param)
 
        host = (struct sdhci_host*)param;
 
+        /*
+         * If this tasklet gets rescheduled while running, it will
+         * be run again afterwards but without any active request.
+         */
+       if (!host->mrq)
+               return;
+
        spin_lock_irqsave(&host->lock, flags);
 
        del_timer(&host->timer);
@@ -1345,7 +1352,7 @@ static void sdhci_tasklet_finish(unsigned long param)
         * upon error conditions.
         */
        if (!(host->flags & SDHCI_DEVICE_DEAD) &&
-               (mrq->cmd->error ||
+           ((mrq->cmd && mrq->cmd->error) ||
                 (mrq->data && (mrq->data->error ||
                  (mrq->data->stop && mrq->data->stop->error))) ||
                   (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) {
index 62d37de..710339a 100644 (file)
@@ -728,15 +728,15 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                tmio_mmc_set_clock(host, ios->clock);
 
        /* Power sequence - OFF -> UP -> ON */
-       if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
+       if (ios->power_mode == MMC_POWER_UP) {
+               /* power up SD bus */
+               if (host->set_pwr)
+                       host->set_pwr(host->pdev, 1);
+       } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
                /* power down SD bus */
                if (ios->power_mode == MMC_POWER_OFF && host->set_pwr)
                        host->set_pwr(host->pdev, 0);
                tmio_mmc_clk_stop(host);
-       } else if (ios->power_mode == MMC_POWER_UP) {
-               /* power up SD bus */
-               if (host->set_pwr)
-                       host->set_pwr(host->pdev, 1);
        } else {
                /* start bus clock */
                tmio_mmc_clk_start(host);
index 96c0b34..657b9f4 100644 (file)
@@ -400,7 +400,7 @@ static uint16_t __init doc200x_ident_chip(struct mtd_info *mtd, int nr)
        doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
        doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
-       /* We can't' use dev_ready here, but at least we wait for the
+       /* We can't use dev_ready here, but at least we wait for the
         * command to complete
         */
        udelay(50);
index 88495c4..241b185 100644 (file)
@@ -106,7 +106,7 @@ MODULE_DESCRIPTION ("AMD8111 based 10/100 Ethernet Controller. Driver Version "M
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, amd8111e_pci_tbl);
 module_param_array(speed_duplex, int, NULL, 0);
-MODULE_PARM_DESC(speed_duplex, "Set device speed and duplex modes, 0: Auto Negotitate, 1: 10Mbps Half Duplex, 2: 10Mbps Full Duplex, 3: 100Mbps Half Duplex, 4: 100Mbps Full Duplex");
+MODULE_PARM_DESC(speed_duplex, "Set device speed and duplex modes, 0: Auto Negotiate, 1: 10Mbps Half Duplex, 2: 10Mbps Full Duplex, 3: 100Mbps Half Duplex, 4: 100Mbps Full Duplex");
 module_param_array(coalesce, bool, NULL, 0);
 MODULE_PARM_DESC(coalesce, "Enable or Disable interrupt coalescing, 1: Enable, 0: Disable");
 module_param_array(dynamic_ipg, bool, NULL, 0);
index 7cb375e..925929d 100644 (file)
@@ -566,9 +566,9 @@ struct atl1c_adapter {
 #define __AT_TESTING        0x0001
 #define __AT_RESETTING      0x0002
 #define __AT_DOWN           0x0003
-       u8 work_event;
-#define ATL1C_WORK_EVENT_RESET                 0x01
-#define ATL1C_WORK_EVENT_LINK_CHANGE   0x02
+       unsigned long work_event;
+#define        ATL1C_WORK_EVENT_RESET          0
+#define        ATL1C_WORK_EVENT_LINK_CHANGE    1
        u32 msg_enable;
 
        bool have_msi;
index 7d9d506..a6e1c36 100644 (file)
@@ -325,7 +325,7 @@ static void atl1c_link_chg_event(struct atl1c_adapter *adapter)
                }
        }
 
-       adapter->work_event |= ATL1C_WORK_EVENT_LINK_CHANGE;
+       set_bit(ATL1C_WORK_EVENT_LINK_CHANGE, &adapter->work_event);
        schedule_work(&adapter->common_task);
 }
 
@@ -337,20 +337,16 @@ static void atl1c_common_task(struct work_struct *work)
        adapter = container_of(work, struct atl1c_adapter, common_task);
        netdev = adapter->netdev;
 
-       if (adapter->work_event & ATL1C_WORK_EVENT_RESET) {
-               adapter->work_event &= ~ATL1C_WORK_EVENT_RESET;
+       if (test_and_clear_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event)) {
                netif_device_detach(netdev);
                atl1c_down(adapter);
                atl1c_up(adapter);
                netif_device_attach(netdev);
-               return;
        }
 
-       if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE) {
-               adapter->work_event &= ~ATL1C_WORK_EVENT_LINK_CHANGE;
+       if (test_and_clear_bit(ATL1C_WORK_EVENT_LINK_CHANGE,
+               &adapter->work_event))
                atl1c_check_link_status(adapter);
-       }
-       return;
 }
 
 
@@ -369,7 +365,7 @@ static void atl1c_tx_timeout(struct net_device *netdev)
        struct atl1c_adapter *adapter = netdev_priv(netdev);
 
        /* Do the reset outside of interrupt context */
-       adapter->work_event |= ATL1C_WORK_EVENT_RESET;
+       set_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event);
        schedule_work(&adapter->common_task);
 }
 
index 7cb5a11..02a0443 100644 (file)
@@ -1873,6 +1873,7 @@ static void be_worker(struct work_struct *work)
                be_detect_dump_ue(adapter);
 
 reschedule:
+       adapter->work_counter++;
        schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
 }
 
index 8e6d618..d8383a9 100644 (file)
@@ -8413,6 +8413,8 @@ bnx2_remove_one(struct pci_dev *pdev)
 
        unregister_netdev(dev);
 
+       del_timer_sync(&bp->timer);
+
        if (bp->mips_firmware)
                release_firmware(bp->mips_firmware);
        if (bp->rv2p_firmware)
index e83ac6d..16581df 100644 (file)
@@ -2019,15 +2019,23 @@ static inline void bnx2x_set_pbd_gso(struct sk_buff *skb,
 static inline  u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
        u32 *parsing_data, u32 xmit_type)
 {
-       *parsing_data |= ((tcp_hdrlen(skb)/4) <<
-               ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) &
-               ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW;
+       *parsing_data |=
+                       ((((u8 *)skb_transport_header(skb) - skb->data) >> 1) <<
+                       ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT) &
+                       ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W;
 
-       *parsing_data |= ((((u8 *)tcp_hdr(skb) - skb->data) / 2) <<
-               ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT) &
-               ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W;
+       if (xmit_type & XMIT_CSUM_TCP) {
+               *parsing_data |= ((tcp_hdrlen(skb) / 4) <<
+                       ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) &
+                       ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW;
 
-       return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data;
+               return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data;
+       } else
+               /* We support checksum offload for TCP and UDP only.
+                * No need to pass the UDP header length - it's a constant.
+                */
+               return skb_transport_header(skb) +
+                               sizeof(struct udphdr) - skb->data;
 }
 
 /**
@@ -2043,7 +2051,7 @@ static inline u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb,
        struct eth_tx_parse_bd_e1x *pbd,
        u32 xmit_type)
 {
-       u8 hlen = (skb_network_header(skb) - skb->data) / 2;
+       u8 hlen = (skb_network_header(skb) - skb->data) >> 1;
 
        /* for now NS flag is not used in Linux */
        pbd->global_data =
@@ -2051,9 +2059,15 @@ static inline u8 bnx2x_set_pbd_csum(struct bnx2x *bp, struct sk_buff *skb,
                         ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT));
 
        pbd->ip_hlen_w = (skb_transport_header(skb) -
-                       skb_network_header(skb)) / 2;
+                       skb_network_header(skb)) >> 1;
 
-       hlen += pbd->ip_hlen_w + tcp_hdrlen(skb) / 2;
+       hlen += pbd->ip_hlen_w;
+
+       /* We support checksum offload for TCP and UDP only */
+       if (xmit_type & XMIT_CSUM_TCP)
+               hlen += tcp_hdrlen(skb) / 2;
+       else
+               hlen += sizeof(struct udphdr) / 2;
 
        pbd->total_hlen_w = cpu_to_le16(hlen);
        hlen = hlen*2;
index 494bf96..31912f1 100644 (file)
@@ -1482,8 +1482,11 @@ static struct aggregator *ad_agg_selection_test(struct aggregator *best,
 
 static int agg_device_up(const struct aggregator *agg)
 {
-       return (netif_running(agg->slave->dev) &&
-               netif_carrier_ok(agg->slave->dev));
+       struct port *port = agg->lag_ports;
+       if (!port)
+               return 0;
+       return (netif_running(port->slave->dev) &&
+               netif_carrier_ok(port->slave->dev));
 }
 
 /**
index f75d314..53c0f04 100644 (file)
@@ -3040,11 +3040,14 @@ static void ehea_rereg_mrs(void)
 
                                        if (dev->flags & IFF_UP) {
                                                mutex_lock(&port->port_lock);
-                                               port_napi_enable(port);
                                                ret = ehea_restart_qps(dev);
-                                               check_sqs(port);
-                                               if (!ret)
+                                               if (!ret) {
+                                                       check_sqs(port);
+                                                       port_napi_enable(port);
                                                        netif_wake_queue(dev);
+                                               } else {
+                                                       netdev_err(dev, "Unable to restart QPS\n");
+                                               }
                                                mutex_unlock(&port->port_lock);
                                        }
                                }
index 61035fc..b9fbc83 100644 (file)
@@ -226,8 +226,8 @@ static void set_multicast_finish(struct net_device *dev)
        }
 
        FC(fecp, r_cntrl, FEC_RCNTRL_PROM);
-       FW(fecp, hash_table_high, fep->fec.hthi);
-       FW(fecp, hash_table_low, fep->fec.htlo);
+       FW(fecp, grp_hash_table_high, fep->fec.hthi);
+       FW(fecp, grp_hash_table_low, fep->fec.htlo);
 }
 
 static void set_multicast_list(struct net_device *dev)
@@ -273,8 +273,8 @@ static void restart(struct net_device *dev)
        /*
         * Reset all multicast.
         */
-       FW(fecp, hash_table_high, fep->fec.hthi);
-       FW(fecp, hash_table_low, fep->fec.htlo);
+       FW(fecp, grp_hash_table_high, fep->fec.hthi);
+       FW(fecp, grp_hash_table_low, fep->fec.htlo);
 
        /*
         * Set maximum receive buffer size.
index a316619..9bd7746 100644 (file)
@@ -139,11 +139,11 @@ static int ftmac100_reset(struct ftmac100 *priv)
                         * that hardware reset completed (what the f*ck).
                         * We still need to wait for a while.
                         */
-                       usleep_range(500, 1000);
+                       udelay(500);
                        return 0;
                }
 
-               usleep_range(1000, 10000);
+               udelay(1000);
        }
 
        netdev_err(netdev, "software reset failed\n");
@@ -772,7 +772,7 @@ static int ftmac100_mdio_read(struct net_device *netdev, int phy_id, int reg)
                if ((phycr & FTMAC100_PHYCR_MIIRD) == 0)
                        return phycr & FTMAC100_PHYCR_MIIRDATA;
 
-               usleep_range(100, 1000);
+               udelay(100);
        }
 
        netdev_err(netdev, "mdio read timed out\n");
@@ -801,7 +801,7 @@ static void ftmac100_mdio_write(struct net_device *netdev, int phy_id, int reg,
                if ((phycr & FTMAC100_PHYCR_MIIWR) == 0)
                        return;
 
-               usleep_range(100, 1000);
+               udelay(100);
        }
 
        netdev_err(netdev, "mdio write timed out\n");
index 0a6c6a2..d4fc00b 100644 (file)
@@ -49,6 +49,10 @@ static u32 mii_get_an(struct mii_if_info *mii, u16 addr)
                result |= ADVERTISED_100baseT_Half;
        if (advert & ADVERTISE_100FULL)
                result |= ADVERTISED_100baseT_Full;
+       if (advert & ADVERTISE_PAUSE_CAP)
+               result |= ADVERTISED_Pause;
+       if (advert & ADVERTISE_PAUSE_ASYM)
+               result |= ADVERTISED_Asym_Pause;
 
        return result;
 }
index dfb67eb..eb41e44 100644 (file)
@@ -671,6 +671,7 @@ static int netconsole_netdev_event(struct notifier_block *this,
                goto done;
 
        spin_lock_irqsave(&target_list_lock, flags);
+restart:
        list_for_each_entry(nt, &target_list, list) {
                netconsole_target_get(nt);
                if (nt->np.dev == dev) {
@@ -683,9 +684,16 @@ static int netconsole_netdev_event(struct notifier_block *this,
                                 * rtnl_lock already held
                                 */
                                if (nt->np.dev) {
+                                       spin_unlock_irqrestore(
+                                                             &target_list_lock,
+                                                             flags);
                                        __netpoll_cleanup(&nt->np);
+                                       spin_lock_irqsave(&target_list_lock,
+                                                         flags);
                                        dev_put(nt->np.dev);
                                        nt->np.dev = NULL;
+                                       netconsole_target_put(nt);
+                                       goto restart;
                                }
                                /* Fall through */
                        case NETDEV_GOING_DOWN:
index 493b0de..397c368 100644 (file)
@@ -170,6 +170,16 @@ static const struct {
 };
 #undef _R
 
+static const struct rtl_firmware_info {
+       int mac_version;
+       const char *fw_name;
+} rtl_firmware_infos[] = {
+       { .mac_version = RTL_GIGA_MAC_VER_25, .fw_name = FIRMWARE_8168D_1 },
+       { .mac_version = RTL_GIGA_MAC_VER_26, .fw_name = FIRMWARE_8168D_2 },
+       { .mac_version = RTL_GIGA_MAC_VER_29, .fw_name = FIRMWARE_8105E_1 },
+       { .mac_version = RTL_GIGA_MAC_VER_30, .fw_name = FIRMWARE_8105E_1 }
+};
+
 enum cfg_version {
        RTL_CFG_0 = 0x00,
        RTL_CFG_1,
@@ -565,6 +575,7 @@ struct rtl8169_private {
        u32 saved_wolopts;
 
        const struct firmware *fw;
+#define RTL_FIRMWARE_UNKNOWN   ERR_PTR(-EAGAIN);
 };
 
 MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@@ -1789,25 +1800,26 @@ rtl_phy_write_fw(struct rtl8169_private *tp, const struct firmware *fw)
 
 static void rtl_release_firmware(struct rtl8169_private *tp)
 {
-       release_firmware(tp->fw);
-       tp->fw = NULL;
+       if (!IS_ERR_OR_NULL(tp->fw))
+               release_firmware(tp->fw);
+       tp->fw = RTL_FIRMWARE_UNKNOWN;
 }
 
-static int rtl_apply_firmware(struct rtl8169_private *tp, const char *fw_name)
+static void rtl_apply_firmware(struct rtl8169_private *tp)
 {
-       const struct firmware **fw = &tp->fw;
-       int rc = !*fw;
-
-       if (rc) {
-               rc = request_firmware(fw, fw_name, &tp->pci_dev->dev);
-               if (rc < 0)
-                       goto out;
-       }
+       const struct firmware *fw = tp->fw;
 
        /* TODO: release firmware once rtl_phy_write_fw signals failures. */
-       rtl_phy_write_fw(tp, *fw);
-out:
-       return rc;
+       if (!IS_ERR_OR_NULL(fw))
+               rtl_phy_write_fw(tp, fw);
+}
+
+static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
+{
+       if (rtl_readphy(tp, reg) != val)
+               netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n");
+       else
+               rtl_apply_firmware(tp);
 }
 
 static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
@@ -2246,10 +2258,8 @@ static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp)
 
        rtl_writephy(tp, 0x1f, 0x0005);
        rtl_writephy(tp, 0x05, 0x001b);
-       if ((rtl_readphy(tp, 0x06) != 0xbf00) ||
-           (rtl_apply_firmware(tp, FIRMWARE_8168D_1) < 0)) {
-               netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
-       }
+
+       rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00);
 
        rtl_writephy(tp, 0x1f, 0x0000);
 }
@@ -2351,10 +2361,8 @@ static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp)
 
        rtl_writephy(tp, 0x1f, 0x0005);
        rtl_writephy(tp, 0x05, 0x001b);
-       if ((rtl_readphy(tp, 0x06) != 0xb300) ||
-           (rtl_apply_firmware(tp, FIRMWARE_8168D_2) < 0)) {
-               netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
-       }
+
+       rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300);
 
        rtl_writephy(tp, 0x1f, 0x0000);
 }
@@ -2474,8 +2482,7 @@ static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
        rtl_writephy(tp, 0x18, 0x0310);
        msleep(100);
 
-       if (rtl_apply_firmware(tp, FIRMWARE_8105E_1) < 0)
-               netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
+       rtl_apply_firmware(tp);
 
        rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
@@ -3237,6 +3244,8 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        tp->timer.data = (unsigned long) dev;
        tp->timer.function = rtl8169_phy_timer;
 
+       tp->fw = RTL_FIRMWARE_UNKNOWN;
+
        rc = register_netdev(dev);
        if (rc < 0)
                goto err_out_msi_4;
@@ -3288,10 +3297,10 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
 
        cancel_delayed_work_sync(&tp->task);
 
-       rtl_release_firmware(tp);
-
        unregister_netdev(dev);
 
+       rtl_release_firmware(tp);
+
        if (pci_dev_run_wake(pdev))
                pm_runtime_get_noresume(&pdev->dev);
 
@@ -3303,6 +3312,37 @@ static void __devexit rtl8169_remove_one(struct pci_dev *pdev)
        pci_set_drvdata(pdev, NULL);
 }
 
+static void rtl_request_firmware(struct rtl8169_private *tp)
+{
+       int i;
+
+       /* Return early if the firmware is already loaded / cached. */
+       if (!IS_ERR(tp->fw))
+               goto out;
+
+       for (i = 0; i < ARRAY_SIZE(rtl_firmware_infos); i++) {
+               const struct rtl_firmware_info *info = rtl_firmware_infos + i;
+
+               if (info->mac_version == tp->mac_version) {
+                       const char *name = info->fw_name;
+                       int rc;
+
+                       rc = request_firmware(&tp->fw, name, &tp->pci_dev->dev);
+                       if (rc < 0) {
+                               netif_warn(tp, ifup, tp->dev, "unable to load "
+                                       "firmware patch %s (%d)\n", name, rc);
+                               goto out_disable_request_firmware;
+                       }
+                       goto out;
+               }
+       }
+
+out_disable_request_firmware:
+       tp->fw = NULL;
+out:
+       return;
+}
+
 static int rtl8169_open(struct net_device *dev)
 {
        struct rtl8169_private *tp = netdev_priv(dev);
@@ -3334,11 +3374,13 @@ static int rtl8169_open(struct net_device *dev)
 
        smp_mb();
 
+       rtl_request_firmware(tp);
+
        retval = request_irq(dev->irq, rtl8169_interrupt,
                             (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED,
                             dev->name, dev);
        if (retval < 0)
-               goto err_release_ring_2;
+               goto err_release_fw_2;
 
        napi_enable(&tp->napi);
 
@@ -3359,7 +3401,8 @@ static int rtl8169_open(struct net_device *dev)
 out:
        return retval;
 
-err_release_ring_2:
+err_release_fw_2:
+       rtl_release_firmware(tp);
        rtl8169_rx_clear(tp);
 err_free_rx_1:
        dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
index b8c5f35..7a5daef 100644 (file)
@@ -12327,8 +12327,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                if (val & VCPU_CFGSHDW_ASPM_DBNC)
                        tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND;
                if ((val & VCPU_CFGSHDW_WOL_ENABLE) &&
-                   (val & VCPU_CFGSHDW_WOL_MAGPKT))
+                   (val & VCPU_CFGSHDW_WOL_MAGPKT)) {
                        tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
+                       device_set_wakeup_enable(&tp->pdev->dev, true);
+               }
                goto done;
        }
 
@@ -12461,8 +12463,10 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
                        tp->tg3_flags &= ~TG3_FLAG_WOL_CAP;
 
                if ((tp->tg3_flags & TG3_FLAG_WOL_CAP) &&
-                   (nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE))
+                   (nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE)) {
                        tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
+                       device_set_wakeup_enable(&tp->pdev->dev, true);
+               }
 
                if (cfg2 & (1 << 17))
                        tp->phy_flags |= TG3_PHYFLG_CAPACITIVE_COUPLING;
index 341f705..a301479 100644 (file)
@@ -460,7 +460,7 @@ static const struct driver_info     cdc_info = {
        .manage_power = cdc_manage_power,
 };
 
-static const struct driver_info mbm_info = {
+static const struct driver_info wwan_info = {
        .description =  "Mobile Broadband Network Device",
        .flags =        FLAG_WWAN,
        .bind =         usbnet_cdc_bind,
@@ -471,6 +471,7 @@ static const struct driver_info mbm_info = {
 
 /*-------------------------------------------------------------------------*/
 
+#define HUAWEI_VENDOR_ID       0x12D1
 
 static const struct usb_device_id      products [] = {
 /*
@@ -587,8 +588,17 @@ static const struct usb_device_id  products [] = {
 }, {
        USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM,
                        USB_CDC_PROTO_NONE),
-       .driver_info = (unsigned long)&mbm_info,
+       .driver_info = (unsigned long)&wwan_info,
 
+}, {
+       /* Various Huawei modems with a network port like the UMG1831 */
+       .match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
+                | USB_DEVICE_ID_MATCH_INT_INFO,
+       .idVendor               = HUAWEI_VENDOR_ID,
+       .bInterfaceClass        = USB_CLASS_COMM,
+       .bInterfaceSubClass     = USB_CDC_SUBCLASS_ETHERNET,
+       .bInterfaceProtocol     = 255,
+       .driver_info = (unsigned long)&wwan_info,
 },
        { },            // END
 };
index 967371f..1033ef6 100644 (file)
 #include <linux/usb/usbnet.h>
 #include <linux/usb/cdc.h>
 
-#define        DRIVER_VERSION                          "7-Feb-2011"
+#define        DRIVER_VERSION                          "23-Apr-2011"
 
 /* CDC NCM subclass 3.2.1 */
 #define USB_CDC_NCM_NDP16_LENGTH_MIN           0x10
 
 /* Maximum NTB length */
-#define        CDC_NCM_NTB_MAX_SIZE_TX                 16384   /* bytes */
+#define        CDC_NCM_NTB_MAX_SIZE_TX                 (16384 + 4) /* bytes, must be short terminated */
 #define        CDC_NCM_NTB_MAX_SIZE_RX                 16384   /* bytes */
 
 /* Minimum value for MaxDatagramSize, ch. 6.2.9 */
index 47a6c87..48d4efd 100644 (file)
@@ -730,7 +730,7 @@ static int smsc95xx_phy_initialize(struct usbnet *dev)
                msleep(10);
                bmcr = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR);
                timeout++;
-       } while ((bmcr & MII_BMCR) && (timeout < 100));
+       } while ((bmcr & BMCR_RESET) && (timeout < 100));
 
        if (timeout >= 100) {
                netdev_warn(dev->net, "timeout on PHY Reset");
index 069c1cf..009bba3 100644 (file)
@@ -736,6 +736,7 @@ int usbnet_open (struct net_device *net)
                }
        }
 
+       set_bit(EVENT_DEV_OPEN, &dev->flags);
        netif_start_queue (net);
        netif_info(dev, ifup, dev->net,
                   "open: enable queueing (rx %d, tx %d) mtu %d %s framing\n",
@@ -1259,6 +1260,9 @@ void usbnet_disconnect (struct usb_interface *intf)
        if (dev->driver_info->unbind)
                dev->driver_info->unbind (dev, intf);
 
+       usb_kill_urb(dev->interrupt);
+       usb_free_urb(dev->interrupt);
+
        free_netdev(net);
        usb_put_dev (xdev);
 }
@@ -1498,6 +1502,10 @@ int usbnet_resume (struct usb_interface *intf)
        int                     retval;
 
        if (!--dev->suspend_count) {
+               /* resume interrupt URBs */
+               if (dev->interrupt && test_bit(EVENT_DEV_OPEN, &dev->flags))
+                       usb_submit_urb(dev->interrupt, GFP_NOIO);
+
                spin_lock_irq(&dev->txq.lock);
                while ((res = usb_get_from_anchor(&dev->deferred))) {
 
index 2de9b90..3b99f64 100644 (file)
@@ -403,6 +403,17 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
        if (tb[IFLA_ADDRESS] == NULL)
                random_ether_addr(dev->dev_addr);
 
+       if (tb[IFLA_IFNAME])
+               nla_strlcpy(dev->name, tb[IFLA_IFNAME], IFNAMSIZ);
+       else
+               snprintf(dev->name, IFNAMSIZ, DRV_NAME "%%d");
+
+       if (strchr(dev->name, '%')) {
+               err = dev_alloc_name(dev, dev->name);
+               if (err < 0)
+                       goto err_alloc_name;
+       }
+
        err = register_netdevice(dev);
        if (err < 0)
                goto err_register_dev;
@@ -422,6 +433,7 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
 
 err_register_dev:
        /* nothing to do */
+err_alloc_name:
 err_configure_peer:
        unregister_netdevice(peer);
        return err;
index dcd19bc..b29c80d 100644 (file)
@@ -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 || reset;
+       return stopped && !reset;
 }
 
 void ath_flushrecv(struct ath_softc *sc)
index d59b016..5af40d9 100644 (file)
@@ -72,6 +72,7 @@ MODULE_FIRMWARE("b43/ucode11.fw");
 MODULE_FIRMWARE("b43/ucode13.fw");
 MODULE_FIRMWARE("b43/ucode14.fw");
 MODULE_FIRMWARE("b43/ucode15.fw");
+MODULE_FIRMWARE("b43/ucode16_mimo.fw");
 MODULE_FIRMWARE("b43/ucode5.fw");
 MODULE_FIRMWARE("b43/ucode9.fw");
 
index 5c40502..79ac081 100644 (file)
@@ -316,12 +316,18 @@ int iwl4965_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        hdr_len = ieee80211_hdrlen(fc);
 
-       /* Find index into station table for destination station */
-       sta_id = iwl_legacy_sta_id_or_broadcast(priv, ctx, info->control.sta);
-       if (sta_id == IWL_INVALID_STATION) {
-               IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
-                              hdr->addr1);
-               goto drop_unlock;
+       /* For management frames use broadcast id to do not break aggregation */
+       if (!ieee80211_is_data(fc))
+               sta_id = ctx->bcast_sta_id;
+       else {
+               /* Find index into station table for destination station */
+               sta_id = iwl_legacy_sta_id_or_broadcast(priv, ctx, info->control.sta);
+
+               if (sta_id == IWL_INVALID_STATION) {
+                       IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
+                                      hdr->addr1);
+                       goto drop_unlock;
+               }
        }
 
        IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
@@ -1127,12 +1133,16 @@ int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
             q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd)) {
 
                tx_info = &txq->txb[txq->q.read_ptr];
-               iwl4965_tx_status(priv, tx_info,
-                                txq_id >= IWL4965_FIRST_AMPDU_QUEUE);
+
+               if (WARN_ON_ONCE(tx_info->skb == NULL))
+                       continue;
 
                hdr = (struct ieee80211_hdr *)tx_info->skb->data;
-               if (hdr && ieee80211_is_data_qos(hdr->frame_control))
+               if (ieee80211_is_data_qos(hdr->frame_control))
                        nfreed++;
+
+               iwl4965_tx_status(priv, tx_info,
+                                txq_id >= IWL4965_FIRST_AMPDU_QUEUE);
                tx_info->skb = NULL;
 
                priv->cfg->ops->lib->txq_free_tfd(priv, txq);
index 15eb8b7..bda0d61 100644 (file)
@@ -48,8 +48,21 @@ module_param(led_mode, int, S_IRUGO);
 MODULE_PARM_DESC(led_mode, "0=system default, "
                "1=On(RF On)/Off(RF Off), 2=blinking");
 
+/* Throughput          OFF time(ms)    ON time (ms)
+ *     >300                    25              25
+ *     >200 to 300             40              40
+ *     >100 to 200             55              55
+ *     >70 to 100              65              65
+ *     >50 to 70               75              75
+ *     >20 to 50               85              85
+ *     >10 to 20               95              95
+ *     >5 to 10                110             110
+ *     >1 to 5                 130             130
+ *     >0 to 1                 167             167
+ *     <=0                                     SOLID ON
+ */
 static const struct ieee80211_tpt_blink iwl_blink[] = {
-       { .throughput = 0 * 1024 - 1, .blink_time = 334 },
+       { .throughput = 0, .blink_time = 334 },
        { .throughput = 1 * 1024 - 1, .blink_time = 260 },
        { .throughput = 5 * 1024 - 1, .blink_time = 220 },
        { .throughput = 10 * 1024 - 1, .blink_time = 190 },
@@ -101,6 +114,11 @@ static int iwl_legacy_led_cmd(struct iwl_priv *priv,
        if (priv->blink_on == on && priv->blink_off == off)
                return 0;
 
+       if (off == 0) {
+               /* led is SOLID_ON */
+               on = IWL_LED_SOLID;
+       }
+
        IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n",
                        priv->cfg->base_params->led_compensation);
        led_cmd.on = iwl_legacy_blink_compensation(priv, on,
index d484c36..a62fe24 100644 (file)
@@ -2984,15 +2984,15 @@ static void iwl4965_bg_txpower_work(struct work_struct *work)
        struct iwl_priv *priv = container_of(work, struct iwl_priv,
                        txpower_work);
 
+       mutex_lock(&priv->mutex);
+
        /* If a scan happened to start before we got here
         * then just return; the statistics notification will
         * kick off another scheduled work to compensate for
         * any temperature delta we missed here. */
        if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
            test_bit(STATUS_SCANNING, &priv->status))
-               return;
-
-       mutex_lock(&priv->mutex);
+               goto out;
 
        /* Regardless of if we are associated, we must reconfigure the
         * TX power since frames can be sent on non-radar channels while
@@ -3002,7 +3002,7 @@ static void iwl4965_bg_txpower_work(struct work_struct *work)
        /* Update last_temperature to keep is_calib_needed from running
         * when it isn't needed... */
        priv->last_temperature = priv->temperature;
-
+out:
        mutex_unlock(&priv->mutex);
 }
 
index dfdbea6..fbbde07 100644 (file)
@@ -335,7 +335,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
        struct ieee80211_channel *channel = conf->channel;
        const struct iwl_channel_info *ch_info;
        int ret = 0;
-       bool ht_changed[NUM_IWL_RXON_CTX] = {};
 
        IWL_DEBUG_MAC80211(priv, "changed %#x", changed);
 
@@ -383,10 +382,8 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
 
                for_each_context(priv, ctx) {
                        /* Configure HT40 channels */
-                       if (ctx->ht.enabled != conf_is_ht(conf)) {
+                       if (ctx->ht.enabled != conf_is_ht(conf))
                                ctx->ht.enabled = conf_is_ht(conf);
-                               ht_changed[ctx->ctxid] = true;
-                       }
 
                        if (ctx->ht.enabled) {
                                if (conf_is_ht40_minus(conf)) {
@@ -455,8 +452,6 @@ int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
                if (!memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
                        continue;
                iwlagn_commit_rxon(priv, ctx);
-               if (ht_changed[ctx->ctxid])
-                       iwlagn_update_qos(priv, ctx);
        }
  out:
        mutex_unlock(&priv->mutex);
index a709d05..0712b67 100644 (file)
@@ -568,12 +568,17 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
 
        hdr_len = ieee80211_hdrlen(fc);
 
-       /* Find index into station table for destination station */
-       sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta);
-       if (sta_id == IWL_INVALID_STATION) {
-               IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
-                              hdr->addr1);
-               goto drop_unlock;
+       /* For management frames use broadcast id to do not break aggregation */
+       if (!ieee80211_is_data(fc))
+               sta_id = ctx->bcast_sta_id;
+       else {
+               /* Find index into station table for destination station */
+               sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta);
+               if (sta_id == IWL_INVALID_STATION) {
+                       IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
+                                      hdr->addr1);
+                       goto drop_unlock;
+               }
        }
 
        IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
@@ -1224,12 +1229,16 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
             q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
 
                tx_info = &txq->txb[txq->q.read_ptr];
-               iwlagn_tx_status(priv, tx_info,
-                                txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
+
+               if (WARN_ON_ONCE(tx_info->skb == NULL))
+                       continue;
 
                hdr = (struct ieee80211_hdr *)tx_info->skb->data;
-               if (hdr && ieee80211_is_data_qos(hdr->frame_control))
+               if (ieee80211_is_data_qos(hdr->frame_control))
                        nfreed++;
+
+               iwlagn_tx_status(priv, tx_info,
+                                txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
                tx_info->skb = NULL;
 
                if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl)
index fe77e82..e8c19de 100644 (file)
@@ -173,7 +173,7 @@ static int pcmcia_access_config(struct pcmcia_device *p_dev,
        c = p_dev->function_config;
 
        if (!(c->state & CONFIG_LOCKED)) {
-               dev_dbg(&p_dev->dev, "Configuration isn't't locked\n");
+               dev_dbg(&p_dev->dev, "Configuration isn't locked\n");
                mutex_unlock(&s->ops_mutex);
                return -EACCES;
        }
index 316f484..80f9c88 100644 (file)
@@ -220,6 +220,7 @@ static int __init coh901331_probe(struct platform_device *pdev)
        }
        clk_disable(rtap->clk);
 
+       platform_set_drvdata(pdev, rtap);
        rtap->rtc = rtc_device_register("coh901331", &pdev->dev, &coh901331_ops,
                                         THIS_MODULE);
        if (IS_ERR(rtap->rtc)) {
@@ -227,11 +228,10 @@ static int __init coh901331_probe(struct platform_device *pdev)
                goto out_no_rtc;
        }
 
-       platform_set_drvdata(pdev, rtap);
-
        return 0;
 
  out_no_rtc:
+       platform_set_drvdata(pdev, NULL);
  out_no_clk_enable:
        clk_put(rtap->clk);
  out_no_clk:
index 174036d..20494b5 100644 (file)
@@ -257,6 +257,8 @@ static int __devinit max8925_rtc_probe(struct platform_device *pdev)
                goto out_irq;
        }
 
+       dev_set_drvdata(&pdev->dev, info);
+
        info->rtc_dev = rtc_device_register("max8925-rtc", &pdev->dev,
                                        &max8925_rtc_ops, THIS_MODULE);
        ret = PTR_ERR(info->rtc_dev);
@@ -265,7 +267,6 @@ static int __devinit max8925_rtc_probe(struct platform_device *pdev)
                goto out_rtc;
        }
 
-       dev_set_drvdata(&pdev->dev, info);
        platform_set_drvdata(pdev, info);
 
        return 0;
index 4d2df2f..475e603 100644 (file)
@@ -2314,15 +2314,14 @@ static void dasd_flush_request_queue(struct dasd_block *block)
 
 static int dasd_open(struct block_device *bdev, fmode_t mode)
 {
-       struct dasd_block *block = bdev->bd_disk->private_data;
        struct dasd_device *base;
        int rc;
 
-       if (!block)
+       base = dasd_device_from_gendisk(bdev->bd_disk);
+       if (!base)
                return -ENODEV;
 
-       base = block->base;
-       atomic_inc(&block->open_count);
+       atomic_inc(&base->block->open_count);
        if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) {
                rc = -ENODEV;
                goto unlock;
@@ -2355,21 +2354,28 @@ static int dasd_open(struct block_device *bdev, fmode_t mode)
                goto out;
        }
 
+       dasd_put_device(base);
        return 0;
 
 out:
        module_put(base->discipline->owner);
 unlock:
-       atomic_dec(&block->open_count);
+       atomic_dec(&base->block->open_count);
+       dasd_put_device(base);
        return rc;
 }
 
 static int dasd_release(struct gendisk *disk, fmode_t mode)
 {
-       struct dasd_block *block = disk->private_data;
+       struct dasd_device *base;
 
-       atomic_dec(&block->open_count);
-       module_put(block->base->discipline->owner);
+       base = dasd_device_from_gendisk(disk);
+       if (!base)
+               return -ENODEV;
+
+       atomic_dec(&base->block->open_count);
+       module_put(base->discipline->owner);
+       dasd_put_device(base);
        return 0;
 }
 
@@ -2378,20 +2384,20 @@ static int dasd_release(struct gendisk *disk, fmode_t mode)
  */
 static int dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-       struct dasd_block *block;
        struct dasd_device *base;
 
-       block = bdev->bd_disk->private_data;
-       if (!block)
+       base = dasd_device_from_gendisk(bdev->bd_disk);
+       if (!base)
                return -ENODEV;
-       base = block->base;
 
        if (!base->discipline ||
-           !base->discipline->fill_geometry)
+           !base->discipline->fill_geometry) {
+               dasd_put_device(base);
                return -EINVAL;
-
-       base->discipline->fill_geometry(block, geo);
-       geo->start = get_start_sect(bdev) >> block->s2b_shift;
+       }
+       base->discipline->fill_geometry(base->block, geo);
+       geo->start = get_start_sect(bdev) >> base->block->s2b_shift;
+       dasd_put_device(base);
        return 0;
 }
 
@@ -2528,7 +2534,6 @@ void dasd_generic_remove(struct ccw_device *cdev)
        dasd_set_target_state(device, DASD_STATE_NEW);
        /* dasd_delete_device destroys the device reference. */
        block = device->block;
-       device->block = NULL;
        dasd_delete_device(device);
        /*
         * life cycle of block is bound to device, so delete it after
@@ -2650,7 +2655,6 @@ int dasd_generic_set_offline(struct ccw_device *cdev)
        dasd_set_target_state(device, DASD_STATE_NEW);
        /* dasd_delete_device destroys the device reference. */
        block = device->block;
-       device->block = NULL;
        dasd_delete_device(device);
        /*
         * life cycle of block is bound to device, so delete it after
index 42e1bf3..d71511c 100644 (file)
@@ -674,6 +674,36 @@ dasd_device_from_cdev(struct ccw_device *cdev)
        return device;
 }
 
+void dasd_add_link_to_gendisk(struct gendisk *gdp, struct dasd_device *device)
+{
+       struct dasd_devmap *devmap;
+
+       devmap = dasd_find_busid(dev_name(&device->cdev->dev));
+       if (IS_ERR(devmap))
+               return;
+       spin_lock(&dasd_devmap_lock);
+       gdp->private_data = devmap;
+       spin_unlock(&dasd_devmap_lock);
+}
+
+struct dasd_device *dasd_device_from_gendisk(struct gendisk *gdp)
+{
+       struct dasd_device *device;
+       struct dasd_devmap *devmap;
+
+       if (!gdp->private_data)
+               return NULL;
+       device = NULL;
+       spin_lock(&dasd_devmap_lock);
+       devmap = gdp->private_data;
+       if (devmap && devmap->device) {
+               device = devmap->device;
+               dasd_get_device(device);
+       }
+       spin_unlock(&dasd_devmap_lock);
+       return device;
+}
+
 /*
  * SECTION: files in sysfs
  */
index 29143ed..85dddb1 100644 (file)
@@ -239,7 +239,6 @@ static void dasd_ext_handler(unsigned int ext_int_code,
        addr_t ip;
        int rc;
 
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_DSD]++;
        switch (ext_int_code >> 24) {
        case DASD_DIAG_CODE_31BIT:
                ip = (addr_t) param32;
@@ -250,6 +249,7 @@ static void dasd_ext_handler(unsigned int ext_int_code,
        default:
                return;
        }
+       kstat_cpu(smp_processor_id()).irqs[EXTINT_DSD]++;
        if (!ip) {              /* no intparm: unsolicited interrupt */
                DBF_EVENT(DBF_NOTICE, "%s", "caught unsolicited "
                              "interrupt");
index db8005d..3ebdf5f 100644 (file)
@@ -2037,7 +2037,7 @@ static void dasd_eckd_check_for_device_change(struct dasd_device *device,
                return;
 
        /* summary unit check */
-       if ((sense[7] == 0x0D) &&
+       if ((sense[27] & DASD_SENSE_BIT_0) && (sense[7] == 0x0D) &&
            (scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK)) {
                dasd_alias_handle_summary_unit_check(device, irb);
                return;
@@ -2053,7 +2053,8 @@ static void dasd_eckd_check_for_device_change(struct dasd_device *device,
        /* loss of device reservation is handled via base devices only
         * as alias devices may be used with several bases
         */
-       if (device->block && (sense[7] == 0x3F) &&
+       if (device->block && (sense[27] & DASD_SENSE_BIT_0) &&
+           (sense[7] == 0x3F) &&
            (scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK) &&
            test_bit(DASD_FLAG_IS_RESERVED, &device->flags)) {
                if (device->features & DASD_FEATURE_FAILONSLCK)
index 5505bc0..19a1ff0 100644 (file)
@@ -73,7 +73,7 @@ int dasd_gendisk_alloc(struct dasd_block *block)
        if (base->features & DASD_FEATURE_READONLY ||
            test_bit(DASD_FLAG_DEVICE_RO, &base->flags))
                set_disk_ro(gdp, 1);
-       gdp->private_data = block;
+       dasd_add_link_to_gendisk(gdp, base);
        gdp->queue = block->request_queue;
        block->gdp = gdp;
        set_capacity(block->gdp, 0);
index df9f699..d1e4f2c 100644 (file)
@@ -686,6 +686,9 @@ struct dasd_device *dasd_device_from_cdev(struct ccw_device *);
 struct dasd_device *dasd_device_from_cdev_locked(struct ccw_device *);
 struct dasd_device *dasd_device_from_devindex(int);
 
+void dasd_add_link_to_gendisk(struct gendisk *, struct dasd_device *);
+struct dasd_device *dasd_device_from_gendisk(struct gendisk *);
+
 int dasd_parse(void);
 int dasd_busid_known(const char *);
 
index 26075e9..72261e4 100644 (file)
@@ -42,16 +42,22 @@ dasd_ioctl_api_version(void __user *argp)
 static int
 dasd_ioctl_enable(struct block_device *bdev)
 {
-       struct dasd_block *block = bdev->bd_disk->private_data;
+       struct dasd_device *base;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
 
-       dasd_enable_device(block->base);
+       base = dasd_device_from_gendisk(bdev->bd_disk);
+       if (!base)
+               return -ENODEV;
+
+       dasd_enable_device(base);
        /* Formatting the dasd device can change the capacity. */
        mutex_lock(&bdev->bd_mutex);
-       i_size_write(bdev->bd_inode, (loff_t)get_capacity(block->gdp) << 9);
+       i_size_write(bdev->bd_inode,
+                    (loff_t)get_capacity(base->block->gdp) << 9);
        mutex_unlock(&bdev->bd_mutex);
+       dasd_put_device(base);
        return 0;
 }
 
@@ -62,11 +68,14 @@ dasd_ioctl_enable(struct block_device *bdev)
 static int
 dasd_ioctl_disable(struct block_device *bdev)
 {
-       struct dasd_block *block = bdev->bd_disk->private_data;
+       struct dasd_device *base;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
 
+       base = dasd_device_from_gendisk(bdev->bd_disk);
+       if (!base)
+               return -ENODEV;
        /*
         * Man this is sick. We don't do a real disable but only downgrade
         * the device to DASD_STATE_BASIC. The reason is that dasdfmt uses
@@ -75,7 +84,7 @@ dasd_ioctl_disable(struct block_device *bdev)
         * using the BIODASDFMT ioctl. Therefore the correct state for the
         * device is DASD_STATE_BASIC that allows to do basic i/o.
         */
-       dasd_set_target_state(block->base, DASD_STATE_BASIC);
+       dasd_set_target_state(base, DASD_STATE_BASIC);
        /*
         * Set i_size to zero, since read, write, etc. check against this
         * value.
@@ -83,6 +92,7 @@ dasd_ioctl_disable(struct block_device *bdev)
        mutex_lock(&bdev->bd_mutex);
        i_size_write(bdev->bd_inode, 0);
        mutex_unlock(&bdev->bd_mutex);
+       dasd_put_device(base);
        return 0;
 }
 
@@ -191,26 +201,36 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata)
 static int
 dasd_ioctl_format(struct block_device *bdev, void __user *argp)
 {
-       struct dasd_block *block = bdev->bd_disk->private_data;
+       struct dasd_device *base;
        struct format_data_t fdata;
+       int rc;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
        if (!argp)
                return -EINVAL;
-
-       if (block->base->features & DASD_FEATURE_READONLY ||
-           test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags))
+       base = dasd_device_from_gendisk(bdev->bd_disk);
+       if (!base)
+               return -ENODEV;
+       if (base->features & DASD_FEATURE_READONLY ||
+           test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) {
+               dasd_put_device(base);
                return -EROFS;
-       if (copy_from_user(&fdata, argp, sizeof(struct format_data_t)))
+       }
+       if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) {
+               dasd_put_device(base);
                return -EFAULT;
+       }
        if (bdev != bdev->bd_contains) {
                pr_warning("%s: The specified DASD is a partition and cannot "
                           "be formatted\n",
-                          dev_name(&block->base->cdev->dev));
+                          dev_name(&base->cdev->dev));
+               dasd_put_device(base);
                return -EINVAL;
        }
-       return dasd_format(block, &fdata);
+       rc = dasd_format(base->block, &fdata);
+       dasd_put_device(base);
+       return rc;
 }
 
 #ifdef CONFIG_DASD_PROFILE
@@ -340,8 +360,8 @@ static int dasd_ioctl_information(struct dasd_block *block,
 static int
 dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp)
 {
-       struct dasd_block *block =  bdev->bd_disk->private_data;
-       int intval;
+       struct dasd_device *base;
+       int intval, rc;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
@@ -350,10 +370,17 @@ dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp)
                return -EINVAL;
        if (get_user(intval, (int __user *)argp))
                return -EFAULT;
-       if (!intval && test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags))
+       base = dasd_device_from_gendisk(bdev->bd_disk);
+       if (!base)
+               return -ENODEV;
+       if (!intval && test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) {
+               dasd_put_device(base);
                return -EROFS;
+       }
        set_disk_ro(bdev->bd_disk, intval);
-       return dasd_set_feature(block->base->cdev, DASD_FEATURE_READONLY, intval);
+       rc = dasd_set_feature(base->cdev, DASD_FEATURE_READONLY, intval);
+       dasd_put_device(base);
+       return rc;
 }
 
 static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd,
@@ -372,59 +399,78 @@ static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd,
 int dasd_ioctl(struct block_device *bdev, fmode_t mode,
               unsigned int cmd, unsigned long arg)
 {
-       struct dasd_block *block = bdev->bd_disk->private_data;
+       struct dasd_block *block;
+       struct dasd_device *base;
        void __user *argp;
+       int rc;
 
        if (is_compat_task())
                argp = compat_ptr(arg);
        else
                argp = (void __user *)arg;
 
-       if (!block)
-                return -ENODEV;
-
        if ((_IOC_DIR(cmd) != _IOC_NONE) && !arg) {
                PRINT_DEBUG("empty data ptr");
                return -EINVAL;
        }
 
+       base = dasd_device_from_gendisk(bdev->bd_disk);
+       if (!base)
+               return -ENODEV;
+       block = base->block;
+       rc = 0;
        switch (cmd) {
        case BIODASDDISABLE:
-               return dasd_ioctl_disable(bdev);
+               rc = dasd_ioctl_disable(bdev);
+               break;
        case BIODASDENABLE:
-               return dasd_ioctl_enable(bdev);
+               rc = dasd_ioctl_enable(bdev);
+               break;
        case BIODASDQUIESCE:
-               return dasd_ioctl_quiesce(block);
+               rc = dasd_ioctl_quiesce(block);
+               break;
        case BIODASDRESUME:
-               return dasd_ioctl_resume(block);
+               rc = dasd_ioctl_resume(block);
+               break;
        case BIODASDFMT:
-               return dasd_ioctl_format(bdev, argp);
+               rc = dasd_ioctl_format(bdev, argp);
+               break;
        case BIODASDINFO:
-               return dasd_ioctl_information(block, cmd, argp);
+               rc = dasd_ioctl_information(block, cmd, argp);
+               break;
        case BIODASDINFO2:
-               return dasd_ioctl_information(block, cmd, argp);
+               rc = dasd_ioctl_information(block, cmd, argp);
+               break;
        case BIODASDPRRD:
-               return dasd_ioctl_read_profile(block, argp);
+               rc = dasd_ioctl_read_profile(block, argp);
+               break;
        case BIODASDPRRST:
-               return dasd_ioctl_reset_profile(block);
+               rc = dasd_ioctl_reset_profile(block);
+               break;
        case BLKROSET:
-               return dasd_ioctl_set_ro(bdev, argp);
+               rc = dasd_ioctl_set_ro(bdev, argp);
+               break;
        case DASDAPIVER:
-               return dasd_ioctl_api_version(argp);
+               rc = dasd_ioctl_api_version(argp);
+               break;
        case BIODASDCMFENABLE:
-               return enable_cmf(block->base->cdev);
+               rc = enable_cmf(base->cdev);
+               break;
        case BIODASDCMFDISABLE:
-               return disable_cmf(block->base->cdev);
+               rc = disable_cmf(base->cdev);
+               break;
        case BIODASDREADALLCMB:
-               return dasd_ioctl_readall_cmb(block, cmd, argp);
+               rc = dasd_ioctl_readall_cmb(block, cmd, argp);
+               break;
        default:
                /* if the discipline has an ioctl method try it. */
-               if (block->base->discipline->ioctl) {
-                       int rval = block->base->discipline->ioctl(block, cmd, argp);
-                       if (rval != -ENOIOCTLCMD)
-                               return rval;
-               }
-
-               return -EINVAL;
+               if (base->discipline->ioctl) {
+                       rc = base->discipline->ioctl(block, cmd, argp);
+                       if (rc == -ENOIOCTLCMD)
+                               rc = -EINVAL;
+               } else
+                       rc = -EINVAL;
        }
+       dasd_put_device(base);
+       return rc;
 }
index c532ba9..e8f267e 100644 (file)
@@ -407,8 +407,11 @@ static inline void account_sbals(struct qdio_q *q, int count)
        q->q_stats.nr_sbals[pos]++;
 }
 
-static void announce_buffer_error(struct qdio_q *q, int count)
+static void process_buffer_error(struct qdio_q *q, int count)
 {
+       unsigned char state = (q->is_input_q) ? SLSB_P_INPUT_NOT_INIT :
+                                       SLSB_P_OUTPUT_NOT_INIT;
+
        q->qdio_error |= QDIO_ERROR_SLSB_STATE;
 
        /* special handling for no target buffer empty */
@@ -426,6 +429,12 @@ static void announce_buffer_error(struct qdio_q *q, int count)
        DBF_ERROR("F14:%2x F15:%2x",
                  q->sbal[q->first_to_check]->element[14].flags & 0xff,
                  q->sbal[q->first_to_check]->element[15].flags & 0xff);
+
+       /*
+        * Interrupts may be avoided as long as the error is present
+        * so change the buffer state immediately to avoid starvation.
+        */
+       set_buf_states(q, q->first_to_check, state, count);
 }
 
 static inline void inbound_primed(struct qdio_q *q, int count)
@@ -506,8 +515,7 @@ static int get_inbound_buffer_frontier(struct qdio_q *q)
                        account_sbals(q, count);
                break;
        case SLSB_P_INPUT_ERROR:
-               announce_buffer_error(q, count);
-               /* process the buffer, the upper layer will take care of it */
+               process_buffer_error(q, count);
                q->first_to_check = add_buf(q->first_to_check, count);
                atomic_sub(count, &q->nr_buf_used);
                if (q->irq_ptr->perf_stat_enabled)
@@ -677,8 +685,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q)
                        account_sbals(q, count);
                break;
        case SLSB_P_OUTPUT_ERROR:
-               announce_buffer_error(q, count);
-               /* process the buffer, the upper layer will take care of it */
+               process_buffer_error(q, count);
                q->first_to_check = add_buf(q->first_to_check, count);
                atomic_sub(count, &q->nr_buf_used);
                if (q->irq_ptr->perf_stat_enabled)
index 414427d..607998f 100644 (file)
@@ -381,10 +381,10 @@ static void kvm_extint_handler(unsigned int ext_int_code,
        u16 subcode;
        u32 param;
 
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_VRT]++;
        subcode = ext_int_code >> 16;
        if ((subcode & 0xff00) != VIRTIO_SUBCODE_64)
                return;
+       kstat_cpu(smp_processor_id()).irqs[EXTINT_VRT]++;
 
        /* The LSB might be overloaded, we have to mask it */
        vq = (struct virtqueue *)(param64 & ~1UL);
index 564e6ec..0119b81 100644 (file)
@@ -394,12 +394,14 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)
        unsigned long flags;
        struct scsi_device *sdev;
        struct scsi_device_handler *scsi_dh = NULL;
+       struct device *dev = NULL;
 
        spin_lock_irqsave(q->queue_lock, flags);
        sdev = q->queuedata;
        if (sdev && sdev->scsi_dh_data)
                scsi_dh = sdev->scsi_dh_data->scsi_dh;
-       if (!scsi_dh || !get_device(&sdev->sdev_gendev) ||
+       dev = get_device(&sdev->sdev_gendev);
+       if (!scsi_dh || !dev ||
            sdev->sdev_state == SDEV_CANCEL ||
            sdev->sdev_state == SDEV_DEL)
                err = SCSI_DH_NOSYS;
@@ -410,12 +412,13 @@ int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)
        if (err) {
                if (fn)
                        fn(data, err);
-               return err;
+               goto out;
        }
 
        if (scsi_dh->activate)
                err = scsi_dh->activate(sdev, fn, data);
-       put_device(&sdev->sdev_gendev);
+out:
+       put_device(dev);
        return err;
 }
 EXPORT_SYMBOL_GPL(scsi_dh_activate);
index 1c6d2b4..d72f1f2 100644 (file)
@@ -688,6 +688,13 @@ _ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
                goto out;
        }
 
+       /* Check for overflow and wraparound */
+       if (karg.data_sge_offset * 4 > ioc->request_sz ||
+           karg.data_sge_offset > (UINT_MAX / 4)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        /* copy in request message frame from user */
        if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) {
                printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__,
@@ -1963,7 +1970,7 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
        Mpi2DiagBufferPostReply_t *mpi_reply;
        int rc, i;
        u8 buffer_type;
-       unsigned long timeleft;
+       unsigned long timeleft, request_size, copy_size;
        u16 smid;
        u16 ioc_status;
        u8 issue_reset = 0;
@@ -1999,6 +2006,8 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
                return -ENOMEM;
        }
 
+       request_size = ioc->diag_buffer_sz[buffer_type];
+
        if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) {
                printk(MPT2SAS_ERR_FMT "%s: either the starting_offset "
                    "or bytes_to_read are not 4 byte aligned\n", ioc->name,
@@ -2006,13 +2015,23 @@ _ctl_diag_read_buffer(void __user *arg, enum block_state state)
                return -EINVAL;
        }
 
+       if (karg.starting_offset > request_size)
+               return -EINVAL;
+
        diag_data = (void *)(request_data + karg.starting_offset);
        dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(%p), "
            "offset(%d), sz(%d)\n", ioc->name, __func__,
            diag_data, karg.starting_offset, karg.bytes_to_read));
 
+       /* Truncate data on requests that are too large */
+       if ((diag_data + karg.bytes_to_read < diag_data) ||
+           (diag_data + karg.bytes_to_read > request_data + request_size))
+               copy_size = request_size - karg.starting_offset;
+       else
+               copy_size = karg.bytes_to_read;
+
        if (copy_to_user((void __user *)uarg->diagnostic_data,
-           diag_data, karg.bytes_to_read)) {
+           diag_data, copy_size)) {
                printk(MPT2SAS_ERR_FMT "%s: Unable to write "
                    "mpt_diag_read_buffer_t data @ %p\n", ioc->name,
                    __func__, diag_data);
index 96d5ad0..7f636b1 100644 (file)
@@ -3814,6 +3814,9 @@ static long pmcraid_ioctl_passthrough(
                        rc = -EFAULT;
                        goto out_free_buffer;
                }
+       } else if (request_size < 0) {
+               rc = -EINVAL;
+               goto out_free_buffer;
        }
 
        /* check if we have any additional command parameters */
index e44ff64..e639125 100644 (file)
@@ -322,14 +322,8 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
                kfree(evt);
        }
 
-       if (sdev->request_queue) {
-               sdev->request_queue->queuedata = NULL;
-               /* user context needed to free queue */
-               scsi_free_queue(sdev->request_queue);
-               /* temporary expedient, try to catch use of queue lock
-                * after free of sdev */
-               sdev->request_queue = NULL;
-       }
+       /* NULL queue means the device can't be used */
+       sdev->request_queue = NULL;
 
        scsi_target_reap(scsi_target(sdev));
 
@@ -937,6 +931,12 @@ void __scsi_remove_device(struct scsi_device *sdev)
        if (sdev->host->hostt->slave_destroy)
                sdev->host->hostt->slave_destroy(sdev);
        transport_destroy_device(dev);
+
+       /* cause the request function to reject all I/O requests */
+       sdev->request_queue->queuedata = NULL;
+
+       /* Freeing the queue signals to block that we're done */
+       scsi_free_queue(sdev->request_queue);
        put_device(dev);
 }
 
index eeb7dd4..830822f 100644 (file)
@@ -2288,7 +2288,3 @@ err_dev:
        free_netdev(dev);
        return NULL;
 }
-
-EXPORT_SYMBOL(init_ft1000_card);
-EXPORT_SYMBOL(stop_ft1000_card);
-EXPORT_SYMBOL(flarion_ft1000_cnt);
index 935608e..bdfb1ae 100644 (file)
@@ -214,6 +214,3 @@ void ft1000CleanupProc(struct net_device *dev)
        remove_proc_entry(FT1000_PROC, init_net.proc_net);
        unregister_netdevice_notifier(&ft1000_netdev_notifier);
 }
-
-EXPORT_SYMBOL(ft1000InitProc);
-EXPORT_SYMBOL(ft1000CleanupProc);
index 5501eb9..ce8beda 100644 (file)
@@ -1,6 +1,6 @@
 config DRM_PSB
        tristate "Intel GMA500 KMS Framebuffer"
-       depends on DRM && PCI
+       depends on DRM && PCI && X86
        select FB_CFB_COPYAREA
         select FB_CFB_FILLRECT
         select FB_CFB_IMAGEBLIT
index 9cc15c1..1ea8142 100644 (file)
@@ -28,6 +28,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/pci.h>
+#include <linux/delay.h>
 #include <linux/file.h>
 #include <asm/mrst.h>
 #include <sound/pcm.h>
index 26d815a..3c6b3ab 100644 (file)
@@ -29,6 +29,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/pci.h>
+#include <linux/delay.h>
 #include <linux/file.h>
 #include "intel_sst.h"
 #include "intelmid_snd_control.h"
index b5d21f6..22c04ea 100644 (file)
@@ -12,6 +12,7 @@
  */
 #include <linux/cs5535.h>
 #include <linux/gpio.h>
+#include <linux/delay.h>
 #include <asm/olpc.h>
 
 #include "olpc_dcon.h"
index bef0bbd..f01a51c 100644 (file)
@@ -444,7 +444,7 @@ int RTMPCheckRxError(struct rt_rtmp_adapter *pAd,
                        return (NDIS_STATUS_FAILURE);
                }
        }
-       /* Drop not U2M frames, can't's drop here because we will drop beacon in this case */
+       /* Drop not U2M frames, can't drop here because we will drop beacon in this case */
        /* I am kind of doubting the U2M bit operation */
        /* if (pRxD->U2M == 0) */
        /*      return(NDIS_STATUS_FAILURE); */
index 5637857..83a62fa 100644 (file)
@@ -860,7 +860,7 @@ int RTMPCheckRxError(struct rt_rtmp_adapter *pAd,
                DBGPRINT_RAW(RT_DEBUG_ERROR, ("received packet too long\n"));
                return NDIS_STATUS_FAILURE;
        }
-       /* Drop not U2M frames, can't's drop here because we will drop beacon in this case */
+       /* Drop not U2M frames, can't drop here because we will drop beacon in this case */
        /* I am kind of doubting the U2M bit operation */
        /* if (pRxD->U2M == 0) */
        /*      return(NDIS_STATUS_FAILURE); */
index e1408b0..ab305be 100644 (file)
@@ -28,7 +28,7 @@
 
 #define RTSX_STOR "rts_pstor: "
 
-#if CONFIG_RTS_PSTOR_DEBUG
+#ifdef CONFIG_RTS_PSTOR_DEBUG
 #define RTSX_DEBUGP(x...) printk(KERN_DEBUG RTSX_STOR x)
 #define RTSX_DEBUGPN(x...) printk(KERN_DEBUG x)
 #define RTSX_DEBUGPX(x...) printk(x)
index 810e170..d89795c 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/blkdev.h>
 #include <linux/kthread.h>
 #include <linux/sched.h>
+#include <linux/vmalloc.h>
 
 #include "rtsx.h"
 #include "rtsx_transport.h"
index d2f1c71..4e60780 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/kthread.h>
 #include <linux/sched.h>
 #include <linux/workqueue.h>
+#include <linux/vmalloc.h>
 
 #include "rtsx.h"
 #include "rtsx_transport.h"
@@ -1311,11 +1312,11 @@ void rtsx_polling_func(struct rtsx_chip *chip)
 
 #ifdef SUPPORT_OCP
        if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
-               #if CONFIG_RTS_PSTOR_DEBUG
+#ifdef CONFIG_RTS_PSTOR_DEBUG
                if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER | MS_OC_NOW | MS_OC_EVER)) {
                        RTSX_DEBUGP("Over current, OCPSTAT is 0x%x\n", chip->ocp_stat);
                }
-               #endif
+#endif
 
                if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
                        if (chip->card_exist & SD_CARD) {
index 20c2464..7de1fae 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/blkdev.h>
 #include <linux/kthread.h>
 #include <linux/sched.h>
+#include <linux/vmalloc.h>
 
 #include "rtsx.h"
 #include "rtsx_transport.h"
index 8d066bd..b1277a6 100644 (file)
@@ -909,7 +909,7 @@ static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir)
                RTSX_WRITE_REG(chip, SD_VPCLK0_CTL, PHASE_NOT_RESET, PHASE_NOT_RESET);
                RTSX_WRITE_REG(chip, CLK_CTL, CHANGE_CLK, 0);
        } else {
-#if CONFIG_RTS_PSTOR_DEBUG
+#ifdef CONFIG_RTS_PSTOR_DEBUG
                rtsx_read_register(chip, SD_VP_CTL, &val);
                RTSX_DEBUGP("SD_VP_CTL: 0x%x\n", val);
                rtsx_read_register(chip, SD_DCMPS_CTL, &val);
@@ -958,7 +958,7 @@ static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir)
        return STATUS_SUCCESS;
 
 Fail:
-#if CONFIG_RTS_PSTOR_DEBUG
+#ifdef CONFIG_RTS_PSTOR_DEBUG
        rtsx_read_register(chip, SD_VP_CTL, &val);
        RTSX_DEBUGP("SD_VP_CTL: 0x%x\n", val);
        rtsx_read_register(chip, SD_DCMPS_CTL, &val);
index 2c668ba..bc83b49 100644 (file)
@@ -82,7 +82,7 @@ do {                                                                                                  \
 #define TRACE_GOTO(chip, label)        goto label
 #endif
 
-#if CONFIG_RTS_PSTOR_DEBUG
+#ifdef CONFIG_RTS_PSTOR_DEBUG
 static inline void rtsx_dump(u8 *buf, int buf_len)
 {
        int i;
index 7bcd468..9f3add1 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/blkdev.h>
 #include <linux/kthread.h>
 #include <linux/sched.h>
+#include <linux/vmalloc.h>
 
 #include "rtsx.h"
 #include "rtsx_transport.h"
index 2cf77c9..03dcac4 100644 (file)
@@ -2,6 +2,7 @@ config SOLO6X10
        tristate "Softlogic 6x10 MPEG codec cards"
        depends on PCI && VIDEO_DEV && SND && I2C
        select VIDEOBUF_DMA_SG
+       select SND_PCM
        ---help---
          This driver supports the Softlogic based MPEG-4 and h.264 codec
          codec cards.
index 20dae73..506547b 100644 (file)
@@ -653,7 +653,7 @@ static int SBD_setup_device(struct spectra_nand_dev *dev, int which)
        }
        dev->queue->queuedata = dev;
 
-       /* As Linux block layer does't support >4KB hardware sector,  */
+       /* As Linux block layer doesn't support >4KB hardware sector,  */
        /* Here we force report 512 byte hardware sector size to Kernel */
        blk_queue_logical_block_size(dev->queue, 512);
 
index 5cecd23..fe1ef0a 100644 (file)
@@ -718,7 +718,7 @@ static void dload_symbols(struct dload_state *dlthis)
         * as a temporary for .dllview record construction.
         * Allocate storage for the whole table.  Add 1 to the section count
         * in case a trampoline section is auto-generated as well as the
-        * size of the trampoline section name so DLLView does't get lost.
+        * size of the trampoline section name so DLLView doesn't get lost.
         */
 
        siz = sym_count * sizeof(struct local_symbol);
index cb24c6d..5c3598e 100644 (file)
@@ -978,7 +978,7 @@ static void sx_change_speed(struct specialix_board *bp,
        spin_lock_irqsave(&bp->lock, flags);
        sx_out(bp, CD186x_CAR, port_No(port));
 
-       /* The Specialix board does't implement the RTS lines.
+       /* The Specialix board doesn't implement the RTS lines.
           They are used to set the IRQ level. Don't touch them. */
        if (sx_crtscts(tty))
                port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
index 0f02a4b..4f4f133 100644 (file)
@@ -876,8 +876,10 @@ static void vhci_shutdown_connection(struct usbip_device *ud)
        }
 
        /* kill threads related to this sdev, if v.c. exists */
-       kthread_stop(vdev->ud.tcp_rx);
-       kthread_stop(vdev->ud.tcp_tx);
+       if (vdev->ud.tcp_rx)
+               kthread_stop(vdev->ud.tcp_rx);
+       if (vdev->ud.tcp_tx)
+               kthread_stop(vdev->ud.tcp_tx);
 
        usbip_uinfo("stop threads\n");
 
@@ -949,9 +951,6 @@ static void vhci_device_init(struct vhci_device *vdev)
 {
        memset(vdev, 0, sizeof(*vdev));
 
-       vdev->ud.tcp_rx = kthread_create(vhci_rx_loop, &vdev->ud, "vhci_rx");
-       vdev->ud.tcp_tx = kthread_create(vhci_tx_loop, &vdev->ud, "vhci_tx");
-
        vdev->ud.side   = USBIP_VHCI;
        vdev->ud.status = VDEV_ST_NULL;
        /* vdev->ud.lock   = SPIN_LOCK_UNLOCKED; */
@@ -1139,7 +1138,7 @@ static int vhci_hcd_probe(struct platform_device *pdev)
                usbip_uerr("create hcd failed\n");
                return -ENOMEM;
        }
-
+       hcd->has_tt = 1;
 
        /* this is private data for vhci_hcd */
        the_controller = hcd_to_vhci(hcd);
index 3f2459f..e2dadbd 100644 (file)
@@ -21,6 +21,7 @@
 #include "vhci.h"
 
 #include <linux/in.h>
+#include <linux/kthread.h>
 
 /* TODO: refine locking ?*/
 
@@ -220,13 +221,13 @@ static ssize_t store_attach(struct device *dev, struct device_attribute *attr,
        vdev->ud.tcp_socket = socket;
        vdev->ud.status     = VDEV_ST_NOTASSIGNED;
 
-       wake_up_process(vdev->ud.tcp_rx);
-       wake_up_process(vdev->ud.tcp_tx);
-
        spin_unlock(&vdev->ud.lock);
        spin_unlock(&the_controller->lock);
        /* end the lock */
 
+       vdev->ud.tcp_rx = kthread_run(vhci_rx_loop, &vdev->ud, "vhci_rx");
+       vdev->ud.tcp_tx = kthread_run(vhci_tx_loop, &vdev->ud, "vhci_tx");
+
        rh_port_connect(rhport, speed);
 
        return count;
index 6a71f52..7637839 100644 (file)
@@ -273,7 +273,7 @@ exit:
 }
 
 int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev,
-                          u8 key_index)
+                          u8 key_index, bool unicast, bool multicast)
 {
        wlandevice_t *wlandev = dev->ml_priv;
 
index 7e41a95..627f3a6 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/slab.h>
 #include <linux/usb/ulpi.h>
 #include <plat/usb.h>
+#include <linux/regulator/consumer.h>
 
 /* EHCI Register Set */
 #define EHCI_INSNREG04                                 (0xA0)
@@ -118,6 +119,8 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
        struct ehci_hcd                         *omap_ehci;
        int                                     ret = -ENODEV;
        int                                     irq;
+       int                                     i;
+       char                                    supply[7];
 
        if (usb_disabled())
                return -ENODEV;
@@ -158,6 +161,23 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev)
        hcd->rsrc_len = resource_size(res);
        hcd->regs = regs;
 
+       /* get ehci regulator and enable */
+       for (i = 0 ; i < OMAP3_HS_USB_PORTS ; i++) {
+               if (pdata->port_mode[i] != OMAP_EHCI_PORT_MODE_PHY) {
+                       pdata->regulator[i] = NULL;
+                       continue;
+               }
+               snprintf(supply, sizeof(supply), "hsusb%d", i);
+               pdata->regulator[i] = regulator_get(dev, supply);
+               if (IS_ERR(pdata->regulator[i])) {
+                       pdata->regulator[i] = NULL;
+                       dev_dbg(dev,
+                       "failed to get ehci port%d regulator\n", i);
+               } else {
+                       regulator_enable(pdata->regulator[i]);
+               }
+       }
+
        ret = omap_usbhs_enable(dev);
        if (ret) {
                dev_err(dev, "failed to start usbhs with err %d\n", ret);
index 795345a..7b2e69a 100644 (file)
@@ -1633,6 +1633,7 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
                        ints[i].qh = NULL;
                        ints[i].qtd = NULL;
 
+                       urb->status = status;
                        isp1760_urb_done(hcd, urb);
                        if (qtd)
                                pe(hcd, qh, qtd);
index a78f2eb..73f75d2 100644 (file)
@@ -777,7 +777,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
                if (t1 != t2)
                        xhci_writel(xhci, t2, port_array[port_index]);
 
-               if (DEV_HIGHSPEED(t1)) {
+               if (hcd->speed != HCD_USB3) {
                        /* enable remote wake up for USB 2.0 */
                        u32 __iomem *addr;
                        u32 tmp;
@@ -866,6 +866,21 @@ int xhci_bus_resume(struct usb_hcd *hcd)
                                temp |= PORT_LINK_STROBE | XDEV_U0;
                                xhci_writel(xhci, temp, port_array[port_index]);
                        }
+                       /* wait for the port to enter U0 and report port link
+                        * state change.
+                        */
+                       spin_unlock_irqrestore(&xhci->lock, flags);
+                       msleep(20);
+                       spin_lock_irqsave(&xhci->lock, flags);
+
+                       /* Clear PLC */
+                       temp = xhci_readl(xhci, port_array[port_index]);
+                       if (temp & PORT_PLC) {
+                               temp = xhci_port_state_to_neutral(temp);
+                               temp |= PORT_PLC;
+                               xhci_writel(xhci, temp, port_array[port_index]);
+                       }
+
                        slot_id = xhci_find_slot_id_by_port(hcd,
                                        xhci, port_index + 1);
                        if (slot_id)
@@ -873,7 +888,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
                } else
                        xhci_writel(xhci, temp, port_array[port_index]);
 
-               if (DEV_HIGHSPEED(temp)) {
+               if (hcd->speed != HCD_USB3) {
                        /* disable remote wake up for USB 2.0 */
                        u32 __iomem *addr;
                        u32 tmp;
index 6dfbf9f..f47c201 100644 (file)
@@ -1887,11 +1887,9 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
                        otg_set_vbus(musb->xceiv, 1);
 
                hcd->self.uses_pio_for_control = 1;
-
-               if (musb->xceiv->last_event == USB_EVENT_NONE)
-                       pm_runtime_put(musb->controller);
-
        }
+       if (musb->xceiv->last_event == USB_EVENT_NONE)
+               pm_runtime_put(musb->controller);
 
        return 0;
 
index 57a27fa..e9e60b6 100644 (file)
@@ -270,7 +270,7 @@ static int musb_otg_notifications(struct notifier_block *nb,
                DBG(4, "VBUS Disconnect\n");
 
 #ifdef CONFIG_USB_GADGET_MUSB_HDRC
-               if (is_otg_enabled(musb))
+               if (is_otg_enabled(musb) || is_peripheral_enabled(musb))
                        if (musb->gadget_driver)
 #endif
                        {
index 35a0d12..5fd020d 100644 (file)
@@ -35,6 +35,7 @@
  *     document number 324645-001, 324646-001: Cougar Point (CPT)
  *     document number TBD                   : Patsburg (PBG)
  *     document number TBD                   : DH89xxCC
+ *     document number TBD                   : Panther Point
  */
 
 /*
@@ -153,6 +154,38 @@ enum iTCO_chipsets {
        TCO_PBG1,       /* Patsburg */
        TCO_PBG2,       /* Patsburg */
        TCO_DH89XXCC,   /* DH89xxCC */
+       TCO_PPT0,       /* Panther Point */
+       TCO_PPT1,       /* Panther Point */
+       TCO_PPT2,       /* Panther Point */
+       TCO_PPT3,       /* Panther Point */
+       TCO_PPT4,       /* Panther Point */
+       TCO_PPT5,       /* Panther Point */
+       TCO_PPT6,       /* Panther Point */
+       TCO_PPT7,       /* Panther Point */
+       TCO_PPT8,       /* Panther Point */
+       TCO_PPT9,       /* Panther Point */
+       TCO_PPT10,      /* Panther Point */
+       TCO_PPT11,      /* Panther Point */
+       TCO_PPT12,      /* Panther Point */
+       TCO_PPT13,      /* Panther Point */
+       TCO_PPT14,      /* Panther Point */
+       TCO_PPT15,      /* Panther Point */
+       TCO_PPT16,      /* Panther Point */
+       TCO_PPT17,      /* Panther Point */
+       TCO_PPT18,      /* Panther Point */
+       TCO_PPT19,      /* Panther Point */
+       TCO_PPT20,      /* Panther Point */
+       TCO_PPT21,      /* Panther Point */
+       TCO_PPT22,      /* Panther Point */
+       TCO_PPT23,      /* Panther Point */
+       TCO_PPT24,      /* Panther Point */
+       TCO_PPT25,      /* Panther Point */
+       TCO_PPT26,      /* Panther Point */
+       TCO_PPT27,      /* Panther Point */
+       TCO_PPT28,      /* Panther Point */
+       TCO_PPT29,      /* Panther Point */
+       TCO_PPT30,      /* Panther Point */
+       TCO_PPT31,      /* Panther Point */
 };
 
 static struct {
@@ -244,6 +277,38 @@ static struct {
        {"Patsburg", 2},
        {"Patsburg", 2},
        {"DH89xxCC", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
+       {"Panther Point", 2},
        {NULL, 0}
 };
 
@@ -363,6 +428,38 @@ static DEFINE_PCI_DEVICE_TABLE(iTCO_wdt_pci_tbl) = {
        { ITCO_PCI_DEVICE(0x1d40,                               TCO_PBG1)},
        { ITCO_PCI_DEVICE(0x1d41,                               TCO_PBG2)},
        { ITCO_PCI_DEVICE(0x2310,                               TCO_DH89XXCC)},
+       { ITCO_PCI_DEVICE(0x1e40,                               TCO_PPT0)},
+       { ITCO_PCI_DEVICE(0x1e41,                               TCO_PPT1)},
+       { ITCO_PCI_DEVICE(0x1e42,                               TCO_PPT2)},
+       { ITCO_PCI_DEVICE(0x1e43,                               TCO_PPT3)},
+       { ITCO_PCI_DEVICE(0x1e44,                               TCO_PPT4)},
+       { ITCO_PCI_DEVICE(0x1e45,                               TCO_PPT5)},
+       { ITCO_PCI_DEVICE(0x1e46,                               TCO_PPT6)},
+       { ITCO_PCI_DEVICE(0x1e47,                               TCO_PPT7)},
+       { ITCO_PCI_DEVICE(0x1e48,                               TCO_PPT8)},
+       { ITCO_PCI_DEVICE(0x1e49,                               TCO_PPT9)},
+       { ITCO_PCI_DEVICE(0x1e4a,                               TCO_PPT10)},
+       { ITCO_PCI_DEVICE(0x1e4b,                               TCO_PPT11)},
+       { ITCO_PCI_DEVICE(0x1e4c,                               TCO_PPT12)},
+       { ITCO_PCI_DEVICE(0x1e4d,                               TCO_PPT13)},
+       { ITCO_PCI_DEVICE(0x1e4e,                               TCO_PPT14)},
+       { ITCO_PCI_DEVICE(0x1e4f,                               TCO_PPT15)},
+       { ITCO_PCI_DEVICE(0x1e50,                               TCO_PPT16)},
+       { ITCO_PCI_DEVICE(0x1e51,                               TCO_PPT17)},
+       { ITCO_PCI_DEVICE(0x1e52,                               TCO_PPT18)},
+       { ITCO_PCI_DEVICE(0x1e53,                               TCO_PPT19)},
+       { ITCO_PCI_DEVICE(0x1e54,                               TCO_PPT20)},
+       { ITCO_PCI_DEVICE(0x1e55,                               TCO_PPT21)},
+       { ITCO_PCI_DEVICE(0x1e56,                               TCO_PPT22)},
+       { ITCO_PCI_DEVICE(0x1e57,                               TCO_PPT23)},
+       { ITCO_PCI_DEVICE(0x1e58,                               TCO_PPT24)},
+       { ITCO_PCI_DEVICE(0x1e59,                               TCO_PPT25)},
+       { ITCO_PCI_DEVICE(0x1e5a,                               TCO_PPT26)},
+       { ITCO_PCI_DEVICE(0x1e5b,                               TCO_PPT27)},
+       { ITCO_PCI_DEVICE(0x1e5c,                               TCO_PPT28)},
+       { ITCO_PCI_DEVICE(0x1e5d,                               TCO_PPT29)},
+       { ITCO_PCI_DEVICE(0x1e5e,                               TCO_PPT30)},
+       { ITCO_PCI_DEVICE(0x1e5f,                               TCO_PPT31)},
        { 0, },                 /* End of list */
 };
 MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl);
index 1ac9412..a2eee57 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/sysrq.h>
 #include <linux/stop_machine.h>
 #include <linux/freezer.h>
+#include <linux/syscore_ops.h>
 
 #include <xen/xen.h>
 #include <xen/xenbus.h>
@@ -70,8 +71,13 @@ static int xen_suspend(void *data)
        BUG_ON(!irqs_disabled());
 
        err = sysdev_suspend(PMSG_FREEZE);
+       if (!err) {
+               err = syscore_suspend();
+               if (err)
+                       sysdev_resume();
+       }
        if (err) {
-               printk(KERN_ERR "xen_suspend: sysdev_suspend failed: %d\n",
+               printk(KERN_ERR "xen_suspend: system core suspend failed: %d\n",
                        err);
                return err;
        }
@@ -95,6 +101,7 @@ static int xen_suspend(void *data)
                xen_timer_resume();
        }
 
+       syscore_resume();
        sysdev_resume();
 
        return 0;
index 2e61fe1..8f4b81d 100644 (file)
@@ -718,7 +718,7 @@ struct btrfs_space_info {
        u64 total_bytes;        /* total bytes in the space,
                                   this doesn't take mirrors into account */
        u64 bytes_used;         /* total bytes used,
-                                  this does't take mirrors into account */
+                                  this doesn't take mirrors into account */
        u64 bytes_pinned;       /* total bytes pinned, will be freed when the
                                   transaction finishes */
        u64 bytes_reserved;     /* total bytes the allocator has reserved for
index 68c84c8..228cf36 100644 (file)
@@ -2824,6 +2824,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
 
        spin_lock(&delayed_refs->lock);
        if (delayed_refs->num_entries == 0) {
+               spin_unlock(&delayed_refs->lock);
                printk(KERN_INFO "delayed_refs has NO entry\n");
                return ret;
        }
index 31f33ba..cd52f7f 100644 (file)
@@ -8059,6 +8059,10 @@ static noinline int relocate_one_extent(struct btrfs_root *extent_root,
                                u64 group_start = group->key.objectid;
                                new_extents = kmalloc(sizeof(*new_extents),
                                                      GFP_NOFS);
+                               if (!new_extents) {
+                                       ret = -ENOMEM;
+                                       goto out;
+                               }
                                nr_extents = 1;
                                ret = get_new_locations(reloc_inode,
                                                        extent_key,
index 3151386..ba41da5 100644 (file)
@@ -2681,7 +2681,7 @@ int extent_readpages(struct extent_io_tree *tree,
                prefetchw(&page->flags);
                list_del(&page->lru);
                if (!add_to_page_cache_lru(page, mapping,
-                                       page->index, GFP_KERNEL)) {
+                                       page->index, GFP_NOFS)) {
                        __extent_read_full_page(tree, page, get_extent,
                                                &bio, 0, &bio_flags);
                }
index 11d2e9c..63731a1 100644 (file)
@@ -1768,10 +1768,13 @@ void btrfs_remove_free_space_cache(struct btrfs_block_group_cache *block_group)
 
        while ((node = rb_last(&block_group->free_space_offset)) != NULL) {
                info = rb_entry(node, struct btrfs_free_space, offset_index);
-               unlink_free_space(block_group, info);
-               if (info->bitmap)
-                       kfree(info->bitmap);
-               kmem_cache_free(btrfs_free_space_cachep, info);
+               if (!info->bitmap) {
+                       unlink_free_space(block_group, info);
+                       kmem_cache_free(btrfs_free_space_cachep, info);
+               } else {
+                       free_bitmap(block_group, info);
+               }
+
                if (need_resched()) {
                        spin_unlock(&block_group->tree_lock);
                        cond_resched();
@@ -2301,7 +2304,7 @@ int btrfs_trim_block_group(struct btrfs_block_group_cache *block_group,
                        start = entry->offset;
                        bytes = min(entry->bytes, end - start);
                        unlink_free_space(block_group, entry);
-                       kfree(entry);
+                       kmem_cache_free(btrfs_free_space_cachep, entry);
                }
 
                spin_unlock(&block_group->tree_lock);
index fcd66b6..7cd8ab0 100644 (file)
@@ -954,6 +954,7 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page,
                         1, 0, NULL, GFP_NOFS);
        while (start < end) {
                async_cow = kmalloc(sizeof(*async_cow), GFP_NOFS);
+               BUG_ON(!async_cow);
                async_cow->inode = inode;
                async_cow->root = root;
                async_cow->locked_page = locked_page;
@@ -4731,9 +4732,10 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry,
        inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
                                dentry->d_name.len, dir->i_ino, objectid,
                                BTRFS_I(dir)->block_group, mode, &index);
-       err = PTR_ERR(inode);
-       if (IS_ERR(inode))
+       if (IS_ERR(inode)) {
+               err = PTR_ERR(inode);
                goto out_unlock;
+       }
 
        err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
        if (err) {
@@ -4792,9 +4794,10 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry,
        inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name,
                                dentry->d_name.len, dir->i_ino, objectid,
                                BTRFS_I(dir)->block_group, mode, &index);
-       err = PTR_ERR(inode);
-       if (IS_ERR(inode))
+       if (IS_ERR(inode)) {
+               err = PTR_ERR(inode);
                goto out_unlock;
+       }
 
        err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
        if (err) {
@@ -4999,6 +5002,8 @@ static noinline int uncompress_inline(struct btrfs_path *path,
        inline_size = btrfs_file_extent_inline_item_len(leaf,
                                        btrfs_item_nr(leaf, path->slots[0]));
        tmp = kmalloc(inline_size, GFP_NOFS);
+       if (!tmp)
+               return -ENOMEM;
        ptr = btrfs_file_extent_inline_start(item);
 
        read_extent_buffer(leaf, tmp, ptr, inline_size);
@@ -6036,7 +6041,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
        ret = btrfs_map_block(map_tree, READ, start_sector << 9,
                              &map_length, NULL, 0);
        if (ret) {
-               bio_put(bio);
+               bio_put(orig_bio);
                return -EIO;
        }
 
@@ -7273,9 +7278,10 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry,
                                dentry->d_name.len, dir->i_ino, objectid,
                                BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO,
                                &index);
-       err = PTR_ERR(inode);
-       if (IS_ERR(inode))
+       if (IS_ERR(inode)) {
+               err = PTR_ERR(inode);
                goto out_unlock;
+       }
 
        err = btrfs_init_inode_security(trans, inode, dir, &dentry->d_name);
        if (err) {
index c50271a..f997ec0 100644 (file)
@@ -2209,8 +2209,10 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
 
        log = root->log_root;
        path = btrfs_alloc_path();
-       if (!path)
-               return -ENOMEM;
+       if (!path) {
+               err = -ENOMEM;
+               goto out_unlock;
+       }
 
        di = btrfs_lookup_dir_item(trans, log, path, dir->i_ino,
                                   name, name_len, -1);
@@ -2271,6 +2273,7 @@ int btrfs_del_dir_entries_in_log(struct btrfs_trans_handle *trans,
        }
 fail:
        btrfs_free_path(path);
+out_unlock:
        mutex_unlock(&BTRFS_I(dir)->log_mutex);
        if (ret == -ENOSPC) {
                root->fs_info->last_trans_log_full_commit = trans->transid;
index 309a57b..c7367ae 100644 (file)
@@ -155,6 +155,15 @@ static noinline int run_scheduled_bios(struct btrfs_device *device)
        unsigned long limit;
        unsigned long last_waited = 0;
        int force_reg = 0;
+       struct blk_plug plug;
+
+       /*
+        * this function runs all the bios we've collected for
+        * a particular device.  We don't want to wander off to
+        * another device without first sending all of these down.
+        * So, setup a plug here and finish it off before we return
+        */
+       blk_start_plug(&plug);
 
        bdi = blk_get_backing_dev_info(device->bdev);
        fs_info = device->dev_root->fs_info;
@@ -294,6 +303,7 @@ loop_lock:
        spin_unlock(&device->io_lock);
 
 done:
+       blk_finish_plug(&plug);
        return 0;
 }
 
index e159c52..38b8ab5 100644 (file)
@@ -775,6 +775,13 @@ get_more_pages:
                                            ci->i_truncate_seq,
                                            ci->i_truncate_size,
                                            &inode->i_mtime, true, 1, 0);
+
+                               if (!req) {
+                                       rc = -ENOMEM;
+                                       unlock_page(page);
+                                       break;
+                               }
+
                                max_pages = req->r_num_pages;
 
                                alloc_page_vec(fsc, req);
index 5323c33..9fa0866 100644 (file)
@@ -1331,10 +1331,11 @@ static void ceph_flush_snaps(struct ceph_inode_info *ci)
 }
 
 /*
- * Mark caps dirty.  If inode is newly dirty, add to the global dirty
- * list.
+ * Mark caps dirty.  If inode is newly dirty, return the dirty flags.
+ * Caller is then responsible for calling __mark_inode_dirty with the
+ * returned flags value.
  */
-void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
+int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
 {
        struct ceph_mds_client *mdsc =
                ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc;
@@ -1357,7 +1358,7 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
                list_add(&ci->i_dirty_item, &mdsc->cap_dirty);
                spin_unlock(&mdsc->cap_dirty_lock);
                if (ci->i_flushing_caps == 0) {
-                       igrab(inode);
+                       ihold(inode);
                        dirty |= I_DIRTY_SYNC;
                }
        }
@@ -1365,9 +1366,8 @@ void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask)
        if (((was | ci->i_flushing_caps) & CEPH_CAP_FILE_BUFFER) &&
            (mask & CEPH_CAP_FILE_BUFFER))
                dirty |= I_DIRTY_DATASYNC;
-       if (dirty)
-               __mark_inode_dirty(inode, dirty);
        __cap_delay_requeue(mdsc, ci);
+       return dirty;
 }
 
 /*
@@ -1991,7 +1991,7 @@ static void __take_cap_refs(struct ceph_inode_info *ci, int got)
                ci->i_wr_ref++;
        if (got & CEPH_CAP_FILE_BUFFER) {
                if (ci->i_wrbuffer_ref == 0)
-                       igrab(&ci->vfs_inode);
+                       ihold(&ci->vfs_inode);
                ci->i_wrbuffer_ref++;
                dout("__take_cap_refs %p wrbuffer %d -> %d (?)\n",
                     &ci->vfs_inode, ci->i_wrbuffer_ref-1, ci->i_wrbuffer_ref);
index 159b512..203252d 100644 (file)
@@ -734,9 +734,12 @@ retry_snap:
                }
        }
        if (ret >= 0) {
+               int dirty;
                spin_lock(&inode->i_lock);
-               __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR);
+               dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_FILE_WR);
                spin_unlock(&inode->i_lock);
+               if (dirty)
+                       __mark_inode_dirty(inode, dirty);
        }
 
 out:
index b54c97d..03d6daf 100644 (file)
@@ -1567,6 +1567,7 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
        int release = 0, dirtied = 0;
        int mask = 0;
        int err = 0;
+       int inode_dirty_flags = 0;
 
        if (ceph_snap(inode) != CEPH_NOSNAP)
                return -EROFS;
@@ -1725,13 +1726,16 @@ int ceph_setattr(struct dentry *dentry, struct iattr *attr)
                dout("setattr %p ATTR_FILE ... hrm!\n", inode);
 
        if (dirtied) {
-               __ceph_mark_dirty_caps(ci, dirtied);
+               inode_dirty_flags = __ceph_mark_dirty_caps(ci, dirtied);
                inode->i_ctime = CURRENT_TIME;
        }
 
        release &= issued;
        spin_unlock(&inode->i_lock);
 
+       if (inode_dirty_flags)
+               __mark_inode_dirty(inode, inode_dirty_flags);
+
        if (mask) {
                req->r_inode = igrab(inode);
                req->r_inode_drop = release;
index 619fe71..b1f1b8b 100644 (file)
@@ -506,7 +506,7 @@ static inline int __ceph_caps_dirty(struct ceph_inode_info *ci)
 {
        return ci->i_dirty_caps | ci->i_flushing_caps;
 }
-extern void __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask);
+extern int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask);
 
 extern int ceph_caps_revoking(struct ceph_inode_info *ci, int mask);
 extern int __ceph_caps_used(struct ceph_inode_info *ci);
index 8c9eba6..f2b6286 100644 (file)
@@ -703,6 +703,7 @@ int ceph_setxattr(struct dentry *dentry, const char *name,
        struct ceph_inode_xattr *xattr = NULL;
        int issued;
        int required_blob_size;
+       int dirty;
 
        if (ceph_snap(inode) != CEPH_NOSNAP)
                return -EROFS;
@@ -763,11 +764,12 @@ retry:
        dout("setxattr %p issued %s\n", inode, ceph_cap_string(issued));
        err = __set_xattr(ci, newname, name_len, newval,
                          val_len, 1, 1, 1, &xattr);
-       __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
+       dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
        ci->i_xattrs.dirty = true;
        inode->i_ctime = CURRENT_TIME;
        spin_unlock(&inode->i_lock);
-
+       if (dirty)
+               __mark_inode_dirty(inode, dirty);
        return err;
 
 do_sync:
@@ -810,6 +812,7 @@ int ceph_removexattr(struct dentry *dentry, const char *name)
        struct ceph_vxattr_cb *vxattrs = ceph_inode_vxattrs(inode);
        int issued;
        int err;
+       int dirty;
 
        if (ceph_snap(inode) != CEPH_NOSNAP)
                return -EROFS;
@@ -833,12 +836,13 @@ int ceph_removexattr(struct dentry *dentry, const char *name)
                goto do_sync;
 
        err = __remove_xattr_by_name(ceph_inode(inode), name);
-       __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
+       dirty = __ceph_mark_dirty_caps(ci, CEPH_CAP_XATTR_EXCL);
        ci->i_xattrs.dirty = true;
        inode->i_ctime = CURRENT_TIME;
 
        spin_unlock(&inode->i_lock);
-
+       if (dirty)
+               __mark_inode_dirty(inode, dirty);
        return err;
 do_sync:
        spin_unlock(&inode->i_lock);
index db9d55b..4bc862a 100644 (file)
@@ -807,8 +807,7 @@ static int
 cifs_parse_mount_options(char *options, const char *devname,
                         struct smb_vol *vol)
 {
-       char *value;
-       char *data;
+       char *value, *data, *end;
        unsigned int  temp_len, i, j;
        char separator[2];
        short int override_uid = -1;
@@ -851,6 +850,7 @@ cifs_parse_mount_options(char *options, const char *devname,
        if (!options)
                return 1;
 
+       end = options + strlen(options);
        if (strncmp(options, "sep=", 4) == 0) {
                if (options[4] != 0) {
                        separator[0] = options[4];
@@ -916,6 +916,7 @@ cifs_parse_mount_options(char *options, const char *devname,
                        the only illegal character in a password is null */
 
                        if ((value[temp_len] == 0) &&
+                           (value + temp_len < end) &&
                            (value[temp_len+1] == separator[0])) {
                                /* reinsert comma */
                                value[temp_len] = separator[0];
index 129a357..22a0ef4 100644 (file)
@@ -99,12 +99,9 @@ static struct kmem_cache *dentry_cache __read_mostly;
 static unsigned int d_hash_mask __read_mostly;
 static unsigned int d_hash_shift __read_mostly;
 
-struct dcache_hash_bucket {
-       struct hlist_bl_head head;
-};
-static struct dcache_hash_bucket *dentry_hashtable __read_mostly;
+static struct hlist_bl_head *dentry_hashtable __read_mostly;
 
-static inline struct dcache_hash_bucket *d_hash(struct dentry *parent,
+static inline struct hlist_bl_head *d_hash(struct dentry *parent,
                                        unsigned long hash)
 {
        hash += ((unsigned long) parent ^ GOLDEN_RATIO_PRIME) / L1_CACHE_BYTES;
@@ -112,16 +109,6 @@ static inline struct dcache_hash_bucket *d_hash(struct dentry *parent,
        return dentry_hashtable + (hash & D_HASHMASK);
 }
 
-static inline void spin_lock_bucket(struct dcache_hash_bucket *b)
-{
-       bit_spin_lock(0, (unsigned long *)&b->head.first);
-}
-
-static inline void spin_unlock_bucket(struct dcache_hash_bucket *b)
-{
-       __bit_spin_unlock(0, (unsigned long *)&b->head.first);
-}
-
 /* Statistics gathering. */
 struct dentry_stat_t dentry_stat = {
        .age_limit = 45,
@@ -167,8 +154,8 @@ static void d_free(struct dentry *dentry)
        if (dentry->d_op && dentry->d_op->d_release)
                dentry->d_op->d_release(dentry);
 
-       /* if dentry was never inserted into hash, immediate free is OK */
-       if (hlist_bl_unhashed(&dentry->d_hash))
+       /* if dentry was never visible to RCU, immediate free is OK */
+       if (!(dentry->d_flags & DCACHE_RCUACCESS))
                __d_free(&dentry->d_u.d_rcu);
        else
                call_rcu(&dentry->d_u.d_rcu, __d_free);
@@ -330,28 +317,19 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
  */
 void __d_drop(struct dentry *dentry)
 {
-       if (!(dentry->d_flags & DCACHE_UNHASHED)) {
-               if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED)) {
-                       bit_spin_lock(0,
-                               (unsigned long *)&dentry->d_sb->s_anon.first);
-                       dentry->d_flags |= DCACHE_UNHASHED;
-                       hlist_bl_del_init(&dentry->d_hash);
-                       __bit_spin_unlock(0,
-                               (unsigned long *)&dentry->d_sb->s_anon.first);
-               } else {
-                       struct dcache_hash_bucket *b;
+       if (!d_unhashed(dentry)) {
+               struct hlist_bl_head *b;
+               if (unlikely(dentry->d_flags & DCACHE_DISCONNECTED))
+                       b = &dentry->d_sb->s_anon;
+               else
                        b = d_hash(dentry->d_parent, dentry->d_name.hash);
-                       spin_lock_bucket(b);
-                       /*
-                        * We may not actually need to put DCACHE_UNHASHED
-                        * manipulations under the hash lock, but follow
-                        * the principle of least surprise.
-                        */
-                       dentry->d_flags |= DCACHE_UNHASHED;
-                       hlist_bl_del_rcu(&dentry->d_hash);
-                       spin_unlock_bucket(b);
-                       dentry_rcuwalk_barrier(dentry);
-               }
+
+               hlist_bl_lock(b);
+               __hlist_bl_del(&dentry->d_hash);
+               dentry->d_hash.pprev = NULL;
+               hlist_bl_unlock(b);
+
+               dentry_rcuwalk_barrier(dentry);
        }
 }
 EXPORT_SYMBOL(__d_drop);
@@ -1304,7 +1282,7 @@ struct dentry *d_alloc(struct dentry * parent, const struct qstr *name)
        dname[name->len] = 0;
 
        dentry->d_count = 1;
-       dentry->d_flags = DCACHE_UNHASHED;
+       dentry->d_flags = 0;
        spin_lock_init(&dentry->d_lock);
        seqcount_init(&dentry->d_seq);
        dentry->d_inode = NULL;
@@ -1606,10 +1584,9 @@ struct dentry *d_obtain_alias(struct inode *inode)
        tmp->d_inode = inode;
        tmp->d_flags |= DCACHE_DISCONNECTED;
        list_add(&tmp->d_alias, &inode->i_dentry);
-       bit_spin_lock(0, (unsigned long *)&tmp->d_sb->s_anon.first);
-       tmp->d_flags &= ~DCACHE_UNHASHED;
+       hlist_bl_lock(&tmp->d_sb->s_anon);
        hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);
-       __bit_spin_unlock(0, (unsigned long *)&tmp->d_sb->s_anon.first);
+       hlist_bl_unlock(&tmp->d_sb->s_anon);
        spin_unlock(&tmp->d_lock);
        spin_unlock(&inode->i_lock);
        security_d_instantiate(tmp, inode);
@@ -1789,7 +1766,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name,
        unsigned int len = name->len;
        unsigned int hash = name->hash;
        const unsigned char *str = name->name;
-       struct dcache_hash_bucket *b = d_hash(parent, hash);
+       struct hlist_bl_head *b = d_hash(parent, hash);
        struct hlist_bl_node *node;
        struct dentry *dentry;
 
@@ -1813,7 +1790,7 @@ struct dentry *__d_lookup_rcu(struct dentry *parent, struct qstr *name,
         *
         * See Documentation/filesystems/path-lookup.txt for more details.
         */
-       hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) {
+       hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) {
                struct inode *i;
                const char *tname;
                int tlen;
@@ -1908,7 +1885,7 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name)
        unsigned int len = name->len;
        unsigned int hash = name->hash;
        const unsigned char *str = name->name;
-       struct dcache_hash_bucket *b = d_hash(parent, hash);
+       struct hlist_bl_head *b = d_hash(parent, hash);
        struct hlist_bl_node *node;
        struct dentry *found = NULL;
        struct dentry *dentry;
@@ -1935,7 +1912,7 @@ struct dentry *__d_lookup(struct dentry *parent, struct qstr *name)
         */
        rcu_read_lock();
        
-       hlist_bl_for_each_entry_rcu(dentry, node, &b->head, d_hash) {
+       hlist_bl_for_each_entry_rcu(dentry, node, b, d_hash) {
                const char *tname;
                int tlen;
 
@@ -2086,13 +2063,13 @@ again:
 }
 EXPORT_SYMBOL(d_delete);
 
-static void __d_rehash(struct dentry * entry, struct dcache_hash_bucket *b)
+static void __d_rehash(struct dentry * entry, struct hlist_bl_head *b)
 {
        BUG_ON(!d_unhashed(entry));
-       spin_lock_bucket(b);
-       entry->d_flags &= ~DCACHE_UNHASHED;
-       hlist_bl_add_head_rcu(&entry->d_hash, &b->head);
-       spin_unlock_bucket(b);
+       hlist_bl_lock(b);
+       entry->d_flags |= DCACHE_RCUACCESS;
+       hlist_bl_add_head_rcu(&entry->d_hash, b);
+       hlist_bl_unlock(b);
 }
 
 static void _d_rehash(struct dentry * entry)
@@ -3025,7 +3002,7 @@ static void __init dcache_init_early(void)
 
        dentry_hashtable =
                alloc_large_system_hash("Dentry cache",
-                                       sizeof(struct dcache_hash_bucket),
+                                       sizeof(struct hlist_bl_head),
                                        dhash_entries,
                                        13,
                                        HASH_EARLY,
@@ -3034,7 +3011,7 @@ static void __init dcache_init_early(void)
                                        0);
 
        for (loop = 0; loop < (1 << d_hash_shift); loop++)
-               INIT_HLIST_BL_HEAD(&dentry_hashtable[loop].head);
+               INIT_HLIST_BL_HEAD(dentry_hashtable + loop);
 }
 
 static void __init dcache_init(void)
@@ -3057,7 +3034,7 @@ static void __init dcache_init(void)
 
        dentry_hashtable =
                alloc_large_system_hash("Dentry cache",
-                                       sizeof(struct dcache_hash_bucket),
+                                       sizeof(struct hlist_bl_head),
                                        dhash_entries,
                                        13,
                                        0,
@@ -3066,7 +3043,7 @@ static void __init dcache_init(void)
                                        0);
 
        for (loop = 0; loop < (1 << d_hash_shift); loop++)
-               INIT_HLIST_BL_HEAD(&dentry_hashtable[loop].head);
+               INIT_HLIST_BL_HEAD(dentry_hashtable + loop);
 }
 
 /* SLAB cache for __getname() consumers */
index d2a70a4..b8d5c80 100644 (file)
@@ -1452,6 +1452,25 @@ static void set_default_header_data(struct ecryptfs_crypt_stat *crypt_stat)
        crypt_stat->metadata_size = ECRYPTFS_MINIMUM_HEADER_EXTENT_SIZE;
 }
 
+void ecryptfs_i_size_init(const char *page_virt, struct inode *inode)
+{
+       struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
+       struct ecryptfs_crypt_stat *crypt_stat;
+       u64 file_size;
+
+       crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat;
+       mount_crypt_stat =
+               &ecryptfs_superblock_to_private(inode->i_sb)->mount_crypt_stat;
+       if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) {
+               file_size = i_size_read(ecryptfs_inode_to_lower(inode));
+               if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
+                       file_size += crypt_stat->metadata_size;
+       } else
+               file_size = get_unaligned_be64(page_virt);
+       i_size_write(inode, (loff_t)file_size);
+       crypt_stat->flags |= ECRYPTFS_I_SIZE_INITIALIZED;
+}
+
 /**
  * ecryptfs_read_headers_virt
  * @page_virt: The virtual address into which to read the headers
@@ -1482,6 +1501,8 @@ static int ecryptfs_read_headers_virt(char *page_virt,
                rc = -EINVAL;
                goto out;
        }
+       if (!(crypt_stat->flags & ECRYPTFS_I_SIZE_INITIALIZED))
+               ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode);
        offset += MAGIC_ECRYPTFS_MARKER_SIZE_BYTES;
        rc = ecryptfs_process_flags(crypt_stat, (page_virt + offset),
                                    &bytes_read);
index bd3cafd..e702827 100644 (file)
@@ -269,6 +269,7 @@ struct ecryptfs_crypt_stat {
 #define ECRYPTFS_ENCFN_USE_MOUNT_FNEK 0x00000800
 #define ECRYPTFS_ENCFN_USE_FEK        0x00001000
 #define ECRYPTFS_UNLINK_SIGS          0x00002000
+#define ECRYPTFS_I_SIZE_INITIALIZED   0x00004000
        u32 flags;
        unsigned int file_version;
        size_t iv_bytes;
@@ -295,6 +296,8 @@ struct ecryptfs_crypt_stat {
 struct ecryptfs_inode_info {
        struct inode vfs_inode;
        struct inode *wii_inode;
+       struct mutex lower_file_mutex;
+       atomic_t lower_file_count;
        struct file *lower_file;
        struct ecryptfs_crypt_stat crypt_stat;
 };
@@ -626,6 +629,7 @@ struct ecryptfs_open_req {
 int ecryptfs_interpose(struct dentry *hidden_dentry,
                       struct dentry *this_dentry, struct super_block *sb,
                       u32 flags);
+void ecryptfs_i_size_init(const char *page_virt, struct inode *inode);
 int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
                                        struct dentry *lower_dentry,
                                        struct inode *ecryptfs_dir_inode);
@@ -757,7 +761,8 @@ int ecryptfs_privileged_open(struct file **lower_file,
                             struct dentry *lower_dentry,
                             struct vfsmount *lower_mnt,
                             const struct cred *cred);
-int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry);
+int ecryptfs_get_lower_file(struct dentry *ecryptfs_dentry);
+void ecryptfs_put_lower_file(struct inode *inode);
 int
 ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
                             size_t *packet_size,
index cedc913..566e547 100644 (file)
@@ -191,10 +191,10 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
                                      | ECRYPTFS_ENCRYPTED);
        }
        mutex_unlock(&crypt_stat->cs_mutex);
-       rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
+       rc = ecryptfs_get_lower_file(ecryptfs_dentry);
        if (rc) {
                printk(KERN_ERR "%s: Error attempting to initialize "
-                       "the persistent file for the dentry with name "
+                       "the lower file for the dentry with name "
                        "[%s]; rc = [%d]\n", __func__,
                        ecryptfs_dentry->d_name.name, rc);
                goto out_free;
@@ -202,9 +202,9 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
        if ((ecryptfs_inode_to_private(inode)->lower_file->f_flags & O_ACCMODE)
            == O_RDONLY && (file->f_flags & O_ACCMODE) != O_RDONLY) {
                rc = -EPERM;
-               printk(KERN_WARNING "%s: Lower persistent file is RO; eCryptfs "
+               printk(KERN_WARNING "%s: Lower file is RO; eCryptfs "
                       "file must hence be opened RO\n", __func__);
-               goto out_free;
+               goto out_put;
        }
        ecryptfs_set_file_lower(
                file, ecryptfs_inode_to_private(inode)->lower_file);
@@ -232,10 +232,11 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
                                       "Plaintext passthrough mode is not "
                                       "enabled; returning -EIO\n");
                                mutex_unlock(&crypt_stat->cs_mutex);
-                               goto out_free;
+                               goto out_put;
                        }
                        rc = 0;
-                       crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
+                       crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
+                                              | ECRYPTFS_ENCRYPTED);
                        mutex_unlock(&crypt_stat->cs_mutex);
                        goto out;
                }
@@ -245,6 +246,8 @@ static int ecryptfs_open(struct inode *inode, struct file *file)
                        "[0x%.16lx] size: [0x%.16llx]\n", inode, inode->i_ino,
                        (unsigned long long)i_size_read(inode));
        goto out;
+out_put:
+       ecryptfs_put_lower_file(inode);
 out_free:
        kmem_cache_free(ecryptfs_file_info_cache,
                        ecryptfs_file_to_private(file));
@@ -254,17 +257,13 @@ out:
 
 static int ecryptfs_flush(struct file *file, fl_owner_t td)
 {
-       int rc = 0;
-       struct file *lower_file = NULL;
-
-       lower_file = ecryptfs_file_to_lower(file);
-       if (lower_file->f_op && lower_file->f_op->flush)
-               rc = lower_file->f_op->flush(lower_file, td);
-       return rc;
+       return file->f_mode & FMODE_WRITE
+              ? filemap_write_and_wait(file->f_mapping) : 0;
 }
 
 static int ecryptfs_release(struct inode *inode, struct file *file)
 {
+       ecryptfs_put_lower_file(inode);
        kmem_cache_free(ecryptfs_file_info_cache,
                        ecryptfs_file_to_private(file));
        return 0;
index f99051b..4d4cc6a 100644 (file)
@@ -168,19 +168,18 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry)
                                "context; rc = [%d]\n", rc);
                goto out;
        }
-       rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
+       rc = ecryptfs_get_lower_file(ecryptfs_dentry);
        if (rc) {
                printk(KERN_ERR "%s: Error attempting to initialize "
-                       "the persistent file for the dentry with name "
+                       "the lower file for the dentry with name "
                        "[%s]; rc = [%d]\n", __func__,
                        ecryptfs_dentry->d_name.name, rc);
                goto out;
        }
        rc = ecryptfs_write_metadata(ecryptfs_dentry);
-       if (rc) {
+       if (rc)
                printk(KERN_ERR "Error writing headers; rc = [%d]\n", rc);
-               goto out;
-       }
+       ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);
 out:
        return rc;
 }
@@ -226,11 +225,9 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
        struct dentry *lower_dir_dentry;
        struct vfsmount *lower_mnt;
        struct inode *lower_inode;
-       struct ecryptfs_mount_crypt_stat *mount_crypt_stat;
        struct ecryptfs_crypt_stat *crypt_stat;
        char *page_virt = NULL;
-       u64 file_size;
-       int rc = 0;
+       int put_lower = 0, rc = 0;
 
        lower_dir_dentry = lower_dentry->d_parent;
        lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(
@@ -277,14 +274,15 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
                rc = -ENOMEM;
                goto out;
        }
-       rc = ecryptfs_init_persistent_file(ecryptfs_dentry);
+       rc = ecryptfs_get_lower_file(ecryptfs_dentry);
        if (rc) {
                printk(KERN_ERR "%s: Error attempting to initialize "
-                       "the persistent file for the dentry with name "
+                       "the lower file for the dentry with name "
                        "[%s]; rc = [%d]\n", __func__,
                        ecryptfs_dentry->d_name.name, rc);
                goto out_free_kmem;
        }
+       put_lower = 1;
        crypt_stat = &ecryptfs_inode_to_private(
                                        ecryptfs_dentry->d_inode)->crypt_stat;
        /* TODO: lock for crypt_stat comparison */
@@ -302,18 +300,7 @@ int ecryptfs_lookup_and_interpose_lower(struct dentry *ecryptfs_dentry,
                }
                crypt_stat->flags |= ECRYPTFS_METADATA_IN_XATTR;
        }
-       mount_crypt_stat = &ecryptfs_superblock_to_private(
-               ecryptfs_dentry->d_sb)->mount_crypt_stat;
-       if (mount_crypt_stat->flags & ECRYPTFS_ENCRYPTED_VIEW_ENABLED) {
-               if (crypt_stat->flags & ECRYPTFS_METADATA_IN_XATTR)
-                       file_size = (crypt_stat->metadata_size
-                                    + i_size_read(lower_dentry->d_inode));
-               else
-                       file_size = i_size_read(lower_dentry->d_inode);
-       } else {
-               file_size = get_unaligned_be64(page_virt);
-       }
-       i_size_write(ecryptfs_dentry->d_inode, (loff_t)file_size);
+       ecryptfs_i_size_init(page_virt, ecryptfs_dentry->d_inode);
 out_free_kmem:
        kmem_cache_free(ecryptfs_header_cache_2, page_virt);
        goto out;
@@ -322,6 +309,8 @@ out_put:
        mntput(lower_mnt);
        d_drop(ecryptfs_dentry);
 out:
+       if (put_lower)
+               ecryptfs_put_lower_file(ecryptfs_dentry->d_inode);
        return rc;
 }
 
@@ -538,8 +527,6 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
        dget(lower_dentry);
        rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
        dput(lower_dentry);
-       if (!rc)
-               d_delete(lower_dentry);
        fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
        dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
        unlock_dir(lower_dir_dentry);
@@ -610,8 +597,8 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
 out_lock:
        unlock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
-       dput(lower_new_dentry->d_parent);
-       dput(lower_old_dentry->d_parent);
+       dput(lower_new_dir_dentry);
+       dput(lower_old_dir_dentry);
        dput(lower_new_dentry);
        dput(lower_old_dentry);
        return rc;
@@ -759,8 +746,11 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
 
        if (unlikely((ia->ia_size == i_size))) {
                lower_ia->ia_valid &= ~ATTR_SIZE;
-               goto out;
+               return 0;
        }
+       rc = ecryptfs_get_lower_file(dentry);
+       if (rc)
+               return rc;
        crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat;
        /* Switch on growing or shrinking file */
        if (ia->ia_size > i_size) {
@@ -838,6 +828,7 @@ static int truncate_upper(struct dentry *dentry, struct iattr *ia,
                        lower_ia->ia_valid &= ~ATTR_SIZE;
        }
 out:
+       ecryptfs_put_lower_file(inode);
        return rc;
 }
 
@@ -913,7 +904,13 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
 
                mount_crypt_stat = &ecryptfs_superblock_to_private(
                        dentry->d_sb)->mount_crypt_stat;
+               rc = ecryptfs_get_lower_file(dentry);
+               if (rc) {
+                       mutex_unlock(&crypt_stat->cs_mutex);
+                       goto out;
+               }
                rc = ecryptfs_read_metadata(dentry);
+               ecryptfs_put_lower_file(inode);
                if (rc) {
                        if (!(mount_crypt_stat->flags
                              & ECRYPTFS_PLAINTEXT_PASSTHROUGH_ENABLED)) {
@@ -927,10 +924,17 @@ static int ecryptfs_setattr(struct dentry *dentry, struct iattr *ia)
                                goto out;
                        }
                        rc = 0;
-                       crypt_stat->flags &= ~(ECRYPTFS_ENCRYPTED);
+                       crypt_stat->flags &= ~(ECRYPTFS_I_SIZE_INITIALIZED
+                                              | ECRYPTFS_ENCRYPTED);
                }
        }
        mutex_unlock(&crypt_stat->cs_mutex);
+       if (S_ISREG(inode->i_mode)) {
+               rc = filemap_write_and_wait(inode->i_mapping);
+               if (rc)
+                       goto out;
+               fsstack_copy_attr_all(inode, lower_inode);
+       }
        memcpy(&lower_ia, ia, sizeof(lower_ia));
        if (ia->ia_valid & ATTR_FILE)
                lower_ia.ia_file = ecryptfs_file_to_lower(ia->ia_file);
index 0851ab6..69f994a 100644 (file)
@@ -44,7 +44,7 @@ static struct task_struct *ecryptfs_kthread;
  * @ignored: ignored
  *
  * The eCryptfs kernel thread that has the responsibility of getting
- * the lower persistent file with RW permissions.
+ * the lower file with RW permissions.
  *
  * Returns zero on success; non-zero otherwise
  */
@@ -141,8 +141,8 @@ int ecryptfs_privileged_open(struct file **lower_file,
        int rc = 0;
 
        /* Corresponding dput() and mntput() are done when the
-        * persistent file is fput() when the eCryptfs inode is
-        * destroyed. */
+        * lower file is fput() when all eCryptfs files for the inode are
+        * released. */
        dget(lower_dentry);
        mntget(lower_mnt);
        flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
index fdb2eb0..89b9338 100644 (file)
@@ -96,7 +96,7 @@ void __ecryptfs_printk(const char *fmt, ...)
 }
 
 /**
- * ecryptfs_init_persistent_file
+ * ecryptfs_init_lower_file
  * @ecryptfs_dentry: Fully initialized eCryptfs dentry object, with
  *                   the lower dentry and the lower mount set
  *
@@ -104,42 +104,70 @@ void __ecryptfs_printk(const char *fmt, ...)
  * inode. All I/O operations to the lower inode occur through that
  * file. When the first eCryptfs dentry that interposes with the first
  * lower dentry for that inode is created, this function creates the
- * persistent file struct and associates it with the eCryptfs
- * inode. When the eCryptfs inode is destroyed, the file is closed.
+ * lower file struct and associates it with the eCryptfs
+ * inode. When all eCryptfs files associated with the inode are released, the
+ * file is closed.
  *
- * The persistent file will be opened with read/write permissions, if
+ * The lower file will be opened with read/write permissions, if
  * possible. Otherwise, it is opened read-only.
  *
- * This function does nothing if a lower persistent file is already
+ * This function does nothing if a lower file is already
  * associated with the eCryptfs inode.
  *
  * Returns zero on success; non-zero otherwise
  */
-int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
+static int ecryptfs_init_lower_file(struct dentry *dentry,
+                                   struct file **lower_file)
 {
        const struct cred *cred = current_cred();
-       struct ecryptfs_inode_info *inode_info =
-               ecryptfs_inode_to_private(ecryptfs_dentry->d_inode);
-       int rc = 0;
+       struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
+       struct vfsmount *lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
+       int rc;
 
-       if (!inode_info->lower_file) {
-               struct dentry *lower_dentry;
-               struct vfsmount *lower_mnt =
-                       ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry);
+       rc = ecryptfs_privileged_open(lower_file, lower_dentry, lower_mnt,
+                                     cred);
+       if (rc) {
+               printk(KERN_ERR "Error opening lower file "
+                      "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
+                      "rc = [%d]\n", lower_dentry, lower_mnt, rc);
+               (*lower_file) = NULL;
+       }
+       return rc;
+}
 
-               lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
-               rc = ecryptfs_privileged_open(&inode_info->lower_file,
-                                             lower_dentry, lower_mnt, cred);
-               if (rc) {
-                       printk(KERN_ERR "Error opening lower persistent file "
-                              "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
-                              "rc = [%d]\n", lower_dentry, lower_mnt, rc);
-                       inode_info->lower_file = NULL;
-               }
+int ecryptfs_get_lower_file(struct dentry *dentry)
+{
+       struct ecryptfs_inode_info *inode_info =
+               ecryptfs_inode_to_private(dentry->d_inode);
+       int count, rc = 0;
+
+       mutex_lock(&inode_info->lower_file_mutex);
+       count = atomic_inc_return(&inode_info->lower_file_count);
+       if (WARN_ON_ONCE(count < 1))
+               rc = -EINVAL;
+       else if (count == 1) {
+               rc = ecryptfs_init_lower_file(dentry,
+                                             &inode_info->lower_file);
+               if (rc)
+                       atomic_set(&inode_info->lower_file_count, 0);
        }
+       mutex_unlock(&inode_info->lower_file_mutex);
        return rc;
 }
 
+void ecryptfs_put_lower_file(struct inode *inode)
+{
+       struct ecryptfs_inode_info *inode_info;
+
+       inode_info = ecryptfs_inode_to_private(inode);
+       if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count,
+                                     &inode_info->lower_file_mutex)) {
+               fput(inode_info->lower_file);
+               inode_info->lower_file = NULL;
+               mutex_unlock(&inode_info->lower_file_mutex);
+       }
+}
+
 static struct inode *ecryptfs_get_inode(struct inode *lower_inode,
                       struct super_block *sb)
 {
index bacc882..245b517 100644 (file)
@@ -55,6 +55,8 @@ static struct inode *ecryptfs_alloc_inode(struct super_block *sb)
        if (unlikely(!inode_info))
                goto out;
        ecryptfs_init_crypt_stat(&inode_info->crypt_stat);
+       mutex_init(&inode_info->lower_file_mutex);
+       atomic_set(&inode_info->lower_file_count, 0);
        inode_info->lower_file = NULL;
        inode = &inode_info->vfs_inode;
 out:
@@ -77,8 +79,7 @@ static void ecryptfs_i_callback(struct rcu_head *head)
  *
  * This is used during the final destruction of the inode.  All
  * allocation of memory related to the inode, including allocated
- * memory in the crypt_stat struct, will be released here. This
- * function also fput()'s the persistent file for the lower inode.
+ * memory in the crypt_stat struct, will be released here.
  * There should be no chance that this deallocation will be missed.
  */
 static void ecryptfs_destroy_inode(struct inode *inode)
@@ -86,16 +87,7 @@ static void ecryptfs_destroy_inode(struct inode *inode)
        struct ecryptfs_inode_info *inode_info;
 
        inode_info = ecryptfs_inode_to_private(inode);
-       if (inode_info->lower_file) {
-               struct dentry *lower_dentry =
-                       inode_info->lower_file->f_dentry;
-
-               BUG_ON(!lower_dentry);
-               if (lower_dentry->d_inode) {
-                       fput(inode_info->lower_file);
-                       inode_info->lower_file = NULL;
-               }
-       }
+       BUG_ON(inode_info->lower_file);
        ecryptfs_destroy_crypt_stat(&inode_info->crypt_stat);
        call_rcu(&inode->i_rcu, ecryptfs_i_callback);
 }
index 0be3447..4c6992d 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -9,6 +9,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/mmzone.h>
 #include <linux/time.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -39,14 +40,17 @@ int sysctl_nr_open_max = 1024 * 1024; /* raised later */
  */
 static DEFINE_PER_CPU(struct fdtable_defer, fdtable_defer_list);
 
-static inline void *alloc_fdmem(unsigned int size)
+static void *alloc_fdmem(unsigned int size)
 {
-       void *data;
-
-       data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN);
-       if (data != NULL)
-               return data;
-
+       /*
+        * Very large allocations can stress page reclaim, so fall back to
+        * vmalloc() if the allocation size will be considered "large" by the VM.
+        */
+       if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
+               void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN);
+               if (data != NULL)
+                       return data;
+       }
        return vmalloc(size);
 }
 
index f07643e..7a4fb63 100644 (file)
@@ -93,14 +93,12 @@ static unsigned int gl_hash(const struct gfs2_sbd *sdp,
 
 static inline void spin_lock_bucket(unsigned int hash)
 {
-       struct hlist_bl_head *bl = &gl_hash_table[hash];
-       bit_spin_lock(0, (unsigned long *)bl);
+       hlist_bl_lock(&gl_hash_table[hash]);
 }
 
 static inline void spin_unlock_bucket(unsigned int hash)
 {
-       struct hlist_bl_head *bl = &gl_hash_table[hash];
-       __bit_spin_unlock(0, (unsigned long *)bl);
+       hlist_bl_unlock(&gl_hash_table[hash]);
 }
 
 static void gfs2_glock_dealloc(struct rcu_head *rcu)
index 33435e4..ce03a18 100644 (file)
@@ -480,10 +480,6 @@ static int logfs_read_sb(struct super_block *sb, int read_only)
                        !read_only)
                return -EIO;
 
-       mutex_init(&super->s_dirop_mutex);
-       mutex_init(&super->s_object_alias_mutex);
-       INIT_LIST_HEAD(&super->s_freeing_list);
-
        ret = logfs_init_rw(sb);
        if (ret)
                return ret;
@@ -601,6 +597,10 @@ static struct dentry *logfs_mount(struct file_system_type *type, int flags,
        if (!super)
                return ERR_PTR(-ENOMEM);
 
+       mutex_init(&super->s_dirop_mutex);
+       mutex_init(&super->s_object_alias_mutex);
+       INIT_LIST_HEAD(&super->s_freeing_list);
+
        if (!devname)
                err = logfs_get_sb_bdev(super, type, devname);
        else if (strncmp(devname, "mtd", 3))
index 89fc160..1f063ba 100644 (file)
@@ -119,7 +119,7 @@ Elong:
 }
 
 #ifdef CONFIG_NFS_V4
-static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors, struct inode *inode)
+static rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *flavors)
 {
        struct gss_api_mech *mech;
        struct xdr_netobj oid;
@@ -166,7 +166,7 @@ static int nfs_negotiate_security(const struct dentry *parent,
                }
                flavors = page_address(page);
                ret = secinfo(parent->d_inode, &dentry->d_name, flavors);
-               *flavor = nfs_find_best_sec(flavors, dentry->d_inode);
+               *flavor = nfs_find_best_sec(flavors);
                put_page(page);
        }
 
index e1c261d..c4a6983 100644 (file)
@@ -47,6 +47,7 @@ enum nfs4_client_state {
        NFS4CLNT_LAYOUTRECALL,
        NFS4CLNT_SESSION_RESET,
        NFS4CLNT_RECALL_SLOT,
+       NFS4CLNT_LEASE_CONFIRM,
 };
 
 enum nfs4_session_state {
index 9bf41ea..69c0f3c 100644 (file)
@@ -46,6 +46,7 @@
 #include <linux/nfs4.h>
 #include <linux/nfs_fs.h>
 #include <linux/nfs_page.h>
+#include <linux/nfs_mount.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
 #include <linux/module.h>
@@ -443,8 +444,8 @@ static int nfs41_sequence_done(struct rpc_task *task, struct nfs4_sequence_res *
        if (res->sr_status == 1)
                res->sr_status = NFS_OK;
 
-       /* -ERESTARTSYS can result in skipping nfs41_sequence_setup */
-       if (!res->sr_slot)
+       /* don't increment the sequence number if the task wasn't sent */
+       if (!RPC_WAS_SENT(task))
                goto out;
 
        /* Check the SEQUENCE operation status */
@@ -2185,9 +2186,14 @@ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle,
        struct nfs4_exception exception = { };
        int err;
        do {
-               err = nfs4_handle_exception(server,
-                               _nfs4_lookup_root(server, fhandle, info),
-                               &exception);
+               err = _nfs4_lookup_root(server, fhandle, info);
+               switch (err) {
+               case 0:
+               case -NFS4ERR_WRONGSEC:
+                       break;
+               default:
+                       err = nfs4_handle_exception(server, err, &exception);
+               }
        } while (exception.retry);
        return err;
 }
@@ -2208,25 +2214,47 @@ out:
        return ret;
 }
 
-/*
- * get the file handle for the "/" directory on the server
- */
-static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
+static int nfs4_find_root_sec(struct nfs_server *server, struct nfs_fh *fhandle,
                              struct nfs_fsinfo *info)
 {
        int i, len, status = 0;
-       rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS + 2];
+       rpc_authflavor_t flav_array[NFS_MAX_SECFLAVORS];
 
-       flav_array[0] = RPC_AUTH_UNIX;
-       len = gss_mech_list_pseudoflavors(&flav_array[1]);
-       flav_array[1+len] = RPC_AUTH_NULL;
-       len += 2;
+       len = gss_mech_list_pseudoflavors(&flav_array[0]);
+       flav_array[len] = RPC_AUTH_NULL;
+       len += 1;
 
        for (i = 0; i < len; i++) {
                status = nfs4_lookup_root_sec(server, fhandle, info, flav_array[i]);
-               if (status != -EPERM)
-                       break;
+               if (status == -NFS4ERR_WRONGSEC || status == -EACCES)
+                       continue;
+               break;
        }
+       /*
+        * -EACCESS could mean that the user doesn't have correct permissions
+        * to access the mount.  It could also mean that we tried to mount
+        * with a gss auth flavor, but rpc.gssd isn't running.  Either way,
+        * existing mount programs don't handle -EACCES very well so it should
+        * be mapped to -EPERM instead.
+        */
+       if (status == -EACCES)
+               status = -EPERM;
+       return status;
+}
+
+/*
+ * get the file handle for the "/" directory on the server
+ */
+static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
+                             struct nfs_fsinfo *info)
+{
+       int status = nfs4_lookup_root(server, fhandle, info);
+       if ((status == -NFS4ERR_WRONGSEC) && !(server->flags & NFS_MOUNT_SECFLAVOUR))
+               /*
+                * A status of -NFS4ERR_WRONGSEC will be mapped to -EPERM
+                * by nfs4_map_errors() as this function exits.
+                */
+               status = nfs4_find_root_sec(server, fhandle, info);
        if (status == 0)
                status = nfs4_server_capabilities(server, fhandle);
        if (status == 0)
@@ -3723,21 +3751,20 @@ int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
                                sizeof(setclientid.sc_uaddr), "%s.%u.%u",
                                clp->cl_ipaddr, port >> 8, port & 255);
 
-               status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+               status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
                if (status != -NFS4ERR_CLID_INUSE)
                        break;
-               if (signalled())
+               if (loop != 0) {
+                       ++clp->cl_id_uniquifier;
                        break;
-               if (loop++ & 1)
-                       ssleep(clp->cl_lease_time / HZ + 1);
-               else
-                       if (++clp->cl_id_uniquifier == 0)
-                               break;
+               }
+               ++loop;
+               ssleep(clp->cl_lease_time / HZ + 1);
        }
        return status;
 }
 
-static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
+int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
                struct nfs4_setclientid_res *arg,
                struct rpc_cred *cred)
 {
@@ -3752,7 +3779,7 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
        int status;
 
        now = jiffies;
-       status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+       status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
        if (status == 0) {
                spin_lock(&clp->cl_lock);
                clp->cl_lease_time = fsinfo.lease_time * HZ;
@@ -3762,26 +3789,6 @@ static int _nfs4_proc_setclientid_confirm(struct nfs_client *clp,
        return status;
 }
 
-int nfs4_proc_setclientid_confirm(struct nfs_client *clp,
-               struct nfs4_setclientid_res *arg,
-               struct rpc_cred *cred)
-{
-       long timeout = 0;
-       int err;
-       do {
-               err = _nfs4_proc_setclientid_confirm(clp, arg, cred);
-               switch (err) {
-                       case 0:
-                               return err;
-                       case -NFS4ERR_RESOURCE:
-                               /* The IBM lawyers misread another document! */
-                       case -NFS4ERR_DELAY:
-                               err = nfs4_delay(clp->cl_rpcclient, &timeout);
-               }
-       } while (err == 0);
-       return err;
-}
-
 struct nfs4_delegreturndata {
        struct nfs4_delegreturnargs args;
        struct nfs4_delegreturnres res;
@@ -4786,7 +4793,7 @@ int nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred)
                                init_utsname()->domainname,
                                clp->cl_rpcclient->cl_auth->au_flavor);
 
-       status = rpc_call_sync(clp->cl_rpcclient, &msg, 0);
+       status = rpc_call_sync(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
        if (!status)
                status = nfs4_check_cl_exchange_flags(clp->cl_exchange_flags);
        dprintk("<-- %s status= %d\n", __func__, status);
@@ -4869,7 +4876,8 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
                .rpc_client = clp->cl_rpcclient,
                .rpc_message = &msg,
                .callback_ops = &nfs4_get_lease_time_ops,
-               .callback_data = &data
+               .callback_data = &data,
+               .flags = RPC_TASK_TIMEOUT,
        };
        int status;
 
@@ -5171,7 +5179,7 @@ static int _nfs4_proc_create_session(struct nfs_client *clp)
        nfs4_init_channel_attrs(&args);
        args.flags = (SESSION4_PERSIST | SESSION4_BACK_CHAN);
 
-       status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0);
+       status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
 
        if (!status)
                /* Verify the session's negotiated channel_attrs values */
@@ -5194,20 +5202,10 @@ int nfs4_proc_create_session(struct nfs_client *clp)
        int status;
        unsigned *ptr;
        struct nfs4_session *session = clp->cl_session;
-       long timeout = 0;
-       int err;
 
        dprintk("--> %s clp=%p session=%p\n", __func__, clp, session);
 
-       do {
-               status = _nfs4_proc_create_session(clp);
-               if (status == -NFS4ERR_DELAY) {
-                       err = nfs4_delay(clp->cl_rpcclient, &timeout);
-                       if (err)
-                               status = err;
-               }
-       } while (status == -NFS4ERR_DELAY);
-
+       status = _nfs4_proc_create_session(clp);
        if (status)
                goto out;
 
@@ -5248,7 +5246,7 @@ int nfs4_proc_destroy_session(struct nfs4_session *session)
        msg.rpc_argp = session;
        msg.rpc_resp = NULL;
        msg.rpc_cred = NULL;
-       status = rpc_call_sync(session->clp->cl_rpcclient, &msg, 0);
+       status = rpc_call_sync(session->clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT);
 
        if (status)
                printk(KERN_WARNING
index a6804f7..036f5ad 100644 (file)
@@ -64,10 +64,15 @@ static LIST_HEAD(nfs4_clientid_list);
 
 int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
 {
-       struct nfs4_setclientid_res clid;
+       struct nfs4_setclientid_res clid = {
+               .clientid = clp->cl_clientid,
+               .confirm = clp->cl_confirm,
+       };
        unsigned short port;
        int status;
 
+       if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state))
+               goto do_confirm;
        port = nfs_callback_tcpport;
        if (clp->cl_addr.ss_family == AF_INET6)
                port = nfs_callback_tcpport6;
@@ -75,10 +80,14 @@ int nfs4_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
        status = nfs4_proc_setclientid(clp, NFS4_CALLBACK, port, cred, &clid);
        if (status != 0)
                goto out;
+       clp->cl_clientid = clid.clientid;
+       clp->cl_confirm = clid.confirm;
+       set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
+do_confirm:
        status = nfs4_proc_setclientid_confirm(clp, &clid, cred);
        if (status != 0)
                goto out;
-       clp->cl_clientid = clid.clientid;
+       clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
        nfs4_schedule_state_renewal(clp);
 out:
        return status;
@@ -230,13 +239,18 @@ int nfs41_init_clientid(struct nfs_client *clp, struct rpc_cred *cred)
 {
        int status;
 
+       if (test_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state))
+               goto do_confirm;
        nfs4_begin_drain_session(clp);
        status = nfs4_proc_exchange_id(clp, cred);
        if (status != 0)
                goto out;
+       set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
+do_confirm:
        status = nfs4_proc_create_session(clp);
        if (status != 0)
                goto out;
+       clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
        nfs41_setup_state_renewal(clp);
        nfs_mark_client_ready(clp, NFS_CS_READY);
 out:
@@ -1584,20 +1598,23 @@ static int nfs4_recall_slot(struct nfs_client *clp) { return 0; }
  */
 static void nfs4_set_lease_expired(struct nfs_client *clp, int status)
 {
-       if (nfs4_has_session(clp)) {
-               switch (status) {
-               case -NFS4ERR_DELAY:
-               case -NFS4ERR_CLID_INUSE:
-               case -EAGAIN:
-                       break;
+       switch (status) {
+       case -NFS4ERR_CLID_INUSE:
+       case -NFS4ERR_STALE_CLIENTID:
+               clear_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
+               break;
+       case -NFS4ERR_DELAY:
+       case -ETIMEDOUT:
+       case -EAGAIN:
+               ssleep(1);
+               break;
 
-               case -EKEYEXPIRED:
-                       nfs4_warn_keyexpired(clp->cl_hostname);
-               case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
-                                        * in nfs4_exchange_id */
-               default:
-                       return;
-               }
+       case -EKEYEXPIRED:
+               nfs4_warn_keyexpired(clp->cl_hostname);
+       case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery
+                                * in nfs4_exchange_id */
+       default:
+               return;
        }
        set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
 }
@@ -1607,7 +1624,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
        int status = 0;
 
        /* Ensure exclusive access to NFSv4 state */
-       for(;;) {
+       do {
                if (test_and_clear_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state)) {
                        /* We're going to have to re-establish a clientid */
                        status = nfs4_reclaim_lease(clp);
@@ -1691,7 +1708,7 @@ static void nfs4_state_manager(struct nfs_client *clp)
                        break;
                if (test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, &clp->cl_state) != 0)
                        break;
-       }
+       } while (atomic_read(&clp->cl_count) > 1);
        return;
 out_error:
        printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s"
index dddfb57..c3ccd2c 100644 (file)
@@ -1452,26 +1452,25 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args,
 
 static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr)
 {
-       uint32_t attrs[2] = {0, 0};
+       uint32_t attrs[2] = {
+               FATTR4_WORD0_RDATTR_ERROR,
+               FATTR4_WORD1_MOUNTED_ON_FILEID,
+       };
        uint32_t dircount = readdir->count >> 1;
        __be32 *p;
 
        if (readdir->plus) {
                attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE|
-                       FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE;
+                       FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE|FATTR4_WORD0_FILEID;
                attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER|
                        FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV|
                        FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS|
                        FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
                dircount >>= 1;
        }
-       attrs[0] |= FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID;
-       attrs[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID;
-       /* Switch to mounted_on_fileid if the server supports it */
-       if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
-               attrs[0] &= ~FATTR4_WORD0_FILEID;
-       else
-               attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
+       /* Use mounted_on_fileid only if the server supports it */
+       if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID))
+               attrs[0] |= FATTR4_WORD0_FILEID;
 
        p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20);
        *p++ = cpu_to_be32(OP_READDIR);
@@ -3140,7 +3139,7 @@ static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitma
                        goto out_overflow;
                xdr_decode_hyper(p, fileid);
                bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
-               ret = NFS_ATTR_FATTR_FILEID;
+               ret = NFS_ATTR_FATTR_MOUNTED_ON_FILEID;
        }
        dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
        return ret;
@@ -4002,7 +4001,6 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
 {
        int status;
        umode_t fmode = 0;
-       uint64_t fileid;
        uint32_t type;
 
        status = decode_attr_type(xdr, bitmap, &type);
@@ -4101,13 +4099,10 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
                goto xdr_error;
        fattr->valid |= status;
 
-       status = decode_attr_mounted_on_fileid(xdr, bitmap, &fileid);
+       status = decode_attr_mounted_on_fileid(xdr, bitmap, &fattr->mounted_on_fileid);
        if (status < 0)
                goto xdr_error;
-       if (status != 0 && !(fattr->valid & status)) {
-               fattr->fileid = fileid;
-               fattr->valid |= status;
-       }
+       fattr->valid |= status;
 
 xdr_error:
        dprintk("%s: xdr returned %d\n", __func__, -status);
@@ -4838,17 +4833,21 @@ static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
        struct nfs4_secinfo_flavor *sec_flavor;
        int status;
        __be32 *p;
-       int i;
+       int i, num_flavors;
 
        status = decode_op_hdr(xdr, OP_SECINFO);
+       if (status)
+               goto out;
        p = xdr_inline_decode(xdr, 4);
        if (unlikely(!p))
                goto out_overflow;
-       res->flavors->num_flavors = be32_to_cpup(p);
 
-       for (i = 0; i < res->flavors->num_flavors; i++) {
+       res->flavors->num_flavors = 0;
+       num_flavors = be32_to_cpup(p);
+
+       for (i = 0; i < num_flavors; i++) {
                sec_flavor = &res->flavors->flavors[i];
-               if ((char *)&sec_flavor[1] - (char *)res > PAGE_SIZE)
+               if ((char *)&sec_flavor[1] - (char *)res->flavors > PAGE_SIZE)
                        break;
 
                p = xdr_inline_decode(xdr, 4);
@@ -4857,13 +4856,15 @@ static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
                sec_flavor->flavor = be32_to_cpup(p);
 
                if (sec_flavor->flavor == RPC_AUTH_GSS) {
-                       if (decode_secinfo_gss(xdr, sec_flavor))
-                               break;
+                       status = decode_secinfo_gss(xdr, sec_flavor);
+                       if (status)
+                               goto out;
                }
+               res->flavors->num_flavors++;
        }
 
-       return 0;
-
+out:
+       return status;
 out_overflow:
        print_overflow_msg(__func__, xdr);
        return -EIO;
@@ -6408,7 +6409,9 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
        if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh,
                                        entry->server, 1) < 0)
                goto out_overflow;
-       if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
+       if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
+               entry->ino = entry->fattr->mounted_on_fileid;
+       else if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
                entry->ino = entry->fattr->fileid;
 
        entry->d_type = DT_UNKNOWN;
index d9ab972..ff681ab 100644 (file)
@@ -1004,6 +1004,7 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata)
 {
        struct nfs_inode *nfsi = NFS_I(wdata->inode);
        loff_t end_pos = wdata->args.offset + wdata->res.count;
+       bool mark_as_dirty = false;
 
        spin_lock(&nfsi->vfs_inode.i_lock);
        if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) {
@@ -1011,13 +1012,18 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata)
                get_lseg(wdata->lseg);
                wdata->lseg->pls_lc_cred =
                        get_rpccred(wdata->args.context->state->owner->so_cred);
-               mark_inode_dirty_sync(wdata->inode);
+               mark_as_dirty = true;
                dprintk("%s: Set layoutcommit for inode %lu ",
                        __func__, wdata->inode->i_ino);
        }
        if (end_pos > wdata->lseg->pls_end_pos)
                wdata->lseg->pls_end_pos = end_pos;
        spin_unlock(&nfsi->vfs_inode.i_lock);
+
+       /* if pnfs_layoutcommit_inode() runs between inode locks, the next one
+        * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */
+       if (mark_as_dirty)
+               mark_inode_dirty_sync(wdata->inode);
 }
 EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit);
 
index 2b8e9a5..e288f06 100644 (file)
@@ -1004,6 +1004,7 @@ static int nfs_parse_security_flavors(char *value,
                return 0;
        }
 
+       mnt->flags |= NFS_MOUNT_SECFLAVOUR;
        mnt->auth_flavor_len = 1;
        return 1;
 }
@@ -1976,6 +1977,15 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data)
        if (error < 0)
                goto out;
 
+       /*
+        * noac is a special case. It implies -o sync, but that's not
+        * necessarily reflected in the mtab options. do_remount_sb
+        * will clear MS_SYNCHRONOUS if -o sync wasn't specified in the
+        * remount options, so we have to explicitly reset it.
+        */
+       if (data->flags & NFS_MOUNT_NOAC)
+               *flags |= MS_SYNCHRONOUS;
+
        /* compare new mount options with old ones */
        error = nfs_compare_remount_data(nfss, data);
 out:
@@ -2235,8 +2245,7 @@ static struct dentry *nfs_fs_mount(struct file_system_type *fs_type,
        if (!s->s_root) {
                /* initial superblock/root creation */
                nfs_fill_super(s, data);
-               nfs_fscache_get_super_cookie(
-                       s, data ? data->fscache_uniq : NULL, NULL);
+               nfs_fscache_get_super_cookie(s, data->fscache_uniq, NULL);
        }
 
        mntroot = nfs_get_root(s, mntfh, dev_name);
index e4cbc11..3bd5d7e 100644 (file)
@@ -680,7 +680,6 @@ static int nfs_writepage_setup(struct nfs_open_context *ctx, struct page *page,
        req = nfs_setup_write_request(ctx, page, offset, count);
        if (IS_ERR(req))
                return PTR_ERR(req);
-       nfs_mark_request_dirty(req);
        /* Update file length */
        nfs_grow_file(page, offset, count);
        nfs_mark_uptodate(page, req->wb_pgbase, req->wb_bytes);
@@ -1418,8 +1417,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
                                 task->tk_pid, task->tk_status);
 
        /* Call the NFS version-specific code */
-       if (NFS_PROTO(data->inode)->commit_done(task, data) != 0)
-               return;
+       NFS_PROTO(data->inode)->commit_done(task, data);
 }
 
 void nfs_commit_release_pages(struct nfs_write_data *data)
index b68f87a..938387a 100644 (file)
@@ -1019,7 +1019,7 @@ struct ocfs2_xattr_entry {
        __le16  xe_name_offset;  /* byte offset from the 1st entry in the
                                    local xattr storage(inode, xattr block or
                                    xattr bucket). */
-       __u8    xe_name_len;     /* xattr name len, does't include prefix. */
+       __u8    xe_name_len;     /* xattr name len, doesn't include prefix. */
        __u8    xe_type;         /* the low 7 bits indicate the name prefix
                                  * type and the highest bit indicates whether
                                  * the EA is stored in the local storage. */
index 4d0cb12..40fa780 100644 (file)
@@ -174,26 +174,6 @@ void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud)
        spin_unlock(&c->buds_lock);
 }
 
-/**
- * ubifs_create_buds_lists - create journal head buds lists for remount rw.
- * @c: UBIFS file-system description object
- */
-void ubifs_create_buds_lists(struct ubifs_info *c)
-{
-       struct rb_node *p;
-
-       spin_lock(&c->buds_lock);
-       p = rb_first(&c->buds);
-       while (p) {
-               struct ubifs_bud *bud = rb_entry(p, struct ubifs_bud, rb);
-               struct ubifs_jhead *jhead = &c->jheads[bud->jhead];
-
-               list_add_tail(&bud->list, &jhead->buds_list);
-               p = rb_next(p);
-       }
-       spin_unlock(&c->buds_lock);
-}
-
 /**
  * ubifs_add_bud_to_log - add a new bud to the log.
  * @c: UBIFS file-system description object
index 936f2cb..3dbad6f 100644 (file)
@@ -317,6 +317,32 @@ int ubifs_recover_master_node(struct ubifs_info *c)
                        goto out_free;
                }
                memcpy(c->rcvrd_mst_node, c->mst_node, UBIFS_MST_NODE_SZ);
+
+               /*
+                * We had to recover the master node, which means there was an
+                * unclean reboot. However, it is possible that the master node
+                * is clean at this point, i.e., %UBIFS_MST_DIRTY is not set.
+                * E.g., consider the following chain of events:
+                *
+                * 1. UBIFS was cleanly unmounted, so the master node is clean
+                * 2. UBIFS is being mounted R/W and starts changing the master
+                *    node in the first (%UBIFS_MST_LNUM). A power cut happens,
+                *    so this LEB ends up with some amount of garbage at the
+                *    end.
+                * 3. UBIFS is being mounted R/O. We reach this place and
+                *    recover the master node from the second LEB
+                *    (%UBIFS_MST_LNUM + 1). But we cannot update the media
+                *    because we are being mounted R/O. We have to defer the
+                *    operation.
+                * 4. However, this master node (@c->mst_node) is marked as
+                *    clean (since the step 1). And if we just return, the
+                *    mount code will be confused and won't recover the master
+                *    node when it is re-mounter R/W later.
+                *
+                *    Thus, to force the recovery by marking the master node as
+                *    dirty.
+                */
+               c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
        } else {
                /* Write the recovered master node */
                c->max_sqnum = le64_to_cpu(mst->ch.sqnum) - 1;
index eed0fcf..d3d6d36 100644 (file)
@@ -59,6 +59,7 @@ enum {
  * @new_size: truncation new size
  * @free: amount of free space in a bud
  * @dirty: amount of dirty space in a bud from padding and deletion nodes
+ * @jhead: journal head number of the bud
  *
  * UBIFS journal replay must compare node sequence numbers, which means it must
  * build a tree of node information to insert into the TNC.
@@ -80,6 +81,7 @@ struct replay_entry {
                struct {
                        int free;
                        int dirty;
+                       int jhead;
                };
        };
 };
@@ -159,6 +161,11 @@ static int set_bud_lprops(struct ubifs_info *c, struct replay_entry *r)
                err = PTR_ERR(lp);
                goto out;
        }
+
+       /* Make sure the journal head points to the latest bud */
+       err = ubifs_wbuf_seek_nolock(&c->jheads[r->jhead].wbuf, r->lnum,
+                                    c->leb_size - r->free, UBI_SHORTTERM);
+
 out:
        ubifs_release_lprops(c);
        return err;
@@ -627,10 +634,6 @@ static int replay_bud(struct ubifs_info *c, int lnum, int offs, int jhead,
        ubifs_assert(sleb->endpt - offs >= used);
        ubifs_assert(sleb->endpt % c->min_io_size == 0);
 
-       if (sleb->endpt + c->min_io_size <= c->leb_size && !c->ro_mount)
-               err = ubifs_wbuf_seek_nolock(&c->jheads[jhead].wbuf, lnum,
-                                            sleb->endpt, UBI_SHORTTERM);
-
        *dirty = sleb->endpt - offs - used;
        *free = c->leb_size - sleb->endpt;
 
@@ -653,12 +656,14 @@ out_dump:
  * @sqnum: sequence number
  * @free: amount of free space in bud
  * @dirty: amount of dirty space from padding and deletion nodes
+ * @jhead: journal head number for the bud
  *
  * This function inserts a reference node to the replay tree and returns zero
  * in case of success or a negative error code in case of failure.
  */
 static int insert_ref_node(struct ubifs_info *c, int lnum, int offs,
-                          unsigned long long sqnum, int free, int dirty)
+                          unsigned long long sqnum, int free, int dirty,
+                          int jhead)
 {
        struct rb_node **p = &c->replay_tree.rb_node, *parent = NULL;
        struct replay_entry *r;
@@ -688,6 +693,7 @@ static int insert_ref_node(struct ubifs_info *c, int lnum, int offs,
        r->flags = REPLAY_REF;
        r->free = free;
        r->dirty = dirty;
+       r->jhead = jhead;
 
        rb_link_node(&r->rb, parent, p);
        rb_insert_color(&r->rb, &c->replay_tree);
@@ -712,7 +718,7 @@ static int replay_buds(struct ubifs_info *c)
                if (err)
                        return err;
                err = insert_ref_node(c, b->bud->lnum, b->bud->start, b->sqnum,
-                                     free, dirty);
+                                     free, dirty, b->bud->jhead);
                if (err)
                        return err;
        }
index c75f613..04ad07f 100644 (file)
@@ -1257,12 +1257,12 @@ static int mount_ubifs(struct ubifs_info *c)
                goto out_free;
        }
 
+       err = alloc_wbufs(c);
+       if (err)
+               goto out_cbuf;
+
        sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id);
        if (!c->ro_mount) {
-               err = alloc_wbufs(c);
-               if (err)
-                       goto out_cbuf;
-
                /* Create background thread */
                c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name);
                if (IS_ERR(c->bgt)) {
@@ -1631,12 +1631,6 @@ static int ubifs_remount_rw(struct ubifs_info *c)
        if (err)
                goto out;
 
-       err = alloc_wbufs(c);
-       if (err)
-               goto out;
-
-       ubifs_create_buds_lists(c);
-
        /* Create background thread */
        c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name);
        if (IS_ERR(c->bgt)) {
@@ -1671,14 +1665,25 @@ static int ubifs_remount_rw(struct ubifs_info *c)
        if (err)
                goto out;
 
+       dbg_gen("re-mounted read-write");
+       c->remounting_rw = 0;
+
        if (c->need_recovery) {
                c->need_recovery = 0;
                ubifs_msg("deferred recovery completed");
+       } else {
+               /*
+                * Do not run the debugging space check if the were doing
+                * recovery, because when we saved the information we had the
+                * file-system in a state where the TNC and lprops has been
+                * modified in memory, but all the I/O operations (including a
+                * commit) were deferred. So the file-system was in
+                * "non-committed" state. Now the file-system is in committed
+                * state, and of course the amount of free space will change
+                * because, for example, the old index size was imprecise.
+                */
+               err = dbg_check_space_info(c);
        }
-
-       dbg_gen("re-mounted read-write");
-       c->remounting_rw = 0;
-       err = dbg_check_space_info(c);
        mutex_unlock(&c->umount_mutex);
        return err;
 
@@ -1733,7 +1738,6 @@ static void ubifs_remount_ro(struct ubifs_info *c)
        if (err)
                ubifs_ro_mode(c, err);
 
-       free_wbufs(c);
        vfree(c->orph_buf);
        c->orph_buf = NULL;
        kfree(c->write_reserve_buf);
@@ -1761,10 +1765,12 @@ static void ubifs_put_super(struct super_block *sb)
         * of the media. For example, there will be dirty inodes if we failed
         * to write them back because of I/O errors.
         */
-       ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0);
-       ubifs_assert(c->budg_idx_growth == 0);
-       ubifs_assert(c->budg_dd_growth == 0);
-       ubifs_assert(c->budg_data_growth == 0);
+       if (!c->ro_error) {
+               ubifs_assert(atomic_long_read(&c->dirty_pg_cnt) == 0);
+               ubifs_assert(c->budg_idx_growth == 0);
+               ubifs_assert(c->budg_dd_growth == 0);
+               ubifs_assert(c->budg_data_growth == 0);
+       }
 
        /*
         * The 'c->umount_lock' prevents races between UBIFS memory shrinker
index f22e7fe..ade09d7 100644 (file)
@@ -118,6 +118,7 @@ int drm_fb_helper_setcolreg(unsigned regno,
                            unsigned transp,
                            struct fb_info *info);
 
+bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper);
 void drm_fb_helper_restore(void);
 void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
                            uint32_t fb_width, uint32_t fb_height);
index 816e30c..f04b2a3 100644 (file)
        {0x1002, 0x6719, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x671c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x671d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x671f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAYMAN|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6720, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6721, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6722, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6729, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6738, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6739, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x673e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BARTS|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6740, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6741, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6742, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x688D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6898, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x6899, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x689b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x689c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HEMLOCK|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x689d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_HEMLOCK|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x689e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x68b0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x68b8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x68b9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x68ba, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x68be, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
+       {0x1002, 0x68bf, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_JUNIPER|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x68c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x68c1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
        {0x1002, 0x68c7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_REDWOOD|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
index 3bce1a4..787f7b6 100644 (file)
@@ -909,6 +909,8 @@ struct drm_radeon_cs {
 #define RADEON_INFO_WANT_CMASK         0x08 /* get access to CMASK on r300 */
 #define RADEON_INFO_CLOCK_CRYSTAL_FREQ 0x09 /* clock crystal frequency */
 #define RADEON_INFO_NUM_BACKENDS       0x0a /* DB/backends for r600+ - need for OQ */
+#define RADEON_INFO_NUM_TILE_PIPES     0x0b /* tile pipes for r600+ */
+#define RADEON_INFO_FUSION_GART_WORKING        0x0c /* fusion writes to GTT were broken before this */
 
 struct drm_radeon_info {
        uint32_t                request;
index e612575..b4326bf 100644 (file)
@@ -23,11 +23,11 @@ static inline void bit_spin_lock(int bitnum, unsigned long *addr)
        preempt_disable();
 #if defined(CONFIG_SMP) || defined(CONFIG_DEBUG_SPINLOCK)
        while (unlikely(test_and_set_bit_lock(bitnum, addr))) {
-               while (test_bit(bitnum, addr)) {
-                       preempt_enable();
+               preempt_enable();
+               do {
                        cpu_relax();
-                       preempt_disable();
-               }
+               } while (test_bit(bitnum, addr));
+               preempt_disable();
        }
 #endif
        __acquire(bitlock);
index f2afed4..19d90a5 100644 (file)
@@ -197,7 +197,7 @@ struct dentry_operations {
       * typically using d_splice_alias. */
 
 #define DCACHE_REFERENCED      0x0008  /* Recently used, don't discard. */
-#define DCACHE_UNHASHED                0x0010  
+#define DCACHE_RCUACCESS       0x0010  /* Entry has ever been RCU-visible */
 #define DCACHE_INOTIFY_PARENT_WATCHED 0x0020
      /* Parent inode is watched by inotify */
 
@@ -384,7 +384,7 @@ extern struct dentry *dget_parent(struct dentry *dentry);
  
 static inline int d_unhashed(struct dentry *dentry)
 {
-       return (dentry->d_flags & DCACHE_UNHASHED);
+       return hlist_bl_unhashed(&dentry->d_hash);
 }
 
 static inline int d_unlinked(struct dentry *dentry)
index 70e4efa..ebeb2f3 100644 (file)
@@ -61,7 +61,7 @@ struct flex_array {
 struct flex_array *flex_array_alloc(int element_size, unsigned int total,
                gfp_t flags);
 int flex_array_prealloc(struct flex_array *fa, unsigned int start,
-               unsigned int end, gfp_t flags);
+               unsigned int nr_elements, gfp_t flags);
 void flex_array_free(struct flex_array *fa);
 void flex_array_free_parts(struct flex_array *fa);
 int flex_array_put(struct flex_array *fa, unsigned int element_nr, void *src,
index df29c8f..8847c8c 100644 (file)
@@ -117,7 +117,7 @@ static inline void vma_adjust_trans_huge(struct vm_area_struct *vma,
                                         unsigned long end,
                                         long adjust_next)
 {
-       if (!vma->anon_vma || vma->vm_ops || vma->vm_file)
+       if (!vma->anon_vma || vma->vm_ops)
                return;
        __vma_adjust_trans_huge(vma, start, end, adjust_next);
 }
index 7f675aa..04f32a3 100644 (file)
@@ -137,8 +137,6 @@ enum {
        ATA_DFLAG_ACPI_PENDING  = (1 << 5), /* ACPI resume action pending */
        ATA_DFLAG_ACPI_FAILED   = (1 << 6), /* ACPI on devcfg has failed */
        ATA_DFLAG_AN            = (1 << 7), /* AN configured */
-       ATA_DFLAG_HIPM          = (1 << 8), /* device supports HIPM */
-       ATA_DFLAG_DIPM          = (1 << 9), /* device supports DIPM */
        ATA_DFLAG_DMADIR        = (1 << 10), /* device requires DMADIR */
        ATA_DFLAG_CFG_MASK      = (1 << 12) - 1,
 
@@ -198,6 +196,7 @@ enum {
                                              * management */
        ATA_FLAG_SW_ACTIVITY    = (1 << 22), /* driver supports sw activity
                                              * led */
+       ATA_FLAG_NO_DIPM        = (1 << 23), /* host not happy with DIPM */
 
        /* bits 24:31 of ap->flags are reserved for LLD specific flags */
 
index 5bad17d..31f9d75 100644 (file)
@@ -2,6 +2,7 @@
 #define _LINUX_LIST_BL_H
 
 #include <linux/list.h>
+#include <linux/bit_spinlock.h>
 
 /*
  * Special version of lists, where head of the list has a lock in the lowest
@@ -114,6 +115,16 @@ static inline void hlist_bl_del_init(struct hlist_bl_node *n)
        }
 }
 
+static inline void hlist_bl_lock(struct hlist_bl_head *b)
+{
+       bit_spin_lock(0, (unsigned long *)b);
+}
+
+static inline void hlist_bl_unlock(struct hlist_bl_head *b)
+{
+       __bit_spin_unlock(0, (unsigned long *)b);
+}
+
 /**
  * hlist_bl_for_each_entry     - iterate over list of given type
  * @tpos:      the type * to use as a loop cursor.
index afe4db4..632d156 100644 (file)
@@ -81,7 +81,9 @@ struct wm831x_touch_pdata {
        int rpu;               /** Pen down sensitivity resistor divider */
        int pressure;          /** Report pressure (boolean) */
        unsigned int data_irq; /** Touch data ready IRQ */
+       int data_irqf;         /** IRQ flags for data ready IRQ */
        unsigned int pd_irq;   /** Touch pendown detect IRQ */
+       int pd_irqf;           /** IRQ flags for pen down IRQ */
 };
 
 enum wm831x_watchdog_action {
index 692dbae..2348db2 100644 (file)
@@ -137,7 +137,8 @@ extern unsigned int kobjsize(const void *objp);
 #define VM_RandomReadHint(v)           ((v)->vm_flags & VM_RAND_READ)
 
 /*
- * special vmas that are non-mergable, non-mlock()able
+ * Special vmas that are non-mergable, non-mlock()able.
+ * Note: mm/huge_memory.c VM_NO_THP depends on this definition.
  */
 #define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP)
 
index bcb793e..eb792cb 100644 (file)
@@ -183,7 +183,6 @@ struct mmc_host {
        struct work_struct      clk_gate_work; /* delayed clock gate */
        unsigned int            clk_old;        /* old clock value cache */
        spinlock_t              clk_lock;       /* lock for clk fields */
-       struct mutex            clk_gate_mutex; /* mutex for clock gating */
 #endif
 
        /* host specific block data */
index 216cea5..87694ca 100644 (file)
@@ -47,6 +47,7 @@ struct nfs_client {
 
 #ifdef CONFIG_NFS_V4
        u64                     cl_clientid;    /* constant */
+       nfs4_verifier           cl_confirm;     /* Clientid verifier */
        unsigned long           cl_state;
 
        spinlock_t              cl_lock;
index 78b101e..890dce2 100644 (file)
@@ -50,6 +50,7 @@ struct nfs_fattr {
        } du;
        struct nfs_fsid         fsid;
        __u64                   fileid;
+       __u64                   mounted_on_fileid;
        struct timespec         atime;
        struct timespec         mtime;
        struct timespec         ctime;
@@ -83,6 +84,7 @@ struct nfs_fattr {
 #define NFS_ATTR_FATTR_PRECHANGE       (1U << 18)
 #define NFS_ATTR_FATTR_V4_REFERRAL     (1U << 19)      /* NFSv4 referral */
 #define NFS_ATTR_FATTR_MOUNTPOINT      (1U << 20)      /* Treat as mountpoint */
+#define NFS_ATTR_FATTR_MOUNTED_ON_FILEID               (1U << 21)
 
 #define NFS_ATTR_FATTR (NFS_ATTR_FATTR_TYPE \
                | NFS_ATTR_FATTR_MODE \
index 4e2c915..8abe8d7 100644 (file)
 #define PCI_DEVICE_ID_INTEL_82840_HB   0x1a21
 #define PCI_DEVICE_ID_INTEL_82845_HB   0x1a30
 #define PCI_DEVICE_ID_INTEL_IOAT       0x1a38
-#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS  0x1c22
 #define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN        0x1c41
 #define PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX        0x1c5f
-#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS     0x1d22
 #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_0     0x1d40
 #define PCI_DEVICE_ID_INTEL_PATSBURG_LPC_1     0x1d41
 #define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN   0x2310
 #define PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX   0x231f
-#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS     0x2330
 #define PCI_DEVICE_ID_INTEL_82801AA_0  0x2410
 #define PCI_DEVICE_ID_INTEL_82801AA_1  0x2411
 #define PCI_DEVICE_ID_INTEL_82801AA_3  0x2413
 #define PCI_DEVICE_ID_INTEL_ICH10_5    0x3a60
 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN      0x3b00
 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX      0x3b1f
-#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS        0x3b30
 #define PCI_DEVICE_ID_INTEL_IOAT_SNB   0x402f
 #define PCI_DEVICE_ID_INTEL_5100_16    0x65f0
 #define PCI_DEVICE_ID_INTEL_5100_21    0x65f5
index 3a5c444..8b97308 100644 (file)
@@ -948,7 +948,7 @@ do {                                                                        \
        irqsafe_generic_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
 # endif
 # define irqsafe_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)    \
-       __pcpu_double_call_return_int(irqsafe_cpu_cmpxchg_double_, (pcp1), (pcp2), (oval1), (oval2), (nval1), (nval2))
+       __pcpu_double_call_return_bool(irqsafe_cpu_cmpxchg_double_, (pcp1), (pcp2), (oval1), (oval2), (nval1), (nval2))
 #endif
 
 #endif /* __LINUX_PERCPU_H */
index d81db80..f73c482 100644 (file)
@@ -127,13 +127,16 @@ struct rpc_task_setup {
 #define RPC_TASK_KILLED                0x0100          /* task was killed */
 #define RPC_TASK_SOFT          0x0200          /* Use soft timeouts */
 #define RPC_TASK_SOFTCONN      0x0400          /* Fail if can't connect */
+#define RPC_TASK_SENT          0x0800          /* message was sent */
+#define RPC_TASK_TIMEOUT       0x1000          /* fail with ETIMEDOUT on timeout */
 
 #define RPC_IS_ASYNC(t)                ((t)->tk_flags & RPC_TASK_ASYNC)
 #define RPC_IS_SWAPPER(t)      ((t)->tk_flags & RPC_TASK_SWAPPER)
 #define RPC_DO_ROOTOVERRIDE(t) ((t)->tk_flags & RPC_TASK_ROOTCREDS)
 #define RPC_ASSASSINATED(t)    ((t)->tk_flags & RPC_TASK_KILLED)
-#define RPC_IS_SOFT(t)         ((t)->tk_flags & RPC_TASK_SOFT)
+#define RPC_IS_SOFT(t)         ((t)->tk_flags & (RPC_TASK_SOFT|RPC_TASK_TIMEOUT))
 #define RPC_IS_SOFTCONN(t)     ((t)->tk_flags & RPC_TASK_SOFTCONN)
+#define RPC_WAS_SENT(t)                ((t)->tk_flags & RPC_TASK_SENT)
 
 #define RPC_TASK_RUNNING       0
 #define RPC_TASK_QUEUED                1
index 0e18550..605b0aa 100644 (file)
@@ -68,6 +68,7 @@ struct usbnet {
 #              define EVENT_RX_PAUSED  5
 #              define EVENT_DEV_WAKING 6
 #              define EVENT_DEV_ASLEEP 7
+#              define EVENT_DEV_OPEN   8
 };
 
 static inline struct usb_driver *driver_of(struct usb_interface *intf)
index 7054a7a..de5c159 100644 (file)
@@ -47,7 +47,7 @@ enum v4l2_mbus_pixelcode {
        V4L2_MBUS_FMT_RGB565_2X8_BE = 0x1007,
        V4L2_MBUS_FMT_RGB565_2X8_LE = 0x1008,
 
-       /* YUV (including grey) - next is 0x2013 */
+       /* YUV (including grey) - next is 0x2014 */
        V4L2_MBUS_FMT_Y8_1X8 = 0x2001,
        V4L2_MBUS_FMT_UYVY8_1_5X8 = 0x2002,
        V4L2_MBUS_FMT_VYUY8_1_5X8 = 0x2003,
@@ -60,6 +60,7 @@ enum v4l2_mbus_pixelcode {
        V4L2_MBUS_FMT_Y10_1X10 = 0x200a,
        V4L2_MBUS_FMT_YUYV10_2X10 = 0x200b,
        V4L2_MBUS_FMT_YVYU10_2X10 = 0x200c,
+       V4L2_MBUS_FMT_Y12_1X12 = 0x2013,
        V4L2_MBUS_FMT_UYVY8_1X16 = 0x200f,
        V4L2_MBUS_FMT_VYUY8_1X16 = 0x2010,
        V4L2_MBUS_FMT_YUYV8_1X16 = 0x2011,
@@ -67,9 +68,11 @@ enum v4l2_mbus_pixelcode {
        V4L2_MBUS_FMT_YUYV10_1X20 = 0x200d,
        V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e,
 
-       /* Bayer - next is 0x3013 */
+       /* Bayer - next is 0x3015 */
        V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001,
+       V4L2_MBUS_FMT_SGBRG8_1X8 = 0x3013,
        V4L2_MBUS_FMT_SGRBG8_1X8 = 0x3002,
+       V4L2_MBUS_FMT_SRGGB8_1X8 = 0x3014,
        V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 = 0x300b,
        V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8 = 0x300c,
        V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 = 0x3009,
index aa6c393..be82c8e 100644 (file)
@@ -308,6 +308,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_Y4      v4l2_fourcc('Y', '0', '4', ' ') /*  4  Greyscale     */
 #define V4L2_PIX_FMT_Y6      v4l2_fourcc('Y', '0', '6', ' ') /*  6  Greyscale     */
 #define V4L2_PIX_FMT_Y10     v4l2_fourcc('Y', '1', '0', ' ') /* 10  Greyscale     */
+#define V4L2_PIX_FMT_Y12     v4l2_fourcc('Y', '1', '2', ' ') /* 12  Greyscale     */
 #define V4L2_PIX_FMT_Y16     v4l2_fourcc('Y', '1', '6', ' ') /* 16  Greyscale     */
 
 /* Palette formats */
index bd102cf..d61febf 100644 (file)
@@ -163,7 +163,7 @@ v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev);
 ({                                                                     \
        struct v4l2_subdev *__sd;                                       \
        __v4l2_device_call_subdevs_until_err_p(v4l2_dev, __sd, cond, o, \
-                                               f, args...);            \
+                                               f , ##args);            \
 })
 
 /* Call the specified callback for all subdevs matching grp_id (if 0, then
index 56240e7..d886b1e 100644 (file)
@@ -924,14 +924,6 @@ menuconfig EXPERT
           environments which can tolerate a "non-standard" kernel.
           Only use this if you really know what you are doing.
 
-config EMBEDDED
-       bool "Embedded system"
-       select EXPERT
-       help
-         This option should be enabled if compiling the kernel for
-         an embedded system so certain expert options are available
-         for configuration.
-
 config UID16
        bool "Enable 16-bit UID system calls" if EXPERT
        depends on ARM || BLACKFIN || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && COMPAT) || UML || (X86_64 && IA32_EMULATION)
@@ -1104,6 +1096,14 @@ config AIO
           by some high performance threaded applications. Disabling
           this option saves about 7k.
 
+config EMBEDDED
+       bool "Embedded system"
+       select EXPERT
+       help
+         This option should be enabled if compiling the kernel for
+         an embedded system so certain expert options are available
+         for configuration.
+
 config HAVE_PERF_EVENTS
        bool
        help
@@ -1226,6 +1226,7 @@ config SLAB
          per cpu and per node queues.
 
 config SLUB
+       depends on BROKEN || NUMA || !DISCONTIGMEM
        bool "SLUB (Unqueued Allocator)"
        help
           SLUB is a slab allocator that minimizes cache line usage
index 9017478..87fdb3f 100644 (file)
@@ -81,7 +81,11 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
        }
 };
 
-static int hrtimer_clock_to_base_table[MAX_CLOCKS];
+static int hrtimer_clock_to_base_table[MAX_CLOCKS] = {
+       [CLOCK_REALTIME]        = HRTIMER_BASE_REALTIME,
+       [CLOCK_MONOTONIC]       = HRTIMER_BASE_MONOTONIC,
+       [CLOCK_BOOTTIME]        = HRTIMER_BASE_BOOTTIME,
+};
 
 static inline int hrtimer_clockid_to_base(clockid_t clock_id)
 {
@@ -1722,10 +1726,6 @@ static struct notifier_block __cpuinitdata hrtimers_nb = {
 
 void __init hrtimers_init(void)
 {
-       hrtimer_clock_to_base_table[CLOCK_REALTIME] = HRTIMER_BASE_REALTIME;
-       hrtimer_clock_to_base_table[CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC;
-       hrtimer_clock_to_base_table[CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME;
-
        hrtimer_cpu_notify(&hrtimers_nb, (unsigned long)CPU_UP_PREPARE,
                          (void *)(long)smp_processor_id());
        register_cpu_notifier(&hrtimers_nb);
index dd201bd..834899f 100644 (file)
@@ -419,7 +419,7 @@ int show_interrupts(struct seq_file *p, void *v)
        } else {
                seq_printf(p, " %8s", "None");
        }
-#ifdef CONFIG_GENIRC_IRQ_SHOW_LEVEL
+#ifdef CONFIG_GENERIC_IRQ_SHOW_LEVEL
        seq_printf(p, " %-8s", irqd_is_level_type(&desc->irq_data) ? "Level" : "Edge");
 #endif
        if (desc->name)
index 55936f9..87b77de 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/vmalloc.h>
 #include <linux/swap.h>
 #include <linux/kmsg_dump.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/page.h>
 #include <asm/uaccess.h>
@@ -1532,6 +1533,11 @@ int kernel_kexec(void)
                local_irq_disable();
                /* Suspend system devices */
                error = sysdev_suspend(PMSG_FREEZE);
+               if (!error) {
+                       error = syscore_suspend();
+                       if (error)
+                               sysdev_resume();
+               }
                if (error)
                        goto Enable_irqs;
        } else
@@ -1546,6 +1552,7 @@ int kernel_kexec(void)
 
 #ifdef CONFIG_KEXEC_JUMP
        if (kexec_image->preserve_context) {
+               syscore_resume();
                sysdev_resume();
  Enable_irqs:
                local_irq_enable();
index aeabd26..50aae66 100644 (file)
@@ -273,8 +273,11 @@ static int create_image(int platform_mode)
        local_irq_disable();
 
        error = sysdev_suspend(PMSG_FREEZE);
-       if (!error)
+       if (!error) {
                error = syscore_suspend();
+               if (error)
+                       sysdev_resume();
+       }
        if (error) {
                printk(KERN_ERR "PM: Some system devices failed to power down, "
                        "aborting hibernation\n");
@@ -407,8 +410,11 @@ static int resume_target_kernel(bool platform_mode)
        local_irq_disable();
 
        error = sysdev_suspend(PMSG_QUIESCE);
-       if (!error)
+       if (!error) {
                error = syscore_suspend();
+               if (error)
+                       sysdev_resume();
+       }
        if (error)
                goto Enable_irqs;
 
index 2814c32..8935369 100644 (file)
@@ -164,8 +164,11 @@ static int suspend_enter(suspend_state_t state)
        BUG_ON(!irqs_disabled());
 
        error = sysdev_suspend(PMSG_SUSPEND);
-       if (!error)
+       if (!error) {
                error = syscore_suspend();
+               if (error)
+                       sysdev_resume();
+       }
        if (!error) {
                if (!(suspend_test(TEST_CORE) || pm_wakeup_pending())) {
                        error = suspend_ops->enter(state);
index 61d7d59..2ad39e5 100644 (file)
@@ -141,7 +141,7 @@ if FTRACE
 config FUNCTION_TRACER
        bool "Kernel Function Tracer"
        depends on HAVE_FUNCTION_TRACER
-       select FRAME_POINTER if !ARM_UNWIND && !S390
+       select FRAME_POINTER if !ARM_UNWIND && !S390 && !MICROBLAZE
        select KALLSYMS
        select GENERIC_TRACER
        select CONTEXT_SWITCH_TRACER
index 140dce7..14733d4 100644 (file)
@@ -430,9 +430,12 @@ static int watchdog_enable(int cpu)
                p = kthread_create(watchdog, (void *)(unsigned long)cpu, "watchdog/%d", cpu);
                if (IS_ERR(p)) {
                        printk(KERN_ERR "softlockup watchdog for %i failed\n", cpu);
-                       if (!err)
+                       if (!err) {
                                /* if hardlockup hasn't already set this */
                                err = PTR_ERR(p);
+                               /* and disable the perf event */
+                               watchdog_nmi_disable(cpu);
+                       }
                        goto out;
                }
                kthread_bind(p, cpu);
index 8859a41..e3378e8 100644 (file)
@@ -1291,8 +1291,14 @@ __acquires(&gcwq->lock)
                        return true;
                spin_unlock_irq(&gcwq->lock);
 
-               /* CPU has come up in between, retry migration */
+               /*
+                * We've raced with CPU hot[un]plug.  Give it a breather
+                * and retry migration.  cond_resched() is required here;
+                * otherwise, we might deadlock against cpu_stop trying to
+                * bring down the CPU on non-preemptive kernel.
+                */
                cpu_relax();
+               cond_resched();
        }
 }
 
index c0ea40b..854b57b 100644 (file)
@@ -232,10 +232,10 @@ EXPORT_SYMBOL(flex_array_clear);
 
 /**
  * flex_array_prealloc - guarantee that array space exists
- * @fa:                the flex array for which to preallocate parts
- * @start:     index of first array element for which space is allocated
- * @end:       index of last (inclusive) element for which space is allocated
- * @flags:     page allocation flags
+ * @fa:                        the flex array for which to preallocate parts
+ * @start:             index of first array element for which space is allocated
+ * @nr_elements:       number of elements for which space is allocated
+ * @flags:             page allocation flags
  *
  * This will guarantee that no future calls to flex_array_put()
  * will allocate memory.  It can be used if you are expecting to
@@ -245,14 +245,24 @@ EXPORT_SYMBOL(flex_array_clear);
  * Locking must be provided by the caller.
  */
 int flex_array_prealloc(struct flex_array *fa, unsigned int start,
-                       unsigned int end, gfp_t flags)
+                       unsigned int nr_elements, gfp_t flags)
 {
        int start_part;
        int end_part;
        int part_nr;
+       unsigned int end;
        struct flex_array_part *part;
 
-       if (start >= fa->total_nr_elements || end >= fa->total_nr_elements)
+       if (!start && !nr_elements)
+               return 0;
+       if (start >= fa->total_nr_elements)
+               return -ENOSPC;
+       if (!nr_elements)
+               return 0;
+
+       end = start + nr_elements - 1;
+
+       if (end >= fa->total_nr_elements)
                return -ENOSPC;
        if (elements_fit_in_base(fa))
                return 0;
@@ -343,6 +353,8 @@ int flex_array_shrink(struct flex_array *fa)
        int part_nr;
        int ret = 0;
 
+       if (!fa->total_nr_elements)
+               return 0;
        if (elements_fit_in_base(fa))
                return ret;
        for (part_nr = 0; part_nr < FLEX_ARRAY_NR_BASE_PTRS; part_nr++) {
index ea5fa4f..a6cdc96 100644 (file)
@@ -969,6 +969,9 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s,
                         */
                        tmp = b->in[b->in_pos++];
 
+                       if (tmp == 0x00)
+                               return XZ_STREAM_END;
+
                        if (tmp >= 0xE0 || tmp == 0x01) {
                                s->lzma2.need_props = true;
                                s->lzma2.need_dict_reset = false;
@@ -1001,9 +1004,6 @@ XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s,
                                                lzma_reset(s);
                                }
                        } else {
-                               if (tmp == 0x00)
-                                       return XZ_STREAM_END;
-
                                if (tmp > 0x02)
                                        return XZ_DATA_ERROR;
 
index 470dcda..83326ad 100644 (file)
@@ -1408,6 +1408,9 @@ out:
        return ret;
 }
 
+#define VM_NO_THP (VM_SPECIAL|VM_INSERTPAGE|VM_MIXEDMAP|VM_SAO| \
+                  VM_HUGETLB|VM_SHARED|VM_MAYSHARE)
+
 int hugepage_madvise(struct vm_area_struct *vma,
                     unsigned long *vm_flags, int advice)
 {
@@ -1416,11 +1419,7 @@ int hugepage_madvise(struct vm_area_struct *vma,
                /*
                 * Be somewhat over-protective like KSM for now!
                 */
-               if (*vm_flags & (VM_HUGEPAGE |
-                                VM_SHARED   | VM_MAYSHARE   |
-                                VM_PFNMAP   | VM_IO      | VM_DONTEXPAND |
-                                VM_RESERVED | VM_HUGETLB | VM_INSERTPAGE |
-                                VM_MIXEDMAP | VM_SAO))
+               if (*vm_flags & (VM_HUGEPAGE | VM_NO_THP))
                        return -EINVAL;
                *vm_flags &= ~VM_NOHUGEPAGE;
                *vm_flags |= VM_HUGEPAGE;
@@ -1436,11 +1435,7 @@ int hugepage_madvise(struct vm_area_struct *vma,
                /*
                 * Be somewhat over-protective like KSM for now!
                 */
-               if (*vm_flags & (VM_NOHUGEPAGE |
-                                VM_SHARED   | VM_MAYSHARE   |
-                                VM_PFNMAP   | VM_IO      | VM_DONTEXPAND |
-                                VM_RESERVED | VM_HUGETLB | VM_INSERTPAGE |
-                                VM_MIXEDMAP | VM_SAO))
+               if (*vm_flags & (VM_NOHUGEPAGE | VM_NO_THP))
                        return -EINVAL;
                *vm_flags &= ~VM_HUGEPAGE;
                *vm_flags |= VM_NOHUGEPAGE;
@@ -1574,10 +1569,14 @@ int khugepaged_enter_vma_merge(struct vm_area_struct *vma)
                 * page fault if needed.
                 */
                return 0;
-       if (vma->vm_file || vma->vm_ops)
+       if (vma->vm_ops)
                /* khugepaged not yet working on file or special mappings */
                return 0;
-       VM_BUG_ON(is_linear_pfn_mapping(vma) || is_pfn_mapping(vma));
+       /*
+        * If is_pfn_mapping() is true is_learn_pfn_mapping() must be
+        * true too, verify it here.
+        */
+       VM_BUG_ON(is_linear_pfn_mapping(vma) || vma->vm_flags & VM_NO_THP);
        hstart = (vma->vm_start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK;
        hend = vma->vm_end & HPAGE_PMD_MASK;
        if (hstart < hend)
@@ -1828,12 +1827,15 @@ static void collapse_huge_page(struct mm_struct *mm,
            (vma->vm_flags & VM_NOHUGEPAGE))
                goto out;
 
-       /* VM_PFNMAP vmas may have vm_ops null but vm_file set */
-       if (!vma->anon_vma || vma->vm_ops || vma->vm_file)
+       if (!vma->anon_vma || vma->vm_ops)
                goto out;
        if (is_vma_temporary_stack(vma))
                goto out;
-       VM_BUG_ON(is_linear_pfn_mapping(vma) || is_pfn_mapping(vma));
+       /*
+        * If is_pfn_mapping() is true is_learn_pfn_mapping() must be
+        * true too, verify it here.
+        */
+       VM_BUG_ON(is_linear_pfn_mapping(vma) || vma->vm_flags & VM_NO_THP);
 
        pgd = pgd_offset(mm, address);
        if (!pgd_present(*pgd))
@@ -2066,13 +2068,16 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages,
                        progress++;
                        continue;
                }
-               /* VM_PFNMAP vmas may have vm_ops null but vm_file set */
-               if (!vma->anon_vma || vma->vm_ops || vma->vm_file)
+               if (!vma->anon_vma || vma->vm_ops)
                        goto skip;
                if (is_vma_temporary_stack(vma))
                        goto skip;
-
-               VM_BUG_ON(is_linear_pfn_mapping(vma) || is_pfn_mapping(vma));
+               /*
+                * If is_pfn_mapping() is true is_learn_pfn_mapping()
+                * must be true too, verify it here.
+                */
+               VM_BUG_ON(is_linear_pfn_mapping(vma) ||
+                         vma->vm_flags & VM_NO_THP);
 
                hstart = (vma->vm_start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK;
                hend = vma->vm_end & HPAGE_PMD_MASK;
index ce22a25..27f4253 100644 (file)
@@ -1359,7 +1359,7 @@ split_fallthrough:
                 */
                mark_page_accessed(page);
        }
-       if (flags & FOLL_MLOCK) {
+       if ((flags & FOLL_MLOCK) && (vma->vm_flags & VM_LOCKED)) {
                /*
                 * The preliminary mapping check is mainly to avoid the
                 * pointless overhead of lock_page on the ZERO_PAGE
@@ -1552,10 +1552,9 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                }
 
                /*
-                * If we don't actually want the page itself,
-                * and it's the stack guard page, just skip it.
+                * For mlock, just skip the stack guard page.
                 */
-               if (!pages && stack_guard_page(vma, start))
+               if ((gup_flags & FOLL_MLOCK) && stack_guard_page(vma, start))
                        goto next_page;
 
                do {
@@ -3396,7 +3395,7 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma,
         * run pte_offset_map on the pmd, if an huge pmd could
         * materialize from under us from a different thread.
         */
-       if (unlikely(__pte_alloc(mm, vma, pmd, address)))
+       if (unlikely(pmd_none(*pmd)) && __pte_alloc(mm, vma, pmd, address))
                return VM_FAULT_OOM;
        /* if an huge pmd materialized from under us just retry later */
        if (unlikely(pmd_trans_huge(*pmd)))
index 6b55e3e..516b2c2 100644 (file)
@@ -162,7 +162,7 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma,
        VM_BUG_ON(end   > vma->vm_end);
        VM_BUG_ON(!rwsem_is_locked(&mm->mmap_sem));
 
-       gup_flags = FOLL_TOUCH;
+       gup_flags = FOLL_TOUCH | FOLL_MLOCK;
        /*
         * We want to touch writable mappings with a write fault in order
         * to break COW, except for shared mappings because these don't COW
@@ -178,9 +178,6 @@ static long __mlock_vma_pages_range(struct vm_area_struct *vma,
        if (vma->vm_flags & (VM_READ | VM_WRITE | VM_EXEC))
                gup_flags |= FOLL_FORCE;
 
-       if (vma->vm_flags & VM_LOCKED)
-               gup_flags |= FOLL_MLOCK;
-
        return __get_user_pages(current, mm, addr, nr_pages, gup_flags,
                                NULL, NULL, nonblocking);
 }
index 83fb72c..f52e85c 100644 (file)
@@ -172,10 +172,13 @@ unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem,
 
        /*
         * The baseline for the badness score is the proportion of RAM that each
-        * task's rss and swap space use.
+        * task's rss, pagetable and swap space use.
         */
-       points = (get_mm_rss(p->mm) + get_mm_counter(p->mm, MM_SWAPENTS)) * 1000 /
-                       totalpages;
+       points = get_mm_rss(p->mm) + p->mm->nr_ptes;
+       points += get_mm_counter(p->mm, MM_SWAPENTS);
+
+       points *= 1000;
+       points /= totalpages;
        task_unlock(p);
 
        /*
index 94d2a33..9d2e5e4 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1940,7 +1940,7 @@ redo:
                 * Since this is without lock semantics the protection is only against
                 * code executing on this cpu *not* from access by other cpus.
                 */
-               if (unlikely(!this_cpu_cmpxchg_double(
+               if (unlikely(!irqsafe_cpu_cmpxchg_double(
                                s->cpu_slab->freelist, s->cpu_slab->tid,
                                object, tid,
                                get_freepointer(s, object), next_tid(tid)))) {
@@ -2145,7 +2145,7 @@ redo:
                set_freepointer(s, object, c->freelist);
 
 #ifdef CONFIG_CMPXCHG_LOCAL
-               if (unlikely(!this_cpu_cmpxchg_double(
+               if (unlikely(!irqsafe_cpu_cmpxchg_double(
                                s->cpu_slab->freelist, s->cpu_slab->tid,
                                c->freelist, tid,
                                object, next_tid(tid)))) {
index c83f618..b5a8afc 100644 (file)
@@ -587,10 +587,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
        hci_req_cancel(hdev, ENODEV);
        hci_req_lock(hdev);
 
-       /* Stop timer, it might be running */
-       del_timer_sync(&hdev->cmd_timer);
-
        if (!test_and_clear_bit(HCI_UP, &hdev->flags)) {
+               del_timer_sync(&hdev->cmd_timer);
                hci_req_unlock(hdev);
                return 0;
        }
@@ -629,6 +627,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 
        /* Drop last sent command */
        if (hdev->sent_cmd) {
+               del_timer_sync(&hdev->cmd_timer);
                kfree_skb(hdev->sent_cmd);
                hdev->sent_cmd = NULL;
        }
index cebe758..b257015 100644 (file)
@@ -2387,8 +2387,6 @@ static inline void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *s
        if (!conn)
                goto unlock;
 
-       hci_conn_hold(conn);
-
        conn->remote_cap = ev->capability;
        conn->remote_oob = ev->oob_data;
        conn->remote_auth = ev->authentication;
index ca27f3a..2c8dd44 100644 (file)
@@ -1051,6 +1051,7 @@ static void l2cap_retransmit_one_frame(struct sock *sk, u8 tx_seq)
        tx_skb = skb_clone(skb, GFP_ATOMIC);
        bt_cb(skb)->retries++;
        control = get_unaligned_le16(tx_skb->data + L2CAP_HDR_SIZE);
+       control &= L2CAP_CTRL_SAR;
 
        if (pi->conn_state & L2CAP_CONN_SEND_FBIT) {
                control |= L2CAP_CTRL_FINAL;
index 42fdffd..94954c7 100644 (file)
@@ -369,6 +369,15 @@ static void __sco_sock_close(struct sock *sk)
 
        case BT_CONNECTED:
        case BT_CONFIG:
+               if (sco_pi(sk)->conn) {
+                       sk->sk_state = BT_DISCONN;
+                       sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
+                       hci_conn_put(sco_pi(sk)->conn->hcon);
+                       sco_pi(sk)->conn = NULL;
+               } else
+                       sco_chan_del(sk, ECONNRESET);
+               break;
+
        case BT_CONNECT:
        case BT_DISCONN:
                sco_chan_del(sk, ECONNRESET);
index e216079..0c7bada 100644 (file)
@@ -164,7 +164,7 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
                        goto drop;
 
                /* If STP is turned off, then forward */
-               if (p->br->stp_enabled == BR_NO_STP)
+               if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0)
                        goto forward;
 
                if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
index 57b1aed..8a6a05e 100644 (file)
@@ -1427,9 +1427,14 @@ static int bcm_init(struct sock *sk)
 static int bcm_release(struct socket *sock)
 {
        struct sock *sk = sock->sk;
-       struct bcm_sock *bo = bcm_sk(sk);
+       struct bcm_sock *bo;
        struct bcm_op *op, *next;
 
+       if (sk == NULL)
+               return 0;
+
+       bo = bcm_sk(sk);
+
        /* remove bcm_ops, timer, rx_unregister(), etc. */
 
        unregister_netdevice_notifier(&bo->notifier);
index 649acfa..0eb39a7 100644 (file)
@@ -305,7 +305,12 @@ static int raw_init(struct sock *sk)
 static int raw_release(struct socket *sock)
 {
        struct sock *sk = sock->sk;
-       struct raw_sock *ro = raw_sk(sk);
+       struct raw_sock *ro;
+
+       if (!sk)
+               return 0;
+
+       ro = raw_sk(sk);
 
        unregister_netdevice_notifier(&ro->notifier);
 
index 05f3578..e15a82c 100644 (file)
@@ -2267,6 +2267,19 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags)
        m->more_to_follow = false;
        m->pool = NULL;
 
+       /* middle */
+       m->middle = NULL;
+
+       /* data */
+       m->nr_pages = 0;
+       m->page_alignment = 0;
+       m->pages = NULL;
+       m->pagelist = NULL;
+       m->bio = NULL;
+       m->bio_iter = NULL;
+       m->bio_seg = 0;
+       m->trail = NULL;
+
        /* front */
        if (front_len) {
                if (front_len > PAGE_CACHE_SIZE) {
@@ -2286,19 +2299,6 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags)
        }
        m->front.iov_len = front_len;
 
-       /* middle */
-       m->middle = NULL;
-
-       /* data */
-       m->nr_pages = 0;
-       m->page_alignment = 0;
-       m->pages = NULL;
-       m->pagelist = NULL;
-       m->bio = NULL;
-       m->bio_iter = NULL;
-       m->bio_seg = 0;
-       m->trail = NULL;
-
        dout("ceph_msg_new %p front %d\n", m, front_len);
        return m;
 
index 5a80f41..6b5dda1 100644 (file)
@@ -470,8 +470,8 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
                                         snapc, ops,
                                         use_mempool,
                                         GFP_NOFS, NULL, NULL);
-       if (IS_ERR(req))
-               return req;
+       if (!req)
+               return NULL;
 
        /* calculate max write size */
        calc_layout(osdc, vino, layout, off, plen, req, ops);
index c2ac599..856b6ee 100644 (file)
@@ -4773,7 +4773,7 @@ static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cm
                 * is never reached
                 */
                WARN_ON(1);
-               err = -EINVAL;
+               err = -ENOTTY;
                break;
 
        }
@@ -5041,7 +5041,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
                /* Set the per device memory buffer space.
                 * Not applicable in our case */
        case SIOCSIFLINK:
-               return -EINVAL;
+               return -ENOTTY;
 
        /*
         *      Unknown or private ioctl.
@@ -5062,7 +5062,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
                /* Take care of Wireless Extensions */
                if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST)
                        return wext_handle_ioctl(net, &ifr, cmd, arg);
-               return -EINVAL;
+               return -ENOTTY;
        }
 }
 
index 87bb5f4..c53ded2 100644 (file)
@@ -41,12 +41,12 @@ config NET_DSA_MV88E6XXX_NEED_PPU
        default n
 
 config NET_DSA_MV88E6131
-       bool "Marvell 88E6095/6095F/6131 ethernet switch chip support"
+       bool "Marvell 88E6085/6095/6095F/6131 ethernet switch chip support"
        select NET_DSA_MV88E6XXX
        select NET_DSA_MV88E6XXX_NEED_PPU
        select NET_DSA_TAG_DSA
        ---help---
-         This enables support for the Marvell 88E6095/6095F/6131
+         This enables support for the Marvell 88E6085/6095/6095F/6131
          ethernet switch chips.
 
 config NET_DSA_MV88E6123_61_65
index 3da4188..45f7411 100644 (file)
@@ -207,8 +207,15 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p)
         * mode, but do not enable forwarding of unknown unicasts.
         */
        val = 0x0433;
-       if (p == dsa_upstream_port(ds))
+       if (p == dsa_upstream_port(ds)) {
                val |= 0x0104;
+               /*
+                * On 6085, unknown multicast forward is controlled
+                * here rather than in Port Control 2 register.
+                */
+               if (ps->id == ID_6085)
+                       val |= 0x0008;
+       }
        if (ds->dsa_port_mask & (1 << p))
                val |= 0x0100;
        REG_WRITE(addr, 0x04, val);
@@ -251,10 +258,19 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p)
         * If this is the upstream port for this switch, enable
         * forwarding of unknown multicast addresses.
         */
-       val = 0x0080 | dsa_upstream_port(ds);
-       if (p == dsa_upstream_port(ds))
-               val |= 0x0040;
-       REG_WRITE(addr, 0x08, val);
+       if (ps->id == ID_6085)
+               /*
+                * on 6085, bits 3:0 are reserved, bit 6 control ARP
+                * mirroring, and multicast forward is handled in
+                * Port Control register.
+                */
+               REG_WRITE(addr, 0x08, 0x0080);
+       else {
+               val = 0x0080 | dsa_upstream_port(ds);
+               if (p == dsa_upstream_port(ds))
+                       val |= 0x0040;
+               REG_WRITE(addr, 0x08, val);
+       }
 
        /*
         * Rate Control: disable ingress rate limiting.
index 5345b0b..cd9ca08 100644 (file)
@@ -1680,7 +1680,7 @@ static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf)
                return;
 
        cnf->sysctl = NULL;
-       unregister_sysctl_table(t->sysctl_header);
+       unregister_net_sysctl_table(t->sysctl_header);
        kfree(t->dev_name);
        kfree(t);
 }
index e9013d6..5fe9b8b 100644 (file)
@@ -1978,9 +1978,6 @@ struct fib_table *fib_trie_table(u32 id)
        t = (struct trie *) tb->tb_data;
        memset(t, 0, sizeof(*t));
 
-       if (id == RT_TABLE_LOCAL)
-               pr_info("IPv4 FIB: Using LC-trie version %s\n", VERSION);
-
        return tb;
 }
 
index c1acf69..99e6e4b 100644 (file)
@@ -2690,6 +2690,12 @@ static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
 }
 
+static u32 *ipv4_rt_blackhole_cow_metrics(struct dst_entry *dst,
+                                         unsigned long old)
+{
+       return NULL;
+}
+
 static struct dst_ops ipv4_dst_blackhole_ops = {
        .family                 =       AF_INET,
        .protocol               =       cpu_to_be16(ETH_P_IP),
@@ -2698,6 +2704,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
        .default_mtu            =       ipv4_blackhole_default_mtu,
        .default_advmss         =       ipv4_default_advmss,
        .update_pmtu            =       ipv4_rt_blackhole_update_pmtu,
+       .cow_metrics            =       ipv4_rt_blackhole_cow_metrics,
 };
 
 struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig)
index 1493534..a7bda07 100644 (file)
@@ -4537,7 +4537,7 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p)
 
        t = p->sysctl;
        p->sysctl = NULL;
-       unregister_sysctl_table(t->sysctl_header);
+       unregister_net_sysctl_table(t->sysctl_header);
        kfree(t->dev_name);
        kfree(t);
 }
index 5aa8ec8..59dccfb 100644 (file)
@@ -371,7 +371,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
        iv = esp_tmp_iv(aead, tmp, seqhilen);
        req = esp_tmp_req(aead, iv);
        asg = esp_req_sg(aead, req);
-       sg = asg + 1;
+       sg = asg + sglists;
 
        skb->ip_summed = CHECKSUM_NONE;
 
index 843406f..fd0eec6 100644 (file)
@@ -153,6 +153,12 @@ static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
 {
 }
 
+static u32 *ip6_rt_blackhole_cow_metrics(struct dst_entry *dst,
+                                        unsigned long old)
+{
+       return NULL;
+}
+
 static struct dst_ops ip6_dst_blackhole_ops = {
        .family                 =       AF_INET6,
        .protocol               =       cpu_to_be16(ETH_P_IPV6),
@@ -161,6 +167,7 @@ static struct dst_ops ip6_dst_blackhole_ops = {
        .default_mtu            =       ip6_blackhole_default_mtu,
        .default_advmss         =       ip6_default_advmss,
        .update_pmtu            =       ip6_rt_blackhole_update_pmtu,
+       .cow_metrics            =       ip6_rt_blackhole_cow_metrics,
 };
 
 static const u32 ip6_template_metrics[RTAX_MAX] = {
@@ -2012,7 +2019,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
        rt->dst.output = ip6_output;
        rt->rt6i_dev = net->loopback_dev;
        rt->rt6i_idev = idev;
-       dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1);
        rt->dst.obsolete = -1;
 
        rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
index 15c3774..9e305d7 100644 (file)
@@ -1335,7 +1335,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features)
        skb->ip_summed = CHECKSUM_NONE;
 
        /* Check if there is enough headroom to insert fragment header. */
-       if ((skb_headroom(skb) < frag_hdr_sz) &&
+       if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) &&
            pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC))
                goto out;
 
index fce9bd3..5c04f3e 100644 (file)
@@ -667,7 +667,7 @@ MODULE_AUTHOR("James Chapman <jchapman@katalix.com>");
 MODULE_DESCRIPTION("L2TP over IP");
 MODULE_VERSION("1.0");
 
-/* Use the value of SOCK_DGRAM (2) directory, because __stringify does't like
+/* Use the value of SOCK_DGRAM (2) directory, because __stringify doesn't like
  * enums
  */
 MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 2, IPPROTO_L2TP);
index 3342135..4404973 100644 (file)
@@ -1504,6 +1504,8 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
        enum ieee80211_smps_mode old_req;
        int err;
 
+       lockdep_assert_held(&sdata->u.mgd.mtx);
+
        old_req = sdata->u.mgd.req_smps;
        sdata->u.mgd.req_smps = smps_mode;
 
index dacace6..9ea7c0d 100644 (file)
@@ -177,9 +177,9 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
        if (sdata->vif.type != NL80211_IFTYPE_STATION)
                return -EOPNOTSUPP;
 
-       mutex_lock(&local->iflist_mtx);
+       mutex_lock(&sdata->u.mgd.mtx);
        err = __ieee80211_request_smps(sdata, smps_mode);
-       mutex_unlock(&local->iflist_mtx);
+       mutex_unlock(&sdata->u.mgd.mtx);
 
        return err;
 }
index dff27d5..61b1f5a 100644 (file)
@@ -554,7 +554,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed(
        memcpy(&ssf->ssf_info, &chunk->sinfo, sizeof(struct sctp_sndrcvinfo));
 
        /* Per TSVWG discussion with Randy. Allow the application to
-        * resemble a fragmented message.
+        * reassemble a fragmented message.
         */
        ssf->ssf_info.sinfo_flags = chunk->chunk_hdr->flags;
 
index 8873fd8..b2198e6 100644 (file)
@@ -18,14 +18,13 @@ config SUNRPC_XPRT_RDMA
          If unsure, say N.
 
 config RPCSEC_GSS_KRB5
-       tristate
+       tristate "Secure RPC: Kerberos V mechanism"
        depends on SUNRPC && CRYPTO
-       prompt "Secure RPC: Kerberos V mechanism" if !(NFS_V4 || NFSD_V4)
+       depends on CRYPTO_MD5 && CRYPTO_DES && CRYPTO_CBC && CRYPTO_CTS
+       depends on CRYPTO_ECB && CRYPTO_HMAC && CRYPTO_SHA1 && CRYPTO_AES
+       depends on CRYPTO_ARC4
        default y
        select SUNRPC_GSS
-       select CRYPTO_MD5
-       select CRYPTO_DES
-       select CRYPTO_CBC
        help
          Choose Y here to enable Secure RPC using the Kerberos version 5
          GSS-API mechanism (RFC 1964).
index f3914d0..339ba64 100644 (file)
@@ -520,7 +520,7 @@ gss_refresh_upcall(struct rpc_task *task)
                warn_gssd();
                task->tk_timeout = 15*HZ;
                rpc_sleep_on(&pipe_version_rpc_waitqueue, task, NULL);
-               return 0;
+               return -EAGAIN;
        }
        if (IS_ERR(gss_msg)) {
                err = PTR_ERR(gss_msg);
@@ -563,10 +563,12 @@ retry:
        if (PTR_ERR(gss_msg) == -EAGAIN) {
                err = wait_event_interruptible_timeout(pipe_version_waitqueue,
                                pipe_version >= 0, 15*HZ);
+               if (pipe_version < 0) {
+                       warn_gssd();
+                       err = -EACCES;
+               }
                if (err)
                        goto out;
-               if (pipe_version < 0)
-                       warn_gssd();
                goto retry;
        }
        if (IS_ERR(gss_msg)) {
index e7a96e4..8d83f9d 100644 (file)
@@ -1508,7 +1508,10 @@ call_timeout(struct rpc_task *task)
                if (clnt->cl_chatty)
                        printk(KERN_NOTICE "%s: server %s not responding, timed out\n",
                                clnt->cl_protname, clnt->cl_server);
-               rpc_exit(task, -EIO);
+               if (task->tk_flags & RPC_TASK_TIMEOUT)
+                       rpc_exit(task, -ETIMEDOUT);
+               else
+                       rpc_exit(task, -EIO);
                return;
        }
 
index 9494c37..ce5eb68 100644 (file)
@@ -906,6 +906,7 @@ void xprt_transmit(struct rpc_task *task)
        }
 
        dprintk("RPC: %5u xmit complete\n", task->tk_pid);
+       task->tk_flags |= RPC_TASK_SENT;
        spin_lock_bh(&xprt->transport_lock);
 
        xprt->ops->set_retrans_timeout(task);
index 3a43a83..b1d75be 100644 (file)
@@ -524,6 +524,8 @@ static int unix_dgram_connect(struct socket *, struct sockaddr *,
                              int, int);
 static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
                                  struct msghdr *, size_t);
+static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *,
+                                 struct msghdr *, size_t, int);
 
 static const struct proto_ops unix_stream_ops = {
        .family =       PF_UNIX,
@@ -583,7 +585,7 @@ static const struct proto_ops unix_seqpacket_ops = {
        .setsockopt =   sock_no_setsockopt,
        .getsockopt =   sock_no_getsockopt,
        .sendmsg =      unix_seqpacket_sendmsg,
-       .recvmsg =      unix_dgram_recvmsg,
+       .recvmsg =      unix_seqpacket_recvmsg,
        .mmap =         sock_no_mmap,
        .sendpage =     sock_no_sendpage,
 };
@@ -1699,6 +1701,18 @@ static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock,
        return unix_dgram_sendmsg(kiocb, sock, msg, len);
 }
 
+static int unix_seqpacket_recvmsg(struct kiocb *iocb, struct socket *sock,
+                             struct msghdr *msg, size_t size,
+                             int flags)
+{
+       struct sock *sk = sock->sk;
+
+       if (sk->sk_state != TCP_ESTABLISHED)
+               return -ENOTCONN;
+
+       return unix_dgram_recvmsg(iocb, sock, msg, size, flags);
+}
+
 static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
 {
        struct unix_sock *u = unix_sk(sk);
index f218385..e8a7814 100644 (file)
@@ -532,7 +532,7 @@ int xfrm_init_replay(struct xfrm_state *x)
 
        if (replay_esn) {
                if (replay_esn->replay_window >
-                   replay_esn->bmp_len * sizeof(__u32))
+                   replay_esn->bmp_len * sizeof(__u32) * 8)
                        return -EINVAL;
 
        if ((x->props.flags & XFRM_STATE_ESN) && x->replay_esn)
index 5d1d60d..c658cb3 100644 (file)
@@ -124,6 +124,9 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
 {
        struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL];
 
+       if ((p->flags & XFRM_STATE_ESN) && !rt)
+               return -EINVAL;
+
        if (!rt)
                return 0;
 
index 659326c..006ad81 100644 (file)
@@ -332,7 +332,7 @@ static int conf_choice(struct menu *menu)
                }
                if (!child)
                        continue;
-               if (line[strlen(line) - 1] == '?') {
+               if (line[0] && line[strlen(line) - 1] == '?') {
                        print_help(child);
                        continue;
                }
index 9da6420..1d027e2 100644 (file)
@@ -471,6 +471,7 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
  * @avd: access vector decisions
  * @result: result from avc_has_perm_noaudit
  * @a:  auxiliary audit data
+ * @flags: VFS walk flags
  *
  * Audit the granting or denial of permissions in accordance
  * with the policy.  This function is typically called by
@@ -481,9 +482,10 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
  * be performed under a lock, to allow the lock to be released
  * before calling the auditing code.
  */
-void avc_audit(u32 ssid, u32 tsid,
+int avc_audit(u32 ssid, u32 tsid,
               u16 tclass, u32 requested,
-              struct av_decision *avd, int result, struct common_audit_data *a)
+              struct av_decision *avd, int result, struct common_audit_data *a,
+              unsigned flags)
 {
        struct common_audit_data stack_data;
        u32 denied, audited;
@@ -515,11 +517,24 @@ void avc_audit(u32 ssid, u32 tsid,
        else
                audited = requested & avd->auditallow;
        if (!audited)
-               return;
+               return 0;
+
        if (!a) {
                a = &stack_data;
                COMMON_AUDIT_DATA_INIT(a, NONE);
        }
+
+       /*
+        * When in a RCU walk do the audit on the RCU retry.  This is because
+        * the collection of the dname in an inode audit message is not RCU
+        * safe.  Note this may drop some audits when the situation changes
+        * during retry. However this is logically just as if the operation
+        * happened a little later.
+        */
+       if ((a->type == LSM_AUDIT_DATA_FS) &&
+           (flags & IPERM_FLAG_RCU))
+               return -ECHILD;
+
        a->selinux_audit_data.tclass = tclass;
        a->selinux_audit_data.requested = requested;
        a->selinux_audit_data.ssid = ssid;
@@ -529,6 +544,7 @@ void avc_audit(u32 ssid, u32 tsid,
        a->lsm_pre_audit = avc_audit_pre_callback;
        a->lsm_post_audit = avc_audit_post_callback;
        common_lsm_audit(a);
+       return 0;
 }
 
 /**
@@ -793,6 +809,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
  * @tclass: target security class
  * @requested: requested permissions, interpreted based on @tclass
  * @auditdata: auxiliary audit data
+ * @flags: VFS walk flags
  *
  * Check the AVC to determine whether the @requested permissions are granted
  * for the SID pair (@ssid, @tsid), interpreting the permissions
@@ -802,14 +819,19 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
  * permissions are granted, -%EACCES if any permissions are denied, or
  * another -errno upon other errors.
  */
-int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
-                u32 requested, struct common_audit_data *auditdata)
+int avc_has_perm_flags(u32 ssid, u32 tsid, u16 tclass,
+                      u32 requested, struct common_audit_data *auditdata,
+                      unsigned flags)
 {
        struct av_decision avd;
-       int rc;
+       int rc, rc2;
 
        rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd);
-       avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
+
+       rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata,
+                       flags);
+       if (rc2)
+               return rc2;
        return rc;
 }
 
index a73f4e4..8fb2488 100644 (file)
@@ -1446,8 +1446,11 @@ static int task_has_capability(struct task_struct *tsk,
        }
 
        rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
-       if (audit == SECURITY_CAP_AUDIT)
-               avc_audit(sid, sid, sclass, av, &avd, rc, &ad);
+       if (audit == SECURITY_CAP_AUDIT) {
+               int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0);
+               if (rc2)
+                       return rc2;
+       }
        return rc;
 }
 
@@ -1467,7 +1470,8 @@ static int task_has_system(struct task_struct *tsk,
 static int inode_has_perm(const struct cred *cred,
                          struct inode *inode,
                          u32 perms,
-                         struct common_audit_data *adp)
+                         struct common_audit_data *adp,
+                         unsigned flags)
 {
        struct inode_security_struct *isec;
        struct common_audit_data ad;
@@ -1487,7 +1491,7 @@ static int inode_has_perm(const struct cred *cred,
                ad.u.fs.inode = inode;
        }
 
-       return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp);
+       return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
 }
 
 /* Same as inode_has_perm, but pass explicit audit data containing
@@ -1504,7 +1508,7 @@ static inline int dentry_has_perm(const struct cred *cred,
        COMMON_AUDIT_DATA_INIT(&ad, FS);
        ad.u.fs.path.mnt = mnt;
        ad.u.fs.path.dentry = dentry;
-       return inode_has_perm(cred, inode, av, &ad);
+       return inode_has_perm(cred, inode, av, &ad, 0);
 }
 
 /* Check whether a task can use an open file descriptor to
@@ -1540,7 +1544,7 @@ static int file_has_perm(const struct cred *cred,
        /* av is zero if only checking access to the descriptor. */
        rc = 0;
        if (av)
-               rc = inode_has_perm(cred, inode, av, &ad);
+               rc = inode_has_perm(cred, inode, av, &ad, 0);
 
 out:
        return rc;
@@ -1574,7 +1578,8 @@ static int may_create(struct inode *dir,
                return rc;
 
        if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
-               rc = security_transition_sid(sid, dsec->sid, tclass, NULL, &newsid);
+               rc = security_transition_sid(sid, dsec->sid, tclass,
+                                            &dentry->d_name, &newsid);
                if (rc)
                        return rc;
        }
@@ -2103,7 +2108,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
                        file = file_priv->file;
                        inode = file->f_path.dentry->d_inode;
                        if (inode_has_perm(cred, inode,
-                                          FILE__READ | FILE__WRITE, NULL)) {
+                                          FILE__READ | FILE__WRITE, NULL, 0)) {
                                drop_tty = 1;
                        }
                }
@@ -2649,10 +2654,6 @@ static int selinux_inode_permission(struct inode *inode, int mask, unsigned flag
        if (!mask)
                return 0;
 
-       /* May be droppable after audit */
-       if (flags & IPERM_FLAG_RCU)
-               return -ECHILD;
-
        COMMON_AUDIT_DATA_INIT(&ad, FS);
        ad.u.fs.inode = inode;
 
@@ -2661,7 +2662,7 @@ static int selinux_inode_permission(struct inode *inode, int mask, unsigned flag
 
        perms = file_mask_to_av(inode->i_mode, mask);
 
-       return inode_has_perm(cred, inode, perms, &ad);
+       return inode_has_perm(cred, inode, perms, &ad, flags);
 }
 
 static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
@@ -3209,7 +3210,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred)
         * new inode label or new policy.
         * This check is not redundant - do not remove.
         */
-       return inode_has_perm(cred, inode, open_file_to_av(file), NULL);
+       return inode_has_perm(cred, inode, open_file_to_av(file), NULL, 0);
 }
 
 /* task security operations */
index 5615081..e77b2ac 100644 (file)
@@ -54,11 +54,11 @@ struct avc_cache_stats {
 
 void __init avc_init(void);
 
-void avc_audit(u32 ssid, u32 tsid,
+int avc_audit(u32 ssid, u32 tsid,
               u16 tclass, u32 requested,
               struct av_decision *avd,
               int result,
-              struct common_audit_data *a);
+             struct common_audit_data *a, unsigned flags);
 
 #define AVC_STRICT 1 /* Ignore permissive mode. */
 int avc_has_perm_noaudit(u32 ssid, u32 tsid,
@@ -66,9 +66,17 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
                         unsigned flags,
                         struct av_decision *avd);
 
-int avc_has_perm(u32 ssid, u32 tsid,
-                u16 tclass, u32 requested,
-                struct common_audit_data *auditdata);
+int avc_has_perm_flags(u32 ssid, u32 tsid,
+                      u16 tclass, u32 requested,
+                      struct common_audit_data *auditdata,
+                      unsigned);
+
+static inline int avc_has_perm(u32 ssid, u32 tsid,
+                              u16 tclass, u32 requested,
+                              struct common_audit_data *auditdata)
+{
+       return avc_has_perm_flags(ssid, tsid, tclass, requested, auditdata, 0);
+}
 
 u32 avc_policy_seqno(void);
 
index e7b850a..e6e7ce0 100644 (file)
@@ -502,7 +502,7 @@ static int policydb_index(struct policydb *p)
                goto out;
 
        rc = flex_array_prealloc(p->type_val_to_struct_array, 0,
-                                p->p_types.nprim - 1, GFP_KERNEL | __GFP_ZERO);
+                                p->p_types.nprim, GFP_KERNEL | __GFP_ZERO);
        if (rc)
                goto out;
 
@@ -519,7 +519,7 @@ static int policydb_index(struct policydb *p)
                        goto out;
 
                rc = flex_array_prealloc(p->sym_val_to_name[i],
-                                        0, p->symtab[i].nprim - 1,
+                                        0, p->symtab[i].nprim,
                                         GFP_KERNEL | __GFP_ZERO);
                if (rc)
                        goto out;
@@ -2375,7 +2375,7 @@ int policydb_read(struct policydb *p, void *fp)
                goto bad;
 
        /* preallocate so we don't have to worry about the put ever failing */
-       rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim - 1,
+       rc = flex_array_prealloc(p->type_attr_map_array, 0, p->p_types.nprim,
                                 GFP_KERNEL | __GFP_ZERO);
        if (rc)
                goto bad;
index 58804c7..fd2188c 100644 (file)
@@ -170,7 +170,7 @@ static void tas_set_volume(struct tas *tas)
        /* analysing the volume and mixer tables shows
         * that they are similar enough when we shift
         * the mixer table down by 4 bits. The error
-        * is minuscule, in just one item the error
+        * is miniscule, in just one item the error
         * is 1, at a value of 0x07f17b (mixer table
         * value is 0x07f17a) */
        tmp = tas_gaintable[left];
index 33f0ba5..62e9591 100644 (file)
@@ -44,10 +44,10 @@ static struct snd_pcm_hardware snd_vortex_playback_hw_adb = {
        .channels_min = 1,
        .channels_max = 2,
        .buffer_bytes_max = 0x10000,
-       .period_bytes_min = 0x1,
+       .period_bytes_min = 0x20,
        .period_bytes_max = 0x1000,
        .periods_min = 2,
-       .periods_max = 32,
+       .periods_max = 1024,
 };
 
 #ifndef CHIP_AU8820
@@ -140,6 +140,9 @@ static int snd_vortex_pcm_open(struct snd_pcm_substream *substream)
                                        SNDRV_PCM_HW_PARAM_PERIOD_BYTES)) < 0)
                return err;
 
+       snd_pcm_hw_constraint_step(runtime, 0,
+                                       SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 64);
+
        if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
 #ifndef CHIP_AU8820
                if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_A3D) {
index d3bd2c1..c82979a 100644 (file)
@@ -1704,11 +1704,11 @@ static void alc_apply_fixup(struct hda_codec *codec, int action)
                                   codec->chip_name, fix->type);
                        break;
                }
-               if (!fix[id].chained)
+               if (!fix->chained)
                        break;
                if (++depth > 10)
                        break;
-               id = fix[id].chain_id;
+               id = fix->chain_id;
        }
 }
 
@@ -5645,6 +5645,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids,
 static struct snd_pci_quirk beep_white_list[] = {
        SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1),
        SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
+       SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
        SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
        {}
 };
@@ -9863,6 +9864,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = {
        SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
        SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
        SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
+       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
 
        SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
        SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
@@ -10699,7 +10701,6 @@ enum {
        PINFIX_LENOVO_Y530,
        PINFIX_PB_M5210,
        PINFIX_ACER_ASPIRE_7736,
-       PINFIX_GIGABYTE_880GM,
 };
 
 static const struct alc_fixup alc882_fixups[] = {
@@ -10731,13 +10732,6 @@ static const struct alc_fixup alc882_fixups[] = {
                .type = ALC_FIXUP_SKU,
                .v.sku = ALC_FIXUP_SKU_IGNORE,
        },
-       [PINFIX_GIGABYTE_880GM] = {
-               .type = ALC_FIXUP_PINS,
-               .v.pins = (const struct alc_pincfg[]) {
-                       { 0x14, 0x1114410 }, /* set as speaker */
-                       { }
-               }
-       },
 };
 
 static struct snd_pci_quirk alc882_fixup_tbl[] = {
@@ -10745,7 +10739,6 @@ static struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
        SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
        SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
-       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte", PINFIX_GIGABYTE_880GM),
        {}
 };
 
@@ -18805,6 +18798,8 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
                      ALC662_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO),
        SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
+       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
+                     ALC662_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13),
        SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
        SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA),
@@ -19478,7 +19473,7 @@ enum {
        ALC662_FIXUP_IDEAPAD,
        ALC272_FIXUP_MARIO,
        ALC662_FIXUP_CZC_P10T,
-       ALC662_FIXUP_GIGABYTE,
+       ALC662_FIXUP_SKU_IGNORE,
 };
 
 static const struct alc_fixup alc662_fixups[] = {
@@ -19507,20 +19502,17 @@ static const struct alc_fixup alc662_fixups[] = {
                        {}
                }
        },
-       [ALC662_FIXUP_GIGABYTE] = {
-               .type = ALC_FIXUP_PINS,
-               .v.pins = (const struct alc_pincfg[]) {
-                       { 0x14, 0x1114410 }, /* set as speaker */
-                       { }
-               }
+       [ALC662_FIXUP_SKU_IGNORE] = {
+               .type = ALC_FIXUP_SKU,
+               .v.sku = ALC_FIXUP_SKU_IGNORE,
        },
 };
 
 static struct snd_pci_quirk alc662_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
+       SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
        SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
-       SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte", ALC662_FIXUP_GIGABYTE),
        SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
        SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
        SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
index 1371b57..0997031 100644 (file)
@@ -1292,14 +1292,18 @@ static void notify_aa_path_ctls(struct hda_codec *codec)
 {
        int i;
        struct snd_ctl_elem_id id;
-       const char *labels[] = {"Mic", "Front Mic", "Line"};
+       const char *labels[] = {"Mic", "Front Mic", "Line", "Rear Mic"};
+       struct snd_kcontrol *ctl;
 
        memset(&id, 0, sizeof(id));
        id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
        for (i = 0; i < ARRAY_SIZE(labels); i++) {
                sprintf(id.name, "%s Playback Volume", labels[i]);
-               snd_ctl_notify(codec->bus->card, SNDRV_CTL_EVENT_MASK_VALUE,
-                              &id);
+               ctl = snd_hda_find_mixer_ctl(codec, id.name);
+               if (ctl)
+                       snd_ctl_notify(codec->bus->card,
+                                       SNDRV_CTL_EVENT_MASK_VALUE,
+                                       &ctl->id);
        }
 }
 
index 5b792d2..f079b5e 100644 (file)
@@ -176,9 +176,11 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof
                        if (!rate)
                                continue;
                        /* C-Media CM6501 mislabels its 96 kHz altsetting */
+                       /* Terratec Aureon 7.1 USB C-Media 6206, too */
                        if (rate == 48000 && nr_rates == 1 &&
                            (chip->usb_id == USB_ID(0x0d8c, 0x0201) ||
-                            chip->usb_id == USB_ID(0x0d8c, 0x0102)) &&
+                            chip->usb_id == USB_ID(0x0d8c, 0x0102) ||
+                            chip->usb_id == USB_ID(0x0ccd, 0x00b1)) &&
                            fp->altsetting == 5 && fp->maxpacksize == 392)
                                rate = 96000;
                        /* Creative VF0470 Live Cam reports 16 kHz instead of 8kHz */
index ec07e62..1b94ec3 100644 (file)
@@ -533,6 +533,7 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
 
        case USB_ID(0x0d8c, 0x0102):
                /* C-Media CM6206 / CM106-Like Sound Device */
+       case USB_ID(0x0ccd, 0x00b1): /* Terratec Aureon 7.1 USB */
                return snd_usb_cm6206_boot_quirk(dev);
 
        case USB_ID(0x133e, 0x0815):