commit:     91c4c3bf6705fa7a7c134cdc3ee029025e41b7db
Author:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
AuthorDate: Thu Mar 10 00:47:52 2016 +0000
Commit:     Mike Pagano <mpagano <AT> gentoo <DOT> org>
CommitDate: Thu Mar 10 00:47:52 2016 +0000
URL:        https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=91c4c3bf

Linux patch 3.10.100

 0000_README               |    4 +
 1099_linux-3.10.100.patch | 1156 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1160 insertions(+)

diff --git a/0000_README b/0000_README
index 44fb3ac..bdc1498 100644
--- a/0000_README
+++ b/0000_README
@@ -438,6 +438,10 @@ Patch:  1098_linux-3.10.99.patch
 From:   http://www.kernel.org
 Desc:   Linux 3.10.99
 
+Patch:  1099_linux-3.10.100.patch
+From:   http://www.kernel.org
+Desc:   Linux 3.10.100
+
 Patch:  1500_XATTR_USER_PREFIX.patch
 From:   https://bugs.gentoo.org/show_bug.cgi?id=470644
 Desc:   Support for namespace user.pax.* on tmpfs.

diff --git a/1099_linux-3.10.100.patch b/1099_linux-3.10.100.patch
new file mode 100644
index 0000000..da39546
--- /dev/null
+++ b/1099_linux-3.10.100.patch
@@ -0,0 +1,1156 @@
+diff --git a/Makefile b/Makefile
+index f1e6491fd7d8..40d4d3bf52c3 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,6 +1,6 @@
+ VERSION = 3
+ PATCHLEVEL = 10
+-SUBLEVEL = 99
++SUBLEVEL = 100
+ EXTRAVERSION =
+ NAME = TOSSUG Baby Fish
+ 
+diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
+index c9305ef1d411..e73982b93537 100644
+--- a/arch/x86/ia32/ia32entry.S
++++ b/arch/x86/ia32/ia32entry.S
+@@ -422,6 +422,7 @@ ENTRY(ia32_syscall)
+       /*CFI_REL_OFFSET        cs,CS-RIP*/
+       CFI_REL_OFFSET  rip,RIP-RIP
+       PARAVIRT_ADJUST_EXCEPTION_FRAME
++      ASM_CLAC                        /* Do this early to minimize exposure */
+       SWAPGS
+       /*
+        * No need to follow this irqs on/off section: the syscall
+diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
+index ec94e11807dc..ca0805633f26 100644
+--- a/arch/x86/kernel/acpi/sleep.c
++++ b/arch/x86/kernel/acpi/sleep.c
+@@ -16,6 +16,7 @@
+ #include <asm/cacheflush.h>
+ #include <asm/realmode.h>
+ 
++#include <linux/ftrace.h>
+ #include "../../realmode/rm/wakeup.h"
+ #include "sleep.h"
+ 
+@@ -96,7 +97,13 @@ int acpi_suspend_lowlevel(void)
+        saved_magic = 0x123456789abcdef0L;
+ #endif /* CONFIG_64BIT */
+ 
++      /*
++       * Pause/unpause graph tracing around do_suspend_lowlevel as it has
++       * inconsistent call/return info after it jumps to the wakeup vector.
++       */
++      pause_graph_tracing();
+       do_suspend_lowlevel();
++      unpause_graph_tracing();
+       return 0;
+ }
+ 
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index 04e7db668362..f3f0801a0e81 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -673,19 +673,18 @@ static int ata_ioc32(struct ata_port *ap)
+ int ata_sas_scsi_ioctl(struct ata_port *ap, struct scsi_device *scsidev,
+                    int cmd, void __user *arg)
+ {
+-      int val = -EINVAL, rc = -EINVAL;
++      unsigned long val;
++      int rc = -EINVAL;
+       unsigned long flags;
+ 
+       switch (cmd) {
+-      case ATA_IOC_GET_IO32:
++      case HDIO_GET_32BIT:
+               spin_lock_irqsave(ap->lock, flags);
+               val = ata_ioc32(ap);
+               spin_unlock_irqrestore(ap->lock, flags);
+-              if (copy_to_user(arg, &val, 1))
+-                      return -EFAULT;
+-              return 0;
++              return put_user(val, (unsigned long __user *)arg);
+ 
+-      case ATA_IOC_SET_IO32:
++      case HDIO_SET_32BIT:
+               val = (unsigned long) arg;
+               rc = 0;
+               spin_lock_irqsave(ap->lock, flags);
+diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
+index 88cd940ece63..453c816b4537 100644
+--- a/drivers/edac/edac_mc_sysfs.c
++++ b/drivers/edac/edac_mc_sysfs.c
+@@ -973,21 +973,26 @@ nomem:
+  */
+ int edac_create_sysfs_mci_device(struct mem_ctl_info *mci)
+ {
++      char *name;
+       int i, err;
+ 
+       /*
+        * The memory controller needs its own bus, in order to avoid
+        * namespace conflicts at /sys/bus/edac.
+        */
+-      mci->bus->name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx);
+-      if (!mci->bus->name)
++      name = kasprintf(GFP_KERNEL, "mc%d", mci->mc_idx);
++      if (!name)
+               return -ENOMEM;
+ 
++      mci->bus->name = name;
++
+       edac_dbg(0, "creating bus %s\n", mci->bus->name);
+ 
+       err = bus_register(mci->bus);
+-      if (err < 0)
++      if (err < 0) {
++              kfree(name);
+               return err;
++      }
+ 
+       /* get the /sys/devices/system/edac subsys reference */
+       mci->dev.type = &mci_attr_type;
+@@ -1071,7 +1076,8 @@ fail:
+ fail2:
+       device_unregister(&mci->dev);
+       bus_unregister(mci->bus);
+-      kfree(mci->bus->name);
++      kfree(name);
++
+       return err;
+ }
+ 
+@@ -1102,10 +1108,12 @@ void edac_remove_sysfs_mci_device(struct mem_ctl_info 
*mci)
+ 
+ void edac_unregister_sysfs(struct mem_ctl_info *mci)
+ {
++      const char *name = mci->bus->name;
++
+       edac_dbg(1, "Unregistering device %s\n", dev_name(&mci->dev));
+       device_unregister(&mci->dev);
+       bus_unregister(mci->bus);
+-      kfree(mci->bus->name);
++      kfree(name);
+ }
+ 
+ static void mc_attr_release(struct device *dev)
+diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
+index 313ccaf25f49..62834322b337 100644
+--- a/drivers/gpu/drm/ast/ast_main.c
++++ b/drivers/gpu/drm/ast/ast_main.c
+@@ -124,7 +124,7 @@ static int ast_get_dram_info(struct drm_device *dev)
+       } while (ast_read32(ast, 0x10000) != 0x01);
+       data = ast_read32(ast, 0x10004);
+ 
+-      if (data & 0x400)
++      if (data & 0x40)
+               ast->dram_bus_width = 16;
+       else
+               ast->dram_bus_width = 32;
+diff --git a/drivers/gpu/drm/radeon/radeon_sa.c 
b/drivers/gpu/drm/radeon/radeon_sa.c
+index bb166849aa6e..f0bac68254b7 100644
+--- a/drivers/gpu/drm/radeon/radeon_sa.c
++++ b/drivers/gpu/drm/radeon/radeon_sa.c
+@@ -349,13 +349,8 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
+                       /* see if we can skip over some allocations */
+               } while (radeon_sa_bo_next_hole(sa_manager, fences, tries));
+ 
+-              for (i = 0; i < RADEON_NUM_RINGS; ++i)
+-                      radeon_fence_ref(fences[i]);
+-
+               spin_unlock(&sa_manager->wq.lock);
+               r = radeon_fence_wait_any(rdev, fences, false);
+-              for (i = 0; i < RADEON_NUM_RINGS; ++i)
+-                      radeon_fence_unref(&fences[i]);
+               spin_lock(&sa_manager->wq.lock);
+               /* if we have nothing to wait for block */
+               if (r == -ENOENT && block) {
+diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c
+index 2a1b6e037e1a..0134ba32a057 100644
+--- a/drivers/mtd/ubi/upd.c
++++ b/drivers/mtd/ubi/upd.c
+@@ -193,7 +193,7 @@ int ubi_start_leb_change(struct ubi_device *ubi, struct 
ubi_volume *vol,
+       vol->changing_leb = 1;
+       vol->ch_lnum = req->lnum;
+ 
+-      vol->upd_buf = vmalloc(req->bytes);
++      vol->upd_buf = vmalloc(ALIGN((int)req->bytes, ubi->min_io_size));
+       if (!vol->upd_buf)
+               return -ENOMEM;
+ 
+diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
+index 303f3b3fb65f..84b770461655 100644
+--- a/drivers/usb/serial/cp210x.c
++++ b/drivers/usb/serial/cp210x.c
+@@ -164,6 +164,7 @@ static const struct usb_device_id id_table[] = {
+       { USB_DEVICE(0x18EF, 0xE025) }, /* ELV Marble Sound Board 1 */
+       { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */
+       { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */
++      { USB_DEVICE(0x19CF, 0x3000) }, /* Parrot NMEA GPS Flight Recorder */
+       { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */
+       { USB_DEVICE(0x1B1C, 0x1C00) }, /* Corsair USB Dongle */
+       { USB_DEVICE(0x1BA4, 0x0002) }, /* Silicon Labs 358x factory default */
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index 9bab34cf01d4..24366a2afea6 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -271,6 +271,7 @@ static void option_instat_callback(struct urb *urb);
+ #define TELIT_PRODUCT_UE910_V2                        0x1012
+ #define TELIT_PRODUCT_LE922_USBCFG0           0x1042
+ #define TELIT_PRODUCT_LE922_USBCFG3           0x1043
++#define TELIT_PRODUCT_LE922_USBCFG5           0x1045
+ #define TELIT_PRODUCT_LE920                   0x1200
+ #define TELIT_PRODUCT_LE910                   0x1201
+ 
+@@ -1140,6 +1141,8 @@ static const struct usb_device_id option_ids[] = {
+       { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */
+       { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */
+       { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */
++      { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9003), /* Quectel UC20 */
++        .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+       { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6001) },
+       { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_CMU_300) },
+       { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6003),
+@@ -1191,6 +1194,8 @@ static const struct usb_device_id option_ids[] = {
+               .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
+       { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG3),
+               .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
++      { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 
TELIT_PRODUCT_LE922_USBCFG5, 0xff),
++              .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
+       { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
+               .driver_info = (kernel_ulong_t)&telit_le910_blacklist },
+       { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
+diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
+index d17c5d72cd29..4c86850bd627 100644
+--- a/fs/cifs/cifssmb.c
++++ b/fs/cifs/cifssmb.c
+@@ -1389,11 +1389,10 @@ openRetry:
+  * current bigbuf.
+  */
+ static int
+-cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
++discard_remaining_data(struct TCP_Server_Info *server)
+ {
+       unsigned int rfclen = get_rfc1002_length(server->smallbuf);
+       int remaining = rfclen + 4 - server->total_read;
+-      struct cifs_readdata *rdata = mid->callback_data;
+ 
+       while (remaining > 0) {
+               int length;
+@@ -1407,10 +1406,20 @@ cifs_readv_discard(struct TCP_Server_Info *server, 
struct mid_q_entry *mid)
+               remaining -= length;
+       }
+ 
+-      dequeue_mid(mid, rdata->result);
+       return 0;
+ }
+ 
++static int
++cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
++{
++      int length;
++      struct cifs_readdata *rdata = mid->callback_data;
++
++      length = discard_remaining_data(server);
++      dequeue_mid(mid, rdata->result);
++      return length;
++}
++
+ int
+ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+ {
+@@ -1439,6 +1448,12 @@ cifs_readv_receive(struct TCP_Server_Info *server, 
struct mid_q_entry *mid)
+               return length;
+       server->total_read += length;
+ 
++      if (server->ops->is_status_pending &&
++          server->ops->is_status_pending(buf, server, 0)) {
++              discard_remaining_data(server);
++              return -1;
++      }
++
+       /* Was the SMB read successful? */
+       rdata->result = server->ops->map_error(buf, false);
+       if (rdata->result != 0) {
+diff --git a/fs/jffs2/README.Locking b/fs/jffs2/README.Locking
+index 3ea36554107f..8918ac905a3b 100644
+--- a/fs/jffs2/README.Locking
++++ b/fs/jffs2/README.Locking
+@@ -2,10 +2,6 @@
+       JFFS2 LOCKING DOCUMENTATION
+       ---------------------------
+ 
+-At least theoretically, JFFS2 does not require the Big Kernel Lock
+-(BKL), which was always helpfully obtained for it by Linux 2.4 VFS
+-code. It has its own locking, as described below.
+-
+ This document attempts to describe the existing locking rules for
+ JFFS2. It is not expected to remain perfectly up to date, but ought to
+ be fairly close.
+@@ -69,6 +65,7 @@ Ordering constraints:
+          any f->sem held.
+       2. Never attempt to lock two file mutexes in one thread.
+          No ordering rules have been made for doing so.
++      3. Never lock a page cache page with f->sem held.
+ 
+ 
+       erase_completion_lock spinlock
+diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c
+index a3750f902adc..c1f04947d7dc 100644
+--- a/fs/jffs2/build.c
++++ b/fs/jffs2/build.c
+@@ -49,7 +49,8 @@ next_inode(int *i, struct jffs2_inode_cache *ic, struct 
jffs2_sb_info *c)
+ 
+ 
+ static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
+-                                  struct jffs2_inode_cache *ic)
++                                  struct jffs2_inode_cache *ic,
++                                  int *dir_hardlinks)
+ {
+       struct jffs2_full_dirent *fd;
+ 
+@@ -68,19 +69,21 @@ static void jffs2_build_inode_pass1(struct jffs2_sb_info 
*c,
+                       dbg_fsbuild("child \"%s\" (ino #%u) of dir ino #%u 
doesn't exist!\n",
+                                 fd->name, fd->ino, ic->ino);
+                       jffs2_mark_node_obsolete(c, fd->raw);
++                      /* Clear the ic/raw union so it doesn't cause problems 
later. */
++                      fd->ic = NULL;
+                       continue;
+               }
+ 
++              /* From this point, fd->raw is no longer used so we can set 
fd->ic */
++              fd->ic = child_ic;
++              child_ic->pino_nlink++;
++              /* If we appear (at this stage) to have hard-linked directories,
++               * set a flag to trigger a scan later */
+               if (fd->type == DT_DIR) {
+-                      if (child_ic->pino_nlink) {
+-                              JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir 
ino #%u appears to be a hard link\n",
+-                                          fd->name, fd->ino, ic->ino);
+-                              /* TODO: What do we do about it? */
+-                      } else {
+-                              child_ic->pino_nlink = ic->ino;
+-                      }
+-              } else
+-                      child_ic->pino_nlink++;
++                      child_ic->flags |= INO_FLAGS_IS_DIR;
++                      if (child_ic->pino_nlink > 1)
++                              *dir_hardlinks = 1;
++              }
+ 
+               dbg_fsbuild("increased nlink for child \"%s\" (ino #%u)\n", 
fd->name, fd->ino);
+               /* Can't free scan_dents so far. We might need them in pass 2 */
+@@ -94,8 +97,7 @@ static void jffs2_build_inode_pass1(struct jffs2_sb_info *c,
+ */
+ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
+ {
+-      int ret;
+-      int i;
++      int ret, i, dir_hardlinks = 0;
+       struct jffs2_inode_cache *ic;
+       struct jffs2_full_dirent *fd;
+       struct jffs2_full_dirent *dead_fds = NULL;
+@@ -119,7 +121,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
+       /* Now scan the directory tree, increasing nlink according to every 
dirent found. */
+       for_each_inode(i, c, ic) {
+               if (ic->scan_dents) {
+-                      jffs2_build_inode_pass1(c, ic);
++                      jffs2_build_inode_pass1(c, ic, &dir_hardlinks);
+                       cond_resched();
+               }
+       }
+@@ -155,6 +157,20 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
+       }
+ 
+       dbg_fsbuild("pass 2a complete\n");
++
++      if (dir_hardlinks) {
++              /* If we detected directory hardlinks earlier, *hopefully*
++               * they are gone now because some of the links were from
++               * dead directories which still had some old dirents lying
++               * around and not yet garbage-collected, but which have
++               * been discarded above. So clear the pino_nlink field
++               * in each directory, so that the final scan below can
++               * print appropriate warnings. */
++              for_each_inode(i, c, ic) {
++                      if (ic->flags & INO_FLAGS_IS_DIR)
++                              ic->pino_nlink = 0;
++              }
++      }
+       dbg_fsbuild("freeing temporary data structures\n");
+ 
+       /* Finally, we can scan again and free the dirent structs */
+@@ -162,6 +178,33 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
+               while(ic->scan_dents) {
+                       fd = ic->scan_dents;
+                       ic->scan_dents = fd->next;
++                      /* We do use the pino_nlink field to count nlink of
++                       * directories during fs build, so set it to the
++                       * parent ino# now. Now that there's hopefully only
++                       * one. */
++                      if (fd->type == DT_DIR) {
++                              if (!fd->ic) {
++                                      /* We'll have complained about it and 
marked the coresponding
++                                         raw node obsolete already. Just skip 
it. */
++                                      continue;
++                              }
++
++                              /* We *have* to have set this in 
jffs2_build_inode_pass1() */
++                              BUG_ON(!(fd->ic->flags & INO_FLAGS_IS_DIR));
++
++                              /* We clear ic->pino_nlink ∀ directories' ic 
*only* if dir_hardlinks
++                               * is set. Otherwise, we know this should never 
trigger anyway, so
++                               * we don't do the check. And ic->pino_nlink 
still contains the nlink
++                               * value (which is 1). */
++                              if (dir_hardlinks && fd->ic->pino_nlink) {
++                                      JFFS2_ERROR("child dir \"%s\" (ino #%u) 
of dir ino #%u is also hard linked from dir ino #%u\n",
++                                                  fd->name, fd->ino, ic->ino, 
fd->ic->pino_nlink);
++                                      /* Should we unlink it from its 
previous parent? */
++                              }
++
++                              /* For directories, ic->pino_nlink holds that 
parent inode # */
++                              fd->ic->pino_nlink = ic->ino;
++                      }
+                       jffs2_free_full_dirent(fd);
+               }
+               ic->scan_dents = NULL;
+@@ -240,11 +283,7 @@ static void jffs2_build_remove_unlinked_inode(struct 
jffs2_sb_info *c,
+ 
+                       /* Reduce nlink of the child. If it's now zero, stick 
it on the
+                          dead_fds list to be cleaned up later. Else just free 
the fd */
+-
+-                      if (fd->type == DT_DIR)
+-                              child_ic->pino_nlink = 0;
+-                      else
+-                              child_ic->pino_nlink--;
++                      child_ic->pino_nlink--;
+ 
+                       if (!child_ic->pino_nlink) {
+                               dbg_fsbuild("inode #%u (\"%s\") now has no 
links; adding to dead_fds list.\n",
+diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c
+index 1506673c087e..60ef3fb707ff 100644
+--- a/fs/jffs2/file.c
++++ b/fs/jffs2/file.c
+@@ -138,39 +138,33 @@ static int jffs2_write_begin(struct file *filp, struct 
address_space *mapping,
+       struct page *pg;
+       struct inode *inode = mapping->host;
+       struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
+-      struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
+-      struct jffs2_raw_inode ri;
+-      uint32_t alloc_len = 0;
+       pgoff_t index = pos >> PAGE_CACHE_SHIFT;
+       uint32_t pageofs = index << PAGE_CACHE_SHIFT;
+       int ret = 0;
+ 
+-      jffs2_dbg(1, "%s()\n", __func__);
+-
+-      if (pageofs > inode->i_size) {
+-              ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
+-                                        ALLOC_NORMAL, 
JFFS2_SUMMARY_INODE_SIZE);
+-              if (ret)
+-                      return ret;
+-      }
+-
+-      mutex_lock(&f->sem);
+       pg = grab_cache_page_write_begin(mapping, index, flags);
+-      if (!pg) {
+-              if (alloc_len)
+-                      jffs2_complete_reservation(c);
+-              mutex_unlock(&f->sem);
++      if (!pg)
+               return -ENOMEM;
+-      }
+       *pagep = pg;
+ 
+-      if (alloc_len) {
++      jffs2_dbg(1, "%s()\n", __func__);
++
++      if (pageofs > inode->i_size) {
+               /* Make new hole frag from old EOF to new page */
++              struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
++              struct jffs2_raw_inode ri;
+               struct jffs2_full_dnode *fn;
++              uint32_t alloc_len;
+ 
+               jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current 
EOF and new page\n",
+                         (unsigned int)inode->i_size, pageofs);
+ 
++              ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len,
++                                        ALLOC_NORMAL, 
JFFS2_SUMMARY_INODE_SIZE);
++              if (ret)
++                      goto out_page;
++
++              mutex_lock(&f->sem);
+               memset(&ri, 0, sizeof(ri));
+ 
+               ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
+@@ -197,6 +191,7 @@ static int jffs2_write_begin(struct file *filp, struct 
address_space *mapping,
+               if (IS_ERR(fn)) {
+                       ret = PTR_ERR(fn);
+                       jffs2_complete_reservation(c);
++                      mutex_unlock(&f->sem);
+                       goto out_page;
+               }
+               ret = jffs2_add_full_dnode_to_inode(c, f, fn);
+@@ -211,10 +206,12 @@ static int jffs2_write_begin(struct file *filp, struct 
address_space *mapping,
+                       jffs2_mark_node_obsolete(c, fn->raw);
+                       jffs2_free_full_dnode(fn);
+                       jffs2_complete_reservation(c);
++                      mutex_unlock(&f->sem);
+                       goto out_page;
+               }
+               jffs2_complete_reservation(c);
+               inode->i_size = pageofs;
++              mutex_unlock(&f->sem);
+       }
+ 
+       /*
+@@ -223,18 +220,18 @@ static int jffs2_write_begin(struct file *filp, struct 
address_space *mapping,
+        * case of a short-copy.
+        */
+       if (!PageUptodate(pg)) {
++              mutex_lock(&f->sem);
+               ret = jffs2_do_readpage_nolock(inode, pg);
++              mutex_unlock(&f->sem);
+               if (ret)
+                       goto out_page;
+       }
+-      mutex_unlock(&f->sem);
+       jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags);
+       return ret;
+ 
+ out_page:
+       unlock_page(pg);
+       page_cache_release(pg);
+-      mutex_unlock(&f->sem);
+       return ret;
+ }
+ 
+diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
+index 5a2dec2b064c..95d5880a63ee 100644
+--- a/fs/jffs2/gc.c
++++ b/fs/jffs2/gc.c
+@@ -1296,14 +1296,17 @@ static int jffs2_garbage_collect_dnode(struct 
jffs2_sb_info *c, struct jffs2_era
+               BUG_ON(start > orig_start);
+       }
+ 
+-      /* First, use readpage() to read the appropriate page into the page 
cache */
+-      /* Q: What happens if we actually try to GC the _same_ page for which 
commit_write()
+-       *    triggered garbage collection in the first place?
+-       * A: I _think_ it's OK. read_cache_page shouldn't deadlock, we'll 
write out the
+-       *    page OK. We'll actually write it out again in commit_write, which 
is a little
+-       *    suboptimal, but at least we're correct.
+-       */
++      /* The rules state that we must obtain the page lock *before* f->sem, so
++       * drop f->sem temporarily. Since we also hold c->alloc_sem, nothing's
++       * actually going to *change* so we're safe; we only allow reading.
++       *
++       * It is important to note that jffs2_write_begin() will ensure that its
++       * page is marked Uptodate before allocating space. That means that if 
we
++       * end up here trying to GC the *same* page that jffs2_write_begin() is
++       * trying to write out, read_cache_page() will not deadlock. */
++      mutex_unlock(&f->sem);
+       pg_ptr = jffs2_gc_fetch_page(c, f, start, &pg);
++      mutex_lock(&f->sem);
+ 
+       if (IS_ERR(pg_ptr)) {
+               pr_warn("read_cache_page() returned error: %ld\n",
+diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h
+index fa35ff79ab35..0637271f3770 100644
+--- a/fs/jffs2/nodelist.h
++++ b/fs/jffs2/nodelist.h
+@@ -194,6 +194,7 @@ struct jffs2_inode_cache {
+ #define INO_STATE_CLEARING    6       /* In clear_inode() */
+ 
+ #define INO_FLAGS_XATTR_CHECKED       0x01    /* has no duplicate xattr_ref */
++#define INO_FLAGS_IS_DIR      0x02    /* is a directory */
+ 
+ #define RAWNODE_CLASS_INODE_CACHE     0
+ #define RAWNODE_CLASS_XATTR_DATUM     1
+@@ -249,7 +250,10 @@ struct jffs2_readinode_info
+ 
+ struct jffs2_full_dirent
+ {
+-      struct jffs2_raw_node_ref *raw;
++      union {
++              struct jffs2_raw_node_ref *raw;
++              struct jffs2_inode_cache *ic; /* Just during part of build */
++      };
+       struct jffs2_full_dirent *next;
+       uint32_t version;
+       uint32_t ino; /* == zero for unlink */
+diff --git a/fs/locks.c b/fs/locks.c
+index 0274c953b07d..f7b1de7e6735 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -1852,7 +1852,6 @@ int fcntl_setlk(unsigned int fd, struct file *filp, 
unsigned int cmd,
+               goto out;
+       }
+ 
+-again:
+       error = flock_to_posix_lock(filp, file_lock, &flock);
+       if (error)
+               goto out;
+@@ -1883,19 +1882,22 @@ again:
+        * Attempt to detect a close/fcntl race and recover by
+        * releasing the lock that was just acquired.
+        */
+-      /*
+-       * we need that spin_lock here - it prevents reordering between
+-       * update of inode->i_flock and check for it done in close().
+-       * rcu_read_lock() wouldn't do.
+-       */
+-      spin_lock(&current->files->file_lock);
+-      f = fcheck(fd);
+-      spin_unlock(&current->files->file_lock);
+-      if (!error && f != filp && flock.l_type != F_UNLCK) {
+-              flock.l_type = F_UNLCK;
+-              goto again;
++      if (!error && file_lock->fl_type != F_UNLCK) {
++              /*
++               * We need that spin_lock here - it prevents reordering between
++               * update of inode->i_flock and check for it done in
++               * close(). rcu_read_lock() wouldn't do.
++               */
++              spin_lock(&current->files->file_lock);
++              f = fcheck(fd);
++              spin_unlock(&current->files->file_lock);
++              if (f != filp) {
++                      file_lock->fl_type = F_UNLCK;
++                      error = do_lock_file_wait(filp, cmd, file_lock);
++                      WARN_ON_ONCE(error);
++                      error = -EBADF;
++              }
+       }
+-
+ out:
+       locks_free_lock(file_lock);
+       return error;
+@@ -1970,7 +1972,6 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, 
unsigned int cmd,
+               goto out;
+       }
+ 
+-again:
+       error = flock64_to_posix_lock(filp, file_lock, &flock);
+       if (error)
+               goto out;
+@@ -2001,14 +2002,22 @@ again:
+        * Attempt to detect a close/fcntl race and recover by
+        * releasing the lock that was just acquired.
+        */
+-      spin_lock(&current->files->file_lock);
+-      f = fcheck(fd);
+-      spin_unlock(&current->files->file_lock);
+-      if (!error && f != filp && flock.l_type != F_UNLCK) {
+-              flock.l_type = F_UNLCK;
+-              goto again;
++      if (!error && file_lock->fl_type != F_UNLCK) {
++              /*
++               * We need that spin_lock here - it prevents reordering between
++               * update of inode->i_flock and check for it done in
++               * close(). rcu_read_lock() wouldn't do.
++               */
++              spin_lock(&current->files->file_lock);
++              f = fcheck(fd);
++              spin_unlock(&current->files->file_lock);
++              if (f != filp) {
++                      file_lock->fl_type = F_UNLCK;
++                      error = do_lock_file_wait(filp, cmd, file_lock);
++                      WARN_ON_ONCE(error);
++                      error = -EBADF;
++              }
+       }
+-
+ out:
+       locks_free_lock(file_lock);
+       return error;
+diff --git a/include/linux/ata.h b/include/linux/ata.h
+index ee0bd9524055..f60ffe29b3a1 100644
+--- a/include/linux/ata.h
++++ b/include/linux/ata.h
+@@ -477,8 +477,8 @@ enum ata_tf_protocols {
+ };
+ 
+ enum ata_ioctls {
+-      ATA_IOC_GET_IO32        = 0x309,
+-      ATA_IOC_SET_IO32        = 0x324,
++      ATA_IOC_GET_IO32        = 0x309, /* HDIO_GET_32BIT */
++      ATA_IOC_SET_IO32        = 0x324, /* HDIO_SET_32BIT */
+ };
+ 
+ /* core structures */
+diff --git a/include/linux/libata.h b/include/linux/libata.h
+index 8ad0771b88ab..8017e5c459cf 100644
+--- a/include/linux/libata.h
++++ b/include/linux/libata.h
+@@ -666,7 +666,7 @@ struct ata_device {
+       union {
+               u16             id[ATA_ID_WORDS]; /* IDENTIFY xxx DEVICE data */
+               u32             gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
+-      };
++      } ____cacheline_aligned;
+ 
+       /* DEVSLP Timing Variables from Identify Device Data Log */
+       u8                      devslp_timing[ATA_LOG_DEVSLP_SIZE];
+diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
+index 2bb95a7a8809..c14565bde887 100644
+--- a/sound/core/control_compat.c
++++ b/sound/core/control_compat.c
+@@ -170,6 +170,19 @@ struct snd_ctl_elem_value32 {
+         unsigned char reserved[128];
+ };
+ 
++#ifdef CONFIG_X86_X32
++/* x32 has a different alignment for 64bit values from ia32 */
++struct snd_ctl_elem_value_x32 {
++      struct snd_ctl_elem_id id;
++      unsigned int indirect;  /* bit-field causes misalignment */
++      union {
++              s32 integer[128];
++              unsigned char data[512];
++              s64 integer64[64];
++      } value;
++      unsigned char reserved[128];
++};
++#endif /* CONFIG_X86_X32 */
+ 
+ /* get the value type and count of the control */
+ static int get_ctl_type(struct snd_card *card, struct snd_ctl_elem_id *id,
+@@ -219,9 +232,11 @@ static int get_elem_size(int type, int count)
+ 
+ static int copy_ctl_value_from_user(struct snd_card *card,
+                                   struct snd_ctl_elem_value *data,
+-                                  struct snd_ctl_elem_value32 __user *data32,
++                                  void __user *userdata,
++                                  void __user *valuep,
+                                   int *typep, int *countp)
+ {
++      struct snd_ctl_elem_value32 __user *data32 = userdata;
+       int i, type, size;
+       int uninitialized_var(count);
+       unsigned int indirect;
+@@ -239,8 +254,9 @@ static int copy_ctl_value_from_user(struct snd_card *card,
+       if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
+           type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
+               for (i = 0; i < count; i++) {
++                      s32 __user *intp = valuep;
+                       int val;
+-                      if (get_user(val, &data32->value.integer[i]))
++                      if (get_user(val, &intp[i]))
+                               return -EFAULT;
+                       data->value.integer.value[i] = val;
+               }
+@@ -250,8 +266,7 @@ static int copy_ctl_value_from_user(struct snd_card *card,
+                       printk(KERN_ERR "snd_ioctl32_ctl_elem_value: unknown 
type %d\n", type);
+                       return -EINVAL;
+               }
+-              if (copy_from_user(data->value.bytes.data,
+-                                 data32->value.data, size))
++              if (copy_from_user(data->value.bytes.data, valuep, size))
+                       return -EFAULT;
+       }
+ 
+@@ -261,7 +276,8 @@ static int copy_ctl_value_from_user(struct snd_card *card,
+ }
+ 
+ /* restore the value to 32bit */
+-static int copy_ctl_value_to_user(struct snd_ctl_elem_value32 __user *data32,
++static int copy_ctl_value_to_user(void __user *userdata,
++                                void __user *valuep,
+                                 struct snd_ctl_elem_value *data,
+                                 int type, int count)
+ {
+@@ -270,22 +286,22 @@ static int copy_ctl_value_to_user(struct 
snd_ctl_elem_value32 __user *data32,
+       if (type == SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
+           type == SNDRV_CTL_ELEM_TYPE_INTEGER) {
+               for (i = 0; i < count; i++) {
++                      s32 __user *intp = valuep;
+                       int val;
+                       val = data->value.integer.value[i];
+-                      if (put_user(val, &data32->value.integer[i]))
++                      if (put_user(val, &intp[i]))
+                               return -EFAULT;
+               }
+       } else {
+               size = get_elem_size(type, count);
+-              if (copy_to_user(data32->value.data,
+-                               data->value.bytes.data, size))
++              if (copy_to_user(valuep, data->value.bytes.data, size))
+                       return -EFAULT;
+       }
+       return 0;
+ }
+ 
+-static int snd_ctl_elem_read_user_compat(struct snd_card *card, 
+-                                       struct snd_ctl_elem_value32 __user 
*data32)
++static int ctl_elem_read_user(struct snd_card *card,
++                            void __user *userdata, void __user *valuep)
+ {
+       struct snd_ctl_elem_value *data;
+       int err, type, count;
+@@ -294,7 +310,9 @@ static int snd_ctl_elem_read_user_compat(struct snd_card 
*card,
+       if (data == NULL)
+               return -ENOMEM;
+ 
+-      if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) 
< 0)
++      err = copy_ctl_value_from_user(card, data, userdata, valuep,
++                                     &type, &count);
++      if (err < 0)
+               goto error;
+ 
+       snd_power_lock(card);
+@@ -303,14 +321,15 @@ static int snd_ctl_elem_read_user_compat(struct snd_card 
*card,
+               err = snd_ctl_elem_read(card, data);
+       snd_power_unlock(card);
+       if (err >= 0)
+-              err = copy_ctl_value_to_user(data32, data, type, count);
++              err = copy_ctl_value_to_user(userdata, valuep, data,
++                                           type, count);
+  error:
+       kfree(data);
+       return err;
+ }
+ 
+-static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
+-                                        struct snd_ctl_elem_value32 __user 
*data32)
++static int ctl_elem_write_user(struct snd_ctl_file *file,
++                             void __user *userdata, void __user *valuep)
+ {
+       struct snd_ctl_elem_value *data;
+       struct snd_card *card = file->card;
+@@ -320,7 +339,9 @@ static int snd_ctl_elem_write_user_compat(struct 
snd_ctl_file *file,
+       if (data == NULL)
+               return -ENOMEM;
+ 
+-      if ((err = copy_ctl_value_from_user(card, data, data32, &type, &count)) 
< 0)
++      err = copy_ctl_value_from_user(card, data, userdata, valuep,
++                                     &type, &count);
++      if (err < 0)
+               goto error;
+ 
+       snd_power_lock(card);
+@@ -329,12 +350,39 @@ static int snd_ctl_elem_write_user_compat(struct 
snd_ctl_file *file,
+               err = snd_ctl_elem_write(card, file, data);
+       snd_power_unlock(card);
+       if (err >= 0)
+-              err = copy_ctl_value_to_user(data32, data, type, count);
++              err = copy_ctl_value_to_user(userdata, valuep, data,
++                                           type, count);
+  error:
+       kfree(data);
+       return err;
+ }
+ 
++static int snd_ctl_elem_read_user_compat(struct snd_card *card,
++                                       struct snd_ctl_elem_value32 __user 
*data32)
++{
++      return ctl_elem_read_user(card, data32, &data32->value);
++}
++
++static int snd_ctl_elem_write_user_compat(struct snd_ctl_file *file,
++                                        struct snd_ctl_elem_value32 __user 
*data32)
++{
++      return ctl_elem_write_user(file, data32, &data32->value);
++}
++
++#ifdef CONFIG_X86_X32
++static int snd_ctl_elem_read_user_x32(struct snd_card *card,
++                                    struct snd_ctl_elem_value_x32 __user 
*data32)
++{
++      return ctl_elem_read_user(card, data32, &data32->value);
++}
++
++static int snd_ctl_elem_write_user_x32(struct snd_ctl_file *file,
++                                     struct snd_ctl_elem_value_x32 __user 
*data32)
++{
++      return ctl_elem_write_user(file, data32, &data32->value);
++}
++#endif /* CONFIG_X86_X32 */
++
+ /* add or replace a user control */
+ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file,
+                                  struct snd_ctl_elem_info32 __user *data32,
+@@ -393,6 +441,10 @@ enum {
+       SNDRV_CTL_IOCTL_ELEM_WRITE32 = _IOWR('U', 0x13, struct 
snd_ctl_elem_value32),
+       SNDRV_CTL_IOCTL_ELEM_ADD32 = _IOWR('U', 0x17, struct 
snd_ctl_elem_info32),
+       SNDRV_CTL_IOCTL_ELEM_REPLACE32 = _IOWR('U', 0x18, struct 
snd_ctl_elem_info32),
++#ifdef CONFIG_X86_X32
++      SNDRV_CTL_IOCTL_ELEM_READ_X32 = _IOWR('U', 0x12, struct 
snd_ctl_elem_value_x32),
++      SNDRV_CTL_IOCTL_ELEM_WRITE_X32 = _IOWR('U', 0x13, struct 
snd_ctl_elem_value_x32),
++#endif /* CONFIG_X86_X32 */
+ };
+ 
+ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, 
unsigned long arg)
+@@ -431,6 +483,12 @@ static inline long snd_ctl_ioctl_compat(struct file 
*file, unsigned int cmd, uns
+               return snd_ctl_elem_add_compat(ctl, argp, 0);
+       case SNDRV_CTL_IOCTL_ELEM_REPLACE32:
+               return snd_ctl_elem_add_compat(ctl, argp, 1);
++#ifdef CONFIG_X86_X32
++      case SNDRV_CTL_IOCTL_ELEM_READ_X32:
++              return snd_ctl_elem_read_user_x32(ctl->card, argp);
++      case SNDRV_CTL_IOCTL_ELEM_WRITE_X32:
++              return snd_ctl_elem_write_user_x32(ctl, argp);
++#endif /* CONFIG_X86_X32 */
+       }
+ 
+       down_read(&snd_ioctl_rwsem);
+diff --git a/sound/core/rawmidi_compat.c b/sound/core/rawmidi_compat.c
+index 5268c1f58c25..09a89094dcf7 100644
+--- a/sound/core/rawmidi_compat.c
++++ b/sound/core/rawmidi_compat.c
+@@ -94,9 +94,58 @@ static int snd_rawmidi_ioctl_status_compat(struct 
snd_rawmidi_file *rfile,
+       return 0;
+ }
+ 
++#ifdef CONFIG_X86_X32
++/* X32 ABI has 64bit timespec and 64bit alignment */
++struct snd_rawmidi_status_x32 {
++      s32 stream;
++      u32 rsvd; /* alignment */
++      struct timespec tstamp;
++      u32 avail;
++      u32 xruns;
++      unsigned char reserved[16];
++} __attribute__((packed));
++
++#define put_timespec(src, dst) copy_to_user(dst, src, sizeof(*dst))
++
++static int snd_rawmidi_ioctl_status_x32(struct snd_rawmidi_file *rfile,
++                                      struct snd_rawmidi_status_x32 __user 
*src)
++{
++      int err;
++      struct snd_rawmidi_status status;
++
++      if (rfile->output == NULL)
++              return -EINVAL;
++      if (get_user(status.stream, &src->stream))
++              return -EFAULT;
++
++      switch (status.stream) {
++      case SNDRV_RAWMIDI_STREAM_OUTPUT:
++              err = snd_rawmidi_output_status(rfile->output, &status);
++              break;
++      case SNDRV_RAWMIDI_STREAM_INPUT:
++              err = snd_rawmidi_input_status(rfile->input, &status);
++              break;
++      default:
++              return -EINVAL;
++      }
++      if (err < 0)
++              return err;
++
++      if (put_timespec(&status.tstamp, &src->tstamp) ||
++          put_user(status.avail, &src->avail) ||
++          put_user(status.xruns, &src->xruns))
++              return -EFAULT;
++
++      return 0;
++}
++#endif /* CONFIG_X86_X32 */
++
+ enum {
+       SNDRV_RAWMIDI_IOCTL_PARAMS32 = _IOWR('W', 0x10, struct 
snd_rawmidi_params32),
+       SNDRV_RAWMIDI_IOCTL_STATUS32 = _IOWR('W', 0x20, struct 
snd_rawmidi_status32),
++#ifdef CONFIG_X86_X32
++      SNDRV_RAWMIDI_IOCTL_STATUS_X32 = _IOWR('W', 0x20, struct 
snd_rawmidi_status_x32),
++#endif /* CONFIG_X86_X32 */
+ };
+ 
+ static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, 
unsigned long arg)
+@@ -115,6 +164,10 @@ static long snd_rawmidi_ioctl_compat(struct file *file, 
unsigned int cmd, unsign
+               return snd_rawmidi_ioctl_params_compat(rfile, argp);
+       case SNDRV_RAWMIDI_IOCTL_STATUS32:
+               return snd_rawmidi_ioctl_status_compat(rfile, argp);
++#ifdef CONFIG_X86_X32
++      case SNDRV_RAWMIDI_IOCTL_STATUS_X32:
++              return snd_rawmidi_ioctl_status_x32(rfile, argp);
++#endif /* CONFIG_X86_X32 */
+       }
+       return -ENOIOCTLCMD;
+ }
+diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
+index 8d4d5e853efe..ab774954c985 100644
+--- a/sound/core/seq/oss/seq_oss.c
++++ b/sound/core/seq/oss/seq_oss.c
+@@ -150,8 +150,6 @@ odev_release(struct inode *inode, struct file *file)
+       if ((dp = file->private_data) == NULL)
+               return 0;
+ 
+-      snd_seq_oss_drain_write(dp);
+-
+       mutex_lock(&register_mutex);
+       snd_seq_oss_release(dp);
+       mutex_unlock(&register_mutex);
+diff --git a/sound/core/seq/oss/seq_oss_device.h 
b/sound/core/seq/oss/seq_oss_device.h
+index c0154a959d55..2464112b08ad 100644
+--- a/sound/core/seq/oss/seq_oss_device.h
++++ b/sound/core/seq/oss/seq_oss_device.h
+@@ -131,7 +131,6 @@ int snd_seq_oss_write(struct seq_oss_devinfo *dp, const 
char __user *buf, int co
+ unsigned int snd_seq_oss_poll(struct seq_oss_devinfo *dp, struct file *file, 
poll_table * wait);
+ 
+ void snd_seq_oss_reset(struct seq_oss_devinfo *dp);
+-void snd_seq_oss_drain_write(struct seq_oss_devinfo *dp);
+ 
+ /* */
+ void snd_seq_oss_process_queue(struct seq_oss_devinfo *dp, abstime_t time);
+diff --git a/sound/core/seq/oss/seq_oss_init.c 
b/sound/core/seq/oss/seq_oss_init.c
+index b3f39b5ed742..f9e09e458227 100644
+--- a/sound/core/seq/oss/seq_oss_init.c
++++ b/sound/core/seq/oss/seq_oss_init.c
+@@ -457,23 +457,6 @@ snd_seq_oss_release(struct seq_oss_devinfo *dp)
+ 
+ 
+ /*
+- * Wait until the queue is empty (if we don't have nonblock)
+- */
+-void
+-snd_seq_oss_drain_write(struct seq_oss_devinfo *dp)
+-{
+-      if (! dp->timer->running)
+-              return;
+-      if (is_write_mode(dp->file_mode) && !is_nonblock_mode(dp->file_mode) &&
+-          dp->writeq) {
+-              debug_printk(("syncing..\n"));
+-              while (snd_seq_oss_writeq_sync(dp->writeq))
+-                      ;
+-      }
+-}
+-
+-
+-/*
+  * reset sequencer devices
+  */
+ void
+diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c
+index e05802ae6e1b..2e908225d754 100644
+--- a/sound/core/timer_compat.c
++++ b/sound/core/timer_compat.c
+@@ -70,13 +70,14 @@ static int snd_timer_user_status_compat(struct file *file,
+                                       struct snd_timer_status32 __user 
*_status)
+ {
+       struct snd_timer_user *tu;
+-      struct snd_timer_status status;
++      struct snd_timer_status32 status;
+       
+       tu = file->private_data;
+       if (snd_BUG_ON(!tu->timeri))
+               return -ENXIO;
+       memset(&status, 0, sizeof(status));
+-      status.tstamp = tu->tstamp;
++      status.tstamp.tv_sec = tu->tstamp.tv_sec;
++      status.tstamp.tv_nsec = tu->tstamp.tv_nsec;
+       status.resolution = snd_timer_resolution(tu->timeri);
+       status.lost = tu->timeri->lost;
+       status.overrun = tu->overrun;
+@@ -88,12 +89,21 @@ static int snd_timer_user_status_compat(struct file *file,
+       return 0;
+ }
+ 
++#ifdef CONFIG_X86_X32
++/* X32 ABI has the same struct as x86-64 */
++#define snd_timer_user_status_x32(file, s) \
++      snd_timer_user_status(file, s)
++#endif /* CONFIG_X86_X32 */
++
+ /*
+  */
+ 
+ enum {
+       SNDRV_TIMER_IOCTL_INFO32 = _IOR('T', 0x11, struct snd_timer_info32),
+       SNDRV_TIMER_IOCTL_STATUS32 = _IOW('T', 0x14, struct snd_timer_status32),
++#ifdef CONFIG_X86_X32
++      SNDRV_TIMER_IOCTL_STATUS_X32 = _IOW('T', 0x14, struct snd_timer_status),
++#endif /* CONFIG_X86_X32 */
+ };
+ 
+ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, 
unsigned long arg)
+@@ -122,6 +132,10 @@ static long snd_timer_user_ioctl_compat(struct file 
*file, unsigned int cmd, uns
+               return snd_timer_user_info_compat(file, argp);
+       case SNDRV_TIMER_IOCTL_STATUS32:
+               return snd_timer_user_status_compat(file, argp);
++#ifdef CONFIG_X86_X32
++      case SNDRV_TIMER_IOCTL_STATUS_X32:
++              return snd_timer_user_status_x32(file, argp);
++#endif /* CONFIG_X86_X32 */
+       }
+       return -ENOIOCTLCMD;
+ }
+diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
+index 94084cdb130c..9a281f45eb9c 100644
+--- a/sound/pci/rme9652/hdsp.c
++++ b/sound/pci/rme9652/hdsp.c
+@@ -2923,7 +2923,7 @@ static int snd_hdsp_get_dds_offset(struct snd_kcontrol 
*kcontrol, struct snd_ctl
+ {
+       struct hdsp *hdsp = snd_kcontrol_chip(kcontrol);
+ 
+-      ucontrol->value.enumerated.item[0] = hdsp_dds_offset(hdsp);
++      ucontrol->value.integer.value[0] = hdsp_dds_offset(hdsp);
+       return 0;
+ }
+ 
+@@ -2935,7 +2935,7 @@ static int snd_hdsp_put_dds_offset(struct snd_kcontrol 
*kcontrol, struct snd_ctl
+ 
+       if (!snd_hdsp_use_is_exclusive(hdsp))
+               return -EBUSY;
+-      val = ucontrol->value.enumerated.item[0];
++      val = ucontrol->value.integer.value[0];
+       spin_lock_irq(&hdsp->lock);
+       if (val != hdsp_dds_offset(hdsp))
+               change = (hdsp_set_dds_offset(hdsp, val) == 0) ? 1 : 0;
+diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
+index dd910d249987..8444098d2a8e 100644
+--- a/sound/pci/rme9652/hdspm.c
++++ b/sound/pci/rme9652/hdspm.c
+@@ -1423,6 +1423,9 @@ static void hdspm_set_dds_value(struct hdspm *hdspm, int 
rate)
+ {
+       u64 n;
+ 
++      if (snd_BUG_ON(rate <= 0))
++              return;
++
+       if (rate >= 112000)
+               rate /= 4;
+       else if (rate >= 56000)
+@@ -2045,6 +2048,8 @@ static int hdspm_get_system_sample_rate(struct hdspm 
*hdspm)
+               } else {
+                       /* slave mode, return external sample rate */
+                       rate = hdspm_external_sample_rate(hdspm);
++                      if (!rate)
++                              rate = hdspm->system_sample_rate;
+               }
+       }
+ 
+@@ -2090,8 +2095,11 @@ static int snd_hdspm_put_system_sample_rate(struct 
snd_kcontrol *kcontrol,
+                                           ucontrol)
+ {
+       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
++      int rate = ucontrol->value.integer.value[0];
+ 
+-      hdspm_set_dds_value(hdspm, ucontrol->value.enumerated.item[0]);
++      if (rate < 27000 || rate > 207000)
++              return -EINVAL;
++      hdspm_set_dds_value(hdspm, ucontrol->value.integer.value[0]);
+       return 0;
+ }
+ 
+@@ -4199,7 +4207,7 @@ static int snd_hdspm_get_tco_word_term(struct 
snd_kcontrol *kcontrol,
+ {
+       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+ 
+-      ucontrol->value.enumerated.item[0] = hdspm->tco->term;
++      ucontrol->value.integer.value[0] = hdspm->tco->term;
+ 
+       return 0;
+ }
+@@ -4210,8 +4218,8 @@ static int snd_hdspm_put_tco_word_term(struct 
snd_kcontrol *kcontrol,
+ {
+       struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
+ 
+-      if (hdspm->tco->term != ucontrol->value.enumerated.item[0]) {
+-              hdspm->tco->term = ucontrol->value.enumerated.item[0];
++      if (hdspm->tco->term != ucontrol->value.integer.value[0]) {
++              hdspm->tco->term = ucontrol->value.integer.value[0];
+ 
+               hdspm_tco_write(hdspm);
+ 

Reply via email to