mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-26 00:31:47 +00:00
1156 lines
38 KiB
Diff
1156 lines
38 KiB
Diff
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(¤t->files->file_lock);
|
|
- f = fcheck(fd);
|
|
- spin_unlock(¤t->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(¤t->files->file_lock);
|
|
+ f = fcheck(fd);
|
|
+ spin_unlock(¤t->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(¤t->files->file_lock);
|
|
- f = fcheck(fd);
|
|
- spin_unlock(¤t->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(¤t->files->file_lock);
|
|
+ f = fcheck(fd);
|
|
+ spin_unlock(¤t->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(®ister_mutex);
|
|
snd_seq_oss_release(dp);
|
|
mutex_unlock(®ister_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);
|
|
|