diff -druN linux-libre-3.0.57-gnu/arch/arm/kernel/swp_emulate.c linux-libre-3.0.58-gnu/arch/arm/kernel/swp_emulate.c
--- linux-libre-3.0.57-gnu/arch/arm/kernel/swp_emulate.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/arch/arm/kernel/swp_emulate.c	2013-01-11 12:04:08.000000000 -0500
@@ -108,10 +108,12 @@
 {
 	siginfo_t info;
 
+	down_read(&current->mm->mmap_sem);
 	if (find_vma(current->mm, addr) == NULL)
 		info.si_code = SEGV_MAPERR;
 	else
 		info.si_code = SEGV_ACCERR;
+	up_read(&current->mm->mmap_sem);
 
 	info.si_signo = SIGSEGV;
 	info.si_errno = 0;
diff -druN linux-libre-3.0.57-gnu/arch/arm/mm/mmu.c linux-libre-3.0.58-gnu/arch/arm/mm/mmu.c
--- linux-libre-3.0.57-gnu/arch/arm/mm/mmu.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/arch/arm/mm/mmu.c	2013-01-11 12:04:08.000000000 -0500
@@ -467,7 +467,7 @@
 	}
 
 	for (i = 0; i < 16; i++) {
-		unsigned long v = pgprot_val(protection_map[i]);
+		pteval_t v = pgprot_val(protection_map[i]);
 		protection_map[i] = __pgprot(v | user_pgprot);
 	}
 
diff -druN linux-libre-3.0.57-gnu/arch/cris/include/asm/io.h linux-libre-3.0.58-gnu/arch/cris/include/asm/io.h
--- linux-libre-3.0.57-gnu/arch/cris/include/asm/io.h	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/arch/cris/include/asm/io.h	2013-01-11 12:04:08.000000000 -0500
@@ -133,12 +133,39 @@
 #define insb(port,addr,count) (cris_iops ? cris_iops->read_io(port,addr,1,count) : 0)
 #define insw(port,addr,count) (cris_iops ? cris_iops->read_io(port,addr,2,count) : 0)
 #define insl(port,addr,count) (cris_iops ? cris_iops->read_io(port,addr,4,count) : 0)
-#define outb(data,port) if (cris_iops) cris_iops->write_io(port,(void*)(unsigned)data,1,1)
-#define outw(data,port) if (cris_iops) cris_iops->write_io(port,(void*)(unsigned)data,2,1)
-#define outl(data,port) if (cris_iops) cris_iops->write_io(port,(void*)(unsigned)data,4,1)
-#define outsb(port,addr,count) if(cris_iops) cris_iops->write_io(port,(void*)addr,1,count)
-#define outsw(port,addr,count) if(cris_iops) cris_iops->write_io(port,(void*)addr,2,count)
-#define outsl(port,addr,count) if(cris_iops) cris_iops->write_io(port,(void*)addr,3,count)
+static inline void outb(unsigned char data, unsigned int port)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *) &data, 1, 1);
+}
+static inline void outw(unsigned short data, unsigned int port)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *) &data, 2, 1);
+}
+static inline void outl(unsigned int data, unsigned int port)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *) &data, 4, 1);
+}
+static inline void outsb(unsigned int port, const void *addr,
+			 unsigned long count)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *)addr, 1, count);
+}
+static inline void outsw(unsigned int port, const void *addr,
+			 unsigned long count)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *)addr, 2, count);
+}
+static inline void outsl(unsigned int port, const void *addr,
+			 unsigned long count)
+{
+	if (cris_iops)
+		cris_iops->write_io(port, (void *)addr, 4, count);
+}
 
 /*
  * Convert a physical pointer to a virtual kernel pointer for /dev/mem
diff -druN linux-libre-3.0.57-gnu/arch/sparc/include/asm/hugetlb.h linux-libre-3.0.58-gnu/arch/sparc/include/asm/hugetlb.h
--- linux-libre-3.0.57-gnu/arch/sparc/include/asm/hugetlb.h	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/arch/sparc/include/asm/hugetlb.h	2013-01-11 12:04:08.000000000 -0500
@@ -58,14 +58,20 @@
 static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
 					   unsigned long addr, pte_t *ptep)
 {
-	ptep_set_wrprotect(mm, addr, ptep);
+	pte_t old_pte = *ptep;
+	set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
 }
 
 static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
 					     unsigned long addr, pte_t *ptep,
 					     pte_t pte, int dirty)
 {
-	return ptep_set_access_flags(vma, addr, ptep, pte, dirty);
+	int changed = !pte_same(*ptep, pte);
+	if (changed) {
+		set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
+		flush_tlb_page(vma, addr);
+	}
+	return changed;
 }
 
 static inline pte_t huge_ptep_get(pte_t *ptep)
diff -druN linux-libre-3.0.57-gnu/arch/x86/kernel/cpu/amd.c linux-libre-3.0.58-gnu/arch/x86/kernel/cpu/amd.c
--- linux-libre-3.0.57-gnu/arch/x86/kernel/cpu/amd.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/arch/x86/kernel/cpu/amd.c	2013-01-11 12:04:08.000000000 -0500
@@ -554,6 +554,20 @@
 		}
 	}
 
+	/*
+	 * The way access filter has a performance penalty on some workloads.
+	 * Disable it on the affected CPUs.
+	 */
+	if ((c->x86 == 0x15) &&
+	    (c->x86_model >= 0x02) && (c->x86_model < 0x20)) {
+		u64 val;
+
+		if (!rdmsrl_safe(0xc0011021, &val) && !(val & 0x1E)) {
+			val |= 0x1E;
+			checking_wrmsrl(0xc0011021, val);
+		}
+	}
+
 	cpu_detect_cache_sizes(c);
 
 	/* Multi core CPU? */
diff -druN linux-libre-3.0.57-gnu/Documentation/networking/ip-sysctl.txt linux-libre-3.0.58-gnu/Documentation/networking/ip-sysctl.txt
--- linux-libre-3.0.57-gnu/Documentation/networking/ip-sysctl.txt	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/Documentation/networking/ip-sysctl.txt	2013-01-11 12:04:08.000000000 -0500
@@ -534,6 +534,11 @@
 	Documentation/networking/tcp-thin.txt
 	Default: 0
 
+tcp_challenge_ack_limit - INTEGER
+	Limits number of Challenge ACK sent per second, as recommended
+	in RFC 5961 (Improving TCP's Robustness to Blind In-Window Attacks)
+	Default: 100
+
 UDP variables:
 
 udp_mem - vector of 3 INTEGERs: min, pressure, max
diff -druN linux-libre-3.0.57-gnu/drivers/acpi/scan.c linux-libre-3.0.58-gnu/drivers/acpi/scan.c
--- linux-libre-3.0.57-gnu/drivers/acpi/scan.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/acpi/scan.c	2013-01-11 12:04:08.000000000 -0500
@@ -1153,7 +1153,7 @@
 			acpi_add_id(device, ACPI_DOCK_HID);
 		else if (!acpi_ibm_smbus_match(device))
 			acpi_add_id(device, ACPI_SMBUS_IBM_HID);
-		else if (!acpi_device_hid(device) &&
+		else if (list_empty(&device->pnp.ids) &&
 			 ACPI_IS_ROOT_DEVICE(device->parent)) {
 			acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */
 			strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME);
diff -druN linux-libre-3.0.57-gnu/drivers/atm/solos-pci.c linux-libre-3.0.58-gnu/drivers/atm/solos-pci.c
--- linux-libre-3.0.57-gnu/drivers/atm/solos-pci.c	2012-12-17 18:43:37.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/atm/solos-pci.c	2013-01-12 13:53:35.000000000 -0500
@@ -965,10 +965,11 @@
 	for (port = 0; tx_pending; tx_pending >>= 1, port++) {
 		if (tx_pending & 1) {
 			struct sk_buff *oldskb = card->tx_skb[port];
-			if (oldskb)
+			if (oldskb) {
 				pci_unmap_single(card->dev, SKB_CB(oldskb)->dma_addr,
 						 oldskb->len, PCI_DMA_TODEVICE);
-
+				card->tx_skb[port] = NULL;
+			}
 			spin_lock(&card->tx_queue_lock);
 			skb = skb_dequeue(&card->tx_queue[port]);
 			if (!skb)
diff -druN linux-libre-3.0.57-gnu/drivers/bluetooth/ath3k.c linux-libre-3.0.58-gnu/drivers/bluetooth/ath3k.c
--- linux-libre-3.0.57-gnu/drivers/bluetooth/ath3k.c	2012-12-17 18:52:29.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/bluetooth/ath3k.c	2013-01-12 14:02:21.000000000 -0500
@@ -65,6 +65,7 @@
 	{ USB_DEVICE(0x13d3, 0x3304) },
 	{ USB_DEVICE(0x0930, 0x0215) },
 	{ USB_DEVICE(0x0489, 0xE03D) },
+	{ USB_DEVICE(0x0489, 0xE027) },
 
 	/* Atheros AR9285 Malbec with sflash firmware */
 	{ USB_DEVICE(0x03F0, 0x311D) },
diff -druN linux-libre-3.0.57-gnu/drivers/bluetooth/btusb.c linux-libre-3.0.58-gnu/drivers/bluetooth/btusb.c
--- linux-libre-3.0.57-gnu/drivers/bluetooth/btusb.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/bluetooth/btusb.c	2013-01-11 12:04:08.000000000 -0500
@@ -130,6 +130,7 @@
 	{ USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE },
 	{ USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE },
 	{ USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE },
+	{ USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE },
 
 	/* Atheros AR9285 Malbec with sflash firmware */
 	{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
diff -druN linux-libre-3.0.57-gnu/drivers/input/joystick/walkera0701.c linux-libre-3.0.58-gnu/drivers/input/joystick/walkera0701.c
--- linux-libre-3.0.57-gnu/drivers/input/joystick/walkera0701.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/input/joystick/walkera0701.c	2013-01-11 12:04:08.000000000 -0500
@@ -196,6 +196,7 @@
 	struct walkera_dev *w = input_get_drvdata(dev);
 
 	parport_disable_irq(w->parport);
+	hrtimer_cancel(&w->timer);
 }
 
 static int walkera0701_connect(struct walkera_dev *w, int parport)
@@ -224,6 +225,9 @@
 	if (parport_claim(w->pardevice))
 		goto init_err1;
 
+	hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	w->timer.function = timer_handler;
+
 	w->input_dev = input_allocate_device();
 	if (!w->input_dev)
 		goto init_err2;
@@ -254,8 +258,6 @@
 	if (err)
 		goto init_err3;
 
-	hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-	w->timer.function = timer_handler;
 	return 0;
 
  init_err3:
@@ -271,7 +273,6 @@
 
 static void walkera0701_disconnect(struct walkera_dev *w)
 {
-	hrtimer_cancel(&w->timer);
 	input_unregister_device(w->input_dev);
 	parport_release(w->pardevice);
 	parport_unregister_device(w->pardevice);
diff -druN linux-libre-3.0.57-gnu/drivers/input/serio/i8042-x86ia64io.h linux-libre-3.0.58-gnu/drivers/input/serio/i8042-x86ia64io.h
--- linux-libre-3.0.57-gnu/drivers/input/serio/i8042-x86ia64io.h	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/input/serio/i8042-x86ia64io.h	2013-01-11 12:04:08.000000000 -0500
@@ -900,6 +900,7 @@
 	int retval;
 
 #ifdef CONFIG_X86
+	u8 a20_on = 0xdf;
 	/* Just return if pre-detection shows no i8042 controller exist */
 	if (!x86_platform.i8042_detect())
 		return -ENODEV;
@@ -939,6 +940,14 @@
 
 	if (dmi_check_system(i8042_dmi_dritek_table))
 		i8042_dritek = true;
+
+	/*
+	 * A20 was already enabled during early kernel init. But some buggy
+	 * BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to
+	 * resume from S3. So we do it here and hope that nothing breaks.
+	 */
+	i8042_command(&a20_on, 0x10d1);
+	i8042_command(NULL, 0x00ff);	/* Null command for SMM firmware */
 #endif /* CONFIG_X86 */
 
 	return retval;
diff -druN linux-libre-3.0.57-gnu/drivers/net/bonding/bond_main.c linux-libre-3.0.58-gnu/drivers/net/bonding/bond_main.c
--- linux-libre-3.0.57-gnu/drivers/net/bonding/bond_main.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/net/bonding/bond_main.c	2013-01-11 12:04:08.000000000 -0500
@@ -1439,6 +1439,8 @@
 	struct net_device *bond_dev = bond->dev;
 	u32 vlan_features = BOND_VLAN_FEATURES;
 	unsigned short max_hard_header_len = ETH_HLEN;
+	unsigned int gso_max_size = GSO_MAX_SIZE;
+	u16 gso_max_segs = GSO_MAX_SEGS;
 	int i;
 
 	read_lock(&bond->lock);
@@ -1452,11 +1454,16 @@
 
 		if (slave->dev->hard_header_len > max_hard_header_len)
 			max_hard_header_len = slave->dev->hard_header_len;
+
+		gso_max_size = min(gso_max_size, slave->dev->gso_max_size);
+		gso_max_segs = min(gso_max_segs, slave->dev->gso_max_segs);
 	}
 
 done:
 	bond_dev->vlan_features = vlan_features;
 	bond_dev->hard_header_len = max_hard_header_len;
+	bond_dev->gso_max_segs = gso_max_segs;
+	netif_set_gso_max_size(bond_dev, gso_max_size);
 
 	read_unlock(&bond->lock);
 
diff -druN linux-libre-3.0.57-gnu/drivers/net/bonding/bond_sysfs.c linux-libre-3.0.58-gnu/drivers/net/bonding/bond_sysfs.c
--- linux-libre-3.0.57-gnu/drivers/net/bonding/bond_sysfs.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/net/bonding/bond_sysfs.c	2013-01-11 12:04:08.000000000 -0500
@@ -1524,6 +1524,7 @@
 		goto out;
 	}
 
+	read_lock(&bond->lock);
 	bond_for_each_slave(bond, slave, i) {
 		if (!bond_is_active_slave(slave)) {
 			if (new_value)
@@ -1532,6 +1533,7 @@
 				slave->inactive = 1;
 		}
 	}
+	read_unlock(&bond->lock);
 out:
 	return ret;
 }
diff -druN linux-libre-3.0.57-gnu/drivers/net/can/dev.c linux-libre-3.0.58-gnu/drivers/net/can/dev.c
--- linux-libre-3.0.57-gnu/drivers/net/can/dev.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/net/can/dev.c	2013-01-11 12:04:08.000000000 -0500
@@ -557,8 +557,7 @@
 {
 	struct can_priv *priv = netdev_priv(dev);
 
-	if (del_timer_sync(&priv->restart_timer))
-		dev_put(dev);
+	del_timer_sync(&priv->restart_timer);
 	can_flush_echo_skb(dev);
 }
 EXPORT_SYMBOL_GPL(close_candev);
diff -druN linux-libre-3.0.57-gnu/drivers/net/irda/sir_dev.c linux-libre-3.0.58-gnu/drivers/net/irda/sir_dev.c
--- linux-libre-3.0.57-gnu/drivers/net/irda/sir_dev.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/net/irda/sir_dev.c	2013-01-11 12:04:08.000000000 -0500
@@ -221,7 +221,7 @@
 			break;
 
 		case SIRDEV_STATE_DONGLE_SPEED:
-			if (dev->dongle_drv->reset) {
+			if (dev->dongle_drv->set_speed) {
 				ret = dev->dongle_drv->set_speed(dev, fsm->param);
 				if (ret < 0) {
 					fsm->result = ret;
diff -druN linux-libre-3.0.57-gnu/drivers/net/ne.c linux-libre-3.0.58-gnu/drivers/net/ne.c
--- linux-libre-3.0.57-gnu/drivers/net/ne.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/net/ne.c	2013-01-11 12:04:08.000000000 -0500
@@ -814,6 +814,7 @@
 		dev->irq = irq[this_dev];
 		dev->mem_end = bad[this_dev];
 	}
+	SET_NETDEV_DEV(dev, &pdev->dev);
 	err = do_ne_probe(dev);
 	if (err) {
 		free_netdev(dev);
diff -druN linux-libre-3.0.57-gnu/drivers/net/usb/ipheth.c linux-libre-3.0.58-gnu/drivers/net/usb/ipheth.c
--- linux-libre-3.0.57-gnu/drivers/net/usb/ipheth.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/net/usb/ipheth.c	2013-01-11 12:04:08.000000000 -0500
@@ -62,6 +62,7 @@
 #define USB_PRODUCT_IPAD 0x129a
 #define USB_PRODUCT_IPHONE_4_VZW 0x129c
 #define USB_PRODUCT_IPHONE_4S	0x12a0
+#define USB_PRODUCT_IPHONE_5	0x12a8
 
 #define IPHETH_USBINTF_CLASS    255
 #define IPHETH_USBINTF_SUBCLASS 253
@@ -113,6 +114,10 @@
 		USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S,
 		IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
 		IPHETH_USBINTF_PROTO) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(
+		USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_5,
+		IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS,
+		IPHETH_USBINTF_PROTO) },
 	{ }
 };
 MODULE_DEVICE_TABLE(usb, ipheth_table);
diff -druN linux-libre-3.0.57-gnu/drivers/net/wireless/p54/p54usb.c linux-libre-3.0.58-gnu/drivers/net/wireless/p54/p54usb.c
--- linux-libre-3.0.57-gnu/drivers/net/wireless/p54/p54usb.c	2012-12-17 18:51:32.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/net/wireless/p54/p54usb.c	2013-01-12 14:01:24.000000000 -0500
@@ -45,6 +45,7 @@
 	{USB_DEVICE(0x0411, 0x0050)},	/* Buffalo WLI2-USB2-G54 */
 	{USB_DEVICE(0x045e, 0x00c2)},	/* Microsoft MN-710 */
 	{USB_DEVICE(0x0506, 0x0a11)},	/* 3COM 3CRWE254G72 */
+	{USB_DEVICE(0x0675, 0x0530)},	/* DrayTek Vigor 530 */
 	{USB_DEVICE(0x06b9, 0x0120)},	/* Thomson SpeedTouch 120g */
 	{USB_DEVICE(0x0707, 0xee06)},	/* SMC 2862W-G */
 	{USB_DEVICE(0x07aa, 0x001c)},	/* Corega CG-WLUSB2GT */
@@ -80,6 +81,8 @@
 	{USB_DEVICE(0x06a9, 0x000e)},	/* Westell 802.11g USB (A90-211WG-01) */
 	{USB_DEVICE(0x06b9, 0x0121)},	/* Thomson SpeedTouch 121g */
 	{USB_DEVICE(0x0707, 0xee13)},   /* SMC 2862W-G version 2 */
+	{USB_DEVICE(0x0803, 0x4310)},	/* Zoom 4410a */
+	{USB_DEVICE(0x083a, 0x4503)},	/* T-Com Sinus 154 data II */
 	{USB_DEVICE(0x083a, 0x4521)},   /* Siemens Gigaset USB Adapter 54 version 2 */
 	{USB_DEVICE(0x083a, 0xc501)},	/* Zoom Wireless-G 4410 */
 	{USB_DEVICE(0x083a, 0xf503)},	/* Accton FD7050E ver 1010ec  */
@@ -99,6 +102,7 @@
 	{USB_DEVICE(0x13B1, 0x000C)},	/* Linksys WUSB54AG */
 	{USB_DEVICE(0x1413, 0x5400)},   /* Telsey 802.11g USB2.0 Adapter */
 	{USB_DEVICE(0x1435, 0x0427)},	/* Inventel UR054G */
+	/* {USB_DEVICE(0x15a9, 0x0002)}, * Also SparkLAN WL-682 with 3887 */
 	{USB_DEVICE(0x1668, 0x1050)},	/* Actiontec 802UIG-1 */
 	{USB_DEVICE(0x1740, 0x1000)},	/* Senao NUB-350 */
 	{USB_DEVICE(0x2001, 0x3704)},	/* DLink DWL-G122 rev A2 */
diff -druN linux-libre-3.0.57-gnu/drivers/pci/quirks.c linux-libre-3.0.58-gnu/drivers/pci/quirks.c
--- linux-libre-3.0.57-gnu/drivers/pci/quirks.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/pci/quirks.c	2013-01-11 12:04:08.000000000 -0500
@@ -2746,7 +2746,7 @@
 	if (PCI_FUNC(dev->devfn))
 		return;
 	/*
-	 * RICOH 0xe823 SD/MMC card reader fails to recognize
+	 * RICOH 0xe822 and 0xe823 SD/MMC card readers fail to recognize
 	 * certain types of SD/MMC cards. Lowering the SD base
 	 * clock frequency from 200Mhz to 50Mhz fixes this issue.
 	 *
@@ -2757,7 +2757,8 @@
 	 * 0xf9  - Key register for 0x150
 	 * 0xfc  - key register for 0xe1
 	 */
-	if (dev->device == PCI_DEVICE_ID_RICOH_R5CE823) {
+	if (dev->device == PCI_DEVICE_ID_RICOH_R5CE822 ||
+	    dev->device == PCI_DEVICE_ID_RICOH_R5CE823) {
 		pci_write_config_byte(dev, 0xf9, 0xfc);
 		pci_write_config_byte(dev, 0x150, 0x10);
 		pci_write_config_byte(dev, 0xf9, 0x00);
@@ -2784,6 +2785,8 @@
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE822, ricoh_mmc_fixup_r5c832);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE822, ricoh_mmc_fixup_r5c832);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE823, ricoh_mmc_fixup_r5c832);
 DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE823, ricoh_mmc_fixup_r5c832);
 #endif /*CONFIG_MMC_RICOH_MMC*/
diff -druN linux-libre-3.0.57-gnu/drivers/pnp/pnpacpi/core.c linux-libre-3.0.58-gnu/drivers/pnp/pnpacpi/core.c
--- linux-libre-3.0.57-gnu/drivers/pnp/pnpacpi/core.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/pnp/pnpacpi/core.c	2013-01-11 12:04:08.000000000 -0500
@@ -57,7 +57,7 @@
 	if (!(('0' <= (c) && (c) <= '9') || ('A' <= (c) && (c) <= 'F'))) \
 		return 0
 #define TEST_ALPHA(c) \
-	if (!('@' <= (c) || (c) <= 'Z')) \
+	if (!('A' <= (c) && (c) <= 'Z')) \
 		return 0
 static int __init ispnpidacpi(const char *id)
 {
diff -druN linux-libre-3.0.57-gnu/drivers/rtc/rtc-vt8500.c linux-libre-3.0.58-gnu/drivers/rtc/rtc-vt8500.c
--- linux-libre-3.0.57-gnu/drivers/rtc/rtc-vt8500.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/rtc/rtc-vt8500.c	2013-01-11 12:04:08.000000000 -0500
@@ -69,7 +69,7 @@
 				| ALARM_SEC_BIT)
 
 #define VT8500_RTC_CR_ENABLE	(1 << 0)	/* Enable RTC */
-#define VT8500_RTC_CR_24H	(1 << 1)	/* 24h time format */
+#define VT8500_RTC_CR_12H	(1 << 1)	/* 12h time format */
 #define VT8500_RTC_CR_SM_ENABLE	(1 << 2)	/* Enable periodic irqs */
 #define VT8500_RTC_CR_SM_SEC	(1 << 3)	/* 0: 1Hz/60, 1: 1Hz */
 #define VT8500_RTC_CR_CALIB	(1 << 4)	/* Enable calibration */
@@ -116,7 +116,7 @@
 	tm->tm_min = bcd2bin((time & TIME_MIN_MASK) >> TIME_MIN_S);
 	tm->tm_hour = bcd2bin((time & TIME_HOUR_MASK) >> TIME_HOUR_S);
 	tm->tm_mday = bcd2bin(date & DATE_DAY_MASK);
-	tm->tm_mon = bcd2bin((date & DATE_MONTH_MASK) >> DATE_MONTH_S);
+	tm->tm_mon = bcd2bin((date & DATE_MONTH_MASK) >> DATE_MONTH_S) - 1;
 	tm->tm_year = bcd2bin((date & DATE_YEAR_MASK) >> DATE_YEAR_S)
 			+ ((date >> DATE_CENTURY_S) & 1 ? 200 : 100);
 	tm->tm_wday = (time & TIME_DOW_MASK) >> TIME_DOW_S;
@@ -135,8 +135,9 @@
 	}
 
 	writel((bin2bcd(tm->tm_year - 100) << DATE_YEAR_S)
-		| (bin2bcd(tm->tm_mon) << DATE_MONTH_S)
-		| (bin2bcd(tm->tm_mday)),
+		| (bin2bcd(tm->tm_mon + 1) << DATE_MONTH_S)
+		| (bin2bcd(tm->tm_mday))
+		| ((tm->tm_year >= 200) << DATE_CENTURY_S),
 		vt8500_rtc->regbase + VT8500_RTC_DS);
 	writel((bin2bcd(tm->tm_wday) << TIME_DOW_S)
 		| (bin2bcd(tm->tm_hour) << TIME_HOUR_S)
@@ -246,7 +247,7 @@
 	}
 
 	/* Enable RTC and set it to 24-hour mode */
-	writel(VT8500_RTC_CR_ENABLE | VT8500_RTC_CR_24H,
+	writel(VT8500_RTC_CR_ENABLE,
 	       vt8500_rtc->regbase + VT8500_RTC_CR);
 
 	vt8500_rtc->rtc = rtc_device_register("vt8500-rtc", &pdev->dev,
diff -druN linux-libre-3.0.57-gnu/drivers/usb/gadget/f_phonet.c linux-libre-3.0.58-gnu/drivers/usb/gadget/f_phonet.c
--- linux-libre-3.0.57-gnu/drivers/usb/gadget/f_phonet.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/usb/gadget/f_phonet.c	2013-01-11 12:04:08.000000000 -0500
@@ -541,7 +541,7 @@
 
 		req = usb_ep_alloc_request(fp->out_ep, GFP_KERNEL);
 		if (!req)
-			goto err;
+			goto err_req;
 
 		req->complete = pn_rx_complete;
 		fp->out_reqv[i] = req;
@@ -550,14 +550,18 @@
 	/* Outgoing USB requests */
 	fp->in_req = usb_ep_alloc_request(fp->in_ep, GFP_KERNEL);
 	if (!fp->in_req)
-		goto err;
+		goto err_req;
 
 	INFO(cdev, "USB CDC Phonet function\n");
 	INFO(cdev, "using %s, OUT %s, IN %s\n", cdev->gadget->name,
 		fp->out_ep->name, fp->in_ep->name);
 	return 0;
 
+err_req:
+	for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++)
+		usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
 err:
+
 	if (fp->out_ep)
 		fp->out_ep->driver_data = NULL;
 	if (fp->in_ep)
diff -druN linux-libre-3.0.57-gnu/drivers/usb/host/ehci-pci.c linux-libre-3.0.58-gnu/drivers/usb/host/ehci-pci.c
--- linux-libre-3.0.57-gnu/drivers/usb/host/ehci-pci.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/usb/host/ehci-pci.c	2013-01-11 12:04:08.000000000 -0500
@@ -359,7 +359,8 @@
 		pdev->vendor == PCI_VENDOR_ID_INTEL &&
 		(pdev->device == 0x1E26 ||
 		 pdev->device == 0x8C2D ||
-		 pdev->device == 0x8C26);
+		 pdev->device == 0x8C26 ||
+		 pdev->device == 0x9C26);
 }
 
 static void ehci_enable_xhci_companion(void)
diff -druN linux-libre-3.0.57-gnu/drivers/usb/host/pci-quirks.c linux-libre-3.0.58-gnu/drivers/usb/host/pci-quirks.c
--- linux-libre-3.0.57-gnu/drivers/usb/host/pci-quirks.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/usb/host/pci-quirks.c	2013-01-11 12:04:08.000000000 -0500
@@ -721,6 +721,7 @@
 }
 
 #define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI	0x8C31
+#define PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI	0x9C31
 
 bool usb_is_intel_ppt_switchable_xhci(struct pci_dev *pdev)
 {
@@ -734,7 +735,8 @@
 {
 	return pdev->class == PCI_CLASS_SERIAL_USB_XHCI &&
 		pdev->vendor == PCI_VENDOR_ID_INTEL &&
-		pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI;
+		(pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI ||
+		 pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI);
 }
 
 bool usb_is_intel_switchable_xhci(struct pci_dev *pdev)
diff -druN linux-libre-3.0.57-gnu/drivers/virtio/virtio_ring.c linux-libre-3.0.58-gnu/drivers/virtio/virtio_ring.c
--- linux-libre-3.0.57-gnu/drivers/virtio/virtio_ring.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/drivers/virtio/virtio_ring.c	2013-01-11 12:04:08.000000000 -0500
@@ -120,6 +120,13 @@
 	unsigned head;
 	int i;
 
+	/*
+	 * We require lowmem mappings for the descriptors because
+	 * otherwise virt_to_phys will give us bogus addresses in the
+	 * virtqueue.
+	 */
+	gfp &= ~(__GFP_HIGHMEM | __GFP_HIGH);
+
 	desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp);
 	if (!desc)
 		return -ENOMEM;
diff -druN linux-libre-3.0.57-gnu/fs/binfmt_misc.c linux-libre-3.0.58-gnu/fs/binfmt_misc.c
--- linux-libre-3.0.57-gnu/fs/binfmt_misc.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/fs/binfmt_misc.c	2013-01-11 12:04:08.000000000 -0500
@@ -176,7 +176,10 @@
 		goto _error;
 	bprm->argc ++;
 
-	bprm->interp = iname;	/* for binfmt_script */
+	/* Update interp in case binfmt_script needs it. */
+	retval = bprm_change_interp(iname, bprm);
+	if (retval < 0)
+		goto _error;
 
 	interp_file = open_exec (iname);
 	retval = PTR_ERR (interp_file);
diff -druN linux-libre-3.0.57-gnu/fs/binfmt_script.c linux-libre-3.0.58-gnu/fs/binfmt_script.c
--- linux-libre-3.0.57-gnu/fs/binfmt_script.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/fs/binfmt_script.c	2013-01-11 12:04:08.000000000 -0500
@@ -82,7 +82,9 @@
 	retval = copy_strings_kernel(1, &i_name, bprm);
 	if (retval) return retval; 
 	bprm->argc++;
-	bprm->interp = interp;
+	retval = bprm_change_interp(interp, bprm);
+	if (retval < 0)
+		return retval;
 
 	/*
 	 * OK, now restart the process with the interpreter's dentry.
diff -druN linux-libre-3.0.57-gnu/fs/exec.c linux-libre-3.0.58-gnu/fs/exec.c
--- linux-libre-3.0.57-gnu/fs/exec.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/fs/exec.c	2013-01-11 12:04:08.000000000 -0500
@@ -1192,9 +1192,24 @@
 		mutex_unlock(&current->signal->cred_guard_mutex);
 		abort_creds(bprm->cred);
 	}
+	/* If a binfmt changed the interp, free it. */
+	if (bprm->interp != bprm->filename)
+		kfree(bprm->interp);
 	kfree(bprm);
 }
 
+int bprm_change_interp(char *interp, struct linux_binprm *bprm)
+{
+	/* If a binfmt changed the interp, free it first. */
+	if (bprm->interp != bprm->filename)
+		kfree(bprm->interp);
+	bprm->interp = kstrdup(interp, GFP_KERNEL);
+	if (!bprm->interp)
+		return -ENOMEM;
+	return 0;
+}
+EXPORT_SYMBOL(bprm_change_interp);
+
 /*
  * install the new credentials for this executable
  */
diff -druN linux-libre-3.0.57-gnu/fs/nfs/client.c linux-libre-3.0.58-gnu/fs/nfs/client.c
--- linux-libre-3.0.57-gnu/fs/nfs/client.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/fs/nfs/client.c	2013-01-11 12:04:08.000000000 -0500
@@ -673,8 +673,7 @@
  */
 static void nfs_destroy_server(struct nfs_server *server)
 {
-	if (!(server->flags & NFS_MOUNT_LOCAL_FLOCK) ||
-			!(server->flags & NFS_MOUNT_LOCAL_FCNTL))
+	if (server->nlm_host)
 		nlmclnt_done(server->nlm_host);
 }
 
diff -druN linux-libre-3.0.57-gnu/fs/nfs/dir.c linux-libre-3.0.58-gnu/fs/nfs/dir.c
--- linux-libre-3.0.57-gnu/fs/nfs/dir.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/fs/nfs/dir.c	2013-01-11 12:04:08.000000000 -0500
@@ -1216,11 +1216,14 @@
 
 }
 
+/* Ensure that we revalidate inode->i_nlink */
 static void nfs_drop_nlink(struct inode *inode)
 {
 	spin_lock(&inode->i_lock);
-	if (inode->i_nlink > 0)
-		drop_nlink(inode);
+	/* drop the inode if we're reasonably sure this is the last link */
+	if (inode->i_nlink == 1)
+		clear_nlink(inode);
+	NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR;
 	spin_unlock(&inode->i_lock);
 }
 
@@ -1235,8 +1238,8 @@
 		NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA;
 
 	if (dentry->d_flags & DCACHE_NFSFS_RENAMED) {
-		drop_nlink(inode);
 		nfs_complete_unlink(dentry, inode);
+		nfs_drop_nlink(inode);
 	}
 	iput(inode);
 }
@@ -1788,10 +1791,8 @@
 	if (inode != NULL) {
 		nfs_inode_return_delegation(inode);
 		error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
-		/* The VFS may want to delete this inode */
 		if (error == 0)
 			nfs_drop_nlink(inode);
-		nfs_mark_for_revalidate(inode);
 	} else
 		error = NFS_PROTO(dir)->remove(dir, &dentry->d_name);
 	if (error == -ENOENT)
diff -druN linux-libre-3.0.57-gnu/fs/nfs/super.c linux-libre-3.0.58-gnu/fs/nfs/super.c
--- linux-libre-3.0.57-gnu/fs/nfs/super.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/fs/nfs/super.c	2013-01-11 12:04:08.000000000 -0500
@@ -1052,7 +1052,7 @@
 {
 	kfree(*option);
 	*option = match_strdup(args);
-	return !option;
+	return !*option;
 }
 
 static int nfs_get_option_ul(substring_t args[], unsigned long *option)
diff -druN linux-libre-3.0.57-gnu/fs/nfsd/nfs4xdr.c linux-libre-3.0.58-gnu/fs/nfsd/nfs4xdr.c
--- linux-libre-3.0.57-gnu/fs/nfsd/nfs4xdr.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/fs/nfsd/nfs4xdr.c	2013-01-11 12:04:08.000000000 -0500
@@ -2682,11 +2682,16 @@
 	len = maxcount;
 	v = 0;
 	while (len > 0) {
-		pn = resp->rqstp->rq_resused++;
+		pn = resp->rqstp->rq_resused;
+		if (!resp->rqstp->rq_respages[pn]) { /* ran out of pages */
+			maxcount -= len;
+			break;
+		}
 		resp->rqstp->rq_vec[v].iov_base =
 			page_address(resp->rqstp->rq_respages[pn]);
 		resp->rqstp->rq_vec[v].iov_len =
 			len < PAGE_SIZE ? len : PAGE_SIZE;
+		resp->rqstp->rq_resused++;
 		v++;
 		len -= PAGE_SIZE;
 	}
@@ -2734,6 +2739,8 @@
 		return nfserr;
 	if (resp->xbuf->page_len)
 		return nfserr_resource;
+	if (!resp->rqstp->rq_respages[resp->rqstp->rq_resused])
+		return nfserr_resource;
 
 	page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]);
 
@@ -2783,6 +2790,8 @@
 		return nfserr;
 	if (resp->xbuf->page_len)
 		return nfserr_resource;
+	if (!resp->rqstp->rq_respages[resp->rqstp->rq_resused])
+		return nfserr_resource;
 
 	RESERVE_SPACE(8);  /* verifier */
 	savep = p;
diff -druN linux-libre-3.0.57-gnu/include/asm-generic/tlb.h linux-libre-3.0.58-gnu/include/asm-generic/tlb.h
--- linux-libre-3.0.57-gnu/include/asm-generic/tlb.h	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/include/asm-generic/tlb.h	2013-01-11 12:04:08.000000000 -0500
@@ -78,6 +78,14 @@
 #define MAX_GATHER_BATCH	\
 	((PAGE_SIZE - sizeof(struct mmu_gather_batch)) / sizeof(void *))
 
+/*
+ * Limit the maximum number of mmu_gather batches to reduce a risk of soft
+ * lockups for non-preemptible kernels on huge machines when a lot of memory
+ * is zapped during unmapping.
+ * 10K pages freed at once should be safe even without a preemption point.
+ */
+#define MAX_GATHER_BATCH_COUNT	(10000UL/MAX_GATHER_BATCH)
+
 /* struct mmu_gather is an opaque type used by the mm code for passing around
  * any data needed by arch specific code for tlb_remove_page.
  */
@@ -94,6 +102,7 @@
 	struct mmu_gather_batch *active;
 	struct mmu_gather_batch	local;
 	struct page		*__pages[MMU_GATHER_BUNDLE];
+	unsigned int		batch_count;
 };
 
 #define HAVE_GENERIC_MMU_GATHER
diff -druN linux-libre-3.0.57-gnu/include/linux/binfmts.h linux-libre-3.0.58-gnu/include/linux/binfmts.h
--- linux-libre-3.0.57-gnu/include/linux/binfmts.h	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/include/linux/binfmts.h	2013-01-11 12:04:08.000000000 -0500
@@ -126,6 +126,7 @@
 			   unsigned long stack_top,
 			   int executable_stack);
 extern int bprm_mm_init(struct linux_binprm *bprm);
+extern int bprm_change_interp(char *interp, struct linux_binprm *bprm);
 extern int copy_strings_kernel(int argc, const char *const *argv,
 			       struct linux_binprm *bprm);
 extern int prepare_bprm_creds(struct linux_binprm *bprm);
diff -druN linux-libre-3.0.57-gnu/include/linux/compiler-gcc.h linux-libre-3.0.58-gnu/include/linux/compiler-gcc.h
--- linux-libre-3.0.57-gnu/include/linux/compiler-gcc.h	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/include/linux/compiler-gcc.h	2013-01-11 12:04:08.000000000 -0500
@@ -50,6 +50,11 @@
 # define inline		inline		__attribute__((always_inline))
 # define __inline__	__inline__	__attribute__((always_inline))
 # define __inline	__inline	__attribute__((always_inline))
+#else
+/* A lot of inline functions can cause havoc with function tracing */
+# define inline		inline		notrace
+# define __inline__	__inline__	notrace
+# define __inline	__inline	notrace
 #endif
 
 #define __deprecated			__attribute__((deprecated))
diff -druN linux-libre-3.0.57-gnu/include/linux/page-flags.h linux-libre-3.0.58-gnu/include/linux/page-flags.h
--- linux-libre-3.0.57-gnu/include/linux/page-flags.h	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/include/linux/page-flags.h	2013-01-11 12:04:08.000000000 -0500
@@ -365,7 +365,7 @@
  * pages on the LRU and/or pagecache.
  */
 TESTPAGEFLAG(Compound, compound)
-__PAGEFLAG(Head, compound)
+__SETPAGEFLAG(Head, compound)  __CLEARPAGEFLAG(Head, compound)
 
 /*
  * PG_reclaim is used in combination with PG_compound to mark the
@@ -377,8 +377,14 @@
  * PG_compound & PG_reclaim	=> Tail page
  * PG_compound & ~PG_reclaim	=> Head page
  */
+#define PG_head_mask ((1L << PG_compound))
 #define PG_head_tail_mask ((1L << PG_compound) | (1L << PG_reclaim))
 
+static inline int PageHead(struct page *page)
+{
+	return ((page->flags & PG_head_tail_mask) == PG_head_mask);
+}
+
 static inline int PageTail(struct page *page)
 {
 	return ((page->flags & PG_head_tail_mask) == PG_head_tail_mask);
diff -druN linux-libre-3.0.57-gnu/include/linux/pci_ids.h linux-libre-3.0.58-gnu/include/linux/pci_ids.h
--- linux-libre-3.0.57-gnu/include/linux/pci_ids.h	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/include/linux/pci_ids.h	2013-01-11 12:04:08.000000000 -0500
@@ -1537,6 +1537,7 @@
 #define PCI_DEVICE_ID_RICOH_RL5C476	0x0476
 #define PCI_DEVICE_ID_RICOH_RL5C478	0x0478
 #define PCI_DEVICE_ID_RICOH_R5C822	0x0822
+#define PCI_DEVICE_ID_RICOH_R5CE822	0xe822
 #define PCI_DEVICE_ID_RICOH_R5CE823	0xe823
 #define PCI_DEVICE_ID_RICOH_R5C832	0x0832
 #define PCI_DEVICE_ID_RICOH_R5C843	0x0843
diff -druN linux-libre-3.0.57-gnu/include/linux/snmp.h linux-libre-3.0.58-gnu/include/linux/snmp.h
--- linux-libre-3.0.57-gnu/include/linux/snmp.h	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/include/linux/snmp.h	2013-01-11 12:04:08.000000000 -0500
@@ -209,7 +209,6 @@
 	LINUX_MIB_TCPDSACKOFOSENT,		/* TCPDSACKOfoSent */
 	LINUX_MIB_TCPDSACKRECV,			/* TCPDSACKRecv */
 	LINUX_MIB_TCPDSACKOFORECV,		/* TCPDSACKOfoRecv */
-	LINUX_MIB_TCPABORTONSYN,		/* TCPAbortOnSyn */
 	LINUX_MIB_TCPABORTONDATA,		/* TCPAbortOnData */
 	LINUX_MIB_TCPABORTONCLOSE,		/* TCPAbortOnClose */
 	LINUX_MIB_TCPABORTONMEMORY,		/* TCPAbortOnMemory */
@@ -231,6 +230,8 @@
 	LINUX_MIB_TCPDEFERACCEPTDROP,
 	LINUX_MIB_IPRPFILTER, /* IP Reverse Path Filter (rp_filter) */
 	LINUX_MIB_TCPTIMEWAITOVERFLOW,		/* TCPTimeWaitOverflow */
+	LINUX_MIB_TCPCHALLENGEACK,		/* TCPChallengeACK */
+	LINUX_MIB_TCPSYNCHALLENGE,		/* TCPSYNChallenge */
 	__LINUX_MIB_MAX
 };
 
diff -druN linux-libre-3.0.57-gnu/include/net/tcp.h linux-libre-3.0.58-gnu/include/net/tcp.h
--- linux-libre-3.0.57-gnu/include/net/tcp.h	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/include/net/tcp.h	2013-01-11 12:04:08.000000000 -0500
@@ -246,6 +246,7 @@
 extern int sysctl_tcp_cookie_size;
 extern int sysctl_tcp_thin_linear_timeouts;
 extern int sysctl_tcp_thin_dupack;
+extern int sysctl_tcp_challenge_ack_limit;
 
 extern atomic_long_t tcp_memory_allocated;
 extern struct percpu_counter tcp_sockets_allocated;
diff -druN linux-libre-3.0.57-gnu/kernel/cgroup.c linux-libre-3.0.58-gnu/kernel/cgroup.c
--- linux-libre-3.0.57-gnu/kernel/cgroup.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/kernel/cgroup.c	2013-01-11 12:04:08.000000000 -0500
@@ -2630,9 +2630,7 @@
 		dentry->d_fsdata = cgrp;
 		inc_nlink(parent->d_inode);
 		rcu_assign_pointer(cgrp->dentry, dentry);
-		dget(dentry);
 	}
-	dput(dentry);
 
 	return error;
 }
diff -druN linux-libre-3.0.57-gnu/kernel/irq/manage.c linux-libre-3.0.58-gnu/kernel/irq/manage.c
--- linux-libre-3.0.57-gnu/kernel/irq/manage.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/kernel/irq/manage.c	2013-01-11 12:04:08.000000000 -0500
@@ -698,6 +698,7 @@
 irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action)
 {
 	cpumask_var_t mask;
+	bool valid = true;
 
 	if (!test_and_clear_bit(IRQTF_AFFINITY, &action->thread_flags))
 		return;
@@ -712,10 +713,18 @@
 	}
 
 	raw_spin_lock_irq(&desc->lock);
-	cpumask_copy(mask, desc->irq_data.affinity);
+	/*
+	 * This code is triggered unconditionally. Check the affinity
+	 * mask pointer. For CPU_MASK_OFFSTACK=n this is optimized out.
+	 */
+	if (desc->irq_data.affinity)
+		cpumask_copy(mask, desc->irq_data.affinity);
+	else
+		valid = false;
 	raw_spin_unlock_irq(&desc->lock);
 
-	set_cpus_allowed_ptr(current, mask);
+	if (valid)
+		set_cpus_allowed_ptr(current, mask);
 	free_cpumask_var(mask);
 }
 #else
@@ -925,6 +934,16 @@
 		 */
 		get_task_struct(t);
 		new->thread = t;
+		/*
+		 * Tell the thread to set its affinity. This is
+		 * important for shared interrupt handlers as we do
+		 * not invoke setup_affinity() for the secondary
+		 * handlers as everything is already set up. Even for
+		 * interrupts marked with IRQF_NO_BALANCE this is
+		 * correct as we want the thread to move to the cpu(s)
+		 * on which the requesting code placed the interrupt.
+		 */
+		set_bit(IRQTF_AFFINITY, &new->thread_flags);
 	}
 
 	if (!alloc_cpumask_var(&mask, GFP_KERNEL)) {
diff -druN linux-libre-3.0.57-gnu/Makefile linux-libre-3.0.58-gnu/Makefile
--- linux-libre-3.0.57-gnu/Makefile	2012-12-17 18:43:09.000000000 -0500
+++ linux-libre-3.0.58-gnu/Makefile	2013-01-12 13:53:06.000000000 -0500
@@ -1,6 +1,6 @@
 VERSION = 3
 PATCHLEVEL = 0
-SUBLEVEL = 57
+SUBLEVEL = 58
 EXTRAVERSION =-gnu
 NAME = Sneaky Weasel
 
diff -druN linux-libre-3.0.57-gnu/mm/memory.c linux-libre-3.0.58-gnu/mm/memory.c
--- linux-libre-3.0.57-gnu/mm/memory.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/mm/memory.c	2013-01-11 12:04:08.000000000 -0500
@@ -205,10 +205,14 @@
 		return 1;
 	}
 
+	if (tlb->batch_count == MAX_GATHER_BATCH_COUNT)
+		return 0;
+
 	batch = (void *)__get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0);
 	if (!batch)
 		return 0;
 
+	tlb->batch_count++;
 	batch->next = NULL;
 	batch->nr   = 0;
 	batch->max  = MAX_GATHER_BATCH;
@@ -235,6 +239,7 @@
 	tlb->local.nr   = 0;
 	tlb->local.max  = ARRAY_SIZE(tlb->__pages);
 	tlb->active     = &tlb->local;
+	tlb->batch_count = 0;
 
 #ifdef CONFIG_HAVE_RCU_TABLE_FREE
 	tlb->batch = NULL;
diff -druN linux-libre-3.0.57-gnu/mm/mempolicy.c linux-libre-3.0.58-gnu/mm/mempolicy.c
--- linux-libre-3.0.57-gnu/mm/mempolicy.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/mm/mempolicy.c	2013-01-11 12:04:08.000000000 -0500
@@ -2308,8 +2308,7 @@
  */
 
 /*
- * "local" is pseudo-policy:  MPOL_PREFERRED with MPOL_F_LOCAL flag
- * Used only for mpol_parse_str() and mpol_to_str()
+ * "local" is implemented internally by MPOL_PREFERRED with MPOL_F_LOCAL flag.
  */
 #define MPOL_LOCAL MPOL_MAX
 static const char * const policy_modes[] =
@@ -2324,28 +2323,21 @@
 
 #ifdef CONFIG_TMPFS
 /**
- * mpol_parse_str - parse string to mempolicy
+ * mpol_parse_str - parse string to mempolicy, for tmpfs mpol mount option.
  * @str:  string containing mempolicy to parse
  * @mpol:  pointer to struct mempolicy pointer, returned on success.
- * @no_context:  flag whether to "contextualize" the mempolicy
+ * @unused:  redundant argument, to be removed later.
  *
  * Format of input:
  *	<mode>[=<flags>][:<nodelist>]
  *
- * if @no_context is true, save the input nodemask in w.user_nodemask in
- * the returned mempolicy.  This will be used to "clone" the mempolicy in
- * a specific context [cpuset] at a later time.  Used to parse tmpfs mpol
- * mount option.  Note that if 'static' or 'relative' mode flags were
- * specified, the input nodemask will already have been saved.  Saving
- * it again is redundant, but safe.
- *
  * On success, returns 0, else 1
  */
-int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context)
+int mpol_parse_str(char *str, struct mempolicy **mpol, int unused)
 {
 	struct mempolicy *new = NULL;
 	unsigned short mode;
-	unsigned short uninitialized_var(mode_flags);
+	unsigned short mode_flags;
 	nodemask_t nodes;
 	char *nodelist = strchr(str, ':');
 	char *flags = strchr(str, '=');
@@ -2433,24 +2425,23 @@
 	if (IS_ERR(new))
 		goto out;
 
-	if (no_context) {
-		/* save for contextualization */
-		new->w.user_nodemask = nodes;
-	} else {
-		int ret;
-		NODEMASK_SCRATCH(scratch);
-		if (scratch) {
-			task_lock(current);
-			ret = mpol_set_nodemask(new, &nodes, scratch);
-			task_unlock(current);
-		} else
-			ret = -ENOMEM;
-		NODEMASK_SCRATCH_FREE(scratch);
-		if (ret) {
-			mpol_put(new);
-			goto out;
-		}
-	}
+	/*
+	 * Save nodes for mpol_to_str() to show the tmpfs mount options
+	 * for /proc/mounts, /proc/pid/mounts and /proc/pid/mountinfo.
+	 */
+	if (mode != MPOL_PREFERRED)
+		new->v.nodes = nodes;
+	else if (nodelist)
+		new->v.preferred_node = first_node(nodes);
+	else
+		new->flags |= MPOL_F_LOCAL;
+
+	/*
+	 * Save nodes for contextualization: this will be used to "clone"
+	 * the mempolicy in a specific context [cpuset] at a later time.
+	 */
+	new->w.user_nodemask = nodes;
+
 	err = 0;
 
 out:
@@ -2470,13 +2461,13 @@
  * @buffer:  to contain formatted mempolicy string
  * @maxlen:  length of @buffer
  * @pol:  pointer to mempolicy to be formatted
- * @no_context:  "context free" mempolicy - use nodemask in w.user_nodemask
+ * @unused:  redundant argument, to be removed later.
  *
  * Convert a mempolicy into a string.
  * Returns the number of characters in buffer (if positive)
  * or an error (negative)
  */
-int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context)
+int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int unused)
 {
 	char *p = buffer;
 	int l;
@@ -2502,7 +2493,7 @@
 	case MPOL_PREFERRED:
 		nodes_clear(nodes);
 		if (flags & MPOL_F_LOCAL)
-			mode = MPOL_LOCAL;	/* pseudo-policy */
+			mode = MPOL_LOCAL;
 		else
 			node_set(pol->v.preferred_node, nodes);
 		break;
@@ -2510,10 +2501,7 @@
 	case MPOL_BIND:
 		/* Fall through */
 	case MPOL_INTERLEAVE:
-		if (no_context)
-			nodes = pol->w.user_nodemask;
-		else
-			nodes = pol->v.nodes;
+		nodes = pol->v.nodes;
 		break;
 
 	default:
diff -druN linux-libre-3.0.57-gnu/net/bluetooth/hci_core.c linux-libre-3.0.58-gnu/net/bluetooth/hci_core.c
--- linux-libre-3.0.57-gnu/net/bluetooth/hci_core.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/net/bluetooth/hci_core.c	2013-01-11 12:04:08.000000000 -0500
@@ -1333,6 +1333,8 @@
 	for (i = 0; i < NUM_REASSEMBLY; i++)
 		kfree_skb(hdev->reassembly[i]);
 
+	cancel_work_sync(&hdev->power_on);
+
 	if (!test_bit(HCI_INIT, &hdev->flags) &&
 					!test_bit(HCI_SETUP, &hdev->flags))
 		mgmt_index_removed(hdev->id);
diff -druN linux-libre-3.0.57-gnu/net/ipv4/proc.c linux-libre-3.0.58-gnu/net/ipv4/proc.c
--- linux-libre-3.0.57-gnu/net/ipv4/proc.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/net/ipv4/proc.c	2013-01-11 12:04:08.000000000 -0500
@@ -232,7 +232,6 @@
 	SNMP_MIB_ITEM("TCPDSACKOfoSent", LINUX_MIB_TCPDSACKOFOSENT),
 	SNMP_MIB_ITEM("TCPDSACKRecv", LINUX_MIB_TCPDSACKRECV),
 	SNMP_MIB_ITEM("TCPDSACKOfoRecv", LINUX_MIB_TCPDSACKOFORECV),
-	SNMP_MIB_ITEM("TCPAbortOnSyn", LINUX_MIB_TCPABORTONSYN),
 	SNMP_MIB_ITEM("TCPAbortOnData", LINUX_MIB_TCPABORTONDATA),
 	SNMP_MIB_ITEM("TCPAbortOnClose", LINUX_MIB_TCPABORTONCLOSE),
 	SNMP_MIB_ITEM("TCPAbortOnMemory", LINUX_MIB_TCPABORTONMEMORY),
@@ -254,6 +253,8 @@
 	SNMP_MIB_ITEM("TCPDeferAcceptDrop", LINUX_MIB_TCPDEFERACCEPTDROP),
 	SNMP_MIB_ITEM("IPReversePathFilter", LINUX_MIB_IPRPFILTER),
 	SNMP_MIB_ITEM("TCPTimeWaitOverflow", LINUX_MIB_TCPTIMEWAITOVERFLOW),
+	SNMP_MIB_ITEM("TCPChallengeACK", LINUX_MIB_TCPCHALLENGEACK),
+	SNMP_MIB_ITEM("TCPSYNChallenge", LINUX_MIB_TCPSYNCHALLENGE),
 	SNMP_MIB_SENTINEL
 };
 
diff -druN linux-libre-3.0.57-gnu/net/ipv4/sysctl_net_ipv4.c linux-libre-3.0.58-gnu/net/ipv4/sysctl_net_ipv4.c
--- linux-libre-3.0.57-gnu/net/ipv4/sysctl_net_ipv4.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/net/ipv4/sysctl_net_ipv4.c	2013-01-11 12:04:08.000000000 -0500
@@ -566,6 +566,13 @@
 		.mode		= 0644,
 		.proc_handler	= proc_dointvec
 	},
+	{
+		.procname	= "tcp_challenge_ack_limit",
+		.data		= &sysctl_tcp_challenge_ack_limit,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec
+	},
 #ifdef CONFIG_NET_DMA
 	{
 		.procname	= "tcp_dma_copybreak",
diff -druN linux-libre-3.0.57-gnu/net/ipv4/tcp_input.c linux-libre-3.0.58-gnu/net/ipv4/tcp_input.c
--- linux-libre-3.0.57-gnu/net/ipv4/tcp_input.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/net/ipv4/tcp_input.c	2013-01-11 12:04:08.000000000 -0500
@@ -86,6 +86,9 @@
 int sysctl_tcp_adv_win_scale __read_mostly = 1;
 EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
 
+/* rfc5961 challenge ack rate limiting */
+int sysctl_tcp_challenge_ack_limit = 100;
+
 int sysctl_tcp_stdurg __read_mostly;
 int sysctl_tcp_rfc1337 __read_mostly;
 int sysctl_tcp_max_orphans __read_mostly = NR_FILE;
@@ -3633,6 +3636,24 @@
 	return 0;
 }
 
+/* RFC 5961 7 [ACK Throttling] */
+static void tcp_send_challenge_ack(struct sock *sk)
+{
+	/* unprotected vars, we dont care of overwrites */
+	static u32 challenge_timestamp;
+	static unsigned int challenge_count;
+	u32 now = jiffies / HZ;
+
+	if (now != challenge_timestamp) {
+		challenge_timestamp = now;
+		challenge_count = 0;
+	}
+	if (++challenge_count <= sysctl_tcp_challenge_ack_limit) {
+		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK);
+		tcp_send_ack(sk);
+	}
+}
+
 /* This routine deals with incoming acks, but not outgoing ones. */
 static int tcp_ack(struct sock *sk, struct sk_buff *skb, int flag)
 {
@@ -3649,8 +3670,14 @@
 	/* If the ack is older than previous acks
 	 * then we can probably ignore it.
 	 */
-	if (before(ack, prior_snd_una))
+	if (before(ack, prior_snd_una)) {
+		/* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */
+		if (before(ack, prior_snd_una - tp->max_window)) {
+			tcp_send_challenge_ack(sk);
+			return -1;
+		}
 		goto old_ack;
+	}
 
 	/* If the ack includes data we haven't sent yet, discard
 	 * this segment (RFC793 Section 3.9).
@@ -5168,8 +5195,8 @@
 /* Does PAWS and seqno based validation of an incoming segment, flags will
  * play significant role here.
  */
-static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
-			      struct tcphdr *th, int syn_inerr)
+static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
+				  struct tcphdr *th, int syn_inerr)
 {
 	u8 *hash_location;
 	struct tcp_sock *tp = tcp_sk(sk);
@@ -5194,38 +5221,48 @@
 		 * an acknowledgment should be sent in reply (unless the RST
 		 * bit is set, if so drop the segment and return)".
 		 */
-		if (!th->rst)
+		if (!th->rst) {
+			if (th->syn)
+				goto syn_challenge;
 			tcp_send_dupack(sk, skb);
+		}
 		goto discard;
 	}
 
 	/* Step 2: check RST bit */
 	if (th->rst) {
-		tcp_reset(sk);
+		/* RFC 5961 3.2 :
+		 * If sequence number exactly matches RCV.NXT, then
+		 *     RESET the connection
+		 * else
+		 *     Send a challenge ACK
+		 */
+		if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt)
+			tcp_reset(sk);
+		else
+			tcp_send_challenge_ack(sk);
 		goto discard;
 	}
 
-	/* ts_recent update must be made after we are sure that the packet
-	 * is in window.
-	 */
-	tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
-
 	/* step 3: check security and precedence [ignored] */
 
-	/* step 4: Check for a SYN in window. */
-	if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) {
+	/* step 4: Check for a SYN
+	 * RFC 5691 4.2 : Send a challenge ack
+	 */
+	if (th->syn) {
+syn_challenge:
 		if (syn_inerr)
 			TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS);
-		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONSYN);
-		tcp_reset(sk);
-		return -1;
+		NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE);
+		tcp_send_challenge_ack(sk);
+		goto discard;
 	}
 
-	return 1;
+	return true;
 
 discard:
 	__kfree_skb(skb);
-	return 0;
+	return false;
 }
 
 /*
@@ -5255,7 +5292,6 @@
 			struct tcphdr *th, unsigned len)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
-	int res;
 
 	/*
 	 *	Header prediction.
@@ -5435,14 +5471,18 @@
 	 *	Standard slow path.
 	 */
 
-	res = tcp_validate_incoming(sk, skb, th, 1);
-	if (res <= 0)
-		return -res;
+	if (!tcp_validate_incoming(sk, skb, th, 1))
+		return 0;
 
 step5:
 	if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0)
 		goto discard;
 
+	/* ts_recent update must be made after we are sure that the packet
+	 * is in window.
+	 */
+	tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
 	tcp_rcv_rtt_measure_ts(sk, skb);
 
 	/* Process urgent data. */
@@ -5747,7 +5787,6 @@
 	struct tcp_sock *tp = tcp_sk(sk);
 	struct inet_connection_sock *icsk = inet_csk(sk);
 	int queued = 0;
-	int res;
 
 	tp->rx_opt.saw_tstamp = 0;
 
@@ -5802,9 +5841,8 @@
 		return 0;
 	}
 
-	res = tcp_validate_incoming(sk, skb, th, 0);
-	if (res <= 0)
-		return -res;
+	if (!tcp_validate_incoming(sk, skb, th, 0))
+		return 0;
 
 	/* step 5: check the ACK field */
 	if (th->ack) {
@@ -5921,6 +5959,11 @@
 	} else
 		goto discard;
 
+	/* ts_recent update must be made after we are sure that the packet
+	 * is in window.
+	 */
+	tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq);
+
 	/* step 6: check the URG bit */
 	tcp_urg(sk, skb, th);
 
diff -druN linux-libre-3.0.57-gnu/net/sched/sch_htb.c linux-libre-3.0.58-gnu/net/sched/sch_htb.c
--- linux-libre-3.0.57-gnu/net/sched/sch_htb.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/net/sched/sch_htb.c	2013-01-11 12:04:08.000000000 -0500
@@ -876,7 +876,7 @@
 	q->now = psched_get_time();
 	start_at = jiffies;
 
-	next_event = q->now + 5 * PSCHED_TICKS_PER_SEC;
+	next_event = q->now + 5LLU * PSCHED_TICKS_PER_SEC;
 
 	for (level = 0; level < TC_HTB_MAXDEPTH; level++) {
 		/* common case optimization - skip event handler quickly */
diff -druN linux-libre-3.0.57-gnu/net/sctp/chunk.c linux-libre-3.0.58-gnu/net/sctp/chunk.c
--- linux-libre-3.0.57-gnu/net/sctp/chunk.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/net/sctp/chunk.c	2013-01-11 12:04:08.000000000 -0500
@@ -183,7 +183,7 @@
 
 	msg = sctp_datamsg_new(GFP_KERNEL);
 	if (!msg)
-		return NULL;
+		return ERR_PTR(-ENOMEM);
 
 	/* Note: Calculate this outside of the loop, so that all fragments
 	 * have the same expiration.
@@ -280,11 +280,14 @@
 
 		chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0);
 
-		if (!chunk)
+		if (!chunk) {
+			err = -ENOMEM;
 			goto errout;
+		}
+
 		err = sctp_user_addto_chunk(chunk, offset, len, msgh->msg_iov);
 		if (err < 0)
-			goto errout;
+			goto errout_chunk_free;
 
 		offset += len;
 
@@ -315,8 +318,10 @@
 
 		chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0);
 
-		if (!chunk)
+		if (!chunk) {
+			err = -ENOMEM;
 			goto errout;
+		}
 
 		err = sctp_user_addto_chunk(chunk, offset, over,msgh->msg_iov);
 
@@ -324,7 +329,7 @@
 		__skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr
 			   - (__u8 *)chunk->skb->data);
 		if (err < 0)
-			goto errout;
+			goto errout_chunk_free;
 
 		sctp_datamsg_assign(msg, chunk);
 		list_add_tail(&chunk->frag_list, &msg->chunks);
@@ -332,6 +337,9 @@
 
 	return msg;
 
+errout_chunk_free:
+	sctp_chunk_free(chunk);
+
 errout:
 	list_for_each_safe(pos, temp, &msg->chunks) {
 		list_del_init(pos);
@@ -339,7 +347,7 @@
 		sctp_chunk_free(chunk);
 	}
 	sctp_datamsg_put(msg);
-	return NULL;
+	return ERR_PTR(err);
 }
 
 /* Check whether this message has expired. */
diff -druN linux-libre-3.0.57-gnu/net/sctp/socket.c linux-libre-3.0.58-gnu/net/sctp/socket.c
--- linux-libre-3.0.57-gnu/net/sctp/socket.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/net/sctp/socket.c	2013-01-11 12:04:08.000000000 -0500
@@ -1837,8 +1837,8 @@
 
 	/* Break the message into multiple chunks of maximum size. */
 	datamsg = sctp_datamsg_from_user(asoc, sinfo, msg, msg_len);
-	if (!datamsg) {
-		err = -ENOMEM;
+	if (IS_ERR(datamsg)) {
+		err = PTR_ERR(datamsg);
 		goto out_free;
 	}
 
diff -druN linux-libre-3.0.57-gnu/sound/usb/midi.c linux-libre-3.0.58-gnu/sound/usb/midi.c
--- linux-libre-3.0.57-gnu/sound/usb/midi.c	2012-12-17 13:56:46.000000000 -0500
+++ linux-libre-3.0.58-gnu/sound/usb/midi.c	2013-01-11 12:04:08.000000000 -0500
@@ -115,6 +115,7 @@
 	struct list_head list;
 	struct timer_list error_timer;
 	spinlock_t disc_lock;
+	struct rw_semaphore disc_rwsem;
 	struct mutex mutex;
 	u32 usb_id;
 	int next_midi_device;
@@ -124,8 +125,10 @@
 		struct snd_usb_midi_in_endpoint *in;
 	} endpoints[MIDI_MAX_ENDPOINTS];
 	unsigned long input_triggered;
-	unsigned int opened;
+	bool autopm_reference;
+	unsigned int opened[2];
 	unsigned char disconnected;
+	unsigned char input_running;
 
 	struct snd_kcontrol *roland_load_ctl;
 };
@@ -147,7 +150,6 @@
 		struct snd_usb_midi_out_endpoint* ep;
 		struct snd_rawmidi_substream *substream;
 		int active;
-		bool autopm_reference;
 		uint8_t cable;		/* cable number << 4 */
 		uint8_t state;
 #define STATE_UNKNOWN	0
@@ -1016,29 +1018,58 @@
 	snd_usbmidi_input_start(&umidi->list);
 }
 
-static void substream_open(struct snd_rawmidi_substream *substream, int open)
+static int substream_open(struct snd_rawmidi_substream *substream, int dir,
+			  int open)
 {
 	struct snd_usb_midi* umidi = substream->rmidi->private_data;
 	struct snd_kcontrol *ctl;
+	int err;
+
+	down_read(&umidi->disc_rwsem);
+	if (umidi->disconnected) {
+		up_read(&umidi->disc_rwsem);
+		return open ? -ENODEV : 0;
+	}
 
 	mutex_lock(&umidi->mutex);
 	if (open) {
-		if (umidi->opened++ == 0 && umidi->roland_load_ctl) {
-			ctl = umidi->roland_load_ctl;
-			ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
-			snd_ctl_notify(umidi->card,
+		if (!umidi->opened[0] && !umidi->opened[1]) {
+			err = usb_autopm_get_interface(umidi->iface);
+			umidi->autopm_reference = err >= 0;
+			if (err < 0 && err != -EACCES) {
+				mutex_unlock(&umidi->mutex);
+				up_read(&umidi->disc_rwsem);
+				return -EIO;
+			}
+			if (umidi->roland_load_ctl) {
+				ctl = umidi->roland_load_ctl;
+				ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+				snd_ctl_notify(umidi->card,
 				       SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
-			update_roland_altsetting(umidi);
+				update_roland_altsetting(umidi);
+			}
 		}
+		umidi->opened[dir]++;
+		if (umidi->opened[1])
+			snd_usbmidi_input_start(&umidi->list);
 	} else {
-		if (--umidi->opened == 0 && umidi->roland_load_ctl) {
-			ctl = umidi->roland_load_ctl;
-			ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
-			snd_ctl_notify(umidi->card,
+		umidi->opened[dir]--;
+		if (!umidi->opened[1])
+			snd_usbmidi_input_stop(&umidi->list);
+		if (!umidi->opened[0] && !umidi->opened[1]) {
+			if (umidi->roland_load_ctl) {
+				ctl = umidi->roland_load_ctl;
+				ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+				snd_ctl_notify(umidi->card,
 				       SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
+			}
+			if (umidi->autopm_reference)
+				usb_autopm_put_interface(umidi->iface);
 		}
 	}
 	mutex_unlock(&umidi->mutex);
+	up_read(&umidi->disc_rwsem);
+	return 0;
 }
 
 static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream)
@@ -1046,7 +1077,6 @@
 	struct snd_usb_midi* umidi = substream->rmidi->private_data;
 	struct usbmidi_out_port* port = NULL;
 	int i, j;
-	int err;
 
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
 		if (umidi->endpoints[i].out)
@@ -1059,25 +1089,15 @@
 		snd_BUG();
 		return -ENXIO;
 	}
-	err = usb_autopm_get_interface(umidi->iface);
-	port->autopm_reference = err >= 0;
-	if (err < 0 && err != -EACCES)
-		return -EIO;
+
 	substream->runtime->private_data = port;
 	port->state = STATE_UNKNOWN;
-	substream_open(substream, 1);
-	return 0;
+	return substream_open(substream, 0, 1);
 }
 
 static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream)
 {
-	struct snd_usb_midi* umidi = substream->rmidi->private_data;
-	struct usbmidi_out_port *port = substream->runtime->private_data;
-
-	substream_open(substream, 0);
-	if (port->autopm_reference)
-		usb_autopm_put_interface(umidi->iface);
-	return 0;
+	return substream_open(substream, 0, 0);
 }
 
 static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream, int up)
@@ -1130,14 +1150,12 @@
 
 static int snd_usbmidi_input_open(struct snd_rawmidi_substream *substream)
 {
-	substream_open(substream, 1);
-	return 0;
+	return substream_open(substream, 1, 1);
 }
 
 static int snd_usbmidi_input_close(struct snd_rawmidi_substream *substream)
 {
-	substream_open(substream, 0);
-	return 0;
+	return substream_open(substream, 1, 0);
 }
 
 static void snd_usbmidi_input_trigger(struct snd_rawmidi_substream *substream, int up)
@@ -1386,9 +1404,12 @@
 	 * a timer may submit an URB. To reliably break the cycle
 	 * a flag under lock must be used
 	 */
+	down_write(&umidi->disc_rwsem);
 	spin_lock_irq(&umidi->disc_lock);
 	umidi->disconnected = 1;
 	spin_unlock_irq(&umidi->disc_lock);
+	up_write(&umidi->disc_rwsem);
+
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
 		struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i];
 		if (ep->out)
@@ -2043,12 +2064,15 @@
 	unsigned int i, j;
 
 	umidi = list_entry(p, struct snd_usb_midi, list);
+	if (!umidi->input_running)
+		return;
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) {
 		struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i];
 		if (ep->in)
 			for (j = 0; j < INPUT_URBS; ++j)
 				usb_kill_urb(ep->in->urbs[j]);
 	}
+	umidi->input_running = 0;
 }
 
 static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep)
@@ -2073,8 +2097,11 @@
 	int i;
 
 	umidi = list_entry(p, struct snd_usb_midi, list);
+	if (umidi->input_running || !umidi->opened[1])
+		return;
 	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
 		snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
+	umidi->input_running = 1;
 }
 
 /*
@@ -2100,6 +2127,7 @@
 	umidi->usb_protocol_ops = &snd_usbmidi_standard_ops;
 	init_timer(&umidi->error_timer);
 	spin_lock_init(&umidi->disc_lock);
+	init_rwsem(&umidi->disc_rwsem);
 	mutex_init(&umidi->mutex);
 	umidi->usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor),
 			       le16_to_cpu(umidi->dev->descriptor.idProduct));
@@ -2201,9 +2229,6 @@
 	}
 
 	list_add_tail(&umidi->list, midi_list);
-
-	for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i)
-		snd_usbmidi_input_start_ep(umidi->endpoints[i].in);
 	return 0;
 }
 
