diff -druNp --no-dereference linux-libre-3.2.77-gnu1/arch/arm/common/icst.c linux-libre-3.2.78-gnu1/arch/arm/common/icst.c
--- linux-libre-3.2.77-gnu1/arch/arm/common/icst.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/arch/arm/common/icst.c	2016-02-27 09:28:50.000000000 -0500
@@ -16,7 +16,7 @@
  */
 #include <linux/module.h>
 #include <linux/kernel.h>
-
+#include <asm/div64.h>
 #include <asm/hardware/icst.h>
 
 /*
@@ -29,7 +29,11 @@ EXPORT_SYMBOL(icst525_s2div);
 
 unsigned long icst_hz(const struct icst_params *p, struct icst_vco vco)
 {
-	return p->ref * 2 * (vco.v + 8) / ((vco.r + 2) * p->s2div[vco.s]);
+	u64 dividend = p->ref * 2 * (u64)(vco.v + 8);
+	u32 divisor = (vco.r + 2) * p->s2div[vco.s];
+
+	do_div(dividend, divisor);
+	return (unsigned long)dividend;
 }
 
 EXPORT_SYMBOL(icst_hz);
@@ -58,6 +62,7 @@ icst_hz_to_vco(const struct icst_params
 
 		if (f > p->vco_min && f <= p->vco_max)
 			break;
+		i++;
 	} while (i < 8);
 
 	if (i >= 8)
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/arch/x86/kvm/x86.c linux-libre-3.2.78-gnu1/arch/x86/kvm/x86.c
--- linux-libre-3.2.77-gnu1/arch/x86/kvm/x86.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/arch/x86/kvm/x86.c	2016-02-27 09:28:50.000000000 -0500
@@ -5257,9 +5257,10 @@ int kvm_arch_init(void *opaque)
 		goto out;
 
 	kvm_set_mmio_spte_mask();
-	kvm_init_msr_list();
 
 	kvm_x86_ops = ops;
+	kvm_init_msr_list();
+
 	kvm_mmu_set_mask_ptes(PT_USER_MASK, PT_ACCESSED_MASK,
 			PT_DIRTY_MASK, PT64_NX_MASK, 0);
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/arch/x86/mm/pageattr.c linux-libre-3.2.78-gnu1/arch/x86/mm/pageattr.c
--- linux-libre-3.2.77-gnu1/arch/x86/mm/pageattr.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/arch/x86/mm/pageattr.c	2016-02-27 09:28:50.000000000 -0500
@@ -32,7 +32,7 @@ struct cpa_data {
 	unsigned long	*vaddr;
 	pgprot_t	mask_set;
 	pgprot_t	mask_clr;
-	int		numpages;
+	unsigned long	numpages;
 	int		flags;
 	unsigned long	pfn;
 	unsigned	force_split : 1;
@@ -820,7 +820,7 @@ static int __change_page_attr_set_clr(st
 		 * CPA operation. Either a large page has been
 		 * preserved or a single page update happened.
 		 */
-		BUG_ON(cpa->numpages > numpages);
+		BUG_ON(cpa->numpages > numpages || !cpa->numpages);
 		numpages -= cpa->numpages;
 		if (cpa->flags & (CPA_PAGES_ARRAY | CPA_ARRAY))
 			cpa->curpage++;
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/crypto/algif_hash.c linux-libre-3.2.78-gnu1/crypto/algif_hash.c
--- linux-libre-3.2.77-gnu1/crypto/algif_hash.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/crypto/algif_hash.c	2016-02-27 09:28:50.000000000 -0500
@@ -56,7 +56,8 @@ static int hash_sendmsg(struct kiocb *un
 
 	lock_sock(sk);
 	if (!ctx->more) {
-		err = crypto_ahash_init(&ctx->req);
+		err = af_alg_wait_for_completion(crypto_ahash_init(&ctx->req),
+						&ctx->completion);
 		if (err)
 			goto unlock;
 	}
@@ -136,6 +137,7 @@ static ssize_t hash_sendpage(struct sock
 	} else {
 		if (!ctx->more) {
 			err = crypto_ahash_init(&ctx->req);
+			err = af_alg_wait_for_completion(err, &ctx->completion);
 			if (err)
 				goto unlock;
 		}
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/crypto/algif_skcipher.c linux-libre-3.2.78-gnu1/crypto/algif_skcipher.c
--- linux-libre-3.2.77-gnu1/crypto/algif_skcipher.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/crypto/algif_skcipher.c	2016-02-27 09:28:50.000000000 -0500
@@ -249,8 +249,11 @@ static int skcipher_sendmsg(struct kiocb
 {
 	struct sock *sk = sock->sk;
 	struct alg_sock *ask = alg_sk(sk);
+	struct sock *psk = ask->parent;
+	struct alg_sock *pask = alg_sk(psk);
 	struct skcipher_ctx *ctx = ask->private;
-	struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(&ctx->req);
+	struct ablkcipher_tfm *skc = pask->private;
+	struct crypto_ablkcipher *tfm = skc->base;
 	unsigned ivsize = crypto_ablkcipher_ivsize(tfm);
 	struct skcipher_sg_list *sgl;
 	struct af_alg_control con = {};
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/crypto/crypto_user.c linux-libre-3.2.78-gnu1/crypto/crypto_user.c
--- linux-libre-3.2.77-gnu1/crypto/crypto_user.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/crypto/crypto_user.c	2016-02-27 09:28:50.000000000 -0500
@@ -390,8 +390,12 @@ static int crypto_user_rcv_msg(struct sk
 		if (link->dump == NULL)
 			return -EINVAL;
 
-		return netlink_dump_start(crypto_nlsk, skb, nlh,
+		down_read(&crypto_alg_sem);
+		err = netlink_dump_start(crypto_nlsk, skb, nlh,
 					  link->dump, link->done, 0);
+		up_read(&crypto_alg_sem);
+
+		return err;
 	}
 
 	err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/crypto/shash.c linux-libre-3.2.78-gnu1/crypto/shash.c
--- linux-libre-3.2.77-gnu1/crypto/shash.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/crypto/shash.c	2016-02-27 09:28:50.000000000 -0500
@@ -353,11 +353,10 @@ int crypto_init_shash_ops_async(struct c
 	crt->final = shash_async_final;
 	crt->finup = shash_async_finup;
 	crt->digest = shash_async_digest;
+	crt->setkey = shash_async_setkey;
+
+	crt->has_setkey = alg->setkey != shash_no_setkey;
 
-	if (alg->setkey) {
-		crt->setkey = shash_async_setkey;
-		crt->has_setkey = true;
-	}
 	if (alg->export)
 		crt->export = shash_async_export;
 	if (alg->import)
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/Documentation/sysctl/fs.txt linux-libre-3.2.78-gnu1/Documentation/sysctl/fs.txt
--- linux-libre-3.2.77-gnu1/Documentation/sysctl/fs.txt	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/Documentation/sysctl/fs.txt	2016-02-27 09:28:50.000000000 -0500
@@ -32,6 +32,8 @@ Currently, these files are in /proc/sys/
 - nr_open
 - overflowuid
 - overflowgid
+- pipe-user-pages-hard
+- pipe-user-pages-soft
 - suid_dumpable
 - super-max
 - super-nr
@@ -157,6 +159,27 @@ The default is 65534.
 
 ==============================================================
 
+pipe-user-pages-hard:
+
+Maximum total number of pages a non-privileged user may allocate for pipes.
+Once this limit is reached, no new pipes may be allocated until usage goes
+below the limit again. When set to 0, no limit is applied, which is the default
+setting.
+
+==============================================================
+
+pipe-user-pages-soft:
+
+Maximum total number of pages a non-privileged user may allocate for pipes
+before the pipe size gets limited to a single page. Once this limit is reached,
+new pipes will be limited to a single page in size for this user in order to
+limit total memory usage, and trying to increase them using fcntl() will be
+denied until usage goes below the limit again. The default value allows to
+allocate up to 1024 pipes at their default size. When set to 0, no limit is
+applied.
+
+==============================================================
+
 suid_dumpable:
 
 This value can be used to query and set the core dump mode for setuid
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/ata/ahci.c linux-libre-3.2.78-gnu1/drivers/ata/ahci.c
--- linux-libre-3.2.77-gnu1/drivers/ata/ahci.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/ata/ahci.c	2016-02-27 09:28:50.000000000 -0500
@@ -274,6 +274,26 @@ static const struct pci_device_id ahci_p
 	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
 	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
 	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19b2), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19b3), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19b4), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19b5), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19b6), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19b7), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19bE), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19bF), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19c0), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19c1), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19c2), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19c3), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19c4), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19c5), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19c6), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19c7), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */
+	{ PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */
 	{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
 	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
 	{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/ata/libahci.c linux-libre-3.2.78-gnu1/drivers/ata/libahci.c
--- linux-libre-3.2.77-gnu1/drivers/ata/libahci.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/ata/libahci.c	2016-02-27 09:28:50.000000000 -0500
@@ -480,8 +480,8 @@ void ahci_save_initial_config(struct dev
 		}
 	}
 
-	/* fabricate port_map from cap.nr_ports */
-	if (!port_map) {
+	/* fabricate port_map from cap.nr_ports for < AHCI 1.3 */
+	if (!port_map && vers < 0x10300) {
 		port_map = (1 << ahci_nr_ports(cap)) - 1;
 		dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/ata/libata-sff.c linux-libre-3.2.78-gnu1/drivers/ata/libata-sff.c
--- linux-libre-3.2.77-gnu1/drivers/ata/libata-sff.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/ata/libata-sff.c	2016-02-27 09:28:50.000000000 -0500
@@ -997,12 +997,9 @@ static inline int ata_hsm_ok_in_wq(struc
 static void ata_hsm_qc_complete(struct ata_queued_cmd *qc, int in_wq)
 {
 	struct ata_port *ap = qc->ap;
-	unsigned long flags;
 
 	if (ap->ops->error_handler) {
 		if (in_wq) {
-			spin_lock_irqsave(ap->lock, flags);
-
 			/* EH might have kicked in while host lock is
 			 * released.
 			 */
@@ -1014,8 +1011,6 @@ static void ata_hsm_qc_complete(struct a
 				} else
 					ata_port_freeze(ap);
 			}
-
-			spin_unlock_irqrestore(ap->lock, flags);
 		} else {
 			if (likely(!(qc->err_mask & AC_ERR_HSM)))
 				ata_qc_complete(qc);
@@ -1024,10 +1019,8 @@ static void ata_hsm_qc_complete(struct a
 		}
 	} else {
 		if (in_wq) {
-			spin_lock_irqsave(ap->lock, flags);
 			ata_sff_irq_on(ap);
 			ata_qc_complete(qc);
-			spin_unlock_irqrestore(ap->lock, flags);
 		} else
 			ata_qc_complete(qc);
 	}
@@ -1048,9 +1041,10 @@ int ata_sff_hsm_move(struct ata_port *ap
 {
 	struct ata_link *link = qc->dev->link;
 	struct ata_eh_info *ehi = &link->eh_info;
-	unsigned long flags = 0;
 	int poll_next;
 
+	lockdep_assert_held(ap->lock);
+
 	WARN_ON_ONCE((qc->flags & ATA_QCFLAG_ACTIVE) == 0);
 
 	/* Make sure ata_sff_qc_issue() does not throw things
@@ -1112,14 +1106,6 @@ fsm_start:
 			}
 		}
 
-		/* Send the CDB (atapi) or the first data block (ata pio out).
-		 * During the state transition, interrupt handler shouldn't
-		 * be invoked before the data transfer is complete and
-		 * hsm_task_state is changed. Hence, the following locking.
-		 */
-		if (in_wq)
-			spin_lock_irqsave(ap->lock, flags);
-
 		if (qc->tf.protocol == ATA_PROT_PIO) {
 			/* PIO data out protocol.
 			 * send first data block.
@@ -1135,9 +1121,6 @@ fsm_start:
 			/* send CDB */
 			atapi_send_cdb(ap, qc);
 
-		if (in_wq)
-			spin_unlock_irqrestore(ap->lock, flags);
-
 		/* if polling, ata_sff_pio_task() handles the rest.
 		 * otherwise, interrupt handler takes over from here.
 		 */
@@ -1361,12 +1344,14 @@ static void ata_sff_pio_task(struct work
 	u8 status;
 	int poll_next;
 
+	spin_lock_irq(ap->lock);
+
 	BUG_ON(ap->sff_pio_task_link == NULL);
 	/* qc can be NULL if timeout occurred */
 	qc = ata_qc_from_tag(ap, link->active_tag);
 	if (!qc) {
 		ap->sff_pio_task_link = NULL;
-		return;
+		goto out_unlock;
 	}
 
 fsm_start:
@@ -1381,11 +1366,14 @@ fsm_start:
 	 */
 	status = ata_sff_busy_wait(ap, ATA_BUSY, 5);
 	if (status & ATA_BUSY) {
+		spin_unlock_irq(ap->lock);
 		ata_msleep(ap, 2);
+		spin_lock_irq(ap->lock);
+
 		status = ata_sff_busy_wait(ap, ATA_BUSY, 10);
 		if (status & ATA_BUSY) {
 			ata_sff_queue_pio_task(link, ATA_SHORT_PAUSE);
-			return;
+			goto out_unlock;
 		}
 	}
 
@@ -1402,6 +1390,8 @@ fsm_start:
 	 */
 	if (poll_next)
 		goto fsm_start;
+out_unlock:
+	spin_unlock_irq(ap->lock);
 }
 
 /**
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c linux-libre-3.2.78-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
--- linux-libre-3.2.77-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c	2016-02-27 09:28:50.000000000 -0500
@@ -25,6 +25,7 @@
  *
  **************************************************************************/
 #include <linux/module.h>
+#include <linux/console.h>
 
 #include "drmP.h"
 #include "vmwgfx_drv.h"
@@ -1142,6 +1143,12 @@ static int vmw_probe(struct pci_dev *pde
 static int __init vmwgfx_init(void)
 {
 	int ret;
+
+#ifdef CONFIG_VGA_CONSOLE
+	if (vgacon_text_force())
+		return -EINVAL;
+#endif
+
 	ret = drm_pci_init(&driver, &vmw_pci_driver);
 	if (ret)
 		DRM_ERROR("Failed initializing DRM.\n");
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/infiniband/hw/cxgb3/iwch_cm.c linux-libre-3.2.78-gnu1/drivers/infiniband/hw/cxgb3/iwch_cm.c
--- linux-libre-3.2.77-gnu1/drivers/infiniband/hw/cxgb3/iwch_cm.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/infiniband/hw/cxgb3/iwch_cm.c	2016-02-27 09:28:50.000000000 -0500
@@ -150,7 +150,7 @@ static int iwch_l2t_send(struct t3cdev *
 	error = l2t_send(tdev, skb, l2e);
 	if (error < 0)
 		kfree_skb(skb);
-	return error;
+	return error < 0 ? error : 0;
 }
 
 int iwch_cxgb3_ofld_send(struct t3cdev *tdev, struct sk_buff *skb)
@@ -166,7 +166,7 @@ int iwch_cxgb3_ofld_send(struct t3cdev *
 	error = cxgb3_ofld_send(tdev, skb);
 	if (error < 0)
 		kfree_skb(skb);
-	return error;
+	return error < 0 ? error : 0;
 }
 
 static void release_tid(struct t3cdev *tdev, u32 hwtid, struct sk_buff *skb)
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/media/dvb/frontends/tda1004x.c linux-libre-3.2.78-gnu1/drivers/media/dvb/frontends/tda1004x.c
--- linux-libre-3.2.77-gnu1/drivers/media/dvb/frontends/tda1004x.c	2016-02-13 23:19:43.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/media/dvb/frontends/tda1004x.c	2016-02-28 20:57:26.000000000 -0500
@@ -890,9 +890,18 @@ static int tda1004x_set_fe(struct dvb_fr
 static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params)
 {
 	struct tda1004x_state* state = fe->demodulator_priv;
+	int status;
 
 	dprintk("%s\n", __func__);
 
+	status = tda1004x_read_byte(state, TDA1004X_STATUS_CD);
+	if (status == -1)
+		return -EIO;
+
+	/* Only update the properties cache if device is locked */
+	if (!(status & 8))
+		return 0;
+
 	// inversion status
 	fe_params->inversion = INVERSION_OFF;
 	if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20)
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/media/video/saa7134/saa7134-alsa.c linux-libre-3.2.78-gnu1/drivers/media/video/saa7134/saa7134-alsa.c
--- linux-libre-3.2.77-gnu1/drivers/media/video/saa7134/saa7134-alsa.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/media/video/saa7134/saa7134-alsa.c	2016-02-27 09:28:50.000000000 -0500
@@ -1145,6 +1145,8 @@ static int alsa_device_init(struct saa71
 
 static int alsa_device_exit(struct saa7134_dev *dev)
 {
+	if (!snd_saa7134_cards[dev->nr])
+		return 1;
 
 	snd_card_free(snd_saa7134_cards[dev->nr]);
 	snd_saa7134_cards[dev->nr] = NULL;
@@ -1194,7 +1196,8 @@ static void saa7134_alsa_exit(void)
 	int idx;
 
 	for (idx = 0; idx < SNDRV_CARDS; idx++) {
-		snd_card_free(snd_saa7134_cards[idx]);
+		if (snd_saa7134_cards[idx])
+			snd_card_free(snd_saa7134_cards[idx]);
 	}
 
 	saa7134_dmasound_init = NULL;
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/net/ppp/pptp.c linux-libre-3.2.78-gnu1/drivers/net/ppp/pptp.c
--- linux-libre-3.2.77-gnu1/drivers/net/ppp/pptp.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/net/ppp/pptp.c	2016-02-27 09:28:50.000000000 -0500
@@ -131,24 +131,27 @@ static int lookup_chan_dst(u16 call_id,
 	return i < MAX_CALLID;
 }
 
-static int add_chan(struct pppox_sock *sock)
+static int add_chan(struct pppox_sock *sock,
+		    struct pptp_addr *sa)
 {
 	static int call_id;
 
 	spin_lock(&chan_lock);
-	if (!sock->proto.pptp.src_addr.call_id)	{
+	if (!sa->call_id)	{
 		call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, call_id + 1);
 		if (call_id == MAX_CALLID) {
 			call_id = find_next_zero_bit(callid_bitmap, MAX_CALLID, 1);
 			if (call_id == MAX_CALLID)
 				goto out_err;
 		}
-		sock->proto.pptp.src_addr.call_id = call_id;
-	} else if (test_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap))
+		sa->call_id = call_id;
+	} else if (test_bit(sa->call_id, callid_bitmap)) {
 		goto out_err;
+	}
 
-	set_bit(sock->proto.pptp.src_addr.call_id, callid_bitmap);
-	rcu_assign_pointer(callid_sock[sock->proto.pptp.src_addr.call_id], sock);
+	sock->proto.pptp.src_addr = *sa;
+	set_bit(sa->call_id, callid_bitmap);
+	rcu_assign_pointer(callid_sock[sa->call_id], sock);
 	spin_unlock(&chan_lock);
 
 	return 0;
@@ -417,7 +420,6 @@ static int pptp_bind(struct socket *sock
 	struct sock *sk = sock->sk;
 	struct sockaddr_pppox *sp = (struct sockaddr_pppox *) uservaddr;
 	struct pppox_sock *po = pppox_sk(sk);
-	struct pptp_opt *opt = &po->proto.pptp;
 	int error = 0;
 
 	if (sockaddr_len < sizeof(struct sockaddr_pppox))
@@ -425,10 +427,22 @@ static int pptp_bind(struct socket *sock
 
 	lock_sock(sk);
 
-	opt->src_addr = sp->sa_addr.pptp;
-	if (add_chan(po))
+	if (sk->sk_state & PPPOX_DEAD) {
+		error = -EALREADY;
+		goto out;
+	}
+
+	if (sk->sk_state & PPPOX_BOUND) {
 		error = -EBUSY;
+		goto out;
+	}
 
+	if (add_chan(po, &sp->sa_addr.pptp))
+		error = -EBUSY;
+	else
+		sk->sk_state |= PPPOX_BOUND;
+
+out:
 	release_sock(sk);
 	return error;
 }
@@ -499,7 +513,7 @@ static int pptp_connect(struct socket *s
 	}
 
 	opt->dst_addr = sp->sa_addr.pptp;
-	sk->sk_state = PPPOX_CONNECTED;
+	sk->sk_state |= PPPOX_CONNECTED;
 
  end:
 	release_sock(sk);
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/pci/pcie/aer/aerdrv.c linux-libre-3.2.78-gnu1/drivers/pci/pcie/aer/aerdrv.c
--- linux-libre-3.2.77-gnu1/drivers/pci/pcie/aer/aerdrv.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/pci/pcie/aer/aerdrv.c	2016-02-27 09:28:50.000000000 -0500
@@ -263,7 +263,6 @@ static struct aer_rpc *aer_alloc_rpc(str
 	rpc->rpd = dev;
 	INIT_WORK(&rpc->dpc_handler, aer_isr);
 	mutex_init(&rpc->rpc_mutex);
-	init_waitqueue_head(&rpc->wait_release);
 
 	/* Use PCIe bus function to store rpc into PCIe device */
 	set_service_data(dev, rpc);
@@ -286,8 +285,7 @@ static void aer_remove(struct pcie_devic
 		if (rpc->isr)
 			free_irq(dev->irq, dev);
 
-		wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx);
-
+		flush_work(&rpc->dpc_handler);
 		aer_disable_rootport(rpc);
 		kfree(rpc);
 		set_service_data(dev, NULL);
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/pci/pcie/aer/aerdrv_core.c linux-libre-3.2.78-gnu1/drivers/pci/pcie/aer/aerdrv_core.c
--- linux-libre-3.2.77-gnu1/drivers/pci/pcie/aer/aerdrv_core.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/pci/pcie/aer/aerdrv_core.c	2016-02-27 09:28:50.000000000 -0500
@@ -823,8 +823,6 @@ void aer_isr(struct work_struct *work)
 	while (get_e_source(rpc, &e_src))
 		aer_isr_one_error(p_device, &e_src);
 	mutex_unlock(&rpc->rpc_mutex);
-
-	wake_up(&rpc->wait_release);
 }
 
 /**
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/pci/pcie/aer/aerdrv.h linux-libre-3.2.78-gnu1/drivers/pci/pcie/aer/aerdrv.h
--- linux-libre-3.2.77-gnu1/drivers/pci/pcie/aer/aerdrv.h	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/pci/pcie/aer/aerdrv.h	2016-02-27 09:28:50.000000000 -0500
@@ -76,7 +76,6 @@ struct aer_rpc {
 					 * recovery on the same
 					 * root port hierarchy
 					 */
-	wait_queue_head_t wait_release;
 };
 
 struct aer_broadcast_data {
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/platform/x86/intel_scu_ipcutil.c linux-libre-3.2.78-gnu1/drivers/platform/x86/intel_scu_ipcutil.c
--- linux-libre-3.2.77-gnu1/drivers/platform/x86/intel_scu_ipcutil.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/platform/x86/intel_scu_ipcutil.c	2016-02-27 09:28:50.000000000 -0500
@@ -52,7 +52,7 @@ struct scu_ipc_data {
 
 static int scu_reg_access(u32 cmd, struct scu_ipc_data  *data)
 {
-	int count = data->count;
+	unsigned int count = data->count;
 
 	if (count == 0 || count == 3 || count > 4)
 		return -EINVAL;
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/scsi/device_handler/scsi_dh_rdac.c linux-libre-3.2.78-gnu1/drivers/scsi/device_handler/scsi_dh_rdac.c
--- linux-libre-3.2.77-gnu1/drivers/scsi/device_handler/scsi_dh_rdac.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/scsi/device_handler/scsi_dh_rdac.c	2016-02-27 09:28:50.000000000 -0500
@@ -573,7 +573,7 @@ static int mode_select_handle_sense(stru
 			/*
 			 * Command Lock contention
 			 */
-			err = SCSI_DH_RETRY;
+			err = SCSI_DH_IMM_RETRY;
 		break;
 	default:
 		break;
@@ -623,6 +623,8 @@ retry:
 		err = mode_select_handle_sense(sdev, h->sense);
 		if (err == SCSI_DH_RETRY && retry_cnt--)
 			goto retry;
+		if (err == SCSI_DH_IMM_RETRY)
+			goto retry;
 	}
 	if (err == SCSI_DH_OK) {
 		h->state = RDAC_STATE_ACTIVE;
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/scsi/sd.c linux-libre-3.2.78-gnu1/drivers/scsi/sd.c
--- linux-libre-3.2.77-gnu1/drivers/scsi/sd.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/scsi/sd.c	2016-02-27 09:28:50.000000000 -0500
@@ -2767,8 +2767,8 @@ static int sd_suspend(struct device *dev
 	struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
 	int ret = 0;
 
-	if (!sdkp)
-		return 0;	/* this can happen */
+	if (!sdkp)	/* E.g.: runtime suspend following sd_remove() */
+		return 0;
 
 	if (sdkp->WCE) {
 		sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
@@ -2792,6 +2792,9 @@ static int sd_resume(struct device *dev)
 	struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
 	int ret = 0;
 
+	if (!sdkp)	/* E.g.: runtime resume at the start of sd_probe() */
+		return 0;
+
 	if (!sdkp->device->manage_start_stop)
 		goto done;
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/tty/tty_io.c linux-libre-3.2.78-gnu1/drivers/tty/tty_io.c
--- linux-libre-3.2.77-gnu1/drivers/tty/tty_io.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/tty/tty_io.c	2016-02-27 09:28:50.000000000 -0500
@@ -2475,6 +2475,28 @@ static int tiocsetd(struct tty_struct *t
 }
 
 /**
+ *	tiocgetd	-	get line discipline
+ *	@tty: tty device
+ *	@p: pointer to user data
+ *
+ *	Retrieves the line discipline id directly from the ldisc.
+ *
+ *	Locking: waits for ldisc reference (in case the line discipline
+ *		is changing or the tty is being hungup)
+ */
+
+static int tiocgetd(struct tty_struct *tty, int __user *p)
+{
+	struct tty_ldisc *ld;
+	int ret;
+
+	ld = tty_ldisc_ref_wait(tty);
+	ret = put_user(ld->ops->num, p);
+	tty_ldisc_deref(ld);
+	return ret;
+}
+
+/**
  *	send_break	-	performed time break
  *	@tty: device to break on
  *	@duration: timeout in mS
@@ -2684,7 +2706,7 @@ long tty_ioctl(struct file *file, unsign
 	case TIOCGSID:
 		return tiocgsid(tty, real_tty, p);
 	case TIOCGETD:
-		return put_user(tty->ldisc->ops->num, (int __user *)p);
+		return tiocgetd(tty, p);
 	case TIOCSETD:
 		return tiocsetd(tty, p);
 	case TIOCVHANGUP:
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/usb/class/cdc-acm.c linux-libre-3.2.78-gnu1/drivers/usb/class/cdc-acm.c
--- linux-libre-3.2.77-gnu1/drivers/usb/class/cdc-acm.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/usb/class/cdc-acm.c	2016-02-27 09:28:50.000000000 -0500
@@ -1237,6 +1237,8 @@ made_compressed_probe:
 				usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
 				NULL, acm->writesize, acm_write_bulk, snd);
 		snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+		if (quirks & SEND_ZERO_PACKET)
+			snd->urb->transfer_flags |= URB_ZERO_PACKET;
 		snd->instance = acm;
 	}
 
@@ -1666,6 +1668,11 @@ static const struct usb_device_id acm_id
 	.driver_info = NO_DATA_INTERFACE,
 	},
 
+	/*Samsung phone in firmware update mode */
+	{ USB_DEVICE(0x04e8, 0x685d),
+	.driver_info = IGNORE_DEVICE,
+	},
+
 	/* Exclude Infineon Flash Loader utility */
 	{ USB_DEVICE(0x058b, 0x0041),
 	.driver_info = IGNORE_DEVICE,
@@ -1689,6 +1696,10 @@ static const struct usb_device_id acm_id
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
 		USB_CDC_ACM_PROTO_AT_CDMA) },
 
+	{ USB_DEVICE(0x1519, 0x0452), /* Intel 7260 modem */
+	.driver_info = SEND_ZERO_PACKET,
+	},
+
 	{ }
 };
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/usb/class/cdc-acm.h linux-libre-3.2.78-gnu1/drivers/usb/class/cdc-acm.h
--- linux-libre-3.2.77-gnu1/drivers/usb/class/cdc-acm.h	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/usb/class/cdc-acm.h	2016-02-27 09:28:50.000000000 -0500
@@ -129,3 +129,4 @@ struct acm {
 #define NO_DATA_INTERFACE		16
 #define IGNORE_DEVICE			32
 #define CLEAR_HALT_CONDITIONS		BIT(7)
+#define SEND_ZERO_PACKET		BIT(8)
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/usb/host/xhci.c linux-libre-3.2.78-gnu1/drivers/usb/host/xhci.c
--- linux-libre-3.2.77-gnu1/drivers/usb/host/xhci.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/usb/host/xhci.c	2016-02-27 09:28:50.000000000 -0500
@@ -1533,7 +1533,9 @@ int xhci_urb_dequeue(struct usb_hcd *hcd
 	if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) {
 		xhci_dbg(xhci, "HW died, freeing TD.\n");
 		urb_priv = urb->hcpriv;
-		for (i = urb_priv->td_cnt; i < urb_priv->length; i++) {
+		for (i = urb_priv->td_cnt;
+		     i < urb_priv->length && xhci->devs[urb->dev->slot_id];
+		     i++) {
 			td = urb_priv->td[i];
 			if (!list_empty(&td->td_list))
 				list_del_init(&td->td_list);
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/usb/host/xhci-pci.c linux-libre-3.2.78-gnu1/drivers/usb/host/xhci-pci.c
--- linux-libre-3.2.77-gnu1/drivers/usb/host/xhci-pci.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/usb/host/xhci-pci.c	2016-02-27 09:28:50.000000000 -0500
@@ -39,6 +39,7 @@
 #define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI		0x22b5
 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI		0xa12f
 #define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI	0x9d2f
+#define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI		0x0aa8
 
 static const char hcd_name[] = "xhci_hcd";
 
@@ -132,7 +133,8 @@ static void xhci_pci_quirks(struct devic
 	if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
 		(pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
 		 pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI ||
-		 pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)) {
+		 pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
+		 pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI)) {
 		xhci->quirks |= XHCI_PME_STUCK_QUIRK;
 	}
 	if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/usb/host/xhci-ring.c linux-libre-3.2.78-gnu1/drivers/usb/host/xhci-ring.c
--- linux-libre-3.2.77-gnu1/drivers/usb/host/xhci-ring.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/usb/host/xhci-ring.c	2016-02-27 09:28:50.000000000 -0500
@@ -2187,10 +2187,6 @@ static int process_bulk_intr_td(struct x
 				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
 	/* Fast path - was this the last TRB in the TD for this URB? */
 	if (event_trb == td->last_trb) {
-		if (td->urb_length_set && trb_comp_code == COMP_SHORT_TX)
-			return finish_td(xhci, td, event_trb, event, ep,
-					 status, false);
-
 		if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
 			td->urb->actual_length =
 				td->urb->transfer_buffer_length -
@@ -2242,12 +2238,6 @@ static int process_bulk_intr_td(struct x
 			td->urb->actual_length +=
 				TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
 				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
-
-		if (trb_comp_code == COMP_SHORT_TX) {
-			xhci_dbg(xhci, "mid bulk/intr SP, wait for last TRB event\n");
-			td->urb_length_set = true;
-			return 0;
-		}
 	}
 
 	return finish_td(xhci, td, event_trb, event, ep, status, false);
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/usb/serial/cp210x.c linux-libre-3.2.78-gnu1/drivers/usb/serial/cp210x.c
--- linux-libre-3.2.77-gnu1/drivers/usb/serial/cp210x.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/usb/serial/cp210x.c	2016-02-27 09:28:50.000000000 -0500
@@ -104,6 +104,7 @@ static const struct usb_device_id id_tab
 	{ USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
 	{ USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */
 	{ USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
+	{ USB_DEVICE(0x10C4, 0x81D7) }, /* IAI Corp. RCB-CV-USB USB to RS485 Adaptor */
 	{ USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
 	{ USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */
 	{ USB_DEVICE(0x10C4, 0x81E8) }, /* Zephyr Bioharness */
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/usb/serial/ftdi_sio.c linux-libre-3.2.78-gnu1/drivers/usb/serial/ftdi_sio.c
--- linux-libre-3.2.77-gnu1/drivers/usb/serial/ftdi_sio.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/usb/serial/ftdi_sio.c	2016-02-27 09:28:50.000000000 -0500
@@ -848,6 +848,7 @@ static struct usb_device_id id_table_com
 	{ USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
+	{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_SCU18) },
 	{ USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
 
 	/* Papouch devices based on FTDI chip */
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/usb/serial/ftdi_sio_ids.h linux-libre-3.2.78-gnu1/drivers/usb/serial/ftdi_sio_ids.h
--- linux-libre-3.2.77-gnu1/drivers/usb/serial/ftdi_sio_ids.h	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/usb/serial/ftdi_sio_ids.h	2016-02-27 09:28:50.000000000 -0500
@@ -615,6 +615,7 @@
  */
 #define RATOC_VENDOR_ID		0x0584
 #define RATOC_PRODUCT_ID_USB60F	0xb020
+#define RATOC_PRODUCT_ID_SCU18	0xb03a
 
 /*
  * Acton Research Corp.
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/usb/serial/option.c linux-libre-3.2.78-gnu1/drivers/usb/serial/option.c
--- linux-libre-3.2.77-gnu1/drivers/usb/serial/option.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/usb/serial/option.c	2016-02-27 09:28:50.000000000 -0500
@@ -269,6 +269,8 @@ static void option_instat_callback(struc
 #define TELIT_PRODUCT_CC864_SINGLE		0x1006
 #define TELIT_PRODUCT_DE910_DUAL		0x1010
 #define TELIT_PRODUCT_UE910_V2			0x1012
+#define TELIT_PRODUCT_LE922_USBCFG0		0x1042
+#define TELIT_PRODUCT_LE922_USBCFG3		0x1043
 #define TELIT_PRODUCT_LE920			0x1200
 #define TELIT_PRODUCT_LE910			0x1201
 
@@ -621,6 +623,16 @@ static const struct option_blacklist_inf
 	.reserved = BIT(1) | BIT(5),
 };
 
+static const struct option_blacklist_info telit_le922_blacklist_usbcfg0 = {
+	.sendsetup = BIT(2),
+	.reserved = BIT(0) | BIT(1) | BIT(3),
+};
+
+static const struct option_blacklist_info telit_le922_blacklist_usbcfg3 = {
+	.sendsetup = BIT(0),
+	.reserved = BIT(1) | BIT(2) | BIT(3),
+};
+
 static const struct usb_device_id option_ids[] = {
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
 	{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -1166,6 +1178,10 @@ static const struct usb_device_id option
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
+	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0),
+		.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(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
 		.driver_info = (kernel_ulong_t)&telit_le910_blacklist },
 	{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/usb/serial/visor.c linux-libre-3.2.78-gnu1/drivers/usb/serial/visor.c
--- linux-libre-3.2.77-gnu1/drivers/usb/serial/visor.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/usb/serial/visor.c	2016-02-27 09:28:50.000000000 -0500
@@ -587,6 +587,11 @@ static int treo_attach(struct usb_serial
 
 	dbg("%s", __func__);
 
+	if (serial->num_bulk_in < 2 || serial->num_interrupt_in < 2) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
+
 	/*
 	* It appears that Treos and Kyoceras want to use the
 	* 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
@@ -635,8 +640,10 @@ static int clie_5_attach(struct usb_seri
 	 */
 
 	/* some sanity check */
-	if (serial->num_ports < 2)
-		return -1;
+	if (serial->num_bulk_out < 2) {
+		dev_err(&serial->interface->dev, "missing bulk out endpoints\n");
+		return -ENODEV;
+	}
 
 	/* port 0 now uses the modified endpoint Address */
 	port = serial->port[0];
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/drivers/virtio/virtio_pci.c linux-libre-3.2.78-gnu1/drivers/virtio/virtio_pci.c
--- linux-libre-3.2.77-gnu1/drivers/virtio/virtio_pci.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/drivers/virtio/virtio_pci.c	2016-02-27 09:28:50.000000000 -0500
@@ -698,6 +698,7 @@ out:
 static void __devexit virtio_pci_remove(struct pci_dev *pci_dev)
 {
 	struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
+	struct device *dev = get_device(&vp_dev->vdev.dev);
 
 	unregister_virtio_device(&vp_dev->vdev);
 
@@ -706,6 +707,7 @@ static void __devexit virtio_pci_remove(
 	pci_iounmap(pci_dev, vp_dev->ioaddr);
 	pci_release_regions(pci_dev);
 	pci_disable_device(pci_dev);
+	put_device(dev);
 }
 
 #ifdef CONFIG_PM
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/fs/btrfs/delayed-inode.c linux-libre-3.2.78-gnu1/fs/btrfs/delayed-inode.c
--- linux-libre-3.2.77-gnu1/fs/btrfs/delayed-inode.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/fs/btrfs/delayed-inode.c	2016-02-27 09:28:50.000000000 -0500
@@ -1593,7 +1593,7 @@ int btrfs_should_delete_dir_index(struct
  */
 int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent,
 				    filldir_t filldir,
-				    struct list_head *ins_list)
+				    struct list_head *ins_list, bool *emitted)
 {
 	struct btrfs_dir_item *di;
 	struct btrfs_delayed_item *curr, *next;
@@ -1637,6 +1637,7 @@ int btrfs_readdir_delayed_dir_index(stru
 
 		if (over)
 			return 1;
+		*emitted = true;
 	}
 	return 0;
 }
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/fs/btrfs/delayed-inode.h linux-libre-3.2.78-gnu1/fs/btrfs/delayed-inode.h
--- linux-libre-3.2.77-gnu1/fs/btrfs/delayed-inode.h	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/fs/btrfs/delayed-inode.h	2016-02-27 09:28:50.000000000 -0500
@@ -133,7 +133,7 @@ int btrfs_should_delete_dir_index(struct
 				  u64 index);
 int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent,
 				    filldir_t filldir,
-				    struct list_head *ins_list);
+				    struct list_head *ins_list, bool *emitted);
 
 /* for init */
 int __init btrfs_delayed_inode_init(void);
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/fs/btrfs/inode.c linux-libre-3.2.78-gnu1/fs/btrfs/inode.c
--- linux-libre-3.2.77-gnu1/fs/btrfs/inode.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/fs/btrfs/inode.c	2016-02-27 09:28:50.000000000 -0500
@@ -4111,6 +4111,7 @@ static int btrfs_real_readdir(struct fil
 	char *name_ptr;
 	int name_len;
 	int is_curr = 0;	/* filp->f_pos points to the current index? */
+	bool emitted;
 
 	/* FIXME, use a real flag for deciding about the key type */
 	if (root->fs_info->tree_root == root)
@@ -4153,6 +4154,7 @@ static int btrfs_real_readdir(struct fil
 	if (ret < 0)
 		goto err;
 
+	emitted = false;
 	while (1) {
 		leaf = path->nodes[0];
 		slot = path->slots[0];
@@ -4254,6 +4256,7 @@ skip:
 
 			if (over)
 				goto nopos;
+			emitted = true;
 			di_len = btrfs_dir_name_len(leaf, di) +
 				 btrfs_dir_data_len(leaf, di) + sizeof(*di);
 			di_cur += di_len;
@@ -4267,11 +4270,20 @@ next:
 		if (is_curr)
 			filp->f_pos++;
 		ret = btrfs_readdir_delayed_dir_index(filp, dirent, filldir,
-						      &ins_list);
+						      &ins_list, &emitted);
 		if (ret)
 			goto nopos;
 	}
 
+	/*
+	 * If we haven't emitted any dir entry, we must not touch filp->f_pos as
+	 * it was was set to the termination value in previous call. We assume
+	 * that "." and ".." were emitted if we reach this point and set the
+	 * termination value as well for an empty directory.
+	 */
+	if (filp->f_pos > 2 && !emitted)
+		goto nopos;
+
 	/* Reached end of directory/root. Bump pos past the last item. */
 	if (key_type == BTRFS_DIR_INDEX_KEY)
 		/*
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/fs/ocfs2/dlm/dlmrecovery.c linux-libre-3.2.78-gnu1/fs/ocfs2/dlm/dlmrecovery.c
--- linux-libre-3.2.77-gnu1/fs/ocfs2/dlm/dlmrecovery.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/fs/ocfs2/dlm/dlmrecovery.c	2016-02-27 09:28:50.000000000 -0500
@@ -2333,6 +2333,8 @@ static void dlm_do_local_recovery_cleanu
 						break;
 					}
 				}
+				dlm_lockres_clear_refmap_bit(dlm, res,
+						dead_node);
 				spin_unlock(&res->spinlock);
 				continue;
 			}
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/fs/pipe.c linux-libre-3.2.78-gnu1/fs/pipe.c
--- linux-libre-3.2.77-gnu1/fs/pipe.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/fs/pipe.c	2016-02-27 09:28:50.000000000 -0500
@@ -35,6 +35,12 @@ unsigned int pipe_max_size = 1048576;
  */
 unsigned int pipe_min_size = PAGE_SIZE;
 
+/* Maximum allocatable pages per user. Hard limit is unset by default, soft
+ * matches default values.
+ */
+unsigned long pipe_user_pages_hard;
+unsigned long pipe_user_pages_soft = PIPE_DEF_BUFFERS * INR_OPEN_CUR;
+
 /*
  * We use a start+len construction, which provides full use of the 
  * allocated memory.
@@ -389,6 +395,7 @@ pipe_read(struct kiocb *iocb, const stru
 			void *addr;
 			size_t chars = buf->len, remaining;
 			int error, atomic;
+			int offset;
 
 			if (chars > total_len)
 				chars = total_len;
@@ -402,9 +409,10 @@ pipe_read(struct kiocb *iocb, const stru
 
 			atomic = !iov_fault_in_pages_write(iov, chars);
 			remaining = chars;
+			offset = buf->offset;
 redo:
 			addr = ops->map(pipe, buf, atomic);
-			error = pipe_iov_copy_to_user(iov, addr, &buf->offset,
+			error = pipe_iov_copy_to_user(iov, addr, &offset,
 						      &remaining, atomic);
 			ops->unmap(pipe, buf, addr);
 			if (unlikely(error)) {
@@ -420,6 +428,7 @@ redo:
 				break;
 			}
 			ret += chars;
+			buf->offset += chars;
 			buf->len -= chars;
 
 			/* Was it a packet buffer? Clean up and exit */
@@ -929,20 +938,49 @@ const struct file_operations rdwr_pipefi
 	.fasync		= pipe_rdwr_fasync,
 };
 
+static void account_pipe_buffers(struct pipe_inode_info *pipe,
+                                 unsigned long old, unsigned long new)
+{
+	atomic_long_add(new - old, &pipe->user->pipe_bufs);
+}
+
+static bool too_many_pipe_buffers_soft(struct user_struct *user)
+{
+	return pipe_user_pages_soft &&
+	       atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_soft;
+}
+
+static bool too_many_pipe_buffers_hard(struct user_struct *user)
+{
+	return pipe_user_pages_hard &&
+	       atomic_long_read(&user->pipe_bufs) >= pipe_user_pages_hard;
+}
+
 struct pipe_inode_info * alloc_pipe_info(struct inode *inode)
 {
 	struct pipe_inode_info *pipe;
 
 	pipe = kzalloc(sizeof(struct pipe_inode_info), GFP_KERNEL);
 	if (pipe) {
-		pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * PIPE_DEF_BUFFERS, GFP_KERNEL);
+		unsigned long pipe_bufs = PIPE_DEF_BUFFERS;
+		struct user_struct *user = get_current_user();
+
+		if (!too_many_pipe_buffers_hard(user)) {
+			if (too_many_pipe_buffers_soft(user))
+				pipe_bufs = 1;
+			pipe->bufs = kzalloc(sizeof(struct pipe_buffer) * pipe_bufs, GFP_KERNEL);
+		}
+
 		if (pipe->bufs) {
 			init_waitqueue_head(&pipe->wait);
 			pipe->r_counter = pipe->w_counter = 1;
 			pipe->inode = inode;
-			pipe->buffers = PIPE_DEF_BUFFERS;
+			pipe->buffers = pipe_bufs;
+			pipe->user = user;
+			account_pipe_buffers(pipe, 0, pipe_bufs);
 			return pipe;
 		}
+		free_uid(user);
 		kfree(pipe);
 	}
 
@@ -953,6 +991,8 @@ void __free_pipe_info(struct pipe_inode_
 {
 	int i;
 
+	account_pipe_buffers(pipe, pipe->buffers, 0);
+	free_uid(pipe->user);
 	for (i = 0; i < pipe->buffers; i++) {
 		struct pipe_buffer *buf = pipe->bufs + i;
 		if (buf->ops)
@@ -1201,6 +1241,7 @@ static long pipe_set_size(struct pipe_in
 			memcpy(bufs + head, pipe->bufs, tail * sizeof(struct pipe_buffer));
 	}
 
+	account_pipe_buffers(pipe, pipe->buffers, nr_pages);
 	pipe->curbuf = 0;
 	kfree(pipe->bufs);
 	pipe->bufs = bufs;
@@ -1274,6 +1315,11 @@ long pipe_fcntl(struct file *file, unsig
 		if (!capable(CAP_SYS_RESOURCE) && size > pipe_max_size) {
 			ret = -EPERM;
 			goto out;
+		} else if ((too_many_pipe_buffers_hard(pipe->user) ||
+			    too_many_pipe_buffers_soft(pipe->user)) &&
+		           !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) {
+			ret = -EPERM;
+			goto out;
 		}
 		ret = pipe_set_size(pipe, nr_pages);
 		break;
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/fs/timerfd.c linux-libre-3.2.78-gnu1/fs/timerfd.c
--- linux-libre-3.2.77-gnu1/fs/timerfd.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/fs/timerfd.c	2016-02-27 09:28:50.000000000 -0500
@@ -123,7 +123,7 @@ static ktime_t timerfd_get_remaining(str
 {
 	ktime_t remaining;
 
-	remaining = hrtimer_expires_remaining(&ctx->tmr);
+	remaining = hrtimer_expires_remaining_adjusted(&ctx->tmr);
 	return remaining.tv64 < 0 ? ktime_set(0, 0): remaining;
 }
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/include/linux/hrtimer.h linux-libre-3.2.78-gnu1/include/linux/hrtimer.h
--- linux-libre-3.2.77-gnu1/include/linux/hrtimer.h	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/include/linux/hrtimer.h	2016-02-27 09:28:50.000000000 -0500
@@ -96,6 +96,7 @@ enum hrtimer_restart {
  * @function:	timer expiry callback function
  * @base:	pointer to the timer base (per cpu and per clock)
  * @state:	state information (See bit values above)
+ * @is_rel:	Set if the timer was armed relative
  * @start_site:	timer statistics field to store the site where the timer
  *		was started
  * @start_comm: timer statistics field to store the name of the process which
@@ -110,7 +111,8 @@ struct hrtimer {
 	ktime_t				_softexpires;
 	enum hrtimer_restart		(*function)(struct hrtimer *);
 	struct hrtimer_clock_base	*base;
-	unsigned long			state;
+	u8				state;
+	u8				is_rel;
 #ifdef CONFIG_TIMER_STATS
 	int				start_pid;
 	void				*start_site;
@@ -315,6 +317,29 @@ static inline void clock_was_set_delayed
 
 #endif
 
+static inline ktime_t
+__hrtimer_expires_remaining_adjusted(const struct hrtimer *timer, ktime_t now)
+{
+	ktime_t rem = ktime_sub(timer->node.expires, now);
+
+	/*
+	 * Adjust relative timers for the extra we added in
+	 * hrtimer_start_range_ns() to prevent short timeouts.
+	 */
+#ifdef CONFIG_TIME_LOW_RES
+	if (timer->is_rel)
+		rem = ktime_sub(rem, KTIME_LOW_RES);
+#endif
+	return rem;
+}
+
+static inline ktime_t
+hrtimer_expires_remaining_adjusted(const struct hrtimer *timer)
+{
+	return __hrtimer_expires_remaining_adjusted(timer,
+						    timer->base->get_time());
+}
+
 extern void clock_was_set(void);
 #ifdef CONFIG_TIMERFD
 extern void timerfd_clock_was_set(void);
@@ -383,7 +408,12 @@ static inline int hrtimer_restart(struct
 }
 
 /* Query timers: */
-extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer);
+extern ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool adjust);
+
+static inline ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
+{
+	return __hrtimer_get_remaining(timer, false);
+}
 extern int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp);
 
 extern ktime_t hrtimer_get_next_event(void);
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/include/linux/pipe_fs_i.h linux-libre-3.2.78-gnu1/include/linux/pipe_fs_i.h
--- linux-libre-3.2.77-gnu1/include/linux/pipe_fs_i.h	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/include/linux/pipe_fs_i.h	2016-02-27 09:28:50.000000000 -0500
@@ -43,6 +43,7 @@ struct pipe_buffer {
  *	@fasync_writers: writer side fasync
  *	@inode: inode this pipe is attached to
  *	@bufs: the circular array of pipe buffers
+ *	@user: the user who created this pipe
  **/
 struct pipe_inode_info {
 	wait_queue_head_t wait;
@@ -57,6 +58,7 @@ struct pipe_inode_info {
 	struct fasync_struct *fasync_writers;
 	struct inode *inode;
 	struct pipe_buffer *bufs;
+	struct user_struct *user;
 };
 
 /*
@@ -142,6 +144,8 @@ void pipe_unlock(struct pipe_inode_info
 void pipe_double_lock(struct pipe_inode_info *, struct pipe_inode_info *);
 
 extern unsigned int pipe_max_size, pipe_min_size;
+extern unsigned long pipe_user_pages_hard;
+extern unsigned long pipe_user_pages_soft;
 int pipe_proc_fn(struct ctl_table *, int, void __user *, size_t *, loff_t *);
 
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/include/linux/sched.h linux-libre-3.2.78-gnu1/include/linux/sched.h
--- linux-libre-3.2.77-gnu1/include/linux/sched.h	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/include/linux/sched.h	2016-02-27 09:28:50.000000000 -0500
@@ -709,6 +709,8 @@ struct user_struct {
 	unsigned long mq_bytes;	/* How many bytes can be allocated to mqueue? */
 #endif
 	unsigned long locked_shm; /* How many pages of mlocked shm ? */
+	unsigned long unix_inflight;	/* How many files in flight in unix sockets */
+	atomic_long_t pipe_bufs;  /* how many pages are allocated in pipe buffers */
 
 #ifdef CONFIG_KEYS
 	struct key *uid_keyring;	/* UID specific keyring */
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/include/net/af_unix.h linux-libre-3.2.78-gnu1/include/net/af_unix.h
--- linux-libre-3.2.77-gnu1/include/net/af_unix.h	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/include/net/af_unix.h	2016-02-27 09:28:50.000000000 -0500
@@ -6,8 +6,8 @@
 #include <linux/mutex.h>
 #include <net/sock.h>
 
-extern void unix_inflight(struct file *fp);
-extern void unix_notinflight(struct file *fp);
+extern void unix_inflight(struct user_struct *user, struct file *fp);
+extern void unix_notinflight(struct user_struct *user, struct file *fp);
 extern void unix_gc(void);
 extern void wait_for_unix_gc(void);
 extern struct sock *unix_get_socket(struct file *filp);
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/include/net/scm.h linux-libre-3.2.78-gnu1/include/net/scm.h
--- linux-libre-3.2.77-gnu1/include/net/scm.h	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/include/net/scm.h	2016-02-27 09:28:50.000000000 -0500
@@ -16,6 +16,7 @@ struct scm_fp_list {
 	struct list_head	list;
 	short			count;
 	short			max;
+	struct user_struct	*user;
 	struct file		*fp[SCM_MAX_FD];
 };
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/include/sound/rawmidi.h linux-libre-3.2.78-gnu1/include/sound/rawmidi.h
--- linux-libre-3.2.77-gnu1/include/sound/rawmidi.h	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/include/sound/rawmidi.h	2016-02-27 09:28:50.000000000 -0500
@@ -167,6 +167,10 @@ int snd_rawmidi_transmit_peek(struct snd
 int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count);
 int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
 			 unsigned char *buffer, int count);
+int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
+			      unsigned char *buffer, int count);
+int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream,
+			       int count);
 
 /* main midi functions */
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/kernel/hrtimer.c linux-libre-3.2.78-gnu1/kernel/hrtimer.c
--- linux-libre-3.2.77-gnu1/kernel/hrtimer.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/kernel/hrtimer.c	2016-02-27 09:28:50.000000000 -0500
@@ -910,7 +910,7 @@ static int enqueue_hrtimer(struct hrtime
  */
 static void __remove_hrtimer(struct hrtimer *timer,
 			     struct hrtimer_clock_base *base,
-			     unsigned long newstate, int reprogram)
+			     u8 newstate, int reprogram)
 {
 	struct timerqueue_node *next_timer;
 	if (!(timer->state & HRTIMER_STATE_ENQUEUED))
@@ -944,7 +944,7 @@ static inline int
 remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base)
 {
 	if (hrtimer_is_queued(timer)) {
-		unsigned long state;
+		u8 state;
 		int reprogram;
 
 		/*
@@ -970,6 +970,22 @@ remove_hrtimer(struct hrtimer *timer, st
 	return 0;
 }
 
+static inline ktime_t hrtimer_update_lowres(struct hrtimer *timer, ktime_t tim,
+					    const enum hrtimer_mode mode)
+{
+#ifdef CONFIG_TIME_LOW_RES
+	/*
+	 * CONFIG_TIME_LOW_RES indicates that the system has no way to return
+	 * granular time values. For relative timers we add KTIME_LOW_RES
+	 * (i.e. one jiffie) to prevent short timeouts.
+	 */
+	timer->is_rel = mode & HRTIMER_MODE_REL;
+	if (timer->is_rel)
+		tim = ktime_add_safe(tim, KTIME_LOW_RES);
+#endif
+	return tim;
+}
+
 int __hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
 		unsigned long delta_ns, const enum hrtimer_mode mode,
 		int wakeup)
@@ -983,19 +999,10 @@ int __hrtimer_start_range_ns(struct hrti
 	/* Remove an active timer from the queue: */
 	ret = remove_hrtimer(timer, base);
 
-	if (mode & HRTIMER_MODE_REL) {
+	if (mode & HRTIMER_MODE_REL)
 		tim = ktime_add_safe(tim, base->get_time());
-		/*
-		 * CONFIG_TIME_LOW_RES is a temporary way for architectures
-		 * to signal that they simply return xtime in
-		 * do_gettimeoffset(). In this case we want to round up by
-		 * resolution when starting a relative timer, to avoid short
-		 * timeouts. This will go away with the GTOD framework.
-		 */
-#ifdef CONFIG_TIME_LOW_RES
-		tim = ktime_add_safe(tim, base->resolution);
-#endif
-	}
+
+	tim = hrtimer_update_lowres(timer, tim, mode);
 
 	hrtimer_set_expires_range_ns(timer, tim, delta_ns);
 
@@ -1120,19 +1127,25 @@ EXPORT_SYMBOL_GPL(hrtimer_cancel);
 /**
  * hrtimer_get_remaining - get remaining time for the timer
  * @timer:	the timer to read
+ * @adjust:	adjust relative timers when CONFIG_TIME_LOW_RES=y
  */
-ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
+ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool adjust)
 {
 	unsigned long flags;
 	ktime_t rem;
 
 	lock_hrtimer_base(timer, &flags);
-	rem = hrtimer_expires_remaining(timer);
+#ifdef CONFIG_TIME_LOW_RES
+	if (adjust)
+		rem = hrtimer_expires_remaining_adjusted(timer);
+	else
+#endif
+		rem = hrtimer_expires_remaining(timer);
 	unlock_hrtimer_base(timer, &flags);
 
 	return rem;
 }
-EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
+EXPORT_SYMBOL_GPL(__hrtimer_get_remaining);
 
 #ifdef CONFIG_NO_HZ
 /**
@@ -1249,6 +1262,15 @@ static void __run_hrtimer(struct hrtimer
 	fn = timer->function;
 
 	/*
+	 * Clear the 'is relative' flag for the TIME_LOW_RES case. If the
+	 * timer is restarted with a period then it becomes an absolute
+	 * timer. If its not restarted it does not matter.
+	 */
+#ifdef CONFIG_TIME_LOW_RES
+	timer->is_rel = false;
+#endif
+
+	/*
 	 * Because we run timers from hardirq context, there is no chance
 	 * they get migrated to another cpu, therefore its safe to unlock
 	 * the timer base.
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/kernel/itimer.c linux-libre-3.2.78-gnu1/kernel/itimer.c
--- linux-libre-3.2.77-gnu1/kernel/itimer.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/kernel/itimer.c	2016-02-27 09:28:50.000000000 -0500
@@ -26,7 +26,7 @@
  */
 static struct timeval itimer_get_remtime(struct hrtimer *timer)
 {
-	ktime_t rem = hrtimer_get_remaining(timer);
+	ktime_t rem = __hrtimer_get_remaining(timer, true);
 
 	/*
 	 * Racy but safe: if the itimer expires after the above
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/kernel/posix-timers.c linux-libre-3.2.78-gnu1/kernel/posix-timers.c
--- linux-libre-3.2.77-gnu1/kernel/posix-timers.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/kernel/posix-timers.c	2016-02-27 09:28:50.000000000 -0500
@@ -706,7 +706,7 @@ common_timer_get(struct k_itimer *timr,
 	    (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
 		timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv);
 
-	remaining = ktime_sub(hrtimer_get_expires(timer), now);
+	remaining = __hrtimer_expires_remaining_adjusted(timer, now);
 	/* Return 0 only, when the timer is expired and not pending */
 	if (remaining.tv64 <= 0) {
 		/*
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/kernel/sched_fair.c linux-libre-3.2.78-gnu1/kernel/sched_fair.c
--- linux-libre-3.2.77-gnu1/kernel/sched_fair.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/kernel/sched_fair.c	2016-02-27 09:28:50.000000000 -0500
@@ -2791,6 +2791,7 @@ int can_migrate_task(struct task_struct
 	 * 1) running (obviously), or
 	 * 2) cannot be migrated to this CPU due to cpus_allowed, or
 	 * 3) are cache-hot on their current CPU.
+	 * 4) p->pi_lock is held.
 	 */
 	if (!cpumask_test_cpu(this_cpu, tsk_cpus_allowed(p))) {
 		schedstat_inc(p, se.statistics.nr_failed_migrations_affine);
@@ -2804,6 +2805,14 @@ int can_migrate_task(struct task_struct
 	}
 
 	/*
+	 * rt -> fair class change may be in progress.  If we sneak in should
+	 * double_lock_balance() release rq->lock, and move the task, we will
+	 * cause switched_to_fair() to meet a passed but no longer valid rq.
+	 */
+	if (raw_spin_is_locked(&p->pi_lock))
+		return 0;
+
+	/*
 	 * Aggressive migration if:
 	 * 1) task is cache cold, or
 	 * 2) too many balance attempts have failed.
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/kernel/sysctl.c linux-libre-3.2.78-gnu1/kernel/sysctl.c
--- linux-libre-3.2.77-gnu1/kernel/sysctl.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/kernel/sysctl.c	2016-02-27 09:28:50.000000000 -0500
@@ -1518,6 +1518,20 @@ static struct ctl_table fs_table[] = {
 		.proc_handler	= &pipe_proc_fn,
 		.extra1		= &pipe_min_size,
 	},
+	{
+		.procname	= "pipe-user-pages-hard",
+		.data		= &pipe_user_pages_hard,
+		.maxlen		= sizeof(pipe_user_pages_hard),
+		.mode		= 0644,
+		.proc_handler	= proc_doulongvec_minmax,
+	},
+	{
+		.procname	= "pipe-user-pages-soft",
+		.data		= &pipe_user_pages_soft,
+		.maxlen		= sizeof(pipe_user_pages_soft),
+		.mode		= 0644,
+		.proc_handler	= proc_doulongvec_minmax,
+	},
 	{ }
 };
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/kernel/time/timer_list.c linux-libre-3.2.78-gnu1/kernel/time/timer_list.c
--- linux-libre-3.2.77-gnu1/kernel/time/timer_list.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/kernel/time/timer_list.c	2016-02-27 09:28:50.000000000 -0500
@@ -57,7 +57,7 @@ print_timer(struct seq_file *m, struct h
 	print_name_offset(m, taddr);
 	SEQ_printf(m, ", ");
 	print_name_offset(m, timer->function);
-	SEQ_printf(m, ", S:%02lx", timer->state);
+	SEQ_printf(m, ", S:%02x", timer->state);
 #ifdef CONFIG_TIMER_STATS
 	SEQ_printf(m, ", ");
 	print_name_offset(m, timer->start_site);
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/lib/klist.c linux-libre-3.2.78-gnu1/lib/klist.c
--- linux-libre-3.2.77-gnu1/lib/klist.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/lib/klist.c	2016-02-27 09:28:50.000000000 -0500
@@ -282,9 +282,9 @@ void klist_iter_init_node(struct klist *
 			  struct klist_node *n)
 {
 	i->i_klist = k;
-	i->i_cur = n;
-	if (n)
-		kref_get(&n->n_ref);
+	i->i_cur = NULL;
+	if (n && kref_get_unless_zero(&n->n_ref))
+		i->i_cur = n;
 }
 EXPORT_SYMBOL_GPL(klist_iter_init_node);
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/Makefile linux-libre-3.2.78-gnu1/Makefile
--- linux-libre-3.2.77-gnu1/Makefile	2016-02-13 23:16:39.000000000 -0500
+++ linux-libre-3.2.78-gnu1/Makefile	2016-02-28 20:53:54.000000000 -0500
@@ -1,6 +1,6 @@
 VERSION = 3
 PATCHLEVEL = 2
-SUBLEVEL = 77
+SUBLEVEL = 78
 EXTRAVERSION =-gnu1
 NAME = Saber-toothed Squirrel
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/mm/backing-dev.c linux-libre-3.2.78-gnu1/mm/backing-dev.c
--- linux-libre-3.2.77-gnu1/mm/backing-dev.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/mm/backing-dev.c	2016-02-27 09:28:50.000000000 -0500
@@ -879,7 +879,7 @@ long wait_iff_congested(struct zone *zon
 		 * here rather than calling cond_resched().
 		 */
 		if (current->flags & PF_WQ_WORKER)
-			schedule_timeout(1);
+			schedule_timeout_uninterruptible(1);
 		else
 			cond_resched();
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/net/core/scm.c linux-libre-3.2.78-gnu1/net/core/scm.c
--- linux-libre-3.2.77-gnu1/net/core/scm.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/net/core/scm.c	2016-02-27 09:28:50.000000000 -0500
@@ -80,6 +80,7 @@ static int scm_fp_copy(struct cmsghdr *c
 		*fplp = fpl;
 		fpl->count = 0;
 		fpl->max = SCM_MAX_FD;
+		fpl->user = NULL;
 	}
 	fpp = &fpl->fp[fpl->count];
 
@@ -100,6 +101,10 @@ static int scm_fp_copy(struct cmsghdr *c
 		*fpp++ = file;
 		fpl->count++;
 	}
+
+	if (!fpl->user)
+		fpl->user = get_uid(current_user());
+
 	return num;
 }
 
@@ -124,6 +129,7 @@ void __scm_destroy(struct scm_cookie *sc
 				list_del(&fpl->list);
 				for (i=fpl->count-1; i>=0; i--)
 					fput(fpl->fp[i]);
+				free_uid(fpl->user);
 				kfree(fpl);
 			}
 
@@ -342,6 +348,7 @@ struct scm_fp_list *scm_fp_dup(struct sc
 		for (i = 0; i < fpl->count; i++)
 			get_file(fpl->fp[i]);
 		new_fpl->max = new_fpl->count;
+		new_fpl->user = get_uid(fpl->user);
 	}
 	return new_fpl;
 }
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/net/rfkill/core.c linux-libre-3.2.78-gnu1/net/rfkill/core.c
--- linux-libre-3.2.77-gnu1/net/rfkill/core.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/net/rfkill/core.c	2016-02-27 09:28:50.000000000 -0500
@@ -1065,17 +1065,6 @@ static unsigned int rfkill_fop_poll(stru
 	return res;
 }
 
-static bool rfkill_readable(struct rfkill_data *data)
-{
-	bool r;
-
-	mutex_lock(&data->mtx);
-	r = !list_empty(&data->events);
-	mutex_unlock(&data->mtx);
-
-	return r;
-}
-
 static ssize_t rfkill_fop_read(struct file *file, char __user *buf,
 			       size_t count, loff_t *pos)
 {
@@ -1092,8 +1081,11 @@ static ssize_t rfkill_fop_read(struct fi
 			goto out;
 		}
 		mutex_unlock(&data->mtx);
+		/* since we re-check and it just compares pointers,
+		 * using !list_empty() without locking isn't a problem
+		 */
 		ret = wait_event_interruptible(data->read_wait,
-					       rfkill_readable(data));
+					       !list_empty(&data->events));
 		mutex_lock(&data->mtx);
 
 		if (ret)
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/net/sctp/socket.c linux-libre-3.2.78-gnu1/net/sctp/socket.c
--- linux-libre-3.2.77-gnu1/net/sctp/socket.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/net/sctp/socket.c	2016-02-27 09:28:50.000000000 -0500
@@ -5309,6 +5309,7 @@ static int sctp_getsockopt_hmac_ident(st
 	struct sctp_hmac_algo_param *hmacs;
 	__u16 data_len = 0;
 	u32 num_idents;
+	int i;
 
 	if (!sctp_auth_enable)
 		return -EACCES;
@@ -5326,8 +5327,12 @@ static int sctp_getsockopt_hmac_ident(st
 		return -EFAULT;
 	if (put_user(num_idents, &p->shmac_num_idents))
 		return -EFAULT;
-	if (copy_to_user(p->shmac_idents, hmacs->hmac_ids, data_len))
-		return -EFAULT;
+	for (i = 0; i < num_idents; i++) {
+		__u16 hmacid = ntohs(hmacs->hmac_ids[i]);
+
+		if (copy_to_user(&p->shmac_idents[i], &hmacid, sizeof(__u16)))
+			return -EFAULT;
+	}
 	return 0;
 }
 
@@ -6241,6 +6246,7 @@ SCTP_STATIC int sctp_msghdr_parse(const
 			/* Minimally, validate the sinfo_flags. */
 			if (cmsgs->info->sinfo_flags &
 			    ~(SCTP_UNORDERED | SCTP_ADDR_OVER |
+			      SCTP_SACK_IMMEDIATELY |
 			      SCTP_ABORT | SCTP_EOF))
 				return -EINVAL;
 			break;
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/net/unix/af_unix.c linux-libre-3.2.78-gnu1/net/unix/af_unix.c
--- linux-libre-3.2.77-gnu1/net/unix/af_unix.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/net/unix/af_unix.c	2016-02-27 09:28:50.000000000 -0500
@@ -1454,7 +1454,7 @@ static void unix_detach_fds(struct scm_c
 	UNIXCB(skb).fp = NULL;
 
 	for (i = scm->fp->count-1; i >= 0; i--)
-		unix_notinflight(scm->fp->fp[i]);
+		unix_notinflight(scm->fp->user, scm->fp->fp[i]);
 }
 
 static void unix_destruct_scm(struct sk_buff *skb)
@@ -1472,6 +1472,21 @@ static void unix_destruct_scm(struct sk_
 	sock_wfree(skb);
 }
 
+/*
+ * The "user->unix_inflight" variable is protected by the garbage
+ * collection lock, and we just read it locklessly here. If you go
+ * over the limit, there might be a tiny race in actually noticing
+ * it across threads. Tough.
+ */
+static inline bool too_many_unix_fds(struct task_struct *p)
+{
+	struct user_struct *user = current_user();
+
+	if (unlikely(user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE)))
+		return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN);
+	return false;
+}
+
 #define MAX_RECURSION_LEVEL 4
 
 static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
@@ -1480,6 +1495,9 @@ static int unix_attach_fds(struct scm_co
 	unsigned char max_level = 0;
 	int unix_sock_count = 0;
 
+	if (too_many_unix_fds(current))
+		return -ETOOMANYREFS;
+
 	for (i = scm->fp->count - 1; i >= 0; i--) {
 		struct sock *sk = unix_get_socket(scm->fp->fp[i]);
 
@@ -1501,10 +1519,8 @@ static int unix_attach_fds(struct scm_co
 	if (!UNIXCB(skb).fp)
 		return -ENOMEM;
 
-	if (unix_sock_count) {
-		for (i = scm->fp->count - 1; i >= 0; i--)
-			unix_inflight(scm->fp->fp[i]);
-	}
+	for (i = scm->fp->count - 1; i >= 0; i--)
+		unix_inflight(scm->fp->user, scm->fp->fp[i]);
 	return max_level;
 }
 
@@ -2100,6 +2116,7 @@ static int unix_stream_recvmsg(struct ki
 
 			if (signal_pending(current)) {
 				err = sock_intr_errno(timeo);
+				scm_destroy(siocb->scm);
 				goto out;
 			}
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/net/unix/garbage.c linux-libre-3.2.78-gnu1/net/unix/garbage.c
--- linux-libre-3.2.77-gnu1/net/unix/garbage.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/net/unix/garbage.c	2016-02-27 09:28:50.000000000 -0500
@@ -122,12 +122,14 @@ struct sock *unix_get_socket(struct file
  *	descriptor if it is for an AF_UNIX socket.
  */
 
-void unix_inflight(struct file *fp)
+void unix_inflight(struct user_struct *user, struct file *fp)
 {
 	struct sock *s = unix_get_socket(fp);
+
+	spin_lock(&unix_gc_lock);
+
 	if (s) {
 		struct unix_sock *u = unix_sk(s);
-		spin_lock(&unix_gc_lock);
 		if (atomic_long_inc_return(&u->inflight) == 1) {
 			BUG_ON(!list_empty(&u->link));
 			list_add_tail(&u->link, &gc_inflight_list);
@@ -135,22 +137,26 @@ void unix_inflight(struct file *fp)
 			BUG_ON(list_empty(&u->link));
 		}
 		unix_tot_inflight++;
-		spin_unlock(&unix_gc_lock);
 	}
+	user->unix_inflight++;
+	spin_unlock(&unix_gc_lock);
 }
 
-void unix_notinflight(struct file *fp)
+void unix_notinflight(struct user_struct *user, struct file *fp)
 {
 	struct sock *s = unix_get_socket(fp);
+
+	spin_lock(&unix_gc_lock);
+
 	if (s) {
 		struct unix_sock *u = unix_sk(s);
-		spin_lock(&unix_gc_lock);
 		BUG_ON(list_empty(&u->link));
 		if (atomic_long_dec_and_test(&u->inflight))
 			list_del_init(&u->link);
 		unix_tot_inflight--;
-		spin_unlock(&unix_gc_lock);
 	}
+	user->unix_inflight--;
+	spin_unlock(&unix_gc_lock);
 }
 
 static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *),
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/sound/core/oss/pcm_oss.c linux-libre-3.2.78-gnu1/sound/core/oss/pcm_oss.c
--- linux-libre-3.2.77-gnu1/sound/core/oss/pcm_oss.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/sound/core/oss/pcm_oss.c	2016-02-27 09:28:50.000000000 -0500
@@ -834,7 +834,8 @@ static int choose_rate(struct snd_pcm_su
 	return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL);
 }
 
-static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
+static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream,
+				     bool trylock)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_pcm_hw_params *params, *sparams;
@@ -848,7 +849,10 @@ static int snd_pcm_oss_change_params(str
 	struct snd_mask sformat_mask;
 	struct snd_mask mask;
 
-	if (mutex_lock_interruptible(&runtime->oss.params_lock))
+	if (trylock) {
+		if (!(mutex_trylock(&runtime->oss.params_lock)))
+			return -EAGAIN;
+	} else if (mutex_lock_interruptible(&runtime->oss.params_lock))
 		return -EINTR;
 	sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL);
 	params = kmalloc(sizeof(*params), GFP_KERNEL);
@@ -1091,7 +1095,7 @@ static int snd_pcm_oss_get_active_substr
 		if (asubstream == NULL)
 			asubstream = substream;
 		if (substream->runtime->oss.params) {
-			err = snd_pcm_oss_change_params(substream);
+			err = snd_pcm_oss_change_params(substream, false);
 			if (err < 0)
 				return err;
 		}
@@ -1130,7 +1134,7 @@ static int snd_pcm_oss_make_ready(struct
 		return 0;
 	runtime = substream->runtime;
 	if (runtime->oss.params) {
-		err = snd_pcm_oss_change_params(substream);
+		err = snd_pcm_oss_change_params(substream, false);
 		if (err < 0)
 			return err;
 	}
@@ -2168,7 +2172,7 @@ static int snd_pcm_oss_get_space(struct
 	runtime = substream->runtime;
 
 	if (runtime->oss.params &&
-	    (err = snd_pcm_oss_change_params(substream)) < 0)
+	    (err = snd_pcm_oss_change_params(substream, false)) < 0)
 		return err;
 
 	info.fragsize = runtime->oss.period_bytes;
@@ -2804,7 +2808,12 @@ static int snd_pcm_oss_mmap(struct file
 		return -EIO;
 	
 	if (runtime->oss.params) {
-		if ((err = snd_pcm_oss_change_params(substream)) < 0)
+		/* use mutex_trylock() for params_lock for avoiding a deadlock
+		 * between mmap_sem and params_lock taken by
+		 * copy_from/to_user() in snd_pcm_oss_write/read()
+		 */
+		err = snd_pcm_oss_change_params(substream, true);
+		if (err < 0)
 			return err;
 	}
 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/sound/core/rawmidi.c linux-libre-3.2.78-gnu1/sound/core/rawmidi.c
--- linux-libre-3.2.77-gnu1/sound/core/rawmidi.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/sound/core/rawmidi.c	2016-02-27 09:28:50.000000000 -0500
@@ -934,31 +934,36 @@ static long snd_rawmidi_kernel_read1(str
 	unsigned long flags;
 	long result = 0, count1;
 	struct snd_rawmidi_runtime *runtime = substream->runtime;
+	unsigned long appl_ptr;
 
+	spin_lock_irqsave(&runtime->lock, flags);
 	while (count > 0 && runtime->avail) {
 		count1 = runtime->buffer_size - runtime->appl_ptr;
 		if (count1 > count)
 			count1 = count;
-		spin_lock_irqsave(&runtime->lock, flags);
 		if (count1 > (int)runtime->avail)
 			count1 = runtime->avail;
+
+		/* update runtime->appl_ptr before unlocking for userbuf */
+		appl_ptr = runtime->appl_ptr;
+		runtime->appl_ptr += count1;
+		runtime->appl_ptr %= runtime->buffer_size;
+		runtime->avail -= count1;
+
 		if (kernelbuf)
-			memcpy(kernelbuf + result, runtime->buffer + runtime->appl_ptr, count1);
+			memcpy(kernelbuf + result, runtime->buffer + appl_ptr, count1);
 		if (userbuf) {
 			spin_unlock_irqrestore(&runtime->lock, flags);
 			if (copy_to_user(userbuf + result,
-					 runtime->buffer + runtime->appl_ptr, count1)) {
+					 runtime->buffer + appl_ptr, count1)) {
 				return result > 0 ? result : -EFAULT;
 			}
 			spin_lock_irqsave(&runtime->lock, flags);
 		}
-		runtime->appl_ptr += count1;
-		runtime->appl_ptr %= runtime->buffer_size;
-		runtime->avail -= count1;
-		spin_unlock_irqrestore(&runtime->lock, flags);
 		result += count1;
 		count -= count1;
 	}
+	spin_unlock_irqrestore(&runtime->lock, flags);
 	return result;
 }
 
@@ -1044,23 +1049,16 @@ int snd_rawmidi_transmit_empty(struct sn
 }
 
 /**
- * snd_rawmidi_transmit_peek - copy data from the internal buffer
+ * __snd_rawmidi_transmit_peek - copy data from the internal buffer
  * @substream: the rawmidi substream
  * @buffer: the buffer pointer
  * @count: data size to transfer
  *
- * Copies data from the internal output buffer to the given buffer.
- *
- * Call this in the interrupt handler when the midi output is ready,
- * and call snd_rawmidi_transmit_ack() after the transmission is
- * finished.
- *
- * Returns the size of copied data, or a negative error code on failure.
+ * This is a variant of snd_rawmidi_transmit_peek() without spinlock.
  */
-int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
+int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
 			      unsigned char *buffer, int count)
 {
-	unsigned long flags;
 	int result, count1;
 	struct snd_rawmidi_runtime *runtime = substream->runtime;
 
@@ -1069,7 +1067,6 @@ int snd_rawmidi_transmit_peek(struct snd
 		return -EINVAL;
 	}
 	result = 0;
-	spin_lock_irqsave(&runtime->lock, flags);
 	if (runtime->avail >= runtime->buffer_size) {
 		/* warning: lowlevel layer MUST trigger down the hardware */
 		goto __skip;
@@ -1094,31 +1091,52 @@ int snd_rawmidi_transmit_peek(struct snd
 		}
 	}
       __skip:
-	spin_unlock_irqrestore(&runtime->lock, flags);
 	return result;
 }
+EXPORT_SYMBOL(__snd_rawmidi_transmit_peek);
 
 /**
- * snd_rawmidi_transmit_ack - acknowledge the transmission
+ * snd_rawmidi_transmit_peek - copy data from the internal buffer
  * @substream: the rawmidi substream
- * @count: the tranferred count
+ * @buffer: the buffer pointer
+ * @count: data size to transfer
  *
- * Advances the hardware pointer for the internal output buffer with
- * the given size and updates the condition.
- * Call after the transmission is finished.
+ * Copies data from the internal output buffer to the given buffer.
  *
- * Returns the advanced size if successful, or a negative error code on failure.
+ * Call this in the interrupt handler when the midi output is ready,
+ * and call snd_rawmidi_transmit_ack() after the transmission is
+ * finished.
+ *
+ * Return: The size of copied data, or a negative error code on failure.
  */
-int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
+int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
+			      unsigned char *buffer, int count)
 {
+	struct snd_rawmidi_runtime *runtime = substream->runtime;
+	int result;
 	unsigned long flags;
+
+	spin_lock_irqsave(&runtime->lock, flags);
+	result = __snd_rawmidi_transmit_peek(substream, buffer, count);
+	spin_unlock_irqrestore(&runtime->lock, flags);
+	return result;
+}
+
+/**
+ * __snd_rawmidi_transmit_ack - acknowledge the transmission
+ * @substream: the rawmidi substream
+ * @count: the tranferred count
+ *
+ * This is a variant of __snd_rawmidi_transmit_ack() without spinlock.
+ */
+int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
+{
 	struct snd_rawmidi_runtime *runtime = substream->runtime;
 
 	if (runtime->buffer == NULL) {
 		snd_printd("snd_rawmidi_transmit_ack: output is not active!!!\n");
 		return -EINVAL;
 	}
-	spin_lock_irqsave(&runtime->lock, flags);
 	snd_BUG_ON(runtime->avail + count > runtime->buffer_size);
 	runtime->hw_ptr += count;
 	runtime->hw_ptr %= runtime->buffer_size;
@@ -1128,9 +1146,32 @@ int snd_rawmidi_transmit_ack(struct snd_
 		if (runtime->drain || snd_rawmidi_ready(substream))
 			wake_up(&runtime->sleep);
 	}
-	spin_unlock_irqrestore(&runtime->lock, flags);
 	return count;
 }
+EXPORT_SYMBOL(__snd_rawmidi_transmit_ack);
+
+/**
+ * snd_rawmidi_transmit_ack - acknowledge the transmission
+ * @substream: the rawmidi substream
+ * @count: the transferred count
+ *
+ * Advances the hardware pointer for the internal output buffer with
+ * the given size and updates the condition.
+ * Call after the transmission is finished.
+ *
+ * Return: The advanced size if successful, or a negative error code on failure.
+ */
+int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
+{
+	struct snd_rawmidi_runtime *runtime = substream->runtime;
+	int result;
+	unsigned long flags;
+
+	spin_lock_irqsave(&runtime->lock, flags);
+	result = __snd_rawmidi_transmit_ack(substream, count);
+	spin_unlock_irqrestore(&runtime->lock, flags);
+	return result;
+}
 
 /**
  * snd_rawmidi_transmit - copy from the buffer to the device
@@ -1145,12 +1186,22 @@ int snd_rawmidi_transmit_ack(struct snd_
 int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
 			 unsigned char *buffer, int count)
 {
+	struct snd_rawmidi_runtime *runtime = substream->runtime;
+	int result;
+	unsigned long flags;
+
+	spin_lock_irqsave(&runtime->lock, flags);
 	if (!substream->opened)
-		return -EBADFD;
-	count = snd_rawmidi_transmit_peek(substream, buffer, count);
-	if (count < 0)
-		return count;
-	return snd_rawmidi_transmit_ack(substream, count);
+		result = -EBADFD;
+	else {
+		count = __snd_rawmidi_transmit_peek(substream, buffer, count);
+		if (count <= 0)
+			result = count;
+		else
+			result = __snd_rawmidi_transmit_ack(substream, count);
+	}
+	spin_unlock_irqrestore(&runtime->lock, flags);
+	return result;
 }
 
 static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
@@ -1161,8 +1212,9 @@ static long snd_rawmidi_kernel_write1(st
 	unsigned long flags;
 	long count1, result;
 	struct snd_rawmidi_runtime *runtime = substream->runtime;
+	unsigned long appl_ptr;
 
-	if (snd_BUG_ON(!kernelbuf && !userbuf))
+	if (!kernelbuf && !userbuf)
 		return -EINVAL;
 	if (snd_BUG_ON(!runtime->buffer))
 		return -EINVAL;
@@ -1181,12 +1233,19 @@ static long snd_rawmidi_kernel_write1(st
 			count1 = count;
 		if (count1 > (long)runtime->avail)
 			count1 = runtime->avail;
+
+		/* update runtime->appl_ptr before unlocking for userbuf */
+		appl_ptr = runtime->appl_ptr;
+		runtime->appl_ptr += count1;
+		runtime->appl_ptr %= runtime->buffer_size;
+		runtime->avail -= count1;
+
 		if (kernelbuf)
-			memcpy(runtime->buffer + runtime->appl_ptr,
+			memcpy(runtime->buffer + appl_ptr,
 			       kernelbuf + result, count1);
 		else if (userbuf) {
 			spin_unlock_irqrestore(&runtime->lock, flags);
-			if (copy_from_user(runtime->buffer + runtime->appl_ptr,
+			if (copy_from_user(runtime->buffer + appl_ptr,
 					   userbuf + result, count1)) {
 				spin_lock_irqsave(&runtime->lock, flags);
 				result = result > 0 ? result : -EFAULT;
@@ -1194,9 +1253,6 @@ static long snd_rawmidi_kernel_write1(st
 			}
 			spin_lock_irqsave(&runtime->lock, flags);
 		}
-		runtime->appl_ptr += count1;
-		runtime->appl_ptr %= runtime->buffer_size;
-		runtime->avail -= count1;
 		result += count1;
 		count -= count1;
 	}
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/sound/core/seq/oss/seq_oss_init.c linux-libre-3.2.78-gnu1/sound/core/seq/oss/seq_oss_init.c
--- linux-libre-3.2.77-gnu1/sound/core/seq/oss/seq_oss_init.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/sound/core/seq/oss/seq_oss_init.c	2016-02-27 09:28:50.000000000 -0500
@@ -196,7 +196,7 @@ snd_seq_oss_open(struct file *file, int
 
 	dp->index = i;
 	if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) {
-		snd_printk(KERN_ERR "too many applications\n");
+		pr_debug("ALSA: seq_oss: too many applications\n");
 		rc = -ENOMEM;
 		goto _error;
 	}
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/sound/core/seq/oss/seq_oss_synth.c linux-libre-3.2.78-gnu1/sound/core/seq/oss/seq_oss_synth.c
--- linux-libre-3.2.77-gnu1/sound/core/seq/oss/seq_oss_synth.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/sound/core/seq/oss/seq_oss_synth.c	2016-02-27 09:28:50.000000000 -0500
@@ -310,7 +310,7 @@ snd_seq_oss_synth_cleanup(struct seq_oss
 	struct seq_oss_synth *rec;
 	struct seq_oss_synthinfo *info;
 
-	if (snd_BUG_ON(dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
+	if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
 		return;
 	for (i = 0; i < dp->max_synthdev; i++) {
 		info = &dp->synths[i];
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/sound/core/seq/seq_clientmgr.c linux-libre-3.2.78-gnu1/sound/core/seq/seq_clientmgr.c
--- linux-libre-3.2.77-gnu1/sound/core/seq/seq_clientmgr.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/sound/core/seq/seq_clientmgr.c	2016-02-27 09:28:50.000000000 -0500
@@ -678,6 +678,9 @@ static int deliver_to_subscribers(struct
 	else
 		down_read(&grp->list_mutex);
 	list_for_each_entry(subs, &grp->list_head, src_list) {
+		/* both ports ready? */
+		if (atomic_read(&subs->ref_count) != 2)
+			continue;
 		event->dest = subs->info.dest;
 		if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)
 			/* convert time according to flag with subscription */
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/sound/core/seq/seq_ports.c linux-libre-3.2.78-gnu1/sound/core/seq/seq_ports.c
--- linux-libre-3.2.77-gnu1/sound/core/seq/seq_ports.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/sound/core/seq/seq_ports.c	2016-02-27 09:28:50.000000000 -0500
@@ -175,10 +175,6 @@ struct snd_seq_client_port *snd_seq_crea
 }
 
 /* */
-enum group_type {
-	SRC_LIST, DEST_LIST
-};
-
 static int subscribe_port(struct snd_seq_client *client,
 			  struct snd_seq_client_port *port,
 			  struct snd_seq_port_subs_info *grp,
@@ -205,6 +201,20 @@ static struct snd_seq_client_port *get_c
 	return NULL;
 }
 
+static void delete_and_unsubscribe_port(struct snd_seq_client *client,
+					struct snd_seq_client_port *port,
+					struct snd_seq_subscribers *subs,
+					bool is_src, bool ack);
+
+static inline struct snd_seq_subscribers *
+get_subscriber(struct list_head *p, bool is_src)
+{
+	if (is_src)
+		return list_entry(p, struct snd_seq_subscribers, src_list);
+	else
+		return list_entry(p, struct snd_seq_subscribers, dest_list);
+}
+
 /*
  * remove all subscribers on the list
  * this is called from port_delete, for each src and dest list.
@@ -212,7 +222,7 @@ static struct snd_seq_client_port *get_c
 static void clear_subscriber_list(struct snd_seq_client *client,
 				  struct snd_seq_client_port *port,
 				  struct snd_seq_port_subs_info *grp,
-				  int grptype)
+				  int is_src)
 {
 	struct list_head *p, *n;
 
@@ -221,15 +231,13 @@ static void clear_subscriber_list(struct
 		struct snd_seq_client *c;
 		struct snd_seq_client_port *aport;
 
-		if (grptype == SRC_LIST) {
-			subs = list_entry(p, struct snd_seq_subscribers, src_list);
+		subs = get_subscriber(p, is_src);
+		if (is_src)
 			aport = get_client_port(&subs->info.dest, &c);
-		} else {
-			subs = list_entry(p, struct snd_seq_subscribers, dest_list);
+		else
 			aport = get_client_port(&subs->info.sender, &c);
-		}
-		list_del(p);
-		unsubscribe_port(client, port, grp, &subs->info, 0);
+		delete_and_unsubscribe_port(client, port, subs, is_src, false);
+
 		if (!aport) {
 			/* looks like the connected port is being deleted.
 			 * we decrease the counter, and when both ports are deleted
@@ -237,21 +245,14 @@ static void clear_subscriber_list(struct
 			 */
 			if (atomic_dec_and_test(&subs->ref_count))
 				kfree(subs);
-		} else {
-			/* ok we got the connected port */
-			struct snd_seq_port_subs_info *agrp;
-			agrp = (grptype == SRC_LIST) ? &aport->c_dest : &aport->c_src;
-			down_write(&agrp->list_mutex);
-			if (grptype == SRC_LIST)
-				list_del(&subs->dest_list);
-			else
-				list_del(&subs->src_list);
-			up_write(&agrp->list_mutex);
-			unsubscribe_port(c, aport, agrp, &subs->info, 1);
-			kfree(subs);
-			snd_seq_port_unlock(aport);
-			snd_seq_client_unlock(c);
+			continue;
 		}
+
+		/* ok we got the connected port */
+		delete_and_unsubscribe_port(c, aport, subs, !is_src, true);
+		kfree(subs);
+		snd_seq_port_unlock(aport);
+		snd_seq_client_unlock(c);
 	}
 }
 
@@ -264,8 +265,8 @@ static int port_delete(struct snd_seq_cl
 	snd_use_lock_sync(&port->use_lock); 
 
 	/* clear subscribers info */
-	clear_subscriber_list(client, port, &port->c_src, SRC_LIST);
-	clear_subscriber_list(client, port, &port->c_dest, DEST_LIST);
+	clear_subscriber_list(client, port, &port->c_src, true);
+	clear_subscriber_list(client, port, &port->c_dest, false);
 
 	if (port->private_free)
 		port->private_free(port->private_data);
@@ -484,85 +485,120 @@ static int match_subs_info(struct snd_se
 	return 0;
 }
 
-
-/* connect two ports */
-int snd_seq_port_connect(struct snd_seq_client *connector,
-			 struct snd_seq_client *src_client,
-			 struct snd_seq_client_port *src_port,
-			 struct snd_seq_client *dest_client,
-			 struct snd_seq_client_port *dest_port,
-			 struct snd_seq_port_subscribe *info)
+static int check_and_subscribe_port(struct snd_seq_client *client,
+				    struct snd_seq_client_port *port,
+				    struct snd_seq_subscribers *subs,
+				    bool is_src, bool exclusive, bool ack)
 {
-	struct snd_seq_port_subs_info *src = &src_port->c_src;
-	struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
-	struct snd_seq_subscribers *subs, *s;
-	int err, src_called = 0;
-	unsigned long flags;
-	int exclusive;
-
-	subs = kzalloc(sizeof(*subs), GFP_KERNEL);
-	if (! subs)
-		return -ENOMEM;
-
-	subs->info = *info;
-	atomic_set(&subs->ref_count, 2);
-
-	down_write(&src->list_mutex);
-	down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
+	struct snd_seq_port_subs_info *grp;
+	struct list_head *p;
+	struct snd_seq_subscribers *s;
+	int err;
 
-	exclusive = info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE ? 1 : 0;
+	grp = is_src ? &port->c_src : &port->c_dest;
 	err = -EBUSY;
+	down_write(&grp->list_mutex);
 	if (exclusive) {
-		if (! list_empty(&src->list_head) || ! list_empty(&dest->list_head))
+		if (!list_empty(&grp->list_head))
 			goto __error;
 	} else {
-		if (src->exclusive || dest->exclusive)
+		if (grp->exclusive)
 			goto __error;
 		/* check whether already exists */
-		list_for_each_entry(s, &src->list_head, src_list) {
-			if (match_subs_info(info, &s->info))
-				goto __error;
-		}
-		list_for_each_entry(s, &dest->list_head, dest_list) {
-			if (match_subs_info(info, &s->info))
+		list_for_each(p, &grp->list_head) {
+			s = get_subscriber(p, is_src);
+			if (match_subs_info(&subs->info, &s->info))
 				goto __error;
 		}
 	}
 
-	if ((err = subscribe_port(src_client, src_port, src, info,
-				  connector->number != src_client->number)) < 0)
-		goto __error;
-	src_called = 1;
-
-	if ((err = subscribe_port(dest_client, dest_port, dest, info,
-				  connector->number != dest_client->number)) < 0)
+	err = subscribe_port(client, port, grp, &subs->info, ack);
+	if (err < 0) {
+		grp->exclusive = 0;
 		goto __error;
+	}
 
 	/* add to list */
-	write_lock_irqsave(&src->list_lock, flags);
-	// write_lock(&dest->list_lock); // no other lock yet
-	list_add_tail(&subs->src_list, &src->list_head);
-	list_add_tail(&subs->dest_list, &dest->list_head);
-	// write_unlock(&dest->list_lock); // no other lock yet
-	write_unlock_irqrestore(&src->list_lock, flags);
+	write_lock_irq(&grp->list_lock);
+	if (is_src)
+		list_add_tail(&subs->src_list, &grp->list_head);
+	else
+		list_add_tail(&subs->dest_list, &grp->list_head);
+	grp->exclusive = exclusive;
+	atomic_inc(&subs->ref_count);
+	write_unlock_irq(&grp->list_lock);
+	err = 0;
 
-	src->exclusive = dest->exclusive = exclusive;
+ __error:
+	up_write(&grp->list_mutex);
+	return err;
+}
+
+static void delete_and_unsubscribe_port(struct snd_seq_client *client,
+					struct snd_seq_client_port *port,
+					struct snd_seq_subscribers *subs,
+					bool is_src, bool ack)
+{
+	struct snd_seq_port_subs_info *grp;
+
+	grp = is_src ? &port->c_src : &port->c_dest;
+	down_write(&grp->list_mutex);
+	write_lock_irq(&grp->list_lock);
+	if (is_src)
+		list_del(&subs->src_list);
+	else
+		list_del(&subs->dest_list);
+	grp->exclusive = 0;
+	write_unlock_irq(&grp->list_lock);
+	up_write(&grp->list_mutex);
+
+	unsubscribe_port(client, port, grp, &subs->info, ack);
+}
+
+/* connect two ports */
+int snd_seq_port_connect(struct snd_seq_client *connector,
+			 struct snd_seq_client *src_client,
+			 struct snd_seq_client_port *src_port,
+			 struct snd_seq_client *dest_client,
+			 struct snd_seq_client_port *dest_port,
+			 struct snd_seq_port_subscribe *info)
+{
+	struct snd_seq_subscribers *subs;
+	bool exclusive;
+	int err;
+
+	subs = kzalloc(sizeof(*subs), GFP_KERNEL);
+	if (!subs)
+		return -ENOMEM;
+
+	subs->info = *info;
+	atomic_set(&subs->ref_count, 0);
+	INIT_LIST_HEAD(&subs->src_list);
+	INIT_LIST_HEAD(&subs->dest_list);
+
+	exclusive = !!(info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE);
+
+	err = check_and_subscribe_port(src_client, src_port, subs, true,
+				       exclusive,
+				       connector->number != src_client->number);
+	if (err < 0)
+		goto error;
+	err = check_and_subscribe_port(dest_client, dest_port, subs, false,
+				       exclusive,
+				       connector->number != dest_client->number);
+	if (err < 0)
+		goto error_dest;
 
-	up_write(&dest->list_mutex);
-	up_write(&src->list_mutex);
 	return 0;
 
- __error:
-	if (src_called)
-		unsubscribe_port(src_client, src_port, src, info,
-				 connector->number != src_client->number);
+ error_dest:
+	delete_and_unsubscribe_port(src_client, src_port, subs, true,
+				    connector->number != src_client->number);
+ error:
 	kfree(subs);
-	up_write(&dest->list_mutex);
-	up_write(&src->list_mutex);
 	return err;
 }
 
-
 /* remove the connection */
 int snd_seq_port_disconnect(struct snd_seq_client *connector,
 			    struct snd_seq_client *src_client,
@@ -572,37 +608,28 @@ int snd_seq_port_disconnect(struct snd_s
 			    struct snd_seq_port_subscribe *info)
 {
 	struct snd_seq_port_subs_info *src = &src_port->c_src;
-	struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
 	struct snd_seq_subscribers *subs;
 	int err = -ENOENT;
-	unsigned long flags;
 
 	down_write(&src->list_mutex);
-	down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
-
 	/* look for the connection */
 	list_for_each_entry(subs, &src->list_head, src_list) {
 		if (match_subs_info(info, &subs->info)) {
-			write_lock_irqsave(&src->list_lock, flags);
-			// write_lock(&dest->list_lock);  // no lock yet
-			list_del(&subs->src_list);
-			list_del(&subs->dest_list);
-			// write_unlock(&dest->list_lock);
-			write_unlock_irqrestore(&src->list_lock, flags);
-			src->exclusive = dest->exclusive = 0;
-			unsubscribe_port(src_client, src_port, src, info,
-					 connector->number != src_client->number);
-			unsubscribe_port(dest_client, dest_port, dest, info,
-					 connector->number != dest_client->number);
-			kfree(subs);
+			atomic_dec(&subs->ref_count); /* mark as not ready */
 			err = 0;
 			break;
 		}
 	}
-
-	up_write(&dest->list_mutex);
 	up_write(&src->list_mutex);
-	return err;
+	if (err < 0)
+		return err;
+
+	delete_and_unsubscribe_port(src_client, src_port, subs, true,
+				    connector->number != src_client->number);
+	delete_and_unsubscribe_port(dest_client, dest_port, subs, false,
+				    connector->number != dest_client->number);
+	kfree(subs);
+	return 0;
 }
 
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/sound/core/seq/seq_timer.c linux-libre-3.2.78-gnu1/sound/core/seq/seq_timer.c
--- linux-libre-3.2.77-gnu1/sound/core/seq/seq_timer.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/sound/core/seq/seq_timer.c	2016-02-27 09:28:50.000000000 -0500
@@ -92,6 +92,9 @@ void snd_seq_timer_delete(struct snd_seq
 
 void snd_seq_timer_defaults(struct snd_seq_timer * tmr)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&tmr->lock, flags);
 	/* setup defaults */
 	tmr->ppq = 96;		/* 96 PPQ */
 	tmr->tempo = 500000;	/* 120 BPM */
@@ -107,21 +110,25 @@ void snd_seq_timer_defaults(struct snd_s
 	tmr->preferred_resolution = seq_default_timer_resolution;
 
 	tmr->skew = tmr->skew_base = SKEW_BASE;
+	spin_unlock_irqrestore(&tmr->lock, flags);
 }
 
-void snd_seq_timer_reset(struct snd_seq_timer * tmr)
+static void seq_timer_reset(struct snd_seq_timer *tmr)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&tmr->lock, flags);
-
 	/* reset time & songposition */
 	tmr->cur_time.tv_sec = 0;
 	tmr->cur_time.tv_nsec = 0;
 
 	tmr->tick.cur_tick = 0;
 	tmr->tick.fraction = 0;
+}
 
+void snd_seq_timer_reset(struct snd_seq_timer *tmr)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&tmr->lock, flags);
+	seq_timer_reset(tmr);
 	spin_unlock_irqrestore(&tmr->lock, flags);
 }
 
@@ -140,8 +147,11 @@ static void snd_seq_timer_interrupt(stru
 	tmr = q->timer;
 	if (tmr == NULL)
 		return;
-	if (!tmr->running)
+	spin_lock_irqsave(&tmr->lock, flags);
+	if (!tmr->running) {
+		spin_unlock_irqrestore(&tmr->lock, flags);
 		return;
+	}
 
 	resolution *= ticks;
 	if (tmr->skew != tmr->skew_base) {
@@ -150,8 +160,6 @@ static void snd_seq_timer_interrupt(stru
 			(((resolution & 0xffff) * tmr->skew) >> 16);
 	}
 
-	spin_lock_irqsave(&tmr->lock, flags);
-
 	/* update timer */
 	snd_seq_inc_time_nsec(&tmr->cur_time, resolution);
 
@@ -298,26 +306,30 @@ int snd_seq_timer_open(struct snd_seq_qu
 	t->callback = snd_seq_timer_interrupt;
 	t->callback_data = q;
 	t->flags |= SNDRV_TIMER_IFLG_AUTO;
+	spin_lock_irq(&tmr->lock);
 	tmr->timeri = t;
+	spin_unlock_irq(&tmr->lock);
 	return 0;
 }
 
 int snd_seq_timer_close(struct snd_seq_queue *q)
 {
 	struct snd_seq_timer *tmr;
+	struct snd_timer_instance *t;
 	
 	tmr = q->timer;
 	if (snd_BUG_ON(!tmr))
 		return -EINVAL;
-	if (tmr->timeri) {
-		snd_timer_stop(tmr->timeri);
-		snd_timer_close(tmr->timeri);
-		tmr->timeri = NULL;
-	}
+	spin_lock_irq(&tmr->lock);
+	t = tmr->timeri;
+	tmr->timeri = NULL;
+	spin_unlock_irq(&tmr->lock);
+	if (t)
+		snd_timer_close(t);
 	return 0;
 }
 
-int snd_seq_timer_stop(struct snd_seq_timer * tmr)
+static int seq_timer_stop(struct snd_seq_timer *tmr)
 {
 	if (! tmr->timeri)
 		return -EINVAL;
@@ -328,6 +340,17 @@ int snd_seq_timer_stop(struct snd_seq_ti
 	return 0;
 }
 
+int snd_seq_timer_stop(struct snd_seq_timer *tmr)
+{
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&tmr->lock, flags);
+	err = seq_timer_stop(tmr);
+	spin_unlock_irqrestore(&tmr->lock, flags);
+	return err;
+}
+
 static int initialize_timer(struct snd_seq_timer *tmr)
 {
 	struct snd_timer *t;
@@ -360,13 +383,13 @@ static int initialize_timer(struct snd_s
 	return 0;
 }
 
-int snd_seq_timer_start(struct snd_seq_timer * tmr)
+static int seq_timer_start(struct snd_seq_timer *tmr)
 {
 	if (! tmr->timeri)
 		return -EINVAL;
 	if (tmr->running)
-		snd_seq_timer_stop(tmr);
-	snd_seq_timer_reset(tmr);
+		seq_timer_stop(tmr);
+	seq_timer_reset(tmr);
 	if (initialize_timer(tmr) < 0)
 		return -EINVAL;
 	snd_timer_start(tmr->timeri, tmr->ticks);
@@ -375,14 +398,25 @@ int snd_seq_timer_start(struct snd_seq_t
 	return 0;
 }
 
-int snd_seq_timer_continue(struct snd_seq_timer * tmr)
+int snd_seq_timer_start(struct snd_seq_timer *tmr)
+{
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&tmr->lock, flags);
+	err = seq_timer_start(tmr);
+	spin_unlock_irqrestore(&tmr->lock, flags);
+	return err;
+}
+
+static int seq_timer_continue(struct snd_seq_timer *tmr)
 {
 	if (! tmr->timeri)
 		return -EINVAL;
 	if (tmr->running)
 		return -EBUSY;
 	if (! tmr->initialized) {
-		snd_seq_timer_reset(tmr);
+		seq_timer_reset(tmr);
 		if (initialize_timer(tmr) < 0)
 			return -EINVAL;
 	}
@@ -392,11 +426,24 @@ int snd_seq_timer_continue(struct snd_se
 	return 0;
 }
 
+int snd_seq_timer_continue(struct snd_seq_timer *tmr)
+{
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&tmr->lock, flags);
+	err = seq_timer_continue(tmr);
+	spin_unlock_irqrestore(&tmr->lock, flags);
+	return err;
+}
+
 /* return current 'real' time. use timeofday() to get better granularity. */
 snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
 {
 	snd_seq_real_time_t cur_time;
+	unsigned long flags;
 
+	spin_lock_irqsave(&tmr->lock, flags);
 	cur_time = tmr->cur_time;
 	if (tmr->running) { 
 		struct timeval tm;
@@ -412,7 +459,7 @@ snd_seq_real_time_t snd_seq_timer_get_cu
 		}
 		snd_seq_sanity_real_time(&cur_time);
 	}
-                
+	spin_unlock_irqrestore(&tmr->lock, flags);
 	return cur_time;	
 }
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/sound/core/seq/seq_virmidi.c linux-libre-3.2.78-gnu1/sound/core/seq/seq_virmidi.c
--- linux-libre-3.2.77-gnu1/sound/core/seq/seq_virmidi.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/sound/core/seq/seq_virmidi.c	2016-02-27 09:28:50.000000000 -0500
@@ -155,21 +155,26 @@ static void snd_virmidi_output_trigger(s
 	struct snd_virmidi *vmidi = substream->runtime->private_data;
 	int count, res;
 	unsigned char buf[32], *pbuf;
+	unsigned long flags;
 
 	if (up) {
 		vmidi->trigger = 1;
 		if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH &&
 		    !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) {
-			snd_rawmidi_transmit_ack(substream, substream->runtime->buffer_size - substream->runtime->avail);
-			return;		/* ignored */
+			while (snd_rawmidi_transmit(substream, buf,
+						    sizeof(buf)) > 0) {
+				/* ignored */
+			}
+			return;
 		}
 		if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
 			if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
 				return;
 			vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
 		}
+		spin_lock_irqsave(&substream->runtime->lock, flags);
 		while (1) {
-			count = snd_rawmidi_transmit_peek(substream, buf, sizeof(buf));
+			count = __snd_rawmidi_transmit_peek(substream, buf, sizeof(buf));
 			if (count <= 0)
 				break;
 			pbuf = buf;
@@ -179,16 +184,18 @@ static void snd_virmidi_output_trigger(s
 					snd_midi_event_reset_encode(vmidi->parser);
 					continue;
 				}
-				snd_rawmidi_transmit_ack(substream, res);
+				__snd_rawmidi_transmit_ack(substream, res);
 				pbuf += res;
 				count -= res;
 				if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
 					if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
-						return;
+						goto out;
 					vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
 				}
 			}
 		}
+	out:
+		spin_unlock_irqrestore(&substream->runtime->lock, flags);
 	} else {
 		vmidi->trigger = 0;
 	}
@@ -254,9 +261,13 @@ static int snd_virmidi_output_open(struc
  */
 static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream)
 {
+	struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
 	struct snd_virmidi *vmidi = substream->runtime->private_data;
-	snd_midi_event_free(vmidi->parser);
+
+	write_lock_irq(&rdev->filelist_lock);
 	list_del(&vmidi->list);
+	write_unlock_irq(&rdev->filelist_lock);
+	snd_midi_event_free(vmidi->parser);
 	substream->runtime->private_data = NULL;
 	kfree(vmidi);
 	return 0;
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/sound/core/timer.c linux-libre-3.2.78-gnu1/sound/core/timer.c
--- linux-libre-3.2.77-gnu1/sound/core/timer.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/sound/core/timer.c	2016-02-27 09:28:50.000000000 -0500
@@ -414,7 +414,7 @@ static void snd_timer_notify1(struct snd
 	spin_lock_irqsave(&timer->lock, flags);
 	list_for_each_entry(ts, &ti->slave_active_head, active_list)
 		if (ts->ccallback)
-			ts->ccallback(ti, event + 100, &tstamp, resolution);
+			ts->ccallback(ts, event + 100, &tstamp, resolution);
 	spin_unlock_irqrestore(&timer->lock, flags);
 }
 
@@ -443,6 +443,10 @@ static int snd_timer_start_slave(struct
 	unsigned long flags;
 
 	spin_lock_irqsave(&slave_active_lock, flags);
+	if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
+		spin_unlock_irqrestore(&slave_active_lock, flags);
+		return -EBUSY;
+	}
 	timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
 	if (timeri->master && timeri->timer) {
 		spin_lock(&timeri->timer->lock);
@@ -467,18 +471,26 @@ int snd_timer_start(struct snd_timer_ins
 		return -EINVAL;
 	if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
 		result = snd_timer_start_slave(timeri);
-		snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
+		if (result >= 0)
+			snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
 		return result;
 	}
 	timer = timeri->timer;
 	if (timer == NULL)
 		return -EINVAL;
 	spin_lock_irqsave(&timer->lock, flags);
+	if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
+			     SNDRV_TIMER_IFLG_START)) {
+		result = -EBUSY;
+		goto unlock;
+	}
 	timeri->ticks = timeri->cticks = ticks;
 	timeri->pticks = 0;
 	result = snd_timer_start1(timer, timeri, ticks);
+ unlock:
 	spin_unlock_irqrestore(&timer->lock, flags);
-	snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
+	if (result >= 0)
+		snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
 	return result;
 }
 
@@ -494,9 +506,17 @@ static int _snd_timer_stop(struct snd_ti
 	if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
 		if (!keep_flag) {
 			spin_lock_irqsave(&slave_active_lock, flags);
+			if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
+				spin_unlock_irqrestore(&slave_active_lock, flags);
+				return -EBUSY;
+			}
+			if (timeri->timer)
+				spin_lock(&timeri->timer->lock);
 			timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
 			list_del_init(&timeri->ack_list);
 			list_del_init(&timeri->active_list);
+			if (timeri->timer)
+				spin_unlock(&timeri->timer->lock);
 			spin_unlock_irqrestore(&slave_active_lock, flags);
 		}
 		goto __end;
@@ -505,6 +525,11 @@ static int _snd_timer_stop(struct snd_ti
 	if (!timer)
 		return -EINVAL;
 	spin_lock_irqsave(&timer->lock, flags);
+	if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
+			       SNDRV_TIMER_IFLG_START))) {
+		spin_unlock_irqrestore(&timer->lock, flags);
+		return -EBUSY;
+	}
 	list_del_init(&timeri->ack_list);
 	list_del_init(&timeri->active_list);
 	if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) &&
@@ -570,10 +595,15 @@ int snd_timer_continue(struct snd_timer_
 	if (! timer)
 		return -EINVAL;
 	spin_lock_irqsave(&timer->lock, flags);
+	if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
+		result = -EBUSY;
+		goto unlock;
+	}
 	if (!timeri->cticks)
 		timeri->cticks = 1;
 	timeri->pticks = 0;
 	result = snd_timer_start1(timer, timeri, timer->sticks);
+ unlock:
 	spin_unlock_irqrestore(&timer->lock, flags);
 	snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE);
 	return result;
@@ -701,8 +731,8 @@ void snd_timer_interrupt(struct snd_time
 			ti->cticks = ti->ticks;
 		} else {
 			ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
-			if (--timer->running)
-				list_del_init(&ti->active_list);
+			--timer->running;
+			list_del_init(&ti->active_list);
 		}
 		if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
 		    (ti->flags & SNDRV_TIMER_IFLG_FAST))
@@ -1860,6 +1890,7 @@ static ssize_t snd_timer_user_read(struc
 {
 	struct snd_timer_user *tu;
 	long result = 0, unit;
+	int qhead;
 	int err = 0;
 
 	tu = file->private_data;
@@ -1871,7 +1902,7 @@ static ssize_t snd_timer_user_read(struc
 
 			if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
 				err = -EAGAIN;
-				break;
+				goto _error;
 			}
 
 			set_current_state(TASK_INTERRUPTIBLE);
@@ -1886,38 +1917,33 @@ static ssize_t snd_timer_user_read(struc
 
 			if (signal_pending(current)) {
 				err = -ERESTARTSYS;
-				break;
+				goto _error;
 			}
 		}
 
+		qhead = tu->qhead++;
+		tu->qhead %= tu->queue_size;
 		spin_unlock_irq(&tu->qlock);
-		if (err < 0)
-			goto _error;
 
 		if (tu->tread) {
-			if (copy_to_user(buffer, &tu->tqueue[tu->qhead++],
-					 sizeof(struct snd_timer_tread))) {
+			if (copy_to_user(buffer, &tu->tqueue[qhead],
+					 sizeof(struct snd_timer_tread)))
 				err = -EFAULT;
-				goto _error;
-			}
 		} else {
-			if (copy_to_user(buffer, &tu->queue[tu->qhead++],
-					 sizeof(struct snd_timer_read))) {
+			if (copy_to_user(buffer, &tu->queue[qhead],
+					 sizeof(struct snd_timer_read)))
 				err = -EFAULT;
-				goto _error;
-			}
 		}
 
-		tu->qhead %= tu->queue_size;
-
-		result += unit;
-		buffer += unit;
-
 		spin_lock_irq(&tu->qlock);
 		tu->qused--;
+		if (err < 0)
+			goto _error;
+		result += unit;
+		buffer += unit;
 	}
-	spin_unlock_irq(&tu->qlock);
  _error:
+	spin_unlock_irq(&tu->qlock);
 	return result > 0 ? result : err;
 }
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/sound/drivers/dummy.c linux-libre-3.2.78-gnu1/sound/drivers/dummy.c
--- linux-libre-3.2.77-gnu1/sound/drivers/dummy.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/sound/drivers/dummy.c	2016-02-27 09:28:50.000000000 -0500
@@ -109,6 +109,9 @@ struct dummy_timer_ops {
 	snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *);
 };
 
+#define get_dummy_ops(substream) \
+	(*(const struct dummy_timer_ops **)(substream)->runtime->private_data)
+
 struct dummy_model {
 	const char *name;
 	int (*playback_constraints)(struct snd_pcm_runtime *runtime);
@@ -134,7 +137,6 @@ struct snd_dummy {
 	spinlock_t mixer_lock;
 	int mixer_volume[MIXER_ADDR_LAST+1][2];
 	int capture_source[MIXER_ADDR_LAST+1][2];
-	const struct dummy_timer_ops *timer_ops;
 };
 
 /*
@@ -228,6 +230,8 @@ struct dummy_model *dummy_models[] = {
  */
 
 struct dummy_systimer_pcm {
+	/* ops must be the first item */
+	const struct dummy_timer_ops *timer_ops;
 	spinlock_t lock;
 	struct timer_list timer;
 	unsigned long base_time;
@@ -365,6 +369,8 @@ static struct dummy_timer_ops dummy_syst
  */
 
 struct dummy_hrtimer_pcm {
+	/* ops must be the first item */
+	const struct dummy_timer_ops *timer_ops;
 	ktime_t base_time;
 	ktime_t period_time;
 	atomic_t running;
@@ -491,31 +497,25 @@ static struct dummy_timer_ops dummy_hrti
 
 static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
 {
-	struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
-
 	switch (cmd) {
 	case SNDRV_PCM_TRIGGER_START:
 	case SNDRV_PCM_TRIGGER_RESUME:
-		return dummy->timer_ops->start(substream);
+		return get_dummy_ops(substream)->start(substream);
 	case SNDRV_PCM_TRIGGER_STOP:
 	case SNDRV_PCM_TRIGGER_SUSPEND:
-		return dummy->timer_ops->stop(substream);
+		return get_dummy_ops(substream)->stop(substream);
 	}
 	return -EINVAL;
 }
 
 static int dummy_pcm_prepare(struct snd_pcm_substream *substream)
 {
-	struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
-
-	return dummy->timer_ops->prepare(substream);
+	return get_dummy_ops(substream)->prepare(substream);
 }
 
 static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream)
 {
-	struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
-
-	return dummy->timer_ops->pointer(substream);
+	return get_dummy_ops(substream)->pointer(substream);
 }
 
 static struct snd_pcm_hardware dummy_pcm_hardware = {
@@ -561,17 +561,19 @@ static int dummy_pcm_open(struct snd_pcm
 	struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
 	struct dummy_model *model = dummy->model;
 	struct snd_pcm_runtime *runtime = substream->runtime;
+	const struct dummy_timer_ops *ops;
 	int err;
 
-	dummy->timer_ops = &dummy_systimer_ops;
+	ops = &dummy_systimer_ops;
 #ifdef CONFIG_HIGH_RES_TIMERS
 	if (hrtimer)
-		dummy->timer_ops = &dummy_hrtimer_ops;
+		ops = &dummy_hrtimer_ops;
 #endif
 
-	err = dummy->timer_ops->create(substream);
+	err = ops->create(substream);
 	if (err < 0)
 		return err;
+	get_dummy_ops(substream) = ops;
 
 	runtime->hw = dummy->pcm_hw;
 	if (substream->pcm->device & 1) {
@@ -593,7 +595,7 @@ static int dummy_pcm_open(struct snd_pcm
 			err = model->capture_constraints(substream->runtime);
 	}
 	if (err < 0) {
-		dummy->timer_ops->free(substream);
+		get_dummy_ops(substream)->free(substream);
 		return err;
 	}
 	return 0;
@@ -601,8 +603,7 @@ static int dummy_pcm_open(struct snd_pcm
 
 static int dummy_pcm_close(struct snd_pcm_substream *substream)
 {
-	struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
-	dummy->timer_ops->free(substream);
+	get_dummy_ops(substream)->free(substream);
 	return 0;
 }
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/sound/usb/midi.c linux-libre-3.2.78-gnu1/sound/usb/midi.c
--- linux-libre-3.2.77-gnu1/sound/usb/midi.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/sound/usb/midi.c	2016-02-27 09:28:50.000000000 -0500
@@ -2289,7 +2289,6 @@ int snd_usbmidi_create(struct snd_card *
 	else
 		err = snd_usbmidi_create_endpoints(umidi, endpoints);
 	if (err < 0) {
-		snd_usbmidi_free(umidi);
 		return err;
 	}
 
diff -druNp --no-dereference linux-libre-3.2.77-gnu1/tools/perf/util/ui/browsers/annotate.c linux-libre-3.2.78-gnu1/tools/perf/util/ui/browsers/annotate.c
--- linux-libre-3.2.77-gnu1/tools/perf/util/ui/browsers/annotate.c	2016-02-13 05:34:14.000000000 -0500
+++ linux-libre-3.2.78-gnu1/tools/perf/util/ui/browsers/annotate.c	2016-02-27 09:28:50.000000000 -0500
@@ -276,11 +276,11 @@ static int annotate_browser__run(struct
 				nd = self->curr_hot;
 			break;
 		case K_UNTAB:
-			if (nd != NULL)
+			if (nd != NULL) {
 				nd = rb_next(nd);
 				if (nd == NULL)
 					nd = rb_first(&self->entries);
-			else
+			} else
 				nd = self->curr_hot;
 			break;
 		case 'H':
