Merge "display: set panel idle porch value" into android-msm-skipjack-3.18-gold
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 83187f4..bb68c92 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -441,13 +441,6 @@
char __user *from = iov->iov_base;
while (seglen) {
- sgl = list_first_entry(&ctx->tsgl,
- struct skcipher_sg_list, list);
- sg = sgl->sg;
-
- while (!sg->length)
- sg++;
-
used = ctx->used;
if (!used) {
err = skcipher_wait_for_data(sk, flags);
@@ -469,6 +462,13 @@
if (!used)
goto free;
+ sgl = list_first_entry(&ctx->tsgl,
+ struct skcipher_sg_list, list);
+ sg = sgl->sg;
+
+ while (!sg->length)
+ sg++;
+
ablkcipher_request_set_crypt(&ctx->req, sg,
ctx->rsgl.sg, used,
ctx->iv);
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index c7d273b..1d6d1f6 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -165,6 +165,11 @@
If you are unsure about this, say N here.
+config FW_CACHE
+ bool "Enable firmware caching during suspend"
+ depends on PM_SLEEP
+ default n
+
config WANT_DEV_COREDUMP
bool
help
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 1004025..97585b7 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -1117,7 +1117,7 @@
return _request_firmware_load(fw_priv, desc->opt_flags, timeout);
}
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_FW_CACHE
/* kill pending requests without uevent to avoid blocking suspend */
static void kill_requests_without_uevent(void)
{
@@ -1595,7 +1595,7 @@
}
EXPORT_SYMBOL_GPL(request_firmware_nowait_into_buf);
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_FW_CACHE
static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain);
/**
@@ -1935,7 +1935,7 @@
INIT_LIST_HEAD(&fw_cache.head);
fw_cache.state = FW_LOADER_NO_CACHE;
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_FW_CACHE
spin_lock_init(&fw_cache.name_lock);
INIT_LIST_HEAD(&fw_cache.fw_names);
@@ -1962,7 +1962,7 @@
static void __exit firmware_class_exit(void)
{
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_FW_CACHE
unregister_syscore_ops(&fw_syscore_ops);
unregister_pm_notifier(&fw_cache.pm_notify);
#endif
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 6cb1beb..94385b9 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1512,9 +1512,8 @@
return err;
}
-static void lo_release(struct gendisk *disk, fmode_t mode)
+static void __lo_release(struct loop_device *lo)
{
- struct loop_device *lo = disk->private_data;
int err;
mutex_lock(&lo->lo_ctl_mutex);
@@ -1542,6 +1541,13 @@
mutex_unlock(&lo->lo_ctl_mutex);
}
+static void lo_release(struct gendisk *disk, fmode_t mode)
+{
+ mutex_lock(&loop_index_mutex);
+ __lo_release(disk->private_data);
+ mutex_unlock(&loop_index_mutex);
+}
+
static const struct block_device_operations lo_fops = {
.owner = THIS_MODULE,
.open = lo_open,
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index a8c74fb..7ab29ec 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -1933,6 +1933,10 @@
sizeof(p.init)));
if (err)
goto bail;
+ VERIFY(err, p.init.init.filelen >= 0 &&
+ p.init.init.memlen >= 0);
+ if (err)
+ goto bail;
VERIFY(err, 0 == fastrpc_init_process(fl, &p.init));
if (err)
goto bail;
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 97342eb..fc280a6 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -967,6 +967,8 @@
unsigned int rsize = 0;
char *rdesc;
int ret, n;
+ int num_descriptors;
+ size_t offset = offsetof(struct hid_descriptor, desc);
quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
le16_to_cpu(dev->descriptor.idProduct));
@@ -989,10 +991,18 @@
return -ENODEV;
}
+ if (hdesc->bLength < sizeof(struct hid_descriptor)) {
+ dbg_hid("hid descriptor is too short\n");
+ return -EINVAL;
+ }
+
hid->version = le16_to_cpu(hdesc->bcdHID);
hid->country = hdesc->bCountryCode;
- for (n = 0; n < hdesc->bNumDescriptors; n++)
+ num_descriptors = min_t(int, hdesc->bNumDescriptors,
+ (hdesc->bLength - offset) / sizeof(struct hid_class_descriptor));
+
+ for (n = 0; n < num_descriptors; n++)
if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT)
rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);
diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c
index 8580456..adc7337 100644
--- a/drivers/input/tablet/gtco.c
+++ b/drivers/input/tablet/gtco.c
@@ -231,13 +231,17 @@
/* Walk this report and pull out the info we need */
while (i < length) {
- prefix = report[i];
-
- /* Skip over prefix */
- i++;
+ prefix = report[i++];
/* Determine data size and save the data in the proper variable */
- size = PREF_SIZE(prefix);
+ size = (1U << PREF_SIZE(prefix)) >> 1;
+ if (i + size > length) {
+ dev_err(ddev,
+ "Not enough data (need %d, have %d)\n",
+ i + size, length);
+ break;
+ }
+
switch (size) {
case 1:
data = report[i];
@@ -245,8 +249,7 @@
case 2:
data16 = get_unaligned_le16(&report[i]);
break;
- case 3:
- size = 4;
+ case 4:
data32 = get_unaligned_le32(&report[i]);
break;
}
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index c1efb2a..1aee073 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -2713,6 +2713,8 @@
.change_bus_speed = mmc_change_bus_speed,
};
+static void ClearMMC_Ready(void);
+static void SetMMC_Ready(void);
/*
* Starting point for MMC card init.
*/
@@ -2724,6 +2726,7 @@
BUG_ON(!host);
WARN_ON(!host->claimed);
+ ClearMMC_Ready();
/* Set correct bus mode for MMC before attempting attach */
if (!mmc_host_is_spi(host))
mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN);
@@ -2772,6 +2775,8 @@
if (err)
goto remove_card;
+ msleep(80); // Wait MMC driver and partition are ready.
+ SetMMC_Ready();
register_reboot_notifier(&host->card->reboot_notify);
return 0;
@@ -2789,3 +2794,19 @@
return err;
}
+
+static bool gMMC_Ready=0;
+static void ClearMMC_Ready(void)
+{
+ gMMC_Ready = 0;
+}
+
+static void SetMMC_Ready(void)
+{
+ gMMC_Ready = 1;
+}
+
+bool GetMMC_Ready(void)
+{
+ return gMMC_Ready;
+}
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
index 0cef44e..0a56cb7 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c
@@ -1157,6 +1157,12 @@
IPADBG("Trying to remove hdr %s offset=%u\n",
entry->name, entry->offset_entry->offset);
if (!entry->offset_entry->offset) {
+ if (entry->is_hdr_proc_ctx) {
+ mutex_unlock(&ipa_ctx->lock);
+ WARN_ON(1);
+ IPAERR("default header is proc ctx\n");
+ return -EFAULT;
+ }
IPADBG("skip default header\n");
continue;
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
index d4ad1d9..4fb8410 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
@@ -1005,6 +1005,12 @@
IPADBG("Trying to remove hdr %s offset=%u\n",
entry->name, entry->offset_entry->offset);
if (!entry->offset_entry->offset) {
+ if (entry->is_hdr_proc_ctx) {
+ IPAERR("default header is proc ctx\n");
+ mutex_unlock(&ipa3_ctx->lock);
+ WARN_ON(1);
+ return -EFAULT;
+ }
IPADBG("skip default header\n");
continue;
}
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index b22e7c6..61e7d51 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -406,6 +406,9 @@
struct sg_header *old_hdr = NULL;
int retval = 0;
+ if (unlikely(segment_eq(get_fs(), KERNEL_DS)))
+ return -EINVAL;
+
if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
return -ENXIO;
SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp,
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index 27e223d..ba8b8de 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -44,6 +44,16 @@
created. Each binder device has its own context manager, and is
therefore logically separated from the other devices.
+config ANDROID_BINDER_IPC_SELFTEST
+ bool "Android Binder IPC Driver Selftest"
+ depends on ANDROID_BINDER_IPC
+ ---help---
+ This feature allows binder selftest to run.
+
+ Binder selftest checks the allocation and free of binder buffers
+ exhaustively with combinations of various buffer sizes and
+ alignments.
+
config ASHMEM
bool "Enable the Anonymous Shared Memory Subsystem"
default n
diff --git a/drivers/staging/android/Makefile b/drivers/staging/android/Makefile
index b2e2a79..f4beec5 100644
--- a/drivers/staging/android/Makefile
+++ b/drivers/staging/android/Makefile
@@ -4,6 +4,7 @@
obj-$(CONFIG_FIQ_DEBUGGER) += fiq_debugger/
obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o binder_alloc.o
+obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
obj-$(CONFIG_ASHMEM) += ashmem.o
obj-$(CONFIG_ANDROID_TIMED_OUTPUT) += timed_output.o
obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o
diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c
index 8cb5d4e..14b4ea2 100644
--- a/drivers/staging/android/ashmem.c
+++ b/drivers/staging/android/ashmem.c
@@ -757,10 +757,12 @@
break;
case ASHMEM_SET_SIZE:
ret = -EINVAL;
+ mutex_lock(&ashmem_mutex);
if (!asma->file) {
ret = 0;
asma->size = (size_t) arg;
}
+ mutex_unlock(&ashmem_mutex);
break;
case ASHMEM_GET_SIZE:
ret = asma->size;
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
index 29fa1c3..926c1f2dc 100644
--- a/drivers/usb/serial/console.c
+++ b/drivers/usb/serial/console.c
@@ -187,6 +187,7 @@
tty_kref_put(tty);
reset_open_count:
port->port.count = 0;
+ info->port = NULL;
usb_autopm_put_interface(serial->interface);
error_get_interface:
usb_serial_put(serial);
diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h
index a451903..a0b9209 100644
--- a/drivers/usb/storage/uas-detect.h
+++ b/drivers/usb/storage/uas-detect.h
@@ -9,7 +9,8 @@
intf->desc.bInterfaceProtocol == USB_PR_UAS);
}
-static int uas_find_uas_alt_setting(struct usb_interface *intf)
+static struct usb_host_interface *uas_find_uas_alt_setting(
+ struct usb_interface *intf)
{
int i;
@@ -17,10 +18,10 @@
struct usb_host_interface *alt = &intf->altsetting[i];
if (uas_is_interface(alt))
- return alt->desc.bAlternateSetting;
+ return alt;
}
- return -ENODEV;
+ return NULL;
}
static int uas_find_endpoints(struct usb_host_interface *alt,
@@ -58,14 +59,14 @@
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
unsigned long flags = id->driver_info;
- int r, alt;
-
+ struct usb_host_interface *alt;
+ int r;
alt = uas_find_uas_alt_setting(intf);
- if (alt < 0)
+ if (!alt)
return 0;
- r = uas_find_endpoints(&intf->altsetting[alt], eps);
+ r = uas_find_endpoints(alt, eps);
if (r < 0)
return 0;
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 2ef0f0a..b7ea35c 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -854,14 +854,14 @@
static int uas_switch_interface(struct usb_device *udev,
struct usb_interface *intf)
{
- int alt;
+ struct usb_host_interface *alt;
alt = uas_find_uas_alt_setting(intf);
- if (alt < 0)
- return alt;
+ if (!alt)
+ return -ENODEV;
- return usb_set_interface(udev,
- intf->altsetting[0].desc.bInterfaceNumber, alt);
+ return usb_set_interface(udev, alt->desc.bInterfaceNumber,
+ alt->desc.bAlternateSetting);
}
static int uas_configure_endpoints(struct uas_dev_info *devinfo)
diff --git a/fs/namespace.c b/fs/namespace.c
index d465e4b..19901b4 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -24,6 +24,7 @@
#include <linux/magic.h>
#include <linux/bootmem.h>
#include <linux/task_work.h>
+#include <linux/delay.h>
#include "pnode.h"
#include "internal.h"
@@ -2593,6 +2594,8 @@
return data ? strndup_user(data, PAGE_SIZE) : NULL;
}
+extern bool GetMMC_Ready(void);
+
/*
* Flags is a 32-bit value that allows up to 31 non-fs dependent flags to
* be given to the mount() call (ie: read-only, no-dev, no-suid etc).
@@ -2613,6 +2616,7 @@
struct path path;
int retval = 0;
int mnt_flags = 0;
+ int retry;
/* Discard magic */
if ((flags & MS_MGC_MSK) == MS_MGC_VAL)
@@ -2675,9 +2679,14 @@
retval = do_change_type(&path, flags);
else if (flags & MS_MOVE)
retval = do_move_mount(&path, dev_name);
- else
+ else {
+ for(retry=60;!GetMMC_Ready() && retry>0;retry--) {
+ pr_err("CEI_TEST:%s, wait 50ms for MMC ready\n",__func__);
+ msleep(50);
+ }
retval = do_new_mount(&path, type_page, flags, mnt_flags,
dev_name, data_page);
+ }
dput_out:
path_put(&path);
return retval;
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index 311dafe..9b18d4e 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -77,6 +77,7 @@
size_t xruns; /* over/underruns counter */
/* misc */
spinlock_t lock;
+ struct mutex realloc_mutex;
wait_queue_head_t sleep;
/* event handler (new bytes, input only) */
void (*event)(struct snd_rawmidi_substream *substream);
diff --git a/kernel/sched/core_ctl.c b/kernel/sched/core_ctl.c
index 0897b8d..458066d 100644
--- a/kernel/sched/core_ctl.c
+++ b/kernel/sched/core_ctl.c
@@ -759,7 +759,7 @@
mutex_lock(&lru_lock);
if (f->online_cpus > need) {
- list_for_each_entry_safe(c, tmp, &f->lru, sib) {
+ list_for_each_entry_safe_reverse(c, tmp, &f->lru, sib) {
if (!c->online)
continue;
@@ -782,7 +782,7 @@
if (f->online_cpus <= f->max_cpus)
goto done;
- list_for_each_entry_safe(c, tmp, &f->lru, sib) {
+ list_for_each_entry_safe_reverse(c, tmp, &f->lru, sib) {
if (!c->online)
continue;
diff --git a/mm/migrate.c b/mm/migrate.c
index 7204f74..79004be 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -37,6 +37,7 @@
#include <linux/gfp.h>
#include <linux/balloon_compaction.h>
#include <linux/mmu_notifier.h>
+#include <linux/ptrace.h>
#include <asm/tlbflush.h>
@@ -1470,7 +1471,6 @@
const int __user *, nodes,
int __user *, status, int, flags)
{
- const struct cred *cred = current_cred(), *tcred;
struct task_struct *task;
struct mm_struct *mm;
int err;
@@ -1494,14 +1494,9 @@
/*
* Check if this process has the right to modify the specified
- * process. The right exists if the process has administrative
- * capabilities, superuser privileges or the same
- * userid as the target process.
+ * process. Use the regular "ptrace_may_access()" checks.
*/
- tcred = __task_cred(task);
- if (!uid_eq(cred->euid, tcred->suid) && !uid_eq(cred->euid, tcred->uid) &&
- !uid_eq(cred->uid, tcred->suid) && !uid_eq(cred->uid, tcred->uid) &&
- !capable(CAP_SYS_NICE)) {
+ if (!ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS)) {
rcu_read_unlock();
err = -EPERM;
goto out;
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index ec2cf37..52650ff 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -533,6 +533,9 @@
BT_DBG("");
+ if (!l2cap_is_socket(sock))
+ return -EBADFD;
+
baswap((void *) dst, &l2cap_pi(sock->sk)->chan->dst);
baswap((void *) src, &l2cap_pi(sock->sk)->chan->src);
diff --git a/net/core/iovec.c b/net/core/iovec.c
index e1ec45a..4c3fd58 100644
--- a/net/core/iovec.c
+++ b/net/core/iovec.c
@@ -88,6 +88,10 @@
__wsum csum = *csump;
int partial_cnt = 0, err = 0;
+ /* No data? Done! */
+ if (len == 0)
+ return 0;
+
/* Skip over the finished iovecs */
while (offset >= iov->iov_len) {
offset -= iov->iov_len;
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 99e640c..29693c5 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4431,6 +4431,10 @@
struct socket *sock;
int err = 0;
+ /* Do not peel off from one netns to another one. */
+ if (!net_eq(current->nsproxy->net_ns, sock_net(sk)))
+ return -EINVAL;
+
if (!asoc)
return -EINVAL;
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 6fc71a4..325a0d6 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -115,6 +115,7 @@
return -ENOMEM;
runtime->substream = substream;
spin_lock_init(&runtime->lock);
+ mutex_init(&runtime->realloc_mutex);
init_waitqueue_head(&runtime->sleep);
INIT_WORK(&runtime->event_work, snd_rawmidi_input_event_work);
runtime->event = NULL;
@@ -637,8 +638,10 @@
struct snd_rawmidi_params * params)
{
char *newbuf;
+ char *oldbuf;
struct snd_rawmidi_runtime *runtime = substream->runtime;
-
+ unsigned long flags;
+
if (substream->append && substream->use_count > 1)
return -EBUSY;
snd_rawmidi_drain_output(substream);
@@ -649,13 +652,22 @@
return -EINVAL;
}
if (params->buffer_size != runtime->buffer_size) {
- newbuf = krealloc(runtime->buffer, params->buffer_size,
+ mutex_lock(&runtime->realloc_mutex);
+ newbuf = __krealloc(runtime->buffer, params->buffer_size,
GFP_KERNEL);
- if (!newbuf)
+ if (!newbuf) {
+ mutex_unlock(&runtime->realloc_mutex);
return -ENOMEM;
+ }
+ spin_lock_irqsave(&runtime->lock, flags);
+ oldbuf = runtime->buffer;
runtime->buffer = newbuf;
runtime->buffer_size = params->buffer_size;
runtime->avail = runtime->buffer_size;
+ spin_unlock_irqrestore(&runtime->lock, flags);
+ if (oldbuf != newbuf)
+ kfree(oldbuf);
+ mutex_unlock(&runtime->realloc_mutex);
}
runtime->avail_min = params->avail_min;
substream->active_sensing = !params->no_active_sensing;
@@ -667,7 +679,9 @@
struct snd_rawmidi_params * params)
{
char *newbuf;
+ char *oldbuf;
struct snd_rawmidi_runtime *runtime = substream->runtime;
+ unsigned long flags;
snd_rawmidi_drain_input(substream);
if (params->buffer_size < 32 || params->buffer_size > 1024L * 1024L) {
@@ -677,12 +691,21 @@
return -EINVAL;
}
if (params->buffer_size != runtime->buffer_size) {
- newbuf = krealloc(runtime->buffer, params->buffer_size,
+ mutex_lock(&runtime->realloc_mutex);
+ newbuf = __krealloc(runtime->buffer, params->buffer_size,
GFP_KERNEL);
- if (!newbuf)
+ if (!newbuf) {
+ mutex_unlock(&runtime->realloc_mutex);
return -ENOMEM;
+ }
+ spin_lock_irqsave(&runtime->lock, flags);
+ oldbuf = runtime->buffer;
runtime->buffer = newbuf;
runtime->buffer_size = params->buffer_size;
+ spin_unlock_irqrestore(&runtime->lock, flags);
+ if (oldbuf != newbuf)
+ kfree(oldbuf);
+ mutex_unlock(&runtime->realloc_mutex);
}
runtime->avail_min = params->avail_min;
return 0;
@@ -953,6 +976,8 @@
long result = 0, count1;
struct snd_rawmidi_runtime *runtime = substream->runtime;
+ if (userbuf)
+ mutex_lock(&runtime->realloc_mutex);
while (count > 0 && runtime->avail) {
count1 = runtime->buffer_size - runtime->appl_ptr;
if (count1 > count)
@@ -966,6 +991,7 @@
spin_unlock_irqrestore(&runtime->lock, flags);
if (copy_to_user(userbuf + result,
runtime->buffer + runtime->appl_ptr, count1)) {
+ mutex_unlock(&runtime->realloc_mutex);
return result > 0 ? result : -EFAULT;
}
spin_lock_irqsave(&runtime->lock, flags);
@@ -977,6 +1003,8 @@
result += count1;
count -= count1;
}
+ if (userbuf)
+ mutex_unlock(&runtime->realloc_mutex);
return result;
}
@@ -1194,10 +1222,14 @@
return -EINVAL;
result = 0;
+ if (userbuf)
+ mutex_lock(&runtime->realloc_mutex);
spin_lock_irqsave(&runtime->lock, flags);
if (substream->append) {
if ((long)runtime->avail < count) {
spin_unlock_irqrestore(&runtime->lock, flags);
+ if (userbuf)
+ mutex_unlock(&runtime->realloc_mutex);
return -EAGAIN;
}
}
@@ -1229,6 +1261,8 @@
__end:
count1 = runtime->avail < runtime->buffer_size;
spin_unlock_irqrestore(&runtime->lock, flags);
+ if (userbuf)
+ mutex_unlock(&runtime->realloc_mutex);
if (count1)
snd_rawmidi_output_trigger(substream, 1);
return result;