summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Gilles <jgilles@multitech.com>2013-04-18 08:47:01 -0500
committerJesse Gilles <jgilles@multitech.com>2013-04-18 08:47:01 -0500
commit3dfe52165099ece47657bd595c431c4888bfb60a (patch)
tree768ffab45c674cb5d1446162b16d9a14c6eb633e
parentf547c4161d0e058326b2341519029fbebc739dce (diff)
linux: add 2.6.39-at91 recipe using Atmel github branch
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.32.3-at25.patch37
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.32.3-atmel_spi.patch12
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.32.3-option-telit.patch23
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.35.14-at91-gpio-pullup.patch43
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.35.14-option-zte.patch12
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.38-sierra-1.7.40.patch1556
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-at91.patch13539
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-at91sam9260-reset.patch26
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-atmel_serial_disable_hwhs.patch32
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-ledtrig-netdev.patch488
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-option-telit.patch43
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/defconfig2328
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-at91sam9_wdt-10second-timeout.patch14
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-at91sam9x5-extreset.patch16
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-atmel-mci-force-detect.patch30
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-atmel-mci-module-alias.patch9
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-cdc-acm-ignore-exar-devices.patch45
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-macb-force-link.patch87
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-mach-at91-mtocgd3.patch425
-rw-r--r--multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-wl12xx-sdio-irq.patch15
-rw-r--r--multitech/recipes/linux/linux_2.6.39-at91.bb39
21 files changed, 18819 insertions, 0 deletions
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.32.3-at25.patch b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.32.3-at25.patch
new file mode 100644
index 0000000..3aa9096
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.32.3-at25.patch
@@ -0,0 +1,37 @@
+diff -uprN -X linux-2.6.32.3/Documentation/dontdiff linux-2.6.32.3-vanilla/drivers/misc/eeprom/at25.c linux-2.6.32.3/drivers/misc/eeprom/at25.c
+--- linux-2.6.32.3-vanilla/drivers/misc/eeprom/at25.c 2010-01-06 17:07:45.000000000 -0600
++++ linux-2.6.32.3/drivers/misc/eeprom/at25.c 2010-10-27 11:05:36.000000000 -0500
+@@ -147,6 +147,7 @@ at25_ee_write(struct at25_data *at25, co
+ unsigned written = 0;
+ unsigned buf_size;
+ u8 *bounce;
++ int a8;
+
+ if (unlikely(off >= at25->bin.size))
+ return -EFBIG;
+@@ -163,6 +164,11 @@ at25_ee_write(struct at25_data *at25, co
+ if (!bounce)
+ return -ENOMEM;
+
++ if (!strcmp(at25->chip.name, "at25040b"))
++ a8 = 1;
++ else
++ a8 = 0;
++
+ /* For write, rollover is within the page ... so we write at
+ * most one page, then manually roll over to the next page.
+ */
+@@ -183,6 +189,13 @@ at25_ee_write(struct at25_data *at25, co
+ break;
+ }
+
++ if (a8) {
++ if (offset & BIT(8))
++ bounce[0] |= BIT(3);
++ else
++ bounce[0] &= ~BIT(3);
++ }
++
+ /* 8/16/24-bit address is written MSB first */
+ switch (at25->addrlen) {
+ default: /* case 3 */
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.32.3-atmel_spi.patch b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.32.3-atmel_spi.patch
new file mode 100644
index 0000000..a7b87b3
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.32.3-atmel_spi.patch
@@ -0,0 +1,12 @@
+diff -uprN -X linux-2.6.32.3/Documentation/dontdiff linux-2.6.32.3-vanilla/drivers/spi/atmel_spi.c linux-2.6.32.3/drivers/spi/atmel_spi.c
+--- linux-2.6.32.3-vanilla/drivers/spi/atmel_spi.c 2010-01-06 17:07:45.000000000 -0600
++++ linux-2.6.32.3/drivers/spi/atmel_spi.c 2010-09-08 13:38:52.000000000 -0500
+@@ -768,7 +768,7 @@ static int __init atmel_spi_probe(struct
+ master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+
+ master->bus_num = pdev->id;
+- master->num_chipselect = 4;
++ master->num_chipselect = 7;
+ master->setup = atmel_spi_setup;
+ master->transfer = atmel_spi_transfer;
+ master->cleanup = atmel_spi_cleanup;
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.32.3-option-telit.patch b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.32.3-option-telit.patch
new file mode 100644
index 0000000..db0283d
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.32.3-option-telit.patch
@@ -0,0 +1,23 @@
+diff linux-2.6.32.3.orig/drivers/usb/serial/option.c linux-2.6.32.3/drivers/usb/serial/option.c
+--- linux-2.6.32.3.orig/drivers/usb/serial/option.c
++++ linux-2.6.32.3/drivers/usb/serial/option.c
+@@ -293,6 +293,9 @@ static int option_resume(struct usb_serial *serial);
+ #define TELIT_VENDOR_ID 0x1bc7
+ #define TELIT_PRODUCT_UC864E 0x1003
+ #define TELIT_PRODUCT_UC864G 0x1004
++#define TELIT_PRODUCT_CC864_DUAL 0x1005
++#define TELIT_PRODUCT_CC864_SINGLE 0x1006
++#define TELIT_PRODUCT_DE910_DUAL 0x1010
+
+ /* ZTE PRODUCTS */
+ #define ZTE_VENDOR_ID 0x19d2
+@@ -523,6 +526,9 @@ static struct usb_device_id option_ids[] = {
+ { USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) },
++ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) },
++ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
++ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0003, 0xff, 0xff, 0xff) },
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.35.14-at91-gpio-pullup.patch b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.35.14-at91-gpio-pullup.patch
new file mode 100644
index 0000000..d967838
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.35.14-at91-gpio-pullup.patch
@@ -0,0 +1,43 @@
+Index: linux-2.6.35/arch/arm/mach-at91/gpio.c
+===================================================================
+--- linux-2.6.35.orig/arch/arm/mach-at91/gpio.c 2011-09-27 14:36:06.587267689 -0500
++++ linux-2.6.35/arch/arm/mach-at91/gpio.c 2011-09-27 14:42:50.997576753 -0500
+@@ -202,6 +202,26 @@
+ }
+ EXPORT_SYMBOL(at91_set_gpio_output);
+
++/*
++ * configure pin for output and enable/disable pullup
++ */
++int __init_or_module at91_set_gpio_output_with_pullup(unsigned pin, int value, int use_pullup)
++{
++ void __iomem *pio = pin_to_controller(pin);
++ unsigned mask = pin_to_mask(pin);
++
++ if (!pio)
++ return -EINVAL;
++
++ __raw_writel(mask, pio + PIO_IDR);
++ __raw_writel(mask, pio + (use_pullup ? PIO_PUER : PIO_PUDR));
++ __raw_writel(mask, pio + (value ? PIO_SODR : PIO_CODR));
++ __raw_writel(mask, pio + PIO_OER);
++ __raw_writel(mask, pio + PIO_PER);
++ return 0;
++}
++EXPORT_SYMBOL(at91_set_gpio_output_with_pullup);
++
+
+ /*
+ * enable/disable the glitch filter; mostly used with IRQ handling.
+Index: linux-2.6.35/arch/arm/mach-at91/include/mach/gpio.h
+===================================================================
+--- linux-2.6.35.orig/arch/arm/mach-at91/include/mach/gpio.h
++++ linux-2.6.35/arch/arm/mach-at91/include/mach/gpio.h
+@@ -194,6 +194,7 @@ extern int __init_or_module at91_set_A_p
+ extern int __init_or_module at91_set_B_periph(unsigned pin, int use_pullup);
+ extern int __init_or_module at91_set_gpio_input(unsigned pin, int use_pullup);
+ extern int __init_or_module at91_set_gpio_output(unsigned pin, int value);
++extern int __init_or_module at91_set_gpio_output_with_pullup(unsigned pin, int value, int use_pullup);
+ extern int __init_or_module at91_set_deglitch(unsigned pin, int is_on);
+ extern int __init_or_module at91_set_multi_drive(unsigned pin, int is_on);
+
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.35.14-option-zte.patch b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.35.14-option-zte.patch
new file mode 100644
index 0000000..776c7ee
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.35.14-option-zte.patch
@@ -0,0 +1,12 @@
+Index: linux-2.6.35/drivers/usb/serial/option.c
+===================================================================
+--- linux-2.6.35.orig/drivers/usb/serial/option.c
++++ linux-2.6.35/drivers/usb/serial/option.c
+@@ -889,6 +889,7 @@ static const struct usb_device_id option
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xffe8, 0xff, 0xff, 0xff) }, // MC2718
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.38-sierra-1.7.40.patch b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.38-sierra-1.7.40.patch
new file mode 100644
index 0000000..6e55adf
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.38-sierra-1.7.40.patch
@@ -0,0 +1,1556 @@
+Index: linux-2.6.39.4/drivers/net/usb/sierra_net.c
+===================================================================
+--- linux-2.6.39.4.orig/drivers/net/usb/sierra_net.c 2012-02-27 15:37:27.810465204 -0600
++++ linux-2.6.39.4/drivers/net/usb/sierra_net.c 2011-09-22 17:05:46.000000000 -0500
+@@ -1,7 +1,7 @@
+ /*
+ * USB-to-WWAN Driver for Sierra Wireless modems
+ *
+- * Copyright (C) 2008, 2009, 2010 Paxton Smith, Matthew Safar, Rory Filer
++ * Copyright (C) 2008 - 2011 Paxton Smith, Matthew Safar, Rory Filer
+ * <linux@sierrawireless.com>
+ *
+ * Portions of this based on the cdc_ether driver by David Brownell (2003-2005)
+@@ -25,13 +25,17 @@
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+-#define DRIVER_VERSION "v.2.0"
++#define DRIVER_VERSION "v.3.2"
+ #define DRIVER_AUTHOR "Paxton Smith, Matthew Safar, Rory Filer"
+ #define DRIVER_DESC "USB-to-WWAN Driver for Sierra Wireless modems"
+ static const char driver_name[] = "sierra_net";
+
+ /* if defined debug messages enabled */
+ /*#define DEBUG*/
++/* more debug messages */
++/*#define VERBOSE*/
++/* Uncomment to force power level set to auto when attaching a device */
++/*#define POWER_LEVEL_AUTO*/
+
+ #include <linux/module.h>
+ #include <linux/etherdevice.h>
+@@ -48,6 +52,7 @@
+
+ #define SWI_USB_REQUEST_GET_FW_ATTR 0x06
+ #define SWI_GET_FW_ATTR_MASK 0x08
++#define SWI_GET_FW_ATTR_APM 0x2
+
+ /* atomic counter partially included in MAC address to make sure 2 devices
+ * do not end up with the same MAC - concept breaks in case of > 255 ifaces
+@@ -68,6 +73,11 @@
+ */
+ #define SIERRA_NET_USBCTL_BUF_LEN 1024
+
++/* The SIERRA_NET_RX_URB_SZ defines the receive urb size
++ * for optimal throughput.
++ */
++#define SIERRA_NET_RX_URB_SZ 1540
++
+ /* list of interface numbers - used for constructing interface lists */
+ struct sierra_net_iface_info {
+ const u32 infolen; /* number of interface numbers on list */
+@@ -139,6 +149,7 @@
+ #define SIERRA_NET_SESSION_IDLE 0x00
+ /* LSI Link types */
+ #define SIERRA_NET_AS_LINK_TYPE_IPv4 0x00
++#define SIERRA_NET_AS_LINK_TYPE_IPv6 0x02
+
+ struct lsi_umts {
+ u8 protocol;
+@@ -200,10 +211,11 @@
+ dev->data[0] = (unsigned long)priv;
+ }
+
+-/* is packet IPv4 */
++/* is packet IP */
+ static inline int is_ip(struct sk_buff *skb)
+ {
+- return skb->protocol == cpu_to_be16(ETH_P_IP);
++ return ((skb->protocol == cpu_to_be16(ETH_P_IP)) ||
++ (skb->protocol == cpu_to_be16(ETH_P_IPV6)));
+ }
+
+ /*
+@@ -312,6 +324,24 @@
+ /*----------------------------------------------------------------------------*
+ * END HIP *
+ *----------------------------------------------------------------------------*/
++/* This should come out before going to kernel.org */
++static void sierra_net_printk_buf(u8 *buf, u16 len)
++{
++#ifdef VERBOSE
++ u16 i;
++ u16 k;
++
++ for (i = k = 0; i < len / 4; i++, k += 4) {
++ printk(KERN_DEBUG "%02x%02x%02x%02x ",
++ buf[k+0], buf[k+1], buf[k+2], buf[k+3]);
++ }
++
++ for (; k < len; k++)
++ printk(KERN_DEBUG "%02x", buf[k]);
++
++ printk("\n");
++#endif
++}
+
+ static int sierra_net_send_cmd(struct usbnet *dev,
+ u8 *cmd, int cmdlen, const char * cmd_name)
+@@ -319,10 +349,12 @@
+ struct sierra_net_data *priv = sierra_net_get_private(dev);
+ int status;
+
++ usb_autopm_get_interface(dev->intf);
+ status = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+ USB_CDC_SEND_ENCAPSULATED_COMMAND,
+ USB_DIR_OUT|USB_TYPE_CLASS|USB_RECIP_INTERFACE, 0,
+ priv->ifnum, cmd, cmdlen, USB_CTRL_SET_TIMEOUT);
++ usb_autopm_put_interface(dev->intf);
+
+ if (status != cmdlen && status != -ENODEV)
+ netdev_err(dev->net, "Submit %s failed %d\n", cmd_name, status);
+@@ -339,8 +371,17 @@
+
+ status = sierra_net_send_cmd(dev, priv->sync_msg,
+ sizeof(priv->sync_msg), "SYNC");
++ return status;
++}
+
+- return status;
++static void sierra_net_send_shutdown(struct usbnet *dev)
++{
++ struct sierra_net_data *priv = sierra_net_get_private(dev);
++
++ dev_dbg(&dev->udev->dev, "%s", __func__);
++
++ sierra_net_send_cmd(dev, priv->shdwn_msg,
++ sizeof(priv->shdwn_msg), "Shutdown");
+ }
+
+ static void sierra_net_set_ctx_index(struct sierra_net_data *priv, u8 ctx_ix)
+@@ -354,7 +395,7 @@
+
+ static inline int sierra_net_is_valid_addrlen(u8 len)
+ {
+- return len == sizeof(struct in_addr);
++ return (len == sizeof(struct in_addr));
+ }
+
+ static int sierra_net_parse_lsi(struct usbnet *dev, char *data, int datalen)
+@@ -383,10 +424,11 @@
+ }
+
+ /* Validate the link type */
+- if (lsi->link_type != SIERRA_NET_AS_LINK_TYPE_IPv4) {
+- netdev_err(dev->net, "Link type unsupported: 0x%02x\n",
++ if ((lsi->link_type != SIERRA_NET_AS_LINK_TYPE_IPv4) &&
++ (lsi->link_type != SIERRA_NET_AS_LINK_TYPE_IPv6)) {
++ netdev_err(dev->net, "Link unavailable: 0x%02x",
+ lsi->link_type);
+- return -1;
++ return 0;
+ }
+
+ /* Validate the coverage */
+@@ -474,13 +516,15 @@
+ return;
+ }
+ ifnum = priv->ifnum;
++ usb_autopm_get_interface(dev->intf);
+ len = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+ USB_CDC_GET_ENCAPSULATED_RESPONSE,
+ USB_DIR_IN|USB_TYPE_CLASS|USB_RECIP_INTERFACE,
+ 0, ifnum, buf, SIERRA_NET_USBCTL_BUF_LEN,
+ USB_CTRL_SET_TIMEOUT);
++ usb_autopm_put_interface(dev->intf);
+
+- if (len < 0) {
++ if (unlikely(len < 0)) {
+ netdev_err(dev->net,
+ "usb_control_msg failed, status %d\n", len);
+ } else {
+@@ -488,6 +532,7 @@
+
+ dev_dbg(&dev->udev->dev, "%s: Received status message,"
+ " %04x bytes", __func__, len);
++ sierra_net_printk_buf(buf, len);
+
+ err = parse_hip(buf, len, &hh);
+ if (err) {
+@@ -534,7 +579,10 @@
+ "extmsgid 0x%04x\n", hh.extmsgid.word);
+ break;
+ case SIERRA_NET_HIP_RCGI:
+- /* Ignored */
++ /* Ignored. It is a firmware
++ * workaround to solve a Windows driver bug and
++ * may be removed in the future.
++ */
+ break;
+ default:
+ netdev_err(dev->net, "Unrecognized HIP msg, "
+@@ -561,7 +609,10 @@
+ struct sierra_net_data *priv = sierra_net_get_private(dev);
+
+ set_bit(work, &priv->kevent_flags);
+- schedule_work(&priv->sierra_net_kevent);
++ if (!schedule_work(&priv->sierra_net_kevent))
++ dev_dbg(&dev->udev->dev, "sierra_net_kevent %d may have been dropped", work);
++ else
++ dev_dbg(&dev->udev->dev, "sierra_net_kevent %d scheduled", work);
+ }
+
+ /*
+@@ -581,6 +632,7 @@
+ struct usb_cdc_notification *event;
+
+ dev_dbg(&dev->udev->dev, "%s", __func__);
++ sierra_net_printk_buf(urb->transfer_buffer, urb->actual_length);
+
+ if (urb->actual_length < sizeof *event)
+ return;
+@@ -661,6 +713,7 @@
+ if (!attrdata)
+ return -ENOMEM;
+
++ usb_autopm_get_interface(dev->intf);
+ result = usb_control_msg(
+ dev->udev,
+ usb_rcvctrlpipe(dev->udev, 0),
+@@ -672,6 +725,7 @@
+ attrdata, /* char *data */
+ sizeof(*attrdata), /* __u16 size */
+ USB_CTRL_SET_TIMEOUT); /* int timeout */
++ usb_autopm_put_interface(dev->intf);
+
+ if (result < 0) {
+ kfree(attrdata);
+@@ -684,6 +738,12 @@
+ return result;
+ }
+
++static int sierra_net_manage_power(struct usbnet *dev, int on)
++{
++ dev->intf->needs_remote_wakeup = on;
++ return 0;
++}
++
+ /*
+ * collects the bulk endpoints, the status endpoint.
+ */
+@@ -735,6 +795,10 @@
+
+ priv->usbnet = dev;
+ priv->ifnum = ifacenum;
++ /* override change_mtu with our own routine - need to bound check */
++ /* replace structure to our own structure where we have our own
++ * routine - need to bound check
++ */
+ dev->net->netdev_ops = &sierra_net_device_ops;
+
+ /* change MAC addr to include, ifacenum, and to be unique */
+@@ -761,6 +825,7 @@
+
+ /* Set up the netdev */
+ dev->net->flags |= IFF_NOARP;
++ dev->net->flags |= IFF_MULTICAST;
+ dev->net->ethtool_ops = &sierra_net_ethtool_ops;
+ netif_carrier_off(dev->net);
+
+@@ -773,11 +838,23 @@
+
+ /* Only need to do this once */
+ init_timer(&priv->sync_timer);
+-
+ /* verify fw attributes */
+ status = sierra_net_get_fw_attr(dev, &fwattr);
+- dev_dbg(&dev->udev->dev, "Fw attr: %x\n", fwattr);
+-
++ dev_dbg(&dev->udev->dev, "Fw attr: %x\n", fwattr);
++ if (status == sizeof(fwattr) && (fwattr & SWI_GET_FW_ATTR_APM)) {
++/*******************************************************************************
++ * If you want the default /sys/bus/usb/devices/.../.../power/level to be forced
++ * to auto, the following needs to be compiled in.
++ */
++#ifdef POWER_LEVEL_AUTO
++ /* make power level default be 'auto' */
++ dev_dbg(&dev->udev->dev, "Enabling APM");
++ usb_enable_autosuspend(dev->udev);
++#endif
++ } else {
++ dev_info(&intf->dev, "Disabling APM - not supported");
++ usb_disable_autosuspend(dev->udev);
++ }
+ /* test whether firmware supports DHCP */
+ if (!(status == sizeof(fwattr) && (fwattr & SWI_GET_FW_ATTR_MASK))) {
+ /* found incompatible firmware version */
+@@ -789,33 +866,45 @@
+ /* prepare sync message from template */
+ memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg));
+
++ return 0;
++}
++
++static void sierra_net_unbind(struct usbnet *dev, struct usb_interface *intf)
++{
++ struct sierra_net_data *priv = sierra_net_get_private(dev);
++
++ dev_dbg(&dev->udev->dev, "%s", __func__);
++
++ sierra_net_set_private(dev, NULL);
++
++ kfree(priv);
++}
++
++static int sierra_net_open(struct usbnet *dev)
++{
++ dev_dbg(&dev->udev->dev, "%s", __func__);
++
+ /* initiate the sync sequence */
+ sierra_net_dosync(dev);
+
+ return 0;
+ }
+
+-static void sierra_net_unbind(struct usbnet *dev, struct usb_interface *intf)
++static int sierra_net_stop(struct usbnet *dev)
+ {
+- int status;
+ struct sierra_net_data *priv = sierra_net_get_private(dev);
+
+ dev_dbg(&dev->udev->dev, "%s", __func__);
+
+- /* kill the timer and work */
++ /* Kill the timer then flush the work queue */
+ del_timer_sync(&priv->sync_timer);
++
+ cancel_work_sync(&priv->sierra_net_kevent);
+
+ /* tell modem we are going away */
+- status = sierra_net_send_cmd(dev, priv->shdwn_msg,
+- sizeof(priv->shdwn_msg), "Shutdown");
+- if (status < 0)
+- netdev_err(dev->net,
+- "usb_control_msg failed, status %d\n", status);
+-
+- sierra_net_set_private(dev, NULL);
++ sierra_net_send_shutdown(dev);
+
+- kfree(priv);
++ return 0;
+ }
+
+ static struct sk_buff *sierra_net_skb_clone(struct usbnet *dev,
+@@ -847,9 +936,13 @@
+ int err;
+ struct hip_hdr hh;
+ struct sk_buff *new_skb;
++ struct ethhdr *eth;
++ struct iphdr *ip;
+
+ dev_dbg(&dev->udev->dev, "%s", __func__);
+
++ sierra_net_printk_buf(skb->data, skb->len);
++
+ /* could contain multiple packets */
+ while (likely(skb->len)) {
+ err = parse_hip(skb->data, skb->len, &hh);
+@@ -879,6 +972,12 @@
+ memcpy(skb->data, sierra_net_get_private(dev)->ethr_hdr_tmpl,
+ ETH_HLEN);
+
++ ip = (struct iphdr *)((char *)skb->data + ETH_HLEN);
++ if(ip->version == 6) {
++ eth = (struct ethhdr *)skb->data;
++ eth->h_proto = cpu_to_be16(ETH_P_IPV6);
++ }
++
+ /* Last packet in batch handled by usbnet */
+ if (hh.payload_len.word == skb->len)
+ return 1;
+@@ -923,6 +1022,8 @@
+ }
+ }
+ build_hip(skb->data, len, priv);
++
++ sierra_net_printk_buf(skb->data, skb->len);
+ return skb;
+ } else {
+ /*
+@@ -942,16 +1043,24 @@
+ return NULL;
+ }
+
++static int sierra_net_reset_resume(struct usb_interface *intf)
++{
++ struct usbnet *dev = usb_get_intfdata(intf);
++ netdev_err(dev->net, "%s\n", __func__);
++ return usbnet_resume(intf);
++}
++
+ static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 };
+-static const struct sierra_net_info_data sierra_net_info_data_68A3 = {
+- .rx_urb_size = 8 * 1024,
++static const struct sierra_net_info_data sierra_net_info_data_direct_ip = {
++ /* .rx_urb_size = 8 * 1024, */
++ .rx_urb_size = SIERRA_NET_RX_URB_SZ,
+ .whitelist = {
+ .infolen = ARRAY_SIZE(sierra_net_ifnum_list),
+ .ifaceinfo = sierra_net_ifnum_list
+ }
+ };
+
+-static const struct driver_info sierra_net_info_68A3 = {
++static const struct driver_info sierra_net_info_direct_ip = {
+ .description = "Sierra Wireless USB-to-WWAN Modem",
+ .flags = FLAG_WWAN | FLAG_SEND_ZLP,
+ .bind = sierra_net_bind,
+@@ -959,12 +1068,21 @@
+ .status = sierra_net_status,
+ .rx_fixup = sierra_net_rx_fixup,
+ .tx_fixup = sierra_net_tx_fixup,
+- .data = (unsigned long)&sierra_net_info_data_68A3,
++ .manage_power = sierra_net_manage_power,
++ .stop = sierra_net_stop,
++ .check_connect = sierra_net_open,
++ .data = (unsigned long)&sierra_net_info_data_direct_ip,
+ };
+
+ static const struct usb_device_id products[] = {
+- {USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */
+- .driver_info = (unsigned long) &sierra_net_info_68A3},
++ {USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modem */
++ .driver_info = (unsigned long) &sierra_net_info_direct_ip},
++ {USB_DEVICE(0xF3D, 0x68A3), /* AT&T Direct IP modem */
++ .driver_info = (unsigned long) &sierra_net_info_direct_ip},
++ {USB_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */
++ .driver_info = (unsigned long) &sierra_net_info_direct_ip},
++ {USB_DEVICE(0xF3D, 0x68AA), /* AT&T Direct IP LTE modem */
++ .driver_info = (unsigned long) &sierra_net_info_direct_ip},
+
+ {}, /* last item */
+ };
+@@ -978,7 +1096,9 @@
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
++ .reset_resume = sierra_net_reset_resume,
+ .no_dynamic_id = 1,
++ .supports_autosuspend = 1,
+ };
+
+ static int __init sierra_net_init(void)
+Index: linux-2.6.39.4/drivers/usb/serial/sierra.c
+===================================================================
+--- linux-2.6.39.4.orig/drivers/usb/serial/sierra.c 2012-02-27 15:38:01.519215085 -0600
++++ linux-2.6.39.4/drivers/usb/serial/sierra.c 2011-09-22 17:05:46.000000000 -0500
+@@ -3,7 +3,7 @@
+
+ Copyright (C) 2006, 2007, 2008 Kevin Lloyd <klloyd@sierrawireless.com>,
+
+- Copyright (C) 2008, 2009 Elina Pasheva, Matthew Safar, Rory Filer
++ Copyright (C) 2008 - 2011 Elina Pasheva, Matthew Safar, Rory Filer
+ <linux@sierrawireless.com>
+
+ IMPORTANT DISCLAIMER: This driver is not commercially supported by
+@@ -17,8 +17,12 @@
+ Whom based his on the Keyspan driver by Hugh Blemings <hugh@blemings.org>
+ */
+ /* Uncomment to log function calls */
+-/* #define DEBUG */
+-#define DRIVER_VERSION "v.1.7.16"
++/*#define DEBUG*/
++/* Uncomment to force power level set to auto when attaching a device */
++/*#define POWER_LEVEL_AUTO*/
++
++/* Sierra driver - kernel 2.6.38 */
++#define DRIVER_VERSION "v.1.7.40"
+ #define DRIVER_AUTHOR "Kevin Lloyd, Elina Pasheva, Matthew Safar, Rory Filer"
+ #define DRIVER_DESC "USB Driver for Sierra Wireless USB modems"
+
+@@ -31,9 +35,13 @@
+ #include <linux/module.h>
+ #include <linux/usb.h>
+ #include <linux/usb/serial.h>
++#include <asm/unaligned.h>
+
+ #define SWIMS_USB_REQUEST_SetPower 0x00
++#define SWIMS_USB_REQUEST_GetFwAttr 0x06
+ #define SWIMS_USB_REQUEST_SetNmea 0x07
++#define USB_REQUEST_TYPE_CLASS 0xA1
++#define USB_REQUEST_IFACE 0x20
+
+ #define N_IN_URB_HM 8
+ #define N_OUT_URB_HM 64
+@@ -46,19 +54,47 @@
+ allocations > PAGE_SIZE and the number of packets in a page
+ is an integer 512 is the largest possible packet on EHCI */
+
++#define SWI_FW_ATTR_PM_MASK 0x02
++/* PORTION_LEN defines the length of device attribute buffer */
++#define PORTION_LEN 4096
++
+ static int debug;
+ static int nmea;
+
++/* sysfs attributes */
++static int sierra_create_sysfs_attrs(struct usb_serial_port *port);
++static int sierra_remove_sysfs_attrs(struct usb_serial_port *port);
++
+ /* Used in interface blacklisting */
+ struct sierra_iface_info {
+ const u32 infolen; /* number of interface numbers on blacklist */
+ const u8 *ifaceinfo; /* pointer to the array holding the numbers */
+ };
+
++/* per interface statistics */
++struct sierra_intf_stats {
++ atomic_t rx_bytes; /* received bytes */
++ atomic_t indat_cb_cnt; /* indat callback count */
++ atomic_t indat_cb_fail; /* indat cb with error */
++
++ atomic_t tx_bytes; /* transmitted bytes */
++ atomic_t write_cnt; /* no. of writes */
++ atomic_t write_err; /* no. of failed writes */
++
++ atomic_t delayed_writes; /* no. of delayed writes */
++ atomic_t delayed_write_err; /* no. of delayed write errs */
++
++ atomic_t outdat_cb_cnt; /* outdat callback count */
++ atomic_t outdat_cb_fail; /* outdat cb with error */
++
++};
++
+ struct sierra_intf_private {
+ spinlock_t susp_lock;
+ unsigned int suspended:1;
+ int in_flight;
++
++ struct sierra_intf_stats stats;
+ };
+
+ static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
+@@ -91,6 +127,38 @@
+ return result;
+ }
+
++static int sierra_get_fw_attr(struct usb_device *udev, u16 *data)
++{
++ int result;
++ u16 *attrdata;
++
++ dev_dbg(&udev->dev, "%s\n", __func__);
++
++ attrdata = kmalloc(sizeof(*attrdata), GFP_KERNEL);
++ if (!attrdata)
++ return -ENOMEM;
++
++ result = usb_control_msg(udev,
++ usb_rcvctrlpipe(udev, 0),
++ SWIMS_USB_REQUEST_GetFwAttr, /* __u8 request*/
++ USB_TYPE_VENDOR | USB_DIR_IN, /* request type*/
++ 0x0000, /* __u16 value */
++ 0x0000, /* __u16 index */
++ attrdata, /* void *data */
++ sizeof(*attrdata), /* _u16 size */
++ USB_CTRL_SET_TIMEOUT); /* in timeout */
++
++ if (result < 0) {
++ kfree(attrdata);
++ return -EIO;
++ }
++
++ *data = *attrdata;
++
++ kfree(attrdata);
++ return result;
++}
++
+ static int sierra_calc_num_ports(struct usb_serial *serial)
+ {
+ int num_ports = 0;
+@@ -150,7 +218,6 @@
+ int interface;
+ struct usb_interface *p_interface;
+ struct usb_host_interface *p_host_interface;
+- dev_dbg(&serial->dev->dev, "%s\n", __func__);
+
+ /* Get the interface structure pointer from the serial struct */
+ p_interface = serial->interface;
+@@ -159,8 +226,7 @@
+ p_host_interface = p_interface->cur_altsetting;
+
+ /* read the interface descriptor for this active altsetting
+- * to find out the interface number we are on
+- */
++ * to find out the interface number we are on */
+ interface = p_host_interface->desc.bInterfaceNumber;
+
+ return interface;
+@@ -171,7 +237,7 @@
+ {
+ int result = 0;
+ struct usb_device *udev;
+- struct sierra_intf_private *data;
++ struct sierra_intf_private *intfdata;
+ u8 ifnum;
+
+ udev = serial->dev;
+@@ -185,7 +251,9 @@
+ if (serial->interface->num_altsetting == 2) {
+ dev_dbg(&udev->dev, "Selecting alt setting for interface %d\n",
+ ifnum);
+- /* We know the alternate setting is 1 for the MC8785 */
++ /* We know the alternate setting is for composite USB interface
++ * modems
++ */
+ usb_set_interface(udev, ifnum, 1);
+ }
+
+@@ -199,10 +267,11 @@
+ return -ENODEV;
+ }
+
+- data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL);
+- if (!data)
++ intfdata = serial->private = kzalloc(sizeof(struct sierra_intf_private),
++ GFP_KERNEL);
++ if (!intfdata)
+ return -ENOMEM;
+- spin_lock_init(&data->susp_lock);
++ spin_lock_init(&intfdata->susp_lock);
+
+ return result;
+ }
+@@ -223,15 +292,15 @@
+ /* 'blacklist' of interfaces not served by this driver */
+ static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11 };
+ static const struct sierra_iface_info direct_ip_interface_blacklist = {
+- .infolen = ARRAY_SIZE(direct_ip_non_serial_ifaces),
++ .infolen = ARRAY_SIZE( direct_ip_non_serial_ifaces ),
+ .ifaceinfo = direct_ip_non_serial_ifaces,
+ };
+
+-static const struct usb_device_id id_table[] = {
++static const struct usb_device_id id_table [] = {
+ { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */
+ { USB_DEVICE(0x03F0, 0x1B1D) }, /* HP ev2200 a.k.a MC5720 */
+- { USB_DEVICE(0x03F0, 0x211D) }, /* HP ev2210 a.k.a MC5725 */
+ { USB_DEVICE(0x03F0, 0x1E1D) }, /* HP hs2300 a.k.a MC8775 */
++ { USB_DEVICE(0x03F0, 0x211D) }, /* HP ev2210 a.k.a MC5725 */
+
+ { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */
+ { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */
+@@ -245,7 +314,10 @@
+ { USB_DEVICE(0x1199, 0x0021) }, /* Sierra Wireless AirCard 597E */
+ { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */
+ { USB_DEVICE(0x1199, 0x0120) }, /* Sierra Wireless USB Dongle 595U */
+- { USB_DEVICE(0x1199, 0x0301) }, /* Sierra Wireless USB Dongle 250U */
++ { USB_DEVICE(0x1199, 0x0301) }, /* Sierra Wireless USB Dongle 250U/3G */
++ /* Sierra Wireless MC5728 */
++ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0400, 0xFF, 0xFF, 0xFF) },
++
+ /* Sierra Wireless C597 */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x0023, 0xFF, 0xFF, 0xFF) },
+ /* Sierra Wireless T598 */
+@@ -253,7 +325,7 @@
+ { USB_DEVICE(0x1199, 0x0026) }, /* Sierra Wireless T11 */
+ { USB_DEVICE(0x1199, 0x0027) }, /* Sierra Wireless AC402 */
+ { USB_DEVICE(0x1199, 0x0028) }, /* Sierra Wireless MC5728 */
+- { USB_DEVICE(0x1199, 0x0029) }, /* Sierra Wireless Device */
++ { USB_DEVICE(0x114F, 0x6000) }, /* Sierra Wireless Q26 Elite */
+
+ { USB_DEVICE(0x1199, 0x6802) }, /* Sierra Wireless MC8755 */
+ { USB_DEVICE(0x1199, 0x6803) }, /* Sierra Wireless MC8765 */
+@@ -277,7 +349,7 @@
+ { USB_DEVICE(0x1199, 0x683A) }, /* Sierra Wireless MC8785 */
+ { USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */
+ /* Sierra Wireless MC8790, MC8791, MC8792 Composite */
+- { USB_DEVICE(0x1199, 0x683C) },
++ { USB_DEVICE(0x1199, 0x683C) },
+ { USB_DEVICE(0x1199, 0x683D) }, /* Sierra Wireless MC8791 Composite */
+ /* Sierra Wireless MC8790, MC8791, MC8792 */
+ { USB_DEVICE(0x1199, 0x683E) },
+@@ -298,22 +370,34 @@
+ /* Sierra Wireless HSPA Non-Composite Device */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x6892, 0xFF, 0xFF, 0xFF)},
+ { USB_DEVICE(0x1199, 0x6893) }, /* Sierra Wireless Device */
+- { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */
+- .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
++ /* Sierra Wireless Direct IP modems */
++ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68A3, 0xFF, 0xFF, 0xFF),
++ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
+ },
+- { USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */
+- .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
++ /* AT&T Direct IP modems */
++ { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68A3, 0xFF, 0xFF, 0xFF),
++ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
+ },
+- { USB_DEVICE(0x413C, 0x08133) }, /* Dell Computer Corp. Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port */
++ /* Sierra Wireless Direct IP LTE modems */
++ { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68AA, 0xFF, 0xFF, 0xFF),
++ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
++ },
++ /* AT&T Direct IP LTE modems */
++ { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF),
++ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist
++ },
++ /* Wireless 5720 VZW Mobile Broadband (EVDO Rev-A) Minicard GPS Port */
++ { USB_DEVICE(0x413C, 0x8133) },
+
+ { }
+ };
+ MODULE_DEVICE_TABLE(usb, id_table);
+
+-
++/* per port private data */
+ struct sierra_port_private {
+ spinlock_t lock; /* lock the structure */
+ int outstanding_urbs; /* number of out urbs in flight */
++
+ struct usb_anchor active;
+ struct usb_anchor delayed;
+
+@@ -335,7 +419,7 @@
+ static int sierra_send_setup(struct usb_serial_port *port)
+ {
+ struct usb_serial *serial = port->serial;
+- struct sierra_port_private *portdata;
++ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ __u16 interface = 0;
+ int val = 0;
+ int do_send = 0;
+@@ -343,8 +427,6 @@
+
+ dev_dbg(&port->dev, "%s\n", __func__);
+
+- portdata = usb_get_serial_port_data(port);
+-
+ if (portdata->dtr_state)
+ val |= 0x01;
+ if (portdata->rts_state)
+@@ -376,10 +458,7 @@
+ if (!do_send)
+ return 0;
+
+- retval = usb_autopm_get_interface(serial->interface);
+- if (retval < 0)
+- return retval;
+-
++ usb_autopm_get_interface(serial->interface);
+ retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ 0x22, 0x21, val, interface, NULL, 0, USB_CTRL_SET_TIMEOUT);
+ usb_autopm_put_interface(serial->interface);
+@@ -395,7 +474,7 @@
+ sierra_send_setup(port);
+ }
+
+-static int sierra_tiocmget(struct tty_struct *tty)
++static int sierra_tiocmget(struct tty_struct *tty, struct file *file)
+ {
+ struct usb_serial_port *port = tty->driver_data;
+ unsigned int value;
+@@ -414,7 +493,7 @@
+ return value;
+ }
+
+-static int sierra_tiocmset(struct tty_struct *tty,
++static int sierra_tiocmset(struct tty_struct *tty, struct file *file,
+ unsigned int set, unsigned int clear)
+ {
+ struct usb_serial_port *port = tty->driver_data;
+@@ -440,11 +519,77 @@
+ if (urb) {
+ port = urb->context;
+ dev_dbg(&port->dev, "%s: %p\n", __func__, urb);
+- kfree(urb->transfer_buffer);
+ usb_free_urb(urb);
+ }
+ }
+
++/* Sysfs Attributes */
++
++static ssize_t show_suspend_status(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct usb_serial_port *port;
++ struct sierra_port_private *portdata;
++ struct sierra_intf_private *intfdata;
++ unsigned long flags;
++ unsigned int flag_suspended = 0;
++
++ port = to_usb_serial_port(dev);
++ portdata = usb_get_serial_port_data(port);
++ intfdata = port->serial->private;
++
++ spin_lock_irqsave(&intfdata->susp_lock, flags);
++ flag_suspended = intfdata->suspended;
++ spin_unlock_irqrestore(&intfdata->susp_lock, flags);
++
++ return snprintf(buf, PORTION_LEN, "%i\n", flag_suspended);
++}
++
++static ssize_t show_stats(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct usb_serial_port *port;
++ struct sierra_intf_private *intfdata;
++
++ port = to_usb_serial_port(dev);
++ intfdata = port->serial->private;
++
++ return snprintf(buf, PORTION_LEN,
++ "rx: %i B\tindat: %i\tindat err: %i\n"
++ "tx: %i B\toutdat: %i\toutdat err: %i\n"
++ "writes: %i\t\twrite err: %i\n"
++ "delayed writes: %i\tdelayed write err: %i\n",
++ atomic_read(&intfdata->stats.rx_bytes), atomic_read(&intfdata->stats.indat_cb_cnt), atomic_read(&intfdata->stats.indat_cb_fail),
++ atomic_read(&intfdata->stats.tx_bytes), atomic_read(&intfdata->stats.outdat_cb_cnt), atomic_read(&intfdata->stats.outdat_cb_fail),
++ atomic_read(&intfdata->stats.write_cnt), atomic_read(&intfdata->stats.write_err),
++ atomic_read(&intfdata->stats.delayed_writes), atomic_read(&intfdata->stats.delayed_write_err)
++ );
++}
++
++/* Read only suspend status */
++static DEVICE_ATTR(suspend_status, S_IWUSR | S_IRUGO, show_suspend_status,
++ NULL);
++
++/* Read only statistics */
++static DEVICE_ATTR(stats, S_IWUSR | S_IRUGO, show_stats, NULL);
++
++static int sierra_create_sysfs_attrs(struct usb_serial_port *port)
++{
++ int result = 0;
++
++ result = device_create_file(&port->dev, &dev_attr_stats);
++ if (unlikely (result < 0))
++ return result;
++ return device_create_file(&port->dev, &dev_attr_suspend_status);
++}
++
++static int sierra_remove_sysfs_attrs(struct usb_serial_port *port)
++{
++ device_remove_file(&port->dev, &dev_attr_stats);
++ device_remove_file(&port->dev, &dev_attr_suspend_status);
++ return 0;
++}
++
+ static void sierra_outdat_callback(struct urb *urb)
+ {
+ struct usb_serial_port *port = urb->context;
+@@ -455,16 +600,20 @@
+ dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number);
+ intfdata = port->serial->private;
+
+- /* free up the transfer buffer, as usb_free_urb() does not do this */
+- kfree(urb->transfer_buffer);
+ usb_autopm_put_interface_async(port->serial->interface);
+- if (status)
++
++ atomic_inc(&intfdata->stats.outdat_cb_cnt);
++
++ if (status) {
+ dev_dbg(&port->dev, "%s - nonzero write bulk status "
+ "received: %d\n", __func__, status);
++ atomic_inc(&intfdata->stats.outdat_cb_fail);
++ }
+
+ spin_lock(&portdata->lock);
+ --portdata->outstanding_urbs;
+ spin_unlock(&portdata->lock);
++
+ spin_lock(&intfdata->susp_lock);
+ --intfdata->in_flight;
+ spin_unlock(&intfdata->susp_lock);
+@@ -473,10 +622,11 @@
+ }
+
+ /* Write */
+-static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
+- const unsigned char *buf, int count)
++static int sierra_write(struct tty_struct *tty,
++ struct usb_serial_port *port,
++ const unsigned char *buf, int count)
+ {
+- struct sierra_port_private *portdata;
++ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ struct sierra_intf_private *intfdata;
+ struct usb_serial *serial = port->serial;
+ unsigned long flags;
+@@ -489,46 +639,49 @@
+ if (count == 0)
+ return 0;
+
+- portdata = usb_get_serial_port_data(port);
++ dev_dbg(&port->dev, "%s: write (%zu bytes)\n", __func__, writesize);
++
+ intfdata = serial->private;
+
+- dev_dbg(&port->dev, "%s: write (%zd bytes)\n", __func__, writesize);
+ spin_lock_irqsave(&portdata->lock, flags);
+- dev_dbg(&port->dev, "%s - outstanding_urbs: %d\n", __func__,
+- portdata->outstanding_urbs);
+ if (portdata->outstanding_urbs > portdata->num_out_urbs) {
+ spin_unlock_irqrestore(&portdata->lock, flags);
+ dev_dbg(&port->dev, "%s - write limit hit\n", __func__);
+ return 0;
+ }
+ portdata->outstanding_urbs++;
+- dev_dbg(&port->dev, "%s - 1, outstanding_urbs: %d\n", __func__,
+- portdata->outstanding_urbs);
+ spin_unlock_irqrestore(&portdata->lock, flags);
+
+ retval = usb_autopm_get_interface_async(serial->interface);
+- if (retval < 0) {
++ if (unlikely(retval < 0)) {
+ spin_lock_irqsave(&portdata->lock, flags);
+ portdata->outstanding_urbs--;
+ spin_unlock_irqrestore(&portdata->lock, flags);
+- goto error_simple;
++ return retval;
+ }
+
+ buffer = kmalloc(writesize, GFP_ATOMIC);
+ if (!buffer) {
+ dev_err(&port->dev, "out of memory\n");
+- retval = -ENOMEM;
+- goto error_no_buffer;
++ spin_lock_irqsave(&portdata->lock, flags);
++ --portdata->outstanding_urbs;
++ spin_unlock_irqrestore(&portdata->lock, flags);
++ usb_autopm_put_interface_async(serial->interface);
++ return -ENOMEM;
+ }
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ dev_err(&port->dev, "no more free urbs\n");
+- retval = -ENOMEM;
+- goto error_no_urb;
++ kfree(buffer);
++ spin_lock_irqsave(&portdata->lock, flags);
++ --portdata->outstanding_urbs;
++ spin_unlock_irqrestore(&portdata->lock, flags);
++ usb_autopm_put_interface_async(serial->interface);
++ return -ENOMEM;
+ }
+
+- memcpy(buffer, buf, writesize);
++ memcpy(buffer, buf, writesize);
+
+ usb_serial_debug_data(debug, &port->dev, __func__, writesize, buffer);
+
+@@ -537,69 +690,73 @@
+ port->bulk_out_endpointAddress),
+ buffer, writesize, sierra_outdat_callback, port);
+
+- /* Handle the need to send a zero length packet */
+- urb->transfer_flags |= URB_ZERO_PACKET;
++ /* Handle the need to send a zero length packet and release the
++ * transfer buffer
++ */
++ urb->transfer_flags |= (URB_ZERO_PACKET | URB_FREE_BUFFER);
+
+ spin_lock_irqsave(&intfdata->susp_lock, flags);
+
+ if (intfdata->suspended) {
+ usb_anchor_urb(urb, &portdata->delayed);
+ spin_unlock_irqrestore(&intfdata->susp_lock, flags);
+- goto skip_power;
+- } else {
+- usb_anchor_urb(urb, &portdata->active);
++ /* release our reference to this urb, the USB core will
++ * eventually free it entirely */
++ usb_free_urb(urb);
++ return writesize;
+ }
++ usb_anchor_urb(urb, &portdata->active);
++
+ /* send it down the pipe */
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+ if (retval) {
+ usb_unanchor_urb(urb);
+ spin_unlock_irqrestore(&intfdata->susp_lock, flags);
++
+ dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed "
+ "with status = %d\n", __func__, retval);
+- goto error;
++ usb_free_urb(urb);
++ spin_lock_irqsave(&portdata->lock, flags);
++ --portdata->outstanding_urbs;
++ spin_unlock_irqrestore(&portdata->lock, flags);
++ usb_autopm_put_interface_async(serial->interface);
++ atomic_inc(&intfdata->stats.write_err);
++ return retval;
+ } else {
+ intfdata->in_flight++;
+ spin_unlock_irqrestore(&intfdata->susp_lock, flags);
++ atomic_inc(&intfdata->stats.write_cnt);
++ atomic_add(writesize, &intfdata->stats.tx_bytes);
+ }
+-
+-skip_power:
+- /* we are done with this urb, so let the host driver
+- * really free it when it is finished with it */
+- usb_free_urb(urb);
++ /* release our reference to this urb, the USB core will eventually
++ * free it entirely */
++ usb_free_urb(urb);
+
+ return writesize;
+-error:
+- usb_free_urb(urb);
+-error_no_urb:
+- kfree(buffer);
+-error_no_buffer:
+- spin_lock_irqsave(&portdata->lock, flags);
+- --portdata->outstanding_urbs;
+- dev_dbg(&port->dev, "%s - 2. outstanding_urbs: %d\n", __func__,
+- portdata->outstanding_urbs);
+- spin_unlock_irqrestore(&portdata->lock, flags);
+- usb_autopm_put_interface_async(serial->interface);
+-error_simple:
+- return retval;
+ }
+
+ static void sierra_indat_callback(struct urb *urb)
+ {
+ int err;
+ int endpoint;
+- struct usb_serial_port *port;
++ struct usb_serial_port *port = urb->context;
+ struct tty_struct *tty;
++ struct sierra_intf_private *intfdata;
+ unsigned char *data = urb->transfer_buffer;
+ int status = urb->status;
+
+ endpoint = usb_pipeendpoint(urb->pipe);
+- port = urb->context;
+
+ dev_dbg(&port->dev, "%s: %p\n", __func__, urb);
+
++ intfdata = port->serial->private;
++
++ atomic_inc(&intfdata->stats.indat_cb_cnt); /* indat calls */
++
+ if (status) {
+ dev_dbg(&port->dev, "%s: nonzero status: %d on"
+ " endpoint %02x\n", __func__, status, endpoint);
++ atomic_inc(&intfdata->stats.indat_cb_fail); /* indat fails */
+ } else {
+ if (urb->actual_length) {
+ tty = tty_port_tty_get(&port->port);
+@@ -609,6 +766,10 @@
+ tty_flip_buffer_push(tty);
+
+ tty_kref_put(tty);
++ /* tty invalid after this point */
++ /* rx'd bytes */
++ atomic_add(urb->actual_length,
++ &intfdata->stats.rx_bytes);
+ usb_serial_debug_data(debug, &port->dev,
+ __func__, urb->actual_length, data);
+ }
+@@ -619,13 +780,15 @@
+ }
+
+ /* Resubmit urb so we continue receiving */
+- if (status != -ESHUTDOWN && status != -EPERM) {
++ if (status != -ESHUTDOWN && status != -ENOENT && status != -ENODEV) {
+ usb_mark_last_busy(port->serial->dev);
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+- if (err && err != -EPERM)
++ if (err && err != -ENODEV)
+ dev_err(&port->dev, "resubmit read urb failed."
+ "(%d)\n", err);
+ }
++
++ return;
+ }
+
+ static void sierra_instat_callback(struct urb *urb)
+@@ -636,31 +799,29 @@
+ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ struct usb_serial *serial = port->serial;
+
+- dev_dbg(&port->dev, "%s: urb %p port %p has data %p\n", __func__,
+- urb, port, portdata);
++ dev_dbg(&port->dev, "%s: %p\n", __func__, urb);
+
+ if (status == 0) {
+ struct usb_ctrlrequest *req_pkt =
+ (struct usb_ctrlrequest *)urb->transfer_buffer;
+
+- if (!req_pkt) {
+- dev_dbg(&port->dev, "%s: NULL req_pkt\n",
+- __func__);
+- return;
+- }
+- if ((req_pkt->bRequestType == 0xA1) &&
+- (req_pkt->bRequest == 0x20)) {
++ const u16 *sigp = (u16 *)(req_pkt + 1);
++ /* usb_ctrlrequest we parsed is followed by two bytes of data
++ * make sure we received that many bytes
++ */
++ if (urb->actual_length >= sizeof(*req_pkt) + sizeof(*sigp) &&
++ req_pkt->bRequestType == USB_REQUEST_TYPE_CLASS &&
++ req_pkt->bRequest == USB_REQUEST_IFACE) {
+ int old_dcd_state;
+- unsigned char signals = *((unsigned char *)
+- urb->transfer_buffer +
+- sizeof(struct usb_ctrlrequest));
++ const u16 signals = get_unaligned_le16(sigp);
+ struct tty_struct *tty;
+
+- dev_dbg(&port->dev, "%s: signal x%x\n", __func__,
++ dev_dbg(&port->dev, "%s: signal 0x%x\n", __func__,
+ signals);
+
+ old_dcd_state = portdata->dcd_state;
+- portdata->cts_state = 1;
++ /* Note: CTS from modem is in reverse logic! */
++ portdata->cts_state = ((signals & 0x100) ? 0 : 1);
+ portdata->dcd_state = ((signals & 0x01) ? 1 : 0);
+ portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
+ portdata->ri_state = ((signals & 0x08) ? 1 : 0);
+@@ -671,19 +832,19 @@
+ tty_hangup(tty);
+ tty_kref_put(tty);
+ } else {
+- dev_dbg(&port->dev, "%s: type %x req %x\n",
+- __func__, req_pkt->bRequestType,
+- req_pkt->bRequest);
++ /* dump the data we don't understand to log */
++ usb_serial_debug_data(1, &port->dev, __func__,
++ urb->actual_length, urb->transfer_buffer);
+ }
+ } else
+ dev_dbg(&port->dev, "%s: error %d\n", __func__, status);
+
+ /* Resubmit urb so we continue receiving IRQ data */
+- if (status != -ESHUTDOWN && status != -ENOENT) {
++ if (status != -ESHUTDOWN && status != -ENOENT && status != -ENODEV) {
+ usb_mark_last_busy(serial->dev);
+ urb->dev = serial->dev;
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+- if (err && err != -EPERM)
++ if (err && err != -ENODEV)
+ dev_err(&port->dev, "%s: resubmit intr urb "
+ "failed. (%d)\n", __func__, err);
+ }
+@@ -694,20 +855,21 @@
+ struct usb_serial_port *port = tty->driver_data;
+ struct sierra_port_private *portdata = usb_get_serial_port_data(port);
+ unsigned long flags;
++ int retval;
+
+ dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number);
+
+ /* try to give a good number back based on if we have any free urbs at
+ * this point in time */
++ retval = MAX_TRANSFER;
++
+ spin_lock_irqsave(&portdata->lock, flags);
+- if (portdata->outstanding_urbs > (portdata->num_out_urbs * 2) / 3) {
+- spin_unlock_irqrestore(&portdata->lock, flags);
+- dev_dbg(&port->dev, "%s - write limit hit\n", __func__);
+- return 0;
++ if (portdata->outstanding_urbs >= portdata->num_out_urbs) {
++ retval = 0;
+ }
+ spin_unlock_irqrestore(&portdata->lock, flags);
+
+- return 2048;
++ return retval;
+ }
+
+ static void sierra_stop_rx_urbs(struct usb_serial_port *port)
+@@ -734,6 +896,7 @@
+ urb = portdata->in_urbs[i];
+ if (!urb)
+ continue;
++ urb->transfer_flags |= URB_FREE_BUFFER;
+ err = usb_submit_urb(urb, mem_flags);
+ if (err) {
+ dev_err(&port->dev, "%s: submit urb failed: %d\n",
+@@ -795,38 +958,31 @@
+
+ return urb;
+ }
+-
+ static void sierra_close(struct usb_serial_port *port)
+ {
+ int i;
++ struct urb *urb;
+ struct usb_serial *serial = port->serial;
+ struct sierra_port_private *portdata;
+ struct sierra_intf_private *intfdata = port->serial->private;
+
+-
+ dev_dbg(&port->dev, "%s\n", __func__);
+ portdata = usb_get_serial_port_data(port);
+
+ portdata->rts_state = 0;
+ portdata->dtr_state = 0;
+
++ usb_autopm_get_interface(serial->interface);
++
+ if (serial->dev) {
+ mutex_lock(&serial->disc_mutex);
+- if (!serial->disconnected) {
+- serial->interface->needs_remote_wakeup = 0;
+- /* odd error handling due to pm counters */
+- if (!usb_autopm_get_interface(serial->interface))
+- sierra_send_setup(port);
+- else
+- usb_autopm_get_interface_no_resume(serial->interface);
+-
+- }
++ if (!serial->disconnected)
++ sierra_send_setup(port);
+ mutex_unlock(&serial->disc_mutex);
+ spin_lock_irq(&intfdata->susp_lock);
+ portdata->opened = 0;
+ spin_unlock_irq(&intfdata->susp_lock);
+
+-
+ /* Stop reading urbs */
+ sierra_stop_rx_urbs(port);
+ /* .. and release them */
+@@ -834,6 +990,14 @@
+ sierra_release_urb(portdata->in_urbs[i]);
+ portdata->in_urbs[i] = NULL;
+ }
++ while((urb = usb_get_from_anchor(&portdata->delayed))) {
++ sierra_release_urb(urb);
++ usb_autopm_put_interface(serial->interface);
++ }
++ /* wait for active to finish */
++ usb_wait_anchor_empty_timeout(&portdata->active, 500);
++ usb_kill_anchored_urbs(&portdata->active);
++
+ }
+ }
+
+@@ -867,18 +1031,41 @@
+ usb_clear_halt(serial->dev,
+ usb_sndbulkpipe(serial->dev, endpoint) | USB_DIR_IN);
+
++ /* reset outstanding out urbs counter */
++ spin_lock_irq(&portdata->lock);
++ portdata->outstanding_urbs = 0;
++ spin_unlock_irq(&portdata->lock);
++
+ err = sierra_submit_rx_urbs(port, GFP_KERNEL);
+ if (err) {
+- /* get rid of everything as in close */
+- sierra_close(port);
+- /* restore balance for autopm */
+- if (!serial->disconnected)
++ /* do everything as in close() but do not call close() because
++ * usbserial calls sierra_open() with mutex taken;
++ * then if we call sierra_close() inside sierra_open() we
++ * violate 'no nested mutexes' kernel condition
++ */
++ portdata->rts_state = 0;
++ portdata->dtr_state = 0;
++ usb_autopm_get_interface(serial->interface);
++ /* Stop reading urbs */
++ sierra_stop_rx_urbs(port);
++ /* .. and release them */
++ for (i = 0; i < portdata->num_in_urbs; i++) {
++ sierra_release_urb(portdata->in_urbs[i]);
++ portdata->in_urbs[i] = NULL;
++ }
++ while((urb = usb_get_from_anchor(&portdata->delayed))) {
++ sierra_release_urb(urb);
+ usb_autopm_put_interface(serial->interface);
++ }
++ /* wait for active to finish */
++ usb_wait_anchor_empty_timeout(&portdata->active, 500);
++ usb_kill_anchored_urbs(&portdata->active);
++ /* restore balance for autopm */
++ usb_autopm_put_interface(serial->interface);
+ return err;
+ }
+ sierra_send_setup(port);
+
+- serial->interface->needs_remote_wakeup = 1;
+ spin_lock_irq(&intfdata->susp_lock);
+ portdata->opened = 1;
+ spin_unlock_irq(&intfdata->susp_lock);
+@@ -887,7 +1074,6 @@
+ return 0;
+ }
+
+-
+ static void sierra_dtr_rts(struct usb_serial_port *port, int on)
+ {
+ struct usb_serial *serial = port->serial;
+@@ -907,11 +1093,13 @@
+
+ static int sierra_startup(struct usb_serial *serial)
+ {
+- struct usb_serial_port *port;
+- struct sierra_port_private *portdata;
++ struct usb_serial_port *port = NULL;
++ struct sierra_port_private *portdata = NULL;
+ struct sierra_iface_info *himemoryp = NULL;
+ int i;
+ u8 ifnum;
++ u16 fw_attr;
++ int result;
+
+ dev_dbg(&serial->dev->dev, "%s\n", __func__);
+
+@@ -922,19 +1110,30 @@
+ if (nmea)
+ sierra_vsc_set_nmea(serial->dev, 1);
+
+- /* Now setup per port private data */
+- for (i = 0; i < serial->num_ports; i++) {
+- port = serial->port[i];
+- portdata = kzalloc(sizeof(*portdata), GFP_KERNEL);
++ if (serial->num_ports) {
++ /* Note: One big piece of memory is allocated for all ports
++ * private data in one shot. This memory is split into equal
++ * pieces for each port.
++ */
++ portdata = (struct sierra_port_private *)kzalloc
++ (sizeof(*portdata) * serial->num_ports, GFP_KERNEL);
+ if (!portdata) {
+- dev_dbg(&port->dev, "%s: kmalloc for "
+- "sierra_port_private (%d) failed!\n",
+- __func__, i);
++ dev_dbg(&serial->dev->dev, "%s: No memory!\n", __func__);
+ return -ENOMEM;
+ }
++ }
++
++ /* Now setup per port private data */
++ for (i = 0; i < serial->num_ports; i++, portdata++) {
++ port = serial->port[i];
++ /* Initialize selected members of private data because these
++ * may be referred to right away */
+ spin_lock_init(&portdata->lock);
+ init_usb_anchor(&portdata->active);
+ init_usb_anchor(&portdata->delayed);
++
++ portdata->cts_state = 1;
++
+ ifnum = i;
+ /* Assume low memory requirements */
+ portdata->num_out_urbs = N_OUT_URB;
+@@ -959,12 +1158,29 @@
+ portdata->num_in_urbs = N_IN_URB_HM;
+ }
+ }
+- dev_dbg(&serial->dev->dev,
++ dev_dbg(&serial->dev->dev,
+ "Memory usage (urbs) interface #%d, in=%d, out=%d\n",
+ ifnum,portdata->num_in_urbs, portdata->num_out_urbs );
+ /* Set the port private data pointer */
+ usb_set_serial_port_data(port, portdata);
+ }
++ serial->interface->needs_remote_wakeup = 1;
++
++ result = sierra_get_fw_attr(serial->dev, &fw_attr);
++ if (result == sizeof(fw_attr) && (fw_attr & SWI_FW_ATTR_PM_MASK) ) {
++ dev_info(&serial->dev->dev,
++ "APM supported, enabling autosuspend.\n");
++/*******************************************************************************
++ * If you want the default /sys/bus/usb/devices/.../.../power/level to be forced
++ * to auto, the following needs to be compiled in.
++ */
++#ifdef POWER_LEVEL_AUTO
++ /* make power level default be 'auto' */
++ usb_enable_autosuspend(serial->dev);
++#endif
++ } else {
++ usb_disable_autosuspend(serial->dev);
++ }
+
+ return 0;
+ }
+@@ -973,19 +1189,29 @@
+ {
+ int i;
+ struct usb_serial_port *port;
+- struct sierra_port_private *portdata;
++ struct sierra_intf_private *intfdata = serial->private;
+
+ dev_dbg(&serial->dev->dev, "%s\n", __func__);
+
++ if (serial->num_ports > 0) {
++ port = serial->port[0];
++ if (port)
++ /* Note: The entire piece of memory that was allocated
++ * in the startup routine can be released by passing
++ * a pointer to the beginning of the piece.
++ * This address corresponds to the address of the chunk
++ * that was given to port 0.
++ */
++ kfree(usb_get_serial_port_data(port));
++ }
++
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ if (!port)
+ continue;
+- portdata = usb_get_serial_port_data(port);
+- if (!portdata)
+- continue;
+- kfree(portdata);
++ usb_set_serial_port_data(port, NULL);
+ }
++ kfree(intfdata);
+ }
+
+ #ifdef CONFIG_PM
+@@ -1007,21 +1233,21 @@
+ static int sierra_suspend(struct usb_serial *serial, pm_message_t message)
+ {
+ struct sierra_intf_private *intfdata;
+- int b;
+
+- if (message.event & PM_EVENT_AUTO) {
+- intfdata = serial->private;
+- spin_lock_irq(&intfdata->susp_lock);
+- b = intfdata->in_flight;
++ dev_dbg(&serial->dev->dev, "%s\n", __func__);
++
++ intfdata = serial->private;
++ spin_lock_irq(&intfdata->susp_lock);
+
+- if (b) {
++ if (message.event & PM_EVENT_AUTO) {
++ if (intfdata->in_flight) {
+ spin_unlock_irq(&intfdata->susp_lock);
+ return -EBUSY;
+- } else {
+- intfdata->suspended = 1;
+- spin_unlock_irq(&intfdata->susp_lock);
+ }
+ }
++ intfdata->suspended = 1;
++ spin_unlock_irq(&intfdata->susp_lock);
++
+ stop_read_write_urbs(serial);
+
+ return 0;
+@@ -1035,22 +1261,35 @@
+ struct urb *urb;
+ int ec = 0;
+ int i, err;
++ int len;
++ int failed_submits;
+
++ dev_dbg(&serial->dev->dev, "%s\n", __func__);
++
+ spin_lock_irq(&intfdata->susp_lock);
+ for (i = 0; i < serial->num_ports; i++) {
+ port = serial->port[i];
+ portdata = usb_get_serial_port_data(port);
+-
++ failed_submits = 0;
+ while ((urb = usb_get_from_anchor(&portdata->delayed))) {
+ usb_anchor_urb(urb, &portdata->active);
+ intfdata->in_flight++;
++ len = urb->transfer_buffer_length;
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (err < 0) {
+ intfdata->in_flight--;
+ usb_unanchor_urb(urb);
+- usb_scuttle_anchored_urbs(&portdata->delayed);
+- break;
++ failed_submits++;
++ atomic_inc(&intfdata->stats.delayed_write_err);
++ /* fix pm_usage_cnt */
++ usb_autopm_put_interface_async(
++ port->serial->interface);
++ } else {
++ atomic_inc(&intfdata->stats.delayed_writes);
++ atomic_add(len, &intfdata->stats.tx_bytes);
+ }
++ /* release urb - usb_get_from_anchor increased kref */
++ usb_free_urb(urb);
+ }
+
+ if (portdata->opened) {
+@@ -1058,12 +1297,24 @@
+ if (err)
+ ec++;
+ }
++ if (failed_submits) {
++ /* fix outstanding_urbs counter */
++ spin_lock(&portdata->lock); /* assuming irq disabled */
++ portdata->outstanding_urbs -= failed_submits;
++ spin_unlock(&portdata->lock);
++ /* unblock a writer */
++ usb_serial_port_softint(port);
++ }
+ }
+ intfdata->suspended = 0;
+ spin_unlock_irq(&intfdata->susp_lock);
+
+ return ec ? -EIO : 0;
+ }
++#else
++#define sierra_suspend NULL
++#define sierra_resume NULL
++#endif
+
+ static int sierra_reset_resume(struct usb_interface *intf)
+ {
+@@ -1071,11 +1322,6 @@
+ dev_err(&serial->dev->dev, "%s\n", __func__);
+ return usb_serial_resume(intf);
+ }
+-#else
+-#define sierra_suspend NULL
+-#define sierra_resume NULL
+-#define sierra_reset_resume NULL
+-#endif
+
+ static struct usb_driver sierra_driver = {
+ .name = "sierra",
+@@ -1085,10 +1331,12 @@
+ .resume = usb_serial_resume,
+ .reset_resume = sierra_reset_resume,
+ .id_table = id_table,
+- .no_dynamic_id = 1,
+- .supports_autosuspend = 1,
++
++ .no_dynamic_id = 1,
++ .supports_autosuspend = 1,
+ };
+
++
+ static struct usb_serial_driver sierra_device = {
+ .driver = {
+ .owner = THIS_MODULE,
+@@ -1109,9 +1357,12 @@
+ .tiocmset = sierra_tiocmset,
+ .attach = sierra_startup,
+ .release = sierra_release,
+- .suspend = sierra_suspend,
+- .resume = sierra_resume,
++ .port_probe = sierra_create_sysfs_attrs,
++ .port_remove = sierra_remove_sysfs_attrs,
++ .suspend = sierra_suspend,
++ .resume = sierra_resume,
+ .read_int_callback = sierra_instat_callback,
++
+ };
+
+ /* Functions used by new usb-serial code. */
+@@ -1122,7 +1373,6 @@
+ if (retval)
+ goto failed_device_register;
+
+-
+ retval = usb_register(&sierra_driver);
+ if (retval)
+ goto failed_driver_register;
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-at91.patch b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-at91.patch
new file mode 100644
index 0000000..579ddfa
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-at91.patch
@@ -0,0 +1,13539 @@
+diff --git a/Documentation/filesystems/caching/netfs-api.txt b/Documentation/filesystems/caching/netfs-api.txt
+index a167ab8..7cc6bf2 100644
+--- a/Documentation/filesystems/caching/netfs-api.txt
++++ b/Documentation/filesystems/caching/netfs-api.txt
+@@ -673,6 +673,22 @@ storage request to complete, or it may attempt to cancel the storage request -
+ in which case the page will not be stored in the cache this time.
+
+
++BULK INODE PAGE UNCACHE
++-----------------------
++
++A convenience routine is provided to perform an uncache on all the pages
++attached to an inode. This assumes that the pages on the inode correspond on a
++1:1 basis with the pages in the cache.
++
++ void fscache_uncache_all_inode_pages(struct fscache_cookie *cookie,
++ struct inode *inode);
++
++This takes the netfs cookie that the pages were cached with and the inode that
++the pages are attached to. This function will wait for pages to finish being
++written to the cache and for the cache to finish with the page generally. No
++error is returned.
++
++
+ ==========================
+ INDEX AND DATA FILE UPDATE
+ ==========================
+diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
+index 5ebf5af..5aa5337 100644
+--- a/Documentation/i2c/writing-clients
++++ b/Documentation/i2c/writing-clients
+@@ -38,7 +38,7 @@ static struct i2c_driver foo_driver = {
+ .name = "foo",
+ },
+
+- .id_table = foo_ids,
++ .id_table = foo_idtable,
+ .probe = foo_probe,
+ .remove = foo_remove,
+ /* if device autodetection is needed: */
+diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
+index cc85a92..066b642 100644
+--- a/Documentation/kernel-parameters.txt
++++ b/Documentation/kernel-parameters.txt
+@@ -2590,6 +2590,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
+ unlock ejectable media);
+ m = MAX_SECTORS_64 (don't transfer more
+ than 64 sectors = 32 KB at a time);
++ n = INITIAL_READ10 (force a retry of the
++ initial READ(10) command);
+ o = CAPACITY_OK (accept the capacity
+ reported by the device);
+ r = IGNORE_RESIDUE (the device reports
+diff --git a/Documentation/usb/linux-cdc-acm.inf b/Documentation/usb/linux-cdc-acm.inf
+index 612e722..37a02ce 100644
+--- a/Documentation/usb/linux-cdc-acm.inf
++++ b/Documentation/usb/linux-cdc-acm.inf
+@@ -90,10 +90,10 @@ ServiceBinary=%12%\USBSER.sys
+ [SourceDisksFiles]
+ [SourceDisksNames]
+ [DeviceList]
+-%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_0525&PID_A4AB&MI_02
++%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02
+
+ [DeviceList.NTamd64]
+-%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_0525&PID_A4AB&MI_02
++%DESCRIPTION%=DriverInstall, USB\VID_0525&PID_A4A7, USB\VID_1D6B&PID_0104&MI_02
+
+
+ ;------------------------------------------------------------------------------
+diff --git a/Documentation/usb/linux.inf b/Documentation/usb/linux.inf
+index 4dee958..4ffa715b0 100644
+--- a/Documentation/usb/linux.inf
++++ b/Documentation/usb/linux.inf
+@@ -18,15 +18,15 @@ DriverVer = 06/21/2006,6.0.6000.16384
+
+ ; Decoration for x86 architecture
+ [LinuxDevices.NTx86]
+-%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_0525&PID_a4ab&MI_00
++%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_1d6b&PID_0104&MI_00
+
+ ; Decoration for x64 architecture
+ [LinuxDevices.NTamd64]
+-%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_0525&PID_a4ab&MI_00
++%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_1d6b&PID_0104&MI_00
+
+ ; Decoration for ia64 architecture
+ [LinuxDevices.NTia64]
+-%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_0525&PID_a4ab&MI_00
++%LinuxDevice% = RNDIS.NT.5.1, USB\VID_0525&PID_a4a2, USB\VID_1d6b&PID_0104&MI_00
+
+ ;@@@ This is the common setting for setup
+ [ControlFlags]
+diff --git a/Makefile b/Makefile
+index 123d858..1b2a736 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ VERSION = 2
+ PATCHLEVEL = 6
+ SUBLEVEL = 39
+-EXTRAVERSION =
++EXTRAVERSION = .4
+ NAME = Flesh-Eating Bats with Fangs
+
+ # *DOCUMENTATION*
+@@ -1374,7 +1374,7 @@ endif # KBUILD_EXTMOD
+ clean: $(clean-dirs)
+ $(call cmd,rmdirs)
+ $(call cmd,rmfiles)
+- @find $(or $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
++ @find $(if $(KBUILD_EXTMOD), $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
+ \( -name '*.[oas]' -o -name '*.ko' -o -name '.*.cmd' \
+ -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
+ -o -name '*.symtypes' -o -name 'modules.order' \
+diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c
+index 376f221..326f0a2 100644
+--- a/arch/alpha/kernel/osf_sys.c
++++ b/arch/alpha/kernel/osf_sys.c
+@@ -409,7 +409,7 @@ SYSCALL_DEFINE2(osf_getdomainname, char __user *, name, int, namelen)
+ return -EFAULT;
+
+ len = namelen;
+- if (namelen > 32)
++ if (len > 32)
+ len = 32;
+
+ down_read(&uts_sem);
+@@ -594,7 +594,7 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count)
+ down_read(&uts_sem);
+ res = sysinfo_table[offset];
+ len = strlen(res)+1;
+- if (len > count)
++ if ((unsigned long)len > (unsigned long)count)
+ len = count;
+ if (copy_to_user(buf, res, len))
+ err = -EFAULT;
+@@ -649,7 +649,7 @@ SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer,
+ return 1;
+
+ case GSI_GET_HWRPB:
+- if (nbytes < sizeof(*hwrpb))
++ if (nbytes > sizeof(*hwrpb))
+ return -EINVAL;
+ if (copy_to_user(buffer, hwrpb, nbytes) != 0)
+ return -EFAULT;
+@@ -1008,6 +1008,7 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options,
+ {
+ struct rusage r;
+ long ret, err;
++ unsigned int status = 0;
+ mm_segment_t old_fs;
+
+ if (!ur)
+@@ -1016,13 +1017,15 @@ SYSCALL_DEFINE4(osf_wait4, pid_t, pid, int __user *, ustatus, int, options,
+ old_fs = get_fs();
+
+ set_fs (KERNEL_DS);
+- ret = sys_wait4(pid, ustatus, options, (struct rusage __user *) &r);
++ ret = sys_wait4(pid, (unsigned int __user *) &status, options,
++ (struct rusage __user *) &r);
+ set_fs (old_fs);
+
+ if (!access_ok(VERIFY_WRITE, ur, sizeof(*ur)))
+ return -EFAULT;
+
+ err = 0;
++ err |= put_user(status, ustatus);
+ err |= __put_user(r.ru_utime.tv_sec, &ur->ru_utime.tv_sec);
+ err |= __put_user(r.ru_utime.tv_usec, &ur->ru_utime.tv_usec);
+ err |= __put_user(r.ru_stime.tv_sec, &ur->ru_stime.tv_sec);
+diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
+index 139e3c8..d284a30 100644
+--- a/arch/arm/kernel/perf_event.c
++++ b/arch/arm/kernel/perf_event.c
+@@ -588,7 +588,7 @@ static int armpmu_event_init(struct perf_event *event)
+ static void armpmu_enable(struct pmu *pmu)
+ {
+ /* Enable all of the perf events on hardware. */
+- int idx;
++ int idx, enabled = 0;
+ struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
+
+ if (!armpmu)
+@@ -601,9 +601,11 @@ static void armpmu_enable(struct pmu *pmu)
+ continue;
+
+ armpmu->enable(&event->hw, idx);
++ enabled = 1;
+ }
+
+- armpmu->start();
++ if (enabled)
++ armpmu->start();
+ }
+
+ static void armpmu_disable(struct pmu *pmu)
+diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
+index c67f684..09a87e6 100644
+--- a/arch/arm/mach-davinci/board-dm365-evm.c
++++ b/arch/arm/mach-davinci/board-dm365-evm.c
+@@ -520,7 +520,7 @@ fail:
+ */
+ if (have_imager()) {
+ label = "HD imager";
+- mux |= 1;
++ mux |= 2;
+
+ /* externally mux MMC1/ENET/AIC33 to imager */
+ mux |= BIT(6) | BIT(5) | BIT(3);
+@@ -540,7 +540,7 @@ fail:
+ resets &= ~BIT(1);
+
+ if (have_tvp7002()) {
+- mux |= 2;
++ mux |= 1;
+ resets &= ~BIT(2);
+ label = "tvp7002 HD";
+ } else {
+diff --git a/arch/arm/mach-exynos4/init.c b/arch/arm/mach-exynos4/init.c
+index cf91f50..a8a83e3 100644
+--- a/arch/arm/mach-exynos4/init.c
++++ b/arch/arm/mach-exynos4/init.c
+@@ -35,6 +35,7 @@ void __init exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+ tcfg->clocks = exynos4_serial_clocks;
+ tcfg->clocks_size = ARRAY_SIZE(exynos4_serial_clocks);
+ }
++ tcfg->flags |= NO_NEED_CHECK_CLKSRC;
+ }
+
+ s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
+diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
+index 72b4e76..ab9f999 100644
+--- a/arch/arm/mach-mmp/pxa168.c
++++ b/arch/arm/mach-mmp/pxa168.c
+@@ -79,7 +79,7 @@ static APBC_CLK(ssp4, PXA168_SSP4, 4, 0);
+ static APBC_CLK(ssp5, PXA168_SSP5, 4, 0);
+ static APBC_CLK(keypad, PXA168_KPC, 0, 32000);
+
+-static APMU_CLK(nand, NAND, 0x01db, 208000000);
++static APMU_CLK(nand, NAND, 0x19b, 156000000);
+ static APMU_CLK(lcd, LCD, 0x7f, 312000000);
+
+ /* device and clock bindings */
+diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
+index 8f92ccd..1464607 100644
+--- a/arch/arm/mach-mmp/pxa910.c
++++ b/arch/arm/mach-mmp/pxa910.c
+@@ -110,7 +110,7 @@ static APBC_CLK(pwm2, PXA910_PWM2, 1, 13000000);
+ static APBC_CLK(pwm3, PXA910_PWM3, 1, 13000000);
+ static APBC_CLK(pwm4, PXA910_PWM4, 1, 13000000);
+
+-static APMU_CLK(nand, NAND, 0x01db, 208000000);
++static APMU_CLK(nand, NAND, 0x19b, 156000000);
+ static APMU_CLK(u2o, USB, 0x1b, 480000000);
+
+ /* device and clock bindings */
+diff --git a/arch/arm/mach-pxa/mfp-pxa2xx.c b/arch/arm/mach-pxa/mfp-pxa2xx.c
+index 1d1419b..dfff1de 100644
+--- a/arch/arm/mach-pxa/mfp-pxa2xx.c
++++ b/arch/arm/mach-pxa/mfp-pxa2xx.c
+@@ -347,9 +347,9 @@ static int pxa2xx_mfp_suspend(struct sys_device *d, pm_message_t state)
+ if ((gpio_desc[i].config & MFP_LPM_KEEP_OUTPUT) &&
+ (GPDR(i) & GPIO_bit(i))) {
+ if (GPLR(i) & GPIO_bit(i))
+- PGSR(i) |= GPIO_bit(i);
++ PGSR(gpio_to_bank(i)) |= GPIO_bit(i);
+ else
+- PGSR(i) &= ~GPIO_bit(i);
++ PGSR(gpio_to_bank(i)) &= ~GPIO_bit(i);
+ }
+ }
+
+diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
+index c96fa1b..73b4a8b 100644
+--- a/arch/arm/mm/cache-v6.S
++++ b/arch/arm/mm/cache-v6.S
+@@ -176,6 +176,7 @@ ENDPROC(v6_coherent_kern_range)
+ */
+ ENTRY(v6_flush_kern_dcache_area)
+ add r1, r0, r1
++ bic r0, r0, #D_CACHE_LINE_SIZE - 1
+ 1:
+ #ifdef HARVARD_CACHE
+ mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line
+diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
+index dc18d81..d32f02b 100644
+--- a/arch/arm/mm/cache-v7.S
++++ b/arch/arm/mm/cache-v7.S
+@@ -221,6 +221,8 @@ ENDPROC(v7_coherent_user_range)
+ ENTRY(v7_flush_kern_dcache_area)
+ dcache_line_size r2, r3
+ add r1, r0, r1
++ sub r3, r2, #1
++ bic r0, r0, r3
+ 1:
+ mcr p15, 0, r0, c7, c14, 1 @ clean & invalidate D line / unified line
+ add r0, r0, r2
+diff --git a/arch/arm/plat-samsung/include/plat/regs-serial.h b/arch/arm/plat-samsung/include/plat/regs-serial.h
+index 788837e9..d2ef07f 100644
+--- a/arch/arm/plat-samsung/include/plat/regs-serial.h
++++ b/arch/arm/plat-samsung/include/plat/regs-serial.h
+@@ -224,6 +224,8 @@
+ #define S5PV210_UFSTAT_RXMASK (255<<0)
+ #define S5PV210_UFSTAT_RXSHIFT (0)
+
++#define NO_NEED_CHECK_CLKSRC 1
++
+ #ifndef __ASSEMBLY__
+
+ /* struct s3c24xx_uart_clksrc
+diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S
+index 9b8393d..c54cca87 100644
+--- a/arch/m68k/kernel/syscalltable.S
++++ b/arch/m68k/kernel/syscalltable.S
+@@ -319,8 +319,8 @@ ENTRY(sys_call_table)
+ .long sys_readlinkat
+ .long sys_fchmodat
+ .long sys_faccessat /* 300 */
+- .long sys_ni_syscall /* Reserved for pselect6 */
+- .long sys_ni_syscall /* Reserved for ppoll */
++ .long sys_pselect6
++ .long sys_ppoll
+ .long sys_unshare
+ .long sys_set_robust_list
+ .long sys_get_robust_list /* 305 */
+diff --git a/arch/parisc/include/asm/unistd.h b/arch/parisc/include/asm/unistd.h
+index 3eb82c2a..9cbc2c3 100644
+--- a/arch/parisc/include/asm/unistd.h
++++ b/arch/parisc/include/asm/unistd.h
+@@ -814,8 +814,14 @@
+ #define __NR_recvmmsg (__NR_Linux + 319)
+ #define __NR_accept4 (__NR_Linux + 320)
+ #define __NR_prlimit64 (__NR_Linux + 321)
+-
+-#define __NR_Linux_syscalls (__NR_prlimit64 + 1)
++#define __NR_fanotify_init (__NR_Linux + 322)
++#define __NR_fanotify_mark (__NR_Linux + 323)
++#define __NR_clock_adjtime (__NR_Linux + 324)
++#define __NR_name_to_handle_at (__NR_Linux + 325)
++#define __NR_open_by_handle_at (__NR_Linux + 326)
++#define __NR_syncfs (__NR_Linux + 327)
++
++#define __NR_Linux_syscalls (__NR_syncfs + 1)
+
+
+ #define __IGNORE_select /* newselect */
+diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c
+index 88a0ad1..dc9a624 100644
+--- a/arch/parisc/kernel/sys_parisc32.c
++++ b/arch/parisc/kernel/sys_parisc32.c
+@@ -228,3 +228,11 @@ asmlinkage long compat_sys_fallocate(int fd, int mode, u32 offhi, u32 offlo,
+ return sys_fallocate(fd, mode, ((loff_t)offhi << 32) | offlo,
+ ((loff_t)lenhi << 32) | lenlo);
+ }
++
++asmlinkage long compat_sys_fanotify_mark(int fan_fd, int flags, u32 mask_hi,
++ u32 mask_lo, int fd,
++ const char __user *pathname)
++{
++ return sys_fanotify_mark(fan_fd, flags, ((u64)mask_hi << 32) | mask_lo,
++ fd, pathname);
++}
+diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
+index 4be85ee..a5b02ce 100644
+--- a/arch/parisc/kernel/syscall_table.S
++++ b/arch/parisc/kernel/syscall_table.S
+@@ -420,6 +420,12 @@
+ ENTRY_COMP(recvmmsg)
+ ENTRY_SAME(accept4) /* 320 */
+ ENTRY_SAME(prlimit64)
++ ENTRY_SAME(fanotify_init)
++ ENTRY_COMP(fanotify_mark)
++ ENTRY_COMP(clock_adjtime)
++ ENTRY_SAME(name_to_handle_at) /* 325 */
++ ENTRY_COMP(open_by_handle_at)
++ ENTRY_SAME(syncfs)
+
+ /* Nothing yet */
+
+diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c
+index 5b5e1f0..c37ff6b 100644
+--- a/arch/powerpc/kernel/crash.c
++++ b/arch/powerpc/kernel/crash.c
+@@ -170,7 +170,7 @@ static void crash_kexec_wait_realmode(int cpu)
+ int i;
+
+ msecs = 10000;
+- for (i=0; i < NR_CPUS && msecs > 0; i++) {
++ for (i=0; i < nr_cpu_ids && msecs > 0; i++) {
+ if (i == cpu)
+ continue;
+
+diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
+index c5c24be..727f40a 100644
+--- a/arch/powerpc/kernel/head_32.S
++++ b/arch/powerpc/kernel/head_32.S
+@@ -896,7 +896,7 @@ _GLOBAL(start_secondary_resume)
+ rlwinm r1,r1,0,0,(31-THREAD_SHIFT) /* current_thread_info() */
+ addi r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
+ li r3,0
+- std r3,0(r1) /* Zero the stack frame pointer */
++ stw r3,0(r1) /* Zero the stack frame pointer */
+ bl start_secondary
+ b .
+ #endif /* CONFIG_SMP */
+diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S
+index 206a321..e89df59 100644
+--- a/arch/powerpc/kernel/misc_64.S
++++ b/arch/powerpc/kernel/misc_64.S
+@@ -462,7 +462,8 @@ _GLOBAL(disable_kernel_fp)
+ * wait for the flag to change, indicating this kernel is going away but
+ * the slave code for the next one is at addresses 0 to 100.
+ *
+- * This is used by all slaves.
++ * This is used by all slaves, even those that did not find a matching
++ * paca in the secondary startup code.
+ *
+ * Physical (hardware) cpu id should be in r3.
+ */
+@@ -471,10 +472,6 @@ _GLOBAL(kexec_wait)
+ 1: mflr r5
+ addi r5,r5,kexec_flag-1b
+
+- li r4,KEXEC_STATE_REAL_MODE
+- stb r4,PACAKEXECSTATE(r13)
+- SYNC
+-
+ 99: HMT_LOW
+ #ifdef CONFIG_KEXEC /* use no memory without kexec */
+ lwz r4,0(r5)
+@@ -499,11 +496,17 @@ kexec_flag:
+ *
+ * get phys id from paca
+ * switch to real mode
++ * mark the paca as no longer used
+ * join other cpus in kexec_wait(phys_id)
+ */
+ _GLOBAL(kexec_smp_wait)
+ lhz r3,PACAHWCPUID(r13)
+ bl real_mode
++
++ li r4,KEXEC_STATE_REAL_MODE
++ stb r4,PACAKEXECSTATE(r13)
++ SYNC
++
+ b .kexec_wait
+
+ /*
+diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
+index cbdbb14..f2dcab7 100644
+--- a/arch/powerpc/kernel/smp.c
++++ b/arch/powerpc/kernel/smp.c
+@@ -410,8 +410,6 @@ int __cpuinit __cpu_up(unsigned int cpu)
+ {
+ int rc, c;
+
+- secondary_ti = current_set[cpu];
+-
+ if (smp_ops == NULL ||
+ (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)))
+ return -EINVAL;
+@@ -421,6 +419,8 @@ int __cpuinit __cpu_up(unsigned int cpu)
+ if (rc)
+ return rc;
+
++ secondary_ti = current_set[cpu];
++
+ /* Make sure callin-map entry is 0 (can be leftover a CPU
+ * hotplug
+ */
+diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c
+index 8ee51a2..e6bec74 100644
+--- a/arch/powerpc/oprofile/op_model_power4.c
++++ b/arch/powerpc/oprofile/op_model_power4.c
+@@ -261,6 +261,28 @@ static int get_kernel(unsigned long pc, unsigned long mmcra)
+ return is_kernel;
+ }
+
++static bool pmc_overflow(unsigned long val)
++{
++ if ((int)val < 0)
++ return true;
++
++ /*
++ * Events on POWER7 can roll back if a speculative event doesn't
++ * eventually complete. Unfortunately in some rare cases they will
++ * raise a performance monitor exception. We need to catch this to
++ * ensure we reset the PMC. In all cases the PMC will be 256 or less
++ * cycles from overflow.
++ *
++ * We only do this if the first pass fails to find any overflowing
++ * PMCs because a user might set a period of less than 256 and we
++ * don't want to mistakenly reset them.
++ */
++ if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256))
++ return true;
++
++ return false;
++}
++
+ static void power4_handle_interrupt(struct pt_regs *regs,
+ struct op_counter_config *ctr)
+ {
+@@ -281,7 +303,7 @@ static void power4_handle_interrupt(struct pt_regs *regs,
+
+ for (i = 0; i < cur_cpu_spec->num_pmcs; ++i) {
+ val = classic_ctr_read(i);
+- if (val < 0) {
++ if (pmc_overflow(val)) {
+ if (oprofile_running && ctr[i].enabled) {
+ oprofile_add_ext_sample(pc, regs, i, is_kernel);
+ classic_ctr_write(i, reset_value[i]);
+diff --git a/arch/sh/kernel/cpu/Makefile b/arch/sh/kernel/cpu/Makefile
+index d49c213..ae95935 100644
+--- a/arch/sh/kernel/cpu/Makefile
++++ b/arch/sh/kernel/cpu/Makefile
+@@ -17,7 +17,5 @@ obj-$(CONFIG_ARCH_SHMOBILE) += shmobile/
+
+ obj-$(CONFIG_SH_ADC) += adc.o
+ obj-$(CONFIG_SH_CLK_CPG_LEGACY) += clock-cpg.o
+-obj-$(CONFIG_SH_FPU) += fpu.o
+-obj-$(CONFIG_SH_FPU_EMU) += fpu.o
+
+-obj-y += irq/ init.o clock.o hwblk.o proc.o
++obj-y += irq/ init.o clock.o fpu.o hwblk.o proc.o
+diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c
+index ea38f0c..1073269 100644
+--- a/arch/tile/kernel/pci.c
++++ b/arch/tile/kernel/pci.c
+@@ -179,12 +179,6 @@ int __init tile_pci_init(void)
+
+ controller = &controllers[num_controllers];
+
+- if (tile_init_irqs(i, controller)) {
+- pr_err("PCI: Could not initialize "
+- "IRQs, aborting.\n");
+- goto err_cont;
+- }
+-
+ controller->index = num_controllers;
+ controller->hv_cfg_fd[0] = hv_cfg_fd0;
+ controller->hv_cfg_fd[1] = hv_cfg_fd1;
+@@ -300,6 +294,11 @@ static int __init pcibios_init(void)
+ struct pci_controller *controller = &controllers[i];
+ struct pci_bus *bus;
+
++ if (tile_init_irqs(i, controller)) {
++ pr_err("PCI: Could not initialize IRQS\n");
++ continue;
++ }
++
+ pr_info("PCI: initializing controller #%d\n", i);
+
+ /*
+diff --git a/arch/um/Kconfig.x86 b/arch/um/Kconfig.x86
+index a9da516..795ea8e 100644
+--- a/arch/um/Kconfig.x86
++++ b/arch/um/Kconfig.x86
+@@ -29,10 +29,10 @@ config X86_64
+ def_bool 64BIT
+
+ config RWSEM_XCHGADD_ALGORITHM
+- def_bool X86_XADD
++ def_bool X86_XADD && 64BIT
+
+ config RWSEM_GENERIC_SPINLOCK
+- def_bool !X86_XADD
++ def_bool !RWSEM_XCHGADD_ALGORITHM
+
+ config 3_LEVEL_PGTABLES
+ bool "Three-level pagetables (EXPERIMENTAL)" if !64BIT
+diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h
+index 91f3e087..cc5b052 100644
+--- a/arch/x86/include/asm/cpufeature.h
++++ b/arch/x86/include/asm/cpufeature.h
+@@ -125,7 +125,7 @@
+ #define X86_FEATURE_OSXSAVE (4*32+27) /* "" XSAVE enabled in the OS */
+ #define X86_FEATURE_AVX (4*32+28) /* Advanced Vector Extensions */
+ #define X86_FEATURE_F16C (4*32+29) /* 16-bit fp conversions */
+-#define X86_FEATURE_RDRND (4*32+30) /* The RDRAND instruction */
++#define X86_FEATURE_RDRAND (4*32+30) /* The RDRAND instruction */
+ #define X86_FEATURE_HYPERVISOR (4*32+31) /* Running on a hypervisor */
+
+ /* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
+diff --git a/arch/x86/include/asm/pvclock.h b/arch/x86/include/asm/pvclock.h
+index 31d84ac..a518c0a 100644
+--- a/arch/x86/include/asm/pvclock.h
++++ b/arch/x86/include/asm/pvclock.h
+@@ -22,6 +22,8 @@ static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift)
+ u64 product;
+ #ifdef __i386__
+ u32 tmp1, tmp2;
++#else
++ ulong tmp;
+ #endif
+
+ if (shift < 0)
+@@ -42,8 +44,11 @@ static inline u64 pvclock_scale_delta(u64 delta, u32 mul_frac, int shift)
+ : "a" ((u32)delta), "1" ((u32)(delta >> 32)), "2" (mul_frac) );
+ #elif defined(__x86_64__)
+ __asm__ (
+- "mul %%rdx ; shrd $32,%%rdx,%%rax"
+- : "=a" (product) : "0" (delta), "d" ((u64)mul_frac) );
++ "mul %[mul_frac] ; shrd $32, %[hi], %[lo]"
++ : [lo]"=a"(product),
++ [hi]"=d"(tmp)
++ : "0"(delta),
++ [mul_frac]"rm"((u64)mul_frac));
+ #else
+ #error implement me!
+ #endif
+diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
+index abd3e0e..99f0ad7 100644
+--- a/arch/x86/include/asm/uaccess.h
++++ b/arch/x86/include/asm/uaccess.h
+@@ -42,7 +42,7 @@
+ * Returns 0 if the range is valid, nonzero otherwise.
+ *
+ * This is equivalent to the following test:
+- * (u33)addr + (u33)size >= (u33)current->addr_limit.seg (u65 for x86_64)
++ * (u33)addr + (u33)size > (u33)current->addr_limit.seg (u65 for x86_64)
+ *
+ * This needs 33-bit (65-bit for x86_64) arithmetic. We have a carry...
+ */
+diff --git a/arch/x86/kernel/acpi/realmode/wakeup.S b/arch/x86/kernel/acpi/realmode/wakeup.S
+index ead21b6..b4fd836 100644
+--- a/arch/x86/kernel/acpi/realmode/wakeup.S
++++ b/arch/x86/kernel/acpi/realmode/wakeup.S
+@@ -28,6 +28,8 @@ pmode_cr3: .long 0 /* Saved %cr3 */
+ pmode_cr4: .long 0 /* Saved %cr4 */
+ pmode_efer: .quad 0 /* Saved EFER */
+ pmode_gdt: .quad 0
++pmode_misc_en: .quad 0 /* Saved MISC_ENABLE MSR */
++pmode_behavior: .long 0 /* Wakeup behavior flags */
+ realmode_flags: .long 0
+ real_magic: .long 0
+ trampoline_segment: .word 0
+@@ -91,6 +93,18 @@ wakeup_code:
+ /* Call the C code */
+ calll main
+
++ /* Restore MISC_ENABLE before entering protected mode, in case
++ BIOS decided to clear XD_DISABLE during S3. */
++ movl pmode_behavior, %eax
++ btl $WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE, %eax
++ jnc 1f
++
++ movl pmode_misc_en, %eax
++ movl pmode_misc_en + 4, %edx
++ movl $MSR_IA32_MISC_ENABLE, %ecx
++ wrmsr
++1:
++
+ /* Do any other stuff... */
+
+ #ifndef CONFIG_64BIT
+diff --git a/arch/x86/kernel/acpi/realmode/wakeup.h b/arch/x86/kernel/acpi/realmode/wakeup.h
+index e1828c0..97a29e1 100644
+--- a/arch/x86/kernel/acpi/realmode/wakeup.h
++++ b/arch/x86/kernel/acpi/realmode/wakeup.h
+@@ -21,6 +21,9 @@ struct wakeup_header {
+ u32 pmode_efer_low; /* Protected mode EFER */
+ u32 pmode_efer_high;
+ u64 pmode_gdt;
++ u32 pmode_misc_en_low; /* Protected mode MISC_ENABLE */
++ u32 pmode_misc_en_high;
++ u32 pmode_behavior; /* Wakeup routine behavior flags */
+ u32 realmode_flags;
+ u32 real_magic;
+ u16 trampoline_segment; /* segment with trampoline code, 64-bit only */
+@@ -39,4 +42,7 @@ extern struct wakeup_header wakeup_header;
+ #define WAKEUP_HEADER_SIGNATURE 0x51ee1111
+ #define WAKEUP_END_SIGNATURE 0x65a22c82
+
++/* Wakeup behavior bits */
++#define WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE 0
++
+ #endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */
+diff --git a/arch/x86/kernel/acpi/sleep.c b/arch/x86/kernel/acpi/sleep.c
+index ff93bc1..cdddffc 100644
+--- a/arch/x86/kernel/acpi/sleep.c
++++ b/arch/x86/kernel/acpi/sleep.c
+@@ -77,6 +77,12 @@ int acpi_suspend_lowlevel(void)
+
+ header->pmode_cr0 = read_cr0();
+ header->pmode_cr4 = read_cr4_safe();
++ header->pmode_behavior = 0;
++ if (!rdmsr_safe(MSR_IA32_MISC_ENABLE,
++ &header->pmode_misc_en_low,
++ &header->pmode_misc_en_high))
++ header->pmode_behavior |=
++ (1 << WAKEUP_BEHAVIOR_RESTORE_MISC_ENABLE);
+ header->realmode_flags = acpi_realmode_flags;
+ header->real_magic = 0x12345678;
+
+diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c
+index 57ca777..e7115c8 100644
+--- a/arch/x86/kernel/amd_iommu.c
++++ b/arch/x86/kernel/amd_iommu.c
+@@ -28,6 +28,7 @@
+ #include <asm/proto.h>
+ #include <asm/iommu.h>
+ #include <asm/gart.h>
++#include <asm/dma.h>
+ #include <asm/amd_iommu_proto.h>
+ #include <asm/amd_iommu_types.h>
+ #include <asm/amd_iommu.h>
+@@ -153,6 +154,10 @@ static int iommu_init_device(struct device *dev)
+ pdev = pci_get_bus_and_slot(PCI_BUS(alias), alias & 0xff);
+ if (pdev)
+ dev_data->alias = &pdev->dev;
++ else {
++ kfree(dev_data);
++ return -ENOTSUPP;
++ }
+
+ atomic_set(&dev_data->bind, 0);
+
+@@ -162,6 +167,20 @@ static int iommu_init_device(struct device *dev)
+ return 0;
+ }
+
++static void iommu_ignore_device(struct device *dev)
++{
++ u16 devid, alias;
++
++ devid = get_device_id(dev);
++ alias = amd_iommu_alias_table[devid];
++
++ memset(&amd_iommu_dev_table[devid], 0, sizeof(struct dev_table_entry));
++ memset(&amd_iommu_dev_table[alias], 0, sizeof(struct dev_table_entry));
++
++ amd_iommu_rlookup_table[devid] = NULL;
++ amd_iommu_rlookup_table[alias] = NULL;
++}
++
+ static void iommu_uninit_device(struct device *dev)
+ {
+ kfree(dev->archdata.iommu);
+@@ -191,7 +210,9 @@ int __init amd_iommu_init_devices(void)
+ continue;
+
+ ret = iommu_init_device(&pdev->dev);
+- if (ret)
++ if (ret == -ENOTSUPP)
++ iommu_ignore_device(&pdev->dev);
++ else if (ret)
+ goto out_free;
+ }
+
+@@ -2296,6 +2317,23 @@ static struct dma_map_ops amd_iommu_dma_ops = {
+ .dma_supported = amd_iommu_dma_supported,
+ };
+
++static unsigned device_dma_ops_init(void)
++{
++ struct pci_dev *pdev = NULL;
++ unsigned unhandled = 0;
++
++ for_each_pci_dev(pdev) {
++ if (!check_device(&pdev->dev)) {
++ unhandled += 1;
++ continue;
++ }
++
++ pdev->dev.archdata.dma_ops = &amd_iommu_dma_ops;
++ }
++
++ return unhandled;
++}
++
+ /*
+ * The function which clues the AMD IOMMU driver into dma_ops.
+ */
+@@ -2308,7 +2346,7 @@ void __init amd_iommu_init_api(void)
+ int __init amd_iommu_init_dma_ops(void)
+ {
+ struct amd_iommu *iommu;
+- int ret;
++ int ret, unhandled;
+
+ /*
+ * first allocate a default protection domain for every IOMMU we
+@@ -2334,7 +2372,11 @@ int __init amd_iommu_init_dma_ops(void)
+ swiotlb = 0;
+
+ /* Make the driver finally visible to the drivers */
+- dma_ops = &amd_iommu_dma_ops;
++ unhandled = device_dma_ops_init();
++ if (unhandled && max_pfn > MAX_DMA32_PFN) {
++ /* There are unhandled devices - initialize swiotlb for them */
++ swiotlb = 1;
++ }
+
+ amd_iommu_stats_init();
+
+diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c
+index 246d727..b9e207e 100644
+--- a/arch/x86/kernel/amd_iommu_init.c
++++ b/arch/x86/kernel/amd_iommu_init.c
+@@ -701,8 +701,8 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu,
+ {
+ u8 *p = (u8 *)h;
+ u8 *end = p, flags = 0;
+- u16 dev_i, devid = 0, devid_start = 0, devid_to = 0;
+- u32 ext_flags = 0;
++ u16 devid = 0, devid_start = 0, devid_to = 0;
++ u32 dev_i, ext_flags = 0;
+ bool alias = false;
+ struct ivhd_entry *e;
+
+@@ -857,7 +857,7 @@ static void __init init_iommu_from_acpi(struct amd_iommu *iommu,
+ /* Initializes the device->iommu mapping for the driver */
+ static int __init init_iommu_devices(struct amd_iommu *iommu)
+ {
+- u16 i;
++ u32 i;
+
+ for (i = iommu->first_device; i <= iommu->last_device; ++i)
+ set_iommu_for_device(iommu, i);
+@@ -1146,7 +1146,7 @@ static int __init init_memory_definitions(struct acpi_table_header *table)
+ */
+ static void init_device_table(void)
+ {
+- u16 devid;
++ u32 devid;
+
+ for (devid = 0; devid <= amd_iommu_last_bdf; ++devid) {
+ set_dev_entry_bit(devid, DEV_ENTRY_VALID);
+diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
+index 45fd33d..df63620 100644
+--- a/arch/x86/kernel/apic/io_apic.c
++++ b/arch/x86/kernel/apic/io_apic.c
+@@ -621,14 +621,14 @@ struct IO_APIC_route_entry **alloc_ioapic_entries(void)
+ struct IO_APIC_route_entry **ioapic_entries;
+
+ ioapic_entries = kzalloc(sizeof(*ioapic_entries) * nr_ioapics,
+- GFP_KERNEL);
++ GFP_ATOMIC);
+ if (!ioapic_entries)
+ return 0;
+
+ for (apic = 0; apic < nr_ioapics; apic++) {
+ ioapic_entries[apic] =
+ kzalloc(sizeof(struct IO_APIC_route_entry) *
+- nr_ioapic_registers[apic], GFP_KERNEL);
++ nr_ioapic_registers[apic], GFP_ATOMIC);
+ if (!ioapic_entries[apic])
+ goto nomem;
+ }
+diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
+index 6f9d1f6..b13ed39 100644
+--- a/arch/x86/kernel/cpu/amd.c
++++ b/arch/x86/kernel/cpu/amd.c
+@@ -612,8 +612,11 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ }
+ #endif
+
+- /* As a rule processors have APIC timer running in deep C states */
+- if (c->x86 > 0xf && !cpu_has_amd_erratum(amd_erratum_400))
++ /*
++ * Family 0x12 and above processors have APIC timer
++ * running in deep C states.
++ */
++ if (c->x86 > 0x11)
+ set_cpu_cap(c, X86_FEATURE_ARAT);
+
+ /*
+@@ -629,10 +632,13 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
+ * Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33012
+ */
+ u64 mask;
++ int err;
+
+- rdmsrl(MSR_AMD64_MCx_MASK(4), mask);
+- mask |= (1 << 10);
+- wrmsrl(MSR_AMD64_MCx_MASK(4), mask);
++ err = rdmsrl_safe(MSR_AMD64_MCx_MASK(4), &mask);
++ if (err == 0) {
++ mask |= (1 << 10);
++ checking_wrmsrl(MSR_AMD64_MCx_MASK(4), mask);
++ }
+ }
+ }
+
+diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
+index e2ced00..173f3a3 100644
+--- a/arch/x86/kernel/cpu/common.c
++++ b/arch/x86/kernel/cpu/common.c
+@@ -565,8 +565,7 @@ void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)
+
+ cpuid_count(0x00000007, 0, &eax, &ebx, &ecx, &edx);
+
+- if (eax > 0)
+- c->x86_capability[9] = ebx;
++ c->x86_capability[9] = ebx;
+ }
+
+ /* AMD-defined flags: level 0x80000001 */
+diff --git a/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
+index 755a31e..907c8e6 100644
+--- a/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
++++ b/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
+@@ -39,7 +39,7 @@
+
+ #include <acpi/processor.h>
+
+-#define PCC_VERSION "1.00.00"
++#define PCC_VERSION "1.10.00"
+ #define POLL_LOOPS 300
+
+ #define CMD_COMPLETE 0x1
+@@ -102,7 +102,7 @@ static struct acpi_generic_address doorbell;
+ static u64 doorbell_preserve;
+ static u64 doorbell_write;
+
+-static u8 OSC_UUID[16] = {0x63, 0x9B, 0x2C, 0x9F, 0x70, 0x91, 0x49, 0x1f,
++static u8 OSC_UUID[16] = {0x9F, 0x2C, 0x9B, 0x63, 0x91, 0x70, 0x1f, 0x49,
+ 0xBB, 0x4F, 0xA5, 0x98, 0x2F, 0xA1, 0xB5, 0x46};
+
+ struct pcc_cpu {
+diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
+index e90f084..bea9c03 100644
+--- a/arch/x86/kernel/devicetree.c
++++ b/arch/x86/kernel/devicetree.c
+@@ -13,6 +13,7 @@
+ #include <linux/slab.h>
+ #include <linux/pci.h>
+ #include <linux/of_pci.h>
++#include <linux/initrd.h>
+
+ #include <asm/hpet.h>
+ #include <asm/irq_controller.h>
+@@ -98,6 +99,16 @@ void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+ return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
+ }
+
++#ifdef CONFIG_BLK_DEV_INITRD
++void __init early_init_dt_setup_initrd_arch(unsigned long start,
++ unsigned long end)
++{
++ initrd_start = (unsigned long)__va(start);
++ initrd_end = (unsigned long)__va(end);
++ initrd_below_start_ok = 1;
++}
++#endif
++
+ void __init add_dtb(u64 data)
+ {
+ initial_dtb = data + offsetof(struct setup_data, data);
+diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
+index 8d12878..a3d0dc5 100644
+--- a/arch/x86/kernel/process_32.c
++++ b/arch/x86/kernel/process_32.c
+@@ -245,7 +245,6 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
+ {
+ set_user_gs(regs, 0);
+ regs->fs = 0;
+- set_fs(USER_DS);
+ regs->ds = __USER_DS;
+ regs->es = __USER_DS;
+ regs->ss = __USER_DS;
+diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
+index 6c9dd92..ca6f7ab 100644
+--- a/arch/x86/kernel/process_64.c
++++ b/arch/x86/kernel/process_64.c
+@@ -338,7 +338,6 @@ start_thread_common(struct pt_regs *regs, unsigned long new_ip,
+ regs->cs = _cs;
+ regs->ss = _ss;
+ regs->flags = X86_EFLAGS_IF;
+- set_fs(USER_DS);
+ /*
+ * Free the old FP and other extended state
+ */
+diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
+index 08c44b0..1def278 100644
+--- a/arch/x86/kernel/reboot.c
++++ b/arch/x86/kernel/reboot.c
+@@ -411,6 +411,14 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "iMac9,1"),
+ },
+ },
++ { /* Handle problems with rebooting on the Latitude E5420. */
++ .callback = set_pci_reboot,
++ .ident = "Dell Latitude E5420",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
++ DMI_MATCH(DMI_PRODUCT_NAME, "Latitude E5420"),
++ },
++ },
+ { }
+ };
+
+diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
+index c2871d3..c58d144 100644
+--- a/arch/x86/kernel/smpboot.c
++++ b/arch/x86/kernel/smpboot.c
+@@ -285,6 +285,19 @@ notrace static void __cpuinit start_secondary(void *unused)
+ per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
+ x86_platform.nmi_init();
+
++ /*
++ * Wait until the cpu which brought this one up marked it
++ * online before enabling interrupts. If we don't do that then
++ * we can end up waking up the softirq thread before this cpu
++ * reached the active state, which makes the scheduler unhappy
++ * and schedule the softirq thread on the wrong cpu. This is
++ * only observable with forced threaded interrupts, but in
++ * theory it could also happen w/o them. It's just way harder
++ * to achieve.
++ */
++ while (!cpumask_test_cpu(smp_processor_id(), cpu_active_mask))
++ cpu_relax();
++
+ /* enable local interrupts */
+ local_irq_enable();
+
+diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c
+index 1cd6089..493ea1f 100644
+--- a/arch/x86/lguest/boot.c
++++ b/arch/x86/lguest/boot.c
+@@ -995,6 +995,7 @@ static void lguest_time_irq(unsigned int irq, struct irq_desc *desc)
+ static void lguest_time_init(void)
+ {
+ /* Set up the timer interrupt (0) to go to our simple timer routine */
++ lguest_setup_irq(0);
+ irq_set_handler(0, lguest_time_irq);
+
+ clocksource_register(&lguest_clock);
+diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S
+index 99e4826..a73397f 100644
+--- a/arch/x86/lib/copy_user_64.S
++++ b/arch/x86/lib/copy_user_64.S
+@@ -72,7 +72,7 @@ ENTRY(_copy_to_user)
+ addq %rdx,%rcx
+ jc bad_to_user
+ cmpq TI_addr_limit(%rax),%rcx
+- jae bad_to_user
++ ja bad_to_user
+ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+ CFI_ENDPROC
+ ENDPROC(_copy_to_user)
+@@ -85,7 +85,7 @@ ENTRY(_copy_from_user)
+ addq %rdx,%rcx
+ jc bad_from_user
+ cmpq TI_addr_limit(%rax),%rcx
+- jae bad_from_user
++ ja bad_from_user
+ ALTERNATIVE_JUMP X86_FEATURE_REP_GOOD,copy_user_generic_unrolled,copy_user_generic_string
+ CFI_ENDPROC
+ ENDPROC(_copy_from_user)
+diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c
+index cf97500..68894fd 100644
+--- a/arch/x86/oprofile/nmi_int.c
++++ b/arch/x86/oprofile/nmi_int.c
+@@ -112,8 +112,10 @@ static void nmi_cpu_start(void *dummy)
+ static int nmi_start(void)
+ {
+ get_online_cpus();
+- on_each_cpu(nmi_cpu_start, NULL, 1);
+ ctr_running = 1;
++ /* make ctr_running visible to the nmi handler: */
++ smp_mb();
++ on_each_cpu(nmi_cpu_start, NULL, 1);
+ put_online_cpus();
+ return 0;
+ }
+@@ -504,15 +506,18 @@ static int nmi_setup(void)
+
+ nmi_enabled = 0;
+ ctr_running = 0;
+- barrier();
++ /* make variables visible to the nmi handler: */
++ smp_mb();
+ err = register_die_notifier(&profile_exceptions_nb);
+ if (err)
+ goto fail;
+
+ get_online_cpus();
+ register_cpu_notifier(&oprofile_cpu_nb);
+- on_each_cpu(nmi_cpu_setup, NULL, 1);
+ nmi_enabled = 1;
++ /* make nmi_enabled visible to the nmi handler: */
++ smp_mb();
++ on_each_cpu(nmi_cpu_setup, NULL, 1);
+ put_online_cpus();
+
+ return 0;
+@@ -531,7 +536,8 @@ static void nmi_shutdown(void)
+ nmi_enabled = 0;
+ ctr_running = 0;
+ put_online_cpus();
+- barrier();
++ /* make variables visible to the nmi handler: */
++ smp_mb();
+ unregister_die_notifier(&profile_exceptions_nb);
+ msrs = &get_cpu_var(cpu_msrs);
+ model->shutdown(msrs);
+diff --git a/arch/x86/oprofile/op_model_amd.c b/arch/x86/oprofile/op_model_amd.c
+index c3b8e24..9fd8a56 100644
+--- a/arch/x86/oprofile/op_model_amd.c
++++ b/arch/x86/oprofile/op_model_amd.c
+@@ -316,16 +316,23 @@ static void op_amd_stop_ibs(void)
+ wrmsrl(MSR_AMD64_IBSOPCTL, 0);
+ }
+
+-static inline int eilvt_is_available(int offset)
++static inline int get_eilvt(int offset)
+ {
+- /* check if we may assign a vector */
+ return !setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_NMI, 1);
+ }
+
++static inline int put_eilvt(int offset)
++{
++ return !setup_APIC_eilvt(offset, 0, 0, 1);
++}
++
+ static inline int ibs_eilvt_valid(void)
+ {
+ int offset;
+ u64 val;
++ int valid = 0;
++
++ preempt_disable();
+
+ rdmsrl(MSR_AMD64_IBSCTL, val);
+ offset = val & IBSCTL_LVT_OFFSET_MASK;
+@@ -333,16 +340,20 @@ static inline int ibs_eilvt_valid(void)
+ if (!(val & IBSCTL_LVT_OFFSET_VALID)) {
+ pr_err(FW_BUG "cpu %d, invalid IBS interrupt offset %d (MSR%08X=0x%016llx)\n",
+ smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
+- return 0;
++ goto out;
+ }
+
+- if (!eilvt_is_available(offset)) {
++ if (!get_eilvt(offset)) {
+ pr_err(FW_BUG "cpu %d, IBS interrupt offset %d not available (MSR%08X=0x%016llx)\n",
+ smp_processor_id(), offset, MSR_AMD64_IBSCTL, val);
+- return 0;
++ goto out;
+ }
+
+- return 1;
++ valid = 1;
++out:
++ preempt_enable();
++
++ return valid;
+ }
+
+ static inline int get_ibs_offset(void)
+@@ -600,67 +611,69 @@ static int setup_ibs_ctl(int ibs_eilvt_off)
+
+ static int force_ibs_eilvt_setup(void)
+ {
+- int i;
++ int offset;
+ int ret;
+
+- /* find the next free available EILVT entry */
+- for (i = 1; i < 4; i++) {
+- if (!eilvt_is_available(i))
+- continue;
+- ret = setup_ibs_ctl(i);
+- if (ret)
+- return ret;
+- pr_err(FW_BUG "using offset %d for IBS interrupts\n", i);
+- return 0;
++ /*
++ * find the next free available EILVT entry, skip offset 0,
++ * pin search to this cpu
++ */
++ preempt_disable();
++ for (offset = 1; offset < APIC_EILVT_NR_MAX; offset++) {
++ if (get_eilvt(offset))
++ break;
+ }
++ preempt_enable();
+
+- printk(KERN_DEBUG "No EILVT entry available\n");
+-
+- return -EBUSY;
+-}
+-
+-static int __init_ibs_nmi(void)
+-{
+- int ret;
+-
+- if (ibs_eilvt_valid())
+- return 0;
++ if (offset == APIC_EILVT_NR_MAX) {
++ printk(KERN_DEBUG "No EILVT entry available\n");
++ return -EBUSY;
++ }
+
+- ret = force_ibs_eilvt_setup();
++ ret = setup_ibs_ctl(offset);
+ if (ret)
+- return ret;
++ goto out;
+
+- if (!ibs_eilvt_valid())
+- return -EFAULT;
++ if (!ibs_eilvt_valid()) {
++ ret = -EFAULT;
++ goto out;
++ }
+
++ pr_err(FW_BUG "using offset %d for IBS interrupts\n", offset);
+ pr_err(FW_BUG "workaround enabled for IBS LVT offset\n");
+
+ return 0;
++out:
++ preempt_disable();
++ put_eilvt(offset);
++ preempt_enable();
++ return ret;
+ }
+
+ /*
+ * check and reserve APIC extended interrupt LVT offset for IBS if
+ * available
+- *
+- * init_ibs() preforms implicitly cpu-local operations, so pin this
+- * thread to its current CPU
+ */
+
+ static void init_ibs(void)
+ {
+- preempt_disable();
+-
+ ibs_caps = get_ibs_caps();
++
+ if (!ibs_caps)
++ return;
++
++ if (ibs_eilvt_valid())
+ goto out;
+
+- if (__init_ibs_nmi() < 0)
+- ibs_caps = 0;
+- else
+- printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps);
++ if (!force_ibs_eilvt_setup())
++ goto out;
++
++ /* Failed to setup ibs */
++ ibs_caps = 0;
++ return;
+
+ out:
+- preempt_enable();
++ printk(KERN_INFO "oprofile: AMD IBS detected (0x%08x)\n", ibs_caps);
+ }
+
+ static int (*create_arch_files)(struct super_block *sb, struct dentry *root);
+diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
+index e37b407..632ba33 100644
+--- a/arch/x86/pci/xen.c
++++ b/arch/x86/pci/xen.c
+@@ -316,7 +316,7 @@ int __init pci_xen_hvm_init(void)
+ }
+
+ #ifdef CONFIG_XEN_DOM0
+-static int xen_register_pirq(u32 gsi, int triggering)
++static int xen_register_pirq(u32 gsi, int gsi_override, int triggering)
+ {
+ int rc, pirq, irq = -1;
+ struct physdev_map_pirq map_irq;
+@@ -333,16 +333,18 @@ static int xen_register_pirq(u32 gsi, int triggering)
+ shareable = 1;
+ name = "ioapic-level";
+ }
+-
+ pirq = xen_allocate_pirq_gsi(gsi);
+ if (pirq < 0)
+ goto out;
+
+- irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name);
++ if (gsi_override >= 0)
++ irq = xen_bind_pirq_gsi_to_irq(gsi_override, pirq, shareable, name);
++ else
++ irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name);
+ if (irq < 0)
+ goto out;
+
+- printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d\n", pirq, irq);
++ printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d (gsi=%d)\n", pirq, irq, gsi);
+
+ map_irq.domid = DOMID_SELF;
+ map_irq.type = MAP_PIRQ_TYPE_GSI;
+@@ -359,7 +361,7 @@ out:
+ return irq;
+ }
+
+-static int xen_register_gsi(u32 gsi, int triggering, int polarity)
++static int xen_register_gsi(u32 gsi, int gsi_override, int triggering, int polarity)
+ {
+ int rc, irq;
+ struct physdev_setup_gsi setup_gsi;
+@@ -370,7 +372,7 @@ static int xen_register_gsi(u32 gsi, int triggering, int polarity)
+ printk(KERN_DEBUG "xen: registering gsi %u triggering %d polarity %d\n",
+ gsi, triggering, polarity);
+
+- irq = xen_register_pirq(gsi, triggering);
++ irq = xen_register_pirq(gsi, gsi_override, triggering);
+
+ setup_gsi.gsi = gsi;
+ setup_gsi.triggering = (triggering == ACPI_EDGE_SENSITIVE ? 0 : 1);
+@@ -392,6 +394,8 @@ static __init void xen_setup_acpi_sci(void)
+ int rc;
+ int trigger, polarity;
+ int gsi = acpi_sci_override_gsi;
++ int irq = -1;
++ int gsi_override = -1;
+
+ if (!gsi)
+ return;
+@@ -408,7 +412,25 @@ static __init void xen_setup_acpi_sci(void)
+ printk(KERN_INFO "xen: sci override: global_irq=%d trigger=%d "
+ "polarity=%d\n", gsi, trigger, polarity);
+
+- gsi = xen_register_gsi(gsi, trigger, polarity);
++ /* Before we bind the GSI to a Linux IRQ, check whether
++ * we need to override it with bus_irq (IRQ) value. Usually for
++ * IRQs below IRQ_LEGACY_IRQ this holds IRQ == GSI, as so:
++ * ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 9 low level)
++ * but there are oddballs where the IRQ != GSI:
++ * ACPI: INT_SRC_OVR (bus 0 bus_irq 9 global_irq 20 low level)
++ * which ends up being: gsi_to_irq[9] == 20
++ * (which is what acpi_gsi_to_irq ends up calling when starting the
++ * the ACPI interpreter and keels over since IRQ 9 has not been
++ * setup as we had setup IRQ 20 for it).
++ */
++ /* Check whether the GSI != IRQ */
++ if (acpi_gsi_to_irq(gsi, &irq) == 0) {
++ if (irq >= 0 && irq != gsi)
++ /* Bugger, we MUST have that IRQ. */
++ gsi_override = irq;
++ }
++
++ gsi = xen_register_gsi(gsi, gsi_override, trigger, polarity);
+ printk(KERN_INFO "xen: acpi sci %d\n", gsi);
+
+ return;
+@@ -417,7 +439,7 @@ static __init void xen_setup_acpi_sci(void)
+ static int acpi_register_gsi_xen(struct device *dev, u32 gsi,
+ int trigger, int polarity)
+ {
+- return xen_register_gsi(gsi, trigger, polarity);
++ return xen_register_gsi(gsi, -1 /* no GSI override */, trigger, polarity);
+ }
+
+ static int __init pci_xen_initial_domain(void)
+@@ -456,7 +478,7 @@ void __init xen_setup_pirqs(void)
+ if (acpi_get_override_irq(irq, &trigger, &polarity) == -1)
+ continue;
+
+- xen_register_pirq(irq,
++ xen_register_pirq(irq, -1 /* no GSI override */,
+ trigger ? ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE);
+ }
+ }
+diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
+index 0684f3c..0d668d1 100644
+--- a/arch/x86/xen/mmu.c
++++ b/arch/x86/xen/mmu.c
+@@ -59,6 +59,7 @@
+ #include <asm/page.h>
+ #include <asm/init.h>
+ #include <asm/pat.h>
++#include <asm/smp.h>
+
+ #include <asm/xen/hypercall.h>
+ #include <asm/xen/hypervisor.h>
+@@ -1187,7 +1188,7 @@ static void drop_other_mm_ref(void *info)
+
+ active_mm = percpu_read(cpu_tlbstate.active_mm);
+
+- if (active_mm == mm)
++ if (active_mm == mm && percpu_read(cpu_tlbstate.state) != TLBSTATE_OK)
+ leave_mm(smp_processor_id());
+
+ /* If this cpu still has a stale cr3 reference, then make sure
+@@ -1353,7 +1354,11 @@ static void xen_flush_tlb_others(const struct cpumask *cpus,
+ {
+ struct {
+ struct mmuext_op op;
++#ifdef CONFIG_SMP
++ DECLARE_BITMAP(mask, num_processors);
++#else
+ DECLARE_BITMAP(mask, NR_CPUS);
++#endif
+ } *args;
+ struct multicall_space mcs;
+
+@@ -1721,6 +1726,11 @@ static __init void xen_map_identity_early(pmd_t *pmd, unsigned long max_pfn)
+ for (pteidx = 0; pteidx < PTRS_PER_PTE; pteidx++, pfn++) {
+ pte_t pte;
+
++#ifdef CONFIG_X86_32
++ if (pfn > max_pfn_mapped)
++ max_pfn_mapped = pfn;
++#endif
++
+ if (!pte_none(pte_page[pteidx]))
+ continue;
+
+@@ -1888,7 +1898,9 @@ __init pgd_t *xen_setup_kernel_pagetable(pgd_t *pgd,
+ initial_kernel_pmd =
+ extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
+
+- max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list));
++ max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) +
++ xen_start_info->nr_pt_frames * PAGE_SIZE +
++ 512*1024);
+
+ kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd);
+ memcpy(initial_kernel_pmd, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
+diff --git a/arch/x86/xen/multicalls.c b/arch/x86/xen/multicalls.c
+index 8bff7e7..1b2b73f 100644
+--- a/arch/x86/xen/multicalls.c
++++ b/arch/x86/xen/multicalls.c
+@@ -189,10 +189,10 @@ struct multicall_space __xen_mc_entry(size_t args)
+ unsigned argidx = roundup(b->argidx, sizeof(u64));
+
+ BUG_ON(preemptible());
+- BUG_ON(b->argidx > MC_ARGS);
++ BUG_ON(b->argidx >= MC_ARGS);
+
+ if (b->mcidx == MC_BATCH ||
+- (argidx + args) > MC_ARGS) {
++ (argidx + args) >= MC_ARGS) {
+ mc_stats_flush(b->mcidx == MC_BATCH ? FL_SLOTS : FL_ARGS);
+ xen_mc_flush();
+ argidx = roundup(b->argidx, sizeof(u64));
+@@ -206,7 +206,7 @@ struct multicall_space __xen_mc_entry(size_t args)
+ ret.args = &b->args[argidx];
+ b->argidx = argidx + args;
+
+- BUG_ON(b->argidx > MC_ARGS);
++ BUG_ON(b->argidx >= MC_ARGS);
+ return ret;
+ }
+
+@@ -216,7 +216,7 @@ struct multicall_space xen_mc_extend_args(unsigned long op, size_t size)
+ struct multicall_space ret = { NULL, NULL };
+
+ BUG_ON(preemptible());
+- BUG_ON(b->argidx > MC_ARGS);
++ BUG_ON(b->argidx >= MC_ARGS);
+
+ if (b->mcidx == 0)
+ return ret;
+@@ -224,14 +224,14 @@ struct multicall_space xen_mc_extend_args(unsigned long op, size_t size)
+ if (b->entries[b->mcidx - 1].op != op)
+ return ret;
+
+- if ((b->argidx + size) > MC_ARGS)
++ if ((b->argidx + size) >= MC_ARGS)
+ return ret;
+
+ ret.mc = &b->entries[b->mcidx - 1];
+ ret.args = &b->args[b->argidx];
+ b->argidx += size;
+
+- BUG_ON(b->argidx > MC_ARGS);
++ BUG_ON(b->argidx >= MC_ARGS);
+ return ret;
+ }
+
+diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
+index 141eb0d..c881ae4 100644
+--- a/arch/x86/xen/p2m.c
++++ b/arch/x86/xen/p2m.c
+@@ -522,11 +522,20 @@ static bool __init __early_alloc_p2m(unsigned long pfn)
+ /* Boundary cross-over for the edges: */
+ if (idx) {
+ unsigned long *p2m = extend_brk(PAGE_SIZE, PAGE_SIZE);
++ unsigned long *mid_mfn_p;
+
+ p2m_init(p2m);
+
+ p2m_top[topidx][mididx] = p2m;
+
++ /* For save/restore we need to MFN of the P2M saved */
++
++ mid_mfn_p = p2m_top_mfn_p[topidx];
++ WARN(mid_mfn_p[mididx] != virt_to_mfn(p2m_missing),
++ "P2M_TOP_P[%d][%d] != MFN of p2m_missing!\n",
++ topidx, mididx);
++ mid_mfn_p[mididx] = virt_to_mfn(p2m);
++
+ }
+ return idx != 0;
+ }
+@@ -549,12 +558,29 @@ unsigned long __init set_phys_range_identity(unsigned long pfn_s,
+ pfn += P2M_MID_PER_PAGE * P2M_PER_PAGE)
+ {
+ unsigned topidx = p2m_top_index(pfn);
+- if (p2m_top[topidx] == p2m_mid_missing) {
+- unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
++ unsigned long *mid_mfn_p;
++ unsigned long **mid;
++
++ mid = p2m_top[topidx];
++ mid_mfn_p = p2m_top_mfn_p[topidx];
++ if (mid == p2m_mid_missing) {
++ mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
+
+ p2m_mid_init(mid);
+
+ p2m_top[topidx] = mid;
++
++ BUG_ON(mid_mfn_p != p2m_mid_missing_mfn);
++ }
++ /* And the save/restore P2M tables.. */
++ if (mid_mfn_p == p2m_mid_missing_mfn) {
++ mid_mfn_p = extend_brk(PAGE_SIZE, PAGE_SIZE);
++ p2m_mid_mfn_init(mid_mfn_p);
++
++ p2m_top_mfn_p[topidx] = mid_mfn_p;
++ p2m_top_mfn[topidx] = virt_to_mfn(mid_mfn_p);
++ /* Note: we don't set mid_mfn_p[midix] here,
++ * look in __early_alloc_p2m */
+ }
+ }
+
+diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
+index 90bac0a..ca6297b 100644
+--- a/arch/x86/xen/setup.c
++++ b/arch/x86/xen/setup.c
+@@ -166,7 +166,7 @@ static unsigned long __init xen_set_identity(const struct e820entry *list,
+ if (last > end)
+ continue;
+
+- if (entry->type == E820_RAM) {
++ if ((entry->type == E820_RAM) || (entry->type == E820_UNUSABLE)) {
+ if (start > start_pci)
+ identity += set_phys_range_identity(
+ PFN_UP(start_pci), PFN_DOWN(start));
+@@ -227,7 +227,11 @@ char * __init xen_memory_setup(void)
+
+ memcpy(map_raw, map, sizeof(map));
+ e820.nr_map = 0;
++#ifdef CONFIG_X86_32
++ xen_extra_mem_start = mem_end;
++#else
+ xen_extra_mem_start = max((1ULL << 32), mem_end);
++#endif
+ for (i = 0; i < memmap.nr_entries; i++) {
+ unsigned long long end;
+
+diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
+index 3061244..ae49046 100644
+--- a/arch/x86/xen/smp.c
++++ b/arch/x86/xen/smp.c
+@@ -206,11 +206,18 @@ static void __init xen_smp_prepare_boot_cpu(void)
+ static void __init xen_smp_prepare_cpus(unsigned int max_cpus)
+ {
+ unsigned cpu;
++ unsigned int i;
+
+ xen_init_lock_cpu(0);
+
+ smp_store_cpu_info(0);
+ cpu_data(0).x86_max_cores = 1;
++
++ for_each_possible_cpu(i) {
++ zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL);
++ zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL);
++ zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL);
++ }
+ set_cpu_sibling_map(0);
+
+ if (xen_smp_intr_init(0))
+diff --git a/block/blk-core.c b/block/blk-core.c
+index 3fe00a1..5323076 100644
+--- a/block/blk-core.c
++++ b/block/blk-core.c
+@@ -345,6 +345,7 @@ void blk_put_queue(struct request_queue *q)
+ {
+ kobject_put(&q->kobj);
+ }
++EXPORT_SYMBOL(blk_put_queue);
+
+ /*
+ * Note: If a driver supplied the queue lock, it should not zap that lock
+@@ -566,6 +567,7 @@ int blk_get_queue(struct request_queue *q)
+
+ return 1;
+ }
++EXPORT_SYMBOL(blk_get_queue);
+
+ static inline void blk_free_request(struct request_queue *q, struct request *rq)
+ {
+diff --git a/block/blk-flush.c b/block/blk-flush.c
+index 6c9b5e1..bb21e4c 100644
+--- a/block/blk-flush.c
++++ b/block/blk-flush.c
+@@ -212,13 +212,19 @@ static void flush_end_io(struct request *flush_rq, int error)
+ }
+
+ /*
+- * Moving a request silently to empty queue_head may stall the
+- * queue. Kick the queue in those cases. This function is called
+- * from request completion path and calling directly into
+- * request_fn may confuse the driver. Always use kblockd.
++ * Kick the queue to avoid stall for two cases:
++ * 1. Moving a request silently to empty queue_head may stall the
++ * queue.
++ * 2. When flush request is running in non-queueable queue, the
++ * queue is hold. Restart the queue after flush request is finished
++ * to avoid stall.
++ * This function is called from request completion path and calling
++ * directly into request_fn may confuse the driver. Always use
++ * kblockd.
+ */
+- if (queued)
++ if (queued || q->flush_queue_delayed)
+ blk_run_queue_async(q);
++ q->flush_queue_delayed = 0;
+ }
+
+ /**
+diff --git a/block/blk-settings.c b/block/blk-settings.c
+index 1fa7692..fa1eb04 100644
+--- a/block/blk-settings.c
++++ b/block/blk-settings.c
+@@ -120,7 +120,7 @@ void blk_set_default_limits(struct queue_limits *lim)
+ lim->discard_granularity = 0;
+ lim->discard_alignment = 0;
+ lim->discard_misaligned = 0;
+- lim->discard_zeroes_data = -1;
++ lim->discard_zeroes_data = 1;
+ lim->logical_block_size = lim->physical_block_size = lim->io_min = 512;
+ lim->bounce_pfn = (unsigned long)(BLK_BOUNCE_ANY >> PAGE_SHIFT);
+ lim->alignment_offset = 0;
+@@ -166,6 +166,7 @@ void blk_queue_make_request(struct request_queue *q, make_request_fn *mfn)
+
+ blk_set_default_limits(&q->limits);
+ blk_queue_max_hw_sectors(q, BLK_SAFE_MAX_SECTORS);
++ q->limits.discard_zeroes_data = 0;
+
+ /*
+ * by default assume old behaviour and bounce for any highmem page
+@@ -790,6 +791,12 @@ void blk_queue_flush(struct request_queue *q, unsigned int flush)
+ }
+ EXPORT_SYMBOL_GPL(blk_queue_flush);
+
++void blk_queue_flush_queueable(struct request_queue *q, bool queueable)
++{
++ q->flush_not_queueable = !queueable;
++}
++EXPORT_SYMBOL_GPL(blk_queue_flush_queueable);
++
+ static int __init blk_settings_init(void)
+ {
+ blk_max_low_pfn = max_low_pfn - 1;
+diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
+index bd23631..d935bd8 100644
+--- a/block/blk-sysfs.c
++++ b/block/blk-sysfs.c
+@@ -152,7 +152,8 @@ static ssize_t queue_discard_granularity_show(struct request_queue *q, char *pag
+
+ static ssize_t queue_discard_max_show(struct request_queue *q, char *page)
+ {
+- return queue_var_show(q->limits.max_discard_sectors << 9, page);
++ return sprintf(page, "%llu\n",
++ (unsigned long long)q->limits.max_discard_sectors << 9);
+ }
+
+ static ssize_t queue_discard_zeroes_data_show(struct request_queue *q, char *page)
+diff --git a/block/blk.h b/block/blk.h
+index 6126346..1566e8d 100644
+--- a/block/blk.h
++++ b/block/blk.h
+@@ -61,8 +61,28 @@ static inline struct request *__elv_next_request(struct request_queue *q)
+ rq = list_entry_rq(q->queue_head.next);
+ return rq;
+ }
+-
+- if (!q->elevator->ops->elevator_dispatch_fn(q, 0))
++ /*
++ * Flush request is running and flush request isn't queueable
++ * in the drive, we can hold the queue till flush request is
++ * finished. Even we don't do this, driver can't dispatch next
++ * requests and will requeue them. And this can improve
++ * throughput too. For example, we have request flush1, write1,
++ * flush 2. flush1 is dispatched, then queue is hold, write1
++ * isn't inserted to queue. After flush1 is finished, flush2
++ * will be dispatched. Since disk cache is already clean,
++ * flush2 will be finished very soon, so looks like flush2 is
++ * folded to flush1.
++ * Since the queue is hold, a flag is set to indicate the queue
++ * should be restarted later. Please see flush_end_io() for
++ * details.
++ */
++ if (q->flush_pending_idx != q->flush_running_idx &&
++ !queue_flush_queueable(q)) {
++ q->flush_queue_delayed = 1;
++ return NULL;
++ }
++ if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags) ||
++ !q->elevator->ops->elevator_dispatch_fn(q, 0))
+ return NULL;
+ }
+ }
+diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
+index ab7a9e6..bd2fa5f 100644
+--- a/block/cfq-iosched.c
++++ b/block/cfq-iosched.c
+@@ -2704,8 +2704,14 @@ static void __cfq_exit_single_io_context(struct cfq_data *cfqd,
+ smp_wmb();
+ cic->key = cfqd_dead_key(cfqd);
+
+- if (ioc->ioc_data == cic)
++ rcu_read_lock();
++ if (rcu_dereference(ioc->ioc_data) == cic) {
++ rcu_read_unlock();
++ spin_lock(&ioc->lock);
+ rcu_assign_pointer(ioc->ioc_data, NULL);
++ spin_unlock(&ioc->lock);
++ } else
++ rcu_read_unlock();
+
+ if (cic->cfqq[BLK_RW_ASYNC]) {
+ cfq_exit_cfqq(cfqd, cic->cfqq[BLK_RW_ASYNC]);
+@@ -3012,7 +3018,8 @@ cfq_drop_dead_cic(struct cfq_data *cfqd, struct io_context *ioc,
+
+ spin_lock_irqsave(&ioc->lock, flags);
+
+- BUG_ON(ioc->ioc_data == cic);
++ BUG_ON(rcu_dereference_check(ioc->ioc_data,
++ lockdep_is_held(&ioc->lock)) == cic);
+
+ radix_tree_delete(&ioc->radix_root, cfqd->cic_index);
+ hlist_del_rcu(&cic->cic_list);
+diff --git a/block/genhd.c b/block/genhd.c
+index 2dd9887..95822ae 100644
+--- a/block/genhd.c
++++ b/block/genhd.c
+@@ -1728,7 +1728,7 @@ static void disk_add_events(struct gendisk *disk)
+ {
+ struct disk_events *ev;
+
+- if (!disk->fops->check_events || !(disk->events | disk->async_events))
++ if (!disk->fops->check_events)
+ return;
+
+ ev = kzalloc(sizeof(*ev), GFP_KERNEL);
+diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
+index dad9fd6..17b74f4 100644
+--- a/drivers/ata/libata-eh.c
++++ b/drivers/ata/libata-eh.c
+@@ -2802,10 +2802,11 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ }
+
+ /*
+- * Some controllers can't be frozen very well and may set
+- * spuruious error conditions during reset. Clear accumulated
+- * error information. As reset is the final recovery action,
+- * nothing is lost by doing this.
++ * Some controllers can't be frozen very well and may set spurious
++ * error conditions during reset. Clear accumulated error
++ * information and re-thaw the port if frozen. As reset is the
++ * final recovery action and we cross check link onlineness against
++ * device classification later, no hotplug event is lost by this.
+ */
+ spin_lock_irqsave(link->ap->lock, flags);
+ memset(&link->eh_info, 0, sizeof(link->eh_info));
+@@ -2814,6 +2815,9 @@ int ata_eh_reset(struct ata_link *link, int classify,
+ ap->pflags &= ~ATA_PFLAG_EH_PENDING;
+ spin_unlock_irqrestore(link->ap->lock, flags);
+
++ if (ap->pflags & ATA_PFLAG_FROZEN)
++ ata_eh_thaw_port(ap);
++
+ /*
+ * Make sure onlineness and classification result correspond.
+ * Hotplug could have happened during reset and some
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index e2f57e9e..d51f979 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -1089,21 +1089,21 @@ static int atapi_drain_needed(struct request *rq)
+ static int ata_scsi_dev_config(struct scsi_device *sdev,
+ struct ata_device *dev)
+ {
++ struct request_queue *q = sdev->request_queue;
++
+ if (!ata_id_has_unload(dev->id))
+ dev->flags |= ATA_DFLAG_NO_UNLOAD;
+
+ /* configure max sectors */
+- blk_queue_max_hw_sectors(sdev->request_queue, dev->max_sectors);
++ blk_queue_max_hw_sectors(q, dev->max_sectors);
+
+ if (dev->class == ATA_DEV_ATAPI) {
+- struct request_queue *q = sdev->request_queue;
+ void *buf;
+
+ sdev->sector_size = ATA_SECT_SIZE;
+
+ /* set DMA padding */
+- blk_queue_update_dma_pad(sdev->request_queue,
+- ATA_DMA_PAD_SZ - 1);
++ blk_queue_update_dma_pad(q, ATA_DMA_PAD_SZ - 1);
+
+ /* configure draining */
+ buf = kmalloc(ATAPI_MAX_DRAIN, q->bounce_gfp | GFP_KERNEL);
+@@ -1131,8 +1131,7 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
+ "sector_size=%u > PAGE_SIZE, PIO may malfunction\n",
+ sdev->sector_size);
+
+- blk_queue_update_dma_alignment(sdev->request_queue,
+- sdev->sector_size - 1);
++ blk_queue_update_dma_alignment(q, sdev->sector_size - 1);
+
+ if (dev->flags & ATA_DFLAG_AN)
+ set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events);
+@@ -1145,6 +1144,8 @@ static int ata_scsi_dev_config(struct scsi_device *sdev,
+ scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, depth);
+ }
+
++ blk_queue_flush_queueable(q, false);
++
+ dev->sdev = sdev;
+ return 0;
+ }
+@@ -2138,7 +2139,7 @@ static unsigned int ata_scsiop_inq_b0(struct ata_scsi_args *args, u8 *rbuf)
+ * with the unmap bit set.
+ */
+ if (ata_id_has_trim(args->id)) {
+- put_unaligned_be32(65535 * 512 / 8, &rbuf[20]);
++ put_unaligned_be64(65535 * 512 / 8, &rbuf[36]);
+ put_unaligned_be32(1, &rbuf[28]);
+ }
+
+diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c
+index 905ff76..635a759 100644
+--- a/drivers/ata/pata_cmd64x.c
++++ b/drivers/ata/pata_cmd64x.c
+@@ -41,6 +41,9 @@
+ enum {
+ CFR = 0x50,
+ CFR_INTR_CH0 = 0x04,
++ CNTRL = 0x51,
++ CNTRL_CH0 = 0x04,
++ CNTRL_CH1 = 0x08,
+ CMDTIM = 0x52,
+ ARTTIM0 = 0x53,
+ DRWTIM0 = 0x54,
+@@ -328,9 +331,19 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ .port_ops = &cmd648_port_ops
+ }
+ };
+- const struct ata_port_info *ppi[] = { &cmd_info[id->driver_data], NULL };
+- u8 mrdmode;
++ const struct ata_port_info *ppi[] = {
++ &cmd_info[id->driver_data],
++ &cmd_info[id->driver_data],
++ NULL
++ };
++ u8 mrdmode, reg;
+ int rc;
++ struct pci_dev *bridge = pdev->bus->self;
++ /* mobility split bridges don't report enabled ports correctly */
++ int port_ok = !(bridge && bridge->vendor ==
++ PCI_VENDOR_ID_MOBILITY_ELECTRONICS);
++ /* all (with exceptions below) apart from 643 have CNTRL_CH0 bit */
++ int cntrl_ch0_ok = (id->driver_data != 0);
+
+ rc = pcim_enable_device(pdev);
+ if (rc)
+@@ -341,11 +354,18 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+
+ if (pdev->device == PCI_DEVICE_ID_CMD_646) {
+ /* Does UDMA work ? */
+- if (pdev->revision > 4)
++ if (pdev->revision > 4) {
+ ppi[0] = &cmd_info[2];
++ ppi[1] = &cmd_info[2];
++ }
+ /* Early rev with other problems ? */
+- else if (pdev->revision == 1)
++ else if (pdev->revision == 1) {
+ ppi[0] = &cmd_info[3];
++ ppi[1] = &cmd_info[3];
++ }
++ /* revs 1,2 have no CNTRL_CH0 */
++ if (pdev->revision < 3)
++ cntrl_ch0_ok = 0;
+ }
+
+ pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 64);
+@@ -354,6 +374,20 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
+ mrdmode |= 0x02; /* Memory read line enable */
+ pci_write_config_byte(pdev, MRDMODE, mrdmode);
+
++ /* check for enabled ports */
++ pci_read_config_byte(pdev, CNTRL, &reg);
++ if (!port_ok)
++ dev_printk(KERN_NOTICE, &pdev->dev, "Mobility Bridge detected, ignoring CNTRL port enable/disable\n");
++ if (port_ok && cntrl_ch0_ok && !(reg & CNTRL_CH0)) {
++ dev_printk(KERN_NOTICE, &pdev->dev, "Primary port is disabled\n");
++ ppi[0] = &ata_dummy_port_info;
++
++ }
++ if (port_ok && !(reg & CNTRL_CH1)) {
++ dev_printk(KERN_NOTICE, &pdev->dev, "Secondary port is disabled\n");
++ ppi[1] = &ata_dummy_port_info;
++ }
++
+ /* Force PIO 0 here.. */
+
+ /* PPC specific fixup copied from old driver */
+diff --git a/drivers/base/platform.c b/drivers/base/platform.c
+index 9e0e4fc..5d5bd1a 100644
+--- a/drivers/base/platform.c
++++ b/drivers/base/platform.c
+@@ -367,7 +367,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister);
+ *
+ * Returns &struct platform_device pointer on success, or ERR_PTR() on error.
+ */
+-struct platform_device *__init_or_module platform_device_register_resndata(
++struct platform_device *platform_device_register_resndata(
+ struct device *parent,
+ const char *name, int id,
+ const struct resource *res, unsigned int num,
+diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
+index abe3ab7..631b5d3 100644
+--- a/drivers/base/power/main.c
++++ b/drivers/base/power/main.c
+@@ -57,7 +57,8 @@ static int async_error;
+ */
+ void device_pm_init(struct device *dev)
+ {
+- dev->power.in_suspend = false;
++ dev->power.is_prepared = false;
++ dev->power.is_suspended = false;
+ init_completion(&dev->power.completion);
+ complete_all(&dev->power.completion);
+ dev->power.wakeup = NULL;
+@@ -91,7 +92,7 @@ void device_pm_add(struct device *dev)
+ pr_debug("PM: Adding info for %s:%s\n",
+ dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
+ mutex_lock(&dpm_list_mtx);
+- if (dev->parent && dev->parent->power.in_suspend)
++ if (dev->parent && dev->parent->power.is_prepared)
+ dev_warn(dev, "parent %s should not be sleeping\n",
+ dev_name(dev->parent));
+ list_add_tail(&dev->power.entry, &dpm_list);
+@@ -513,7 +514,14 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
+ dpm_wait(dev->parent, async);
+ device_lock(dev);
+
+- dev->power.in_suspend = false;
++ /*
++ * This is a fib. But we'll allow new children to be added below
++ * a resumed device, even if the device hasn't been completed yet.
++ */
++ dev->power.is_prepared = false;
++
++ if (!dev->power.is_suspended)
++ goto Unlock;
+
+ if (dev->pwr_domain) {
+ pm_dev_dbg(dev, state, "power domain ");
+@@ -549,6 +557,9 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
+ }
+
+ End:
++ dev->power.is_suspended = false;
++
++ Unlock:
+ device_unlock(dev);
+ complete_all(&dev->power.completion);
+
+@@ -668,7 +679,7 @@ static void dpm_complete(pm_message_t state)
+ struct device *dev = to_device(dpm_prepared_list.prev);
+
+ get_device(dev);
+- dev->power.in_suspend = false;
++ dev->power.is_prepared = false;
+ list_move(&dev->power.entry, &list);
+ mutex_unlock(&dpm_list_mtx);
+
+@@ -834,11 +845,11 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
+ device_lock(dev);
+
+ if (async_error)
+- goto End;
++ goto Unlock;
+
+ if (pm_wakeup_pending()) {
+ async_error = -EBUSY;
+- goto End;
++ goto Unlock;
+ }
+
+ if (dev->type && dev->type->pm) {
+@@ -876,6 +887,9 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
+ }
+
+ End:
++ dev->power.is_suspended = !error;
++
++ Unlock:
+ device_unlock(dev);
+ complete_all(&dev->power.completion);
+
+@@ -1037,7 +1051,7 @@ static int dpm_prepare(pm_message_t state)
+ put_device(dev);
+ break;
+ }
+- dev->power.in_suspend = true;
++ dev->power.is_prepared = true;
+ if (!list_empty(&dev->power.entry))
+ list_move_tail(&dev->power.entry, &dpm_prepared_list);
+ put_device(dev);
+diff --git a/drivers/block/brd.c b/drivers/block/brd.c
+index b7f51e4..c94bc48 100644
+--- a/drivers/block/brd.c
++++ b/drivers/block/brd.c
+@@ -552,7 +552,7 @@ static struct kobject *brd_probe(dev_t dev, int *part, void *data)
+ struct kobject *kobj;
+
+ mutex_lock(&brd_devices_mutex);
+- brd = brd_init_one(dev & MINORMASK);
++ brd = brd_init_one(MINOR(dev) >> part_shift);
+ kobj = brd ? get_disk(brd->brd_disk) : ERR_PTR(-ENOMEM);
+ mutex_unlock(&brd_devices_mutex);
+
+@@ -585,15 +585,18 @@ static int __init brd_init(void)
+ if (max_part > 0)
+ part_shift = fls(max_part);
+
++ if ((1UL << part_shift) > DISK_MAX_PARTS)
++ return -EINVAL;
++
+ if (rd_nr > 1UL << (MINORBITS - part_shift))
+ return -EINVAL;
+
+ if (rd_nr) {
+ nr = rd_nr;
+- range = rd_nr;
++ range = rd_nr << part_shift;
+ } else {
+ nr = CONFIG_BLK_DEV_RAM_COUNT;
+- range = 1UL << (MINORBITS - part_shift);
++ range = 1UL << MINORBITS;
+ }
+
+ if (register_blkdev(RAMDISK_MAJOR, "ramdisk"))
+@@ -632,7 +635,7 @@ static void __exit brd_exit(void)
+ unsigned long range;
+ struct brd_device *brd, *next;
+
+- range = rd_nr ? rd_nr : 1UL << (MINORBITS - part_shift);
++ range = rd_nr ? rd_nr << part_shift : 1UL << MINORBITS;
+
+ list_for_each_entry_safe(brd, next, &brd_devices, brd_list)
+ brd_del_one(brd);
+diff --git a/drivers/block/loop.c b/drivers/block/loop.c
+index a076a14..c59a672 100644
+--- a/drivers/block/loop.c
++++ b/drivers/block/loop.c
+@@ -1658,7 +1658,7 @@ static struct kobject *loop_probe(dev_t dev, int *part, void *data)
+ struct kobject *kobj;
+
+ mutex_lock(&loop_devices_mutex);
+- lo = loop_init_one(dev & MINORMASK);
++ lo = loop_init_one(MINOR(dev) >> part_shift);
+ kobj = lo ? get_disk(lo->lo_disk) : ERR_PTR(-ENOMEM);
+ mutex_unlock(&loop_devices_mutex);
+
+@@ -1691,15 +1691,18 @@ static int __init loop_init(void)
+ if (max_part > 0)
+ part_shift = fls(max_part);
+
++ if ((1UL << part_shift) > DISK_MAX_PARTS)
++ return -EINVAL;
++
+ if (max_loop > 1UL << (MINORBITS - part_shift))
+ return -EINVAL;
+
+ if (max_loop) {
+ nr = max_loop;
+- range = max_loop;
++ range = max_loop << part_shift;
+ } else {
+ nr = 8;
+- range = 1UL << (MINORBITS - part_shift);
++ range = 1UL << MINORBITS;
+ }
+
+ if (register_blkdev(LOOP_MAJOR, "loop"))
+@@ -1738,7 +1741,7 @@ static void __exit loop_exit(void)
+ unsigned long range;
+ struct loop_device *lo, *next;
+
+- range = max_loop ? max_loop : 1UL << (MINORBITS - part_shift);
++ range = max_loop ? max_loop << part_shift : 1UL << MINORBITS;
+
+ list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
+ loop_del_one(lo);
+diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
+index e6fc716..a576406 100644
+--- a/drivers/block/nbd.c
++++ b/drivers/block/nbd.c
+@@ -756,6 +756,12 @@ static int __init nbd_init(void)
+ if (max_part > 0)
+ part_shift = fls(max_part);
+
++ if ((1UL << part_shift) > DISK_MAX_PARTS)
++ return -EINVAL;
++
++ if (nbds_max > 1UL << (MINORBITS - part_shift))
++ return -EINVAL;
++
+ for (i = 0; i < nbds_max; i++) {
+ struct gendisk *disk = alloc_disk(1 << part_shift);
+ if (!disk)
+diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c
+index 8690e31..46b8136 100644
+--- a/drivers/block/paride/pcd.c
++++ b/drivers/block/paride/pcd.c
+@@ -320,6 +320,7 @@ static void pcd_init_units(void)
+ disk->first_minor = unit;
+ strcpy(disk->disk_name, cd->name); /* umm... */
+ disk->fops = &pcd_bdops;
++ disk->flags = GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
+ }
+ }
+
+diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
+index e427fbe..7878da8 100644
+--- a/drivers/cdrom/viocd.c
++++ b/drivers/cdrom/viocd.c
+@@ -625,7 +625,8 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
+ blk_queue_max_hw_sectors(q, 4096 / 512);
+ gendisk->queue = q;
+ gendisk->fops = &viocd_fops;
+- gendisk->flags = GENHD_FL_CD|GENHD_FL_REMOVABLE;
++ gendisk->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE |
++ GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
+ set_capacity(gendisk, 0);
+ gendisk->private_data = d;
+ d->viocd_disk = gendisk;
+diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
+index d72433f..ee01716 100644
+--- a/drivers/char/i8k.c
++++ b/drivers/char/i8k.c
+@@ -139,8 +139,8 @@ static int i8k_smm(struct smm_regs *regs)
+ "movl %%edi,20(%%rax)\n\t"
+ "popq %%rdx\n\t"
+ "movl %%edx,0(%%rax)\n\t"
+- "lahf\n\t"
+- "shrl $8,%%eax\n\t"
++ "pushfq\n\t"
++ "popq %%rax\n\t"
+ "andl $1,%%eax\n"
+ :"=a"(rc)
+ : "a"(regs)
+diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
+index 219d88a..dde6a0f 100644
+--- a/drivers/connector/connector.c
++++ b/drivers/connector/connector.c
+@@ -139,6 +139,7 @@ static int cn_call_callback(struct sk_buff *skb)
+ spin_unlock_bh(&dev->cbdev->queue_lock);
+
+ if (cbq != NULL) {
++ err = 0;
+ cbq->callback(msg, nsp);
+ kfree_skb(skb);
+ cn_queue_release_callback(cbq);
+diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
+index 2dafc5c..7c10f96 100644
+--- a/drivers/cpufreq/cpufreq.c
++++ b/drivers/cpufreq/cpufreq.c
+@@ -1208,12 +1208,28 @@ static int __cpufreq_remove_dev(struct sys_device *sys_dev)
+ cpufreq_driver->exit(data);
+ unlock_policy_rwsem_write(cpu);
+
++ cpufreq_debug_enable_ratelimit();
++
++#ifdef CONFIG_HOTPLUG_CPU
++ /* when the CPU which is the parent of the kobj is hotplugged
++ * offline, check for siblings, and create cpufreq sysfs interface
++ * and symlinks
++ */
++ if (unlikely(cpumask_weight(data->cpus) > 1)) {
++ /* first sibling now owns the new sysfs dir */
++ cpumask_clear_cpu(cpu, data->cpus);
++ cpufreq_add_dev(get_cpu_sysdev(cpumask_first(data->cpus)));
++
++ /* finally remove our own symlink */
++ lock_policy_rwsem_write(cpu);
++ __cpufreq_remove_dev(sys_dev);
++ }
++#endif
++
+ free_cpumask_var(data->related_cpus);
+ free_cpumask_var(data->cpus);
+ kfree(data);
+- per_cpu(cpufreq_cpu_data, cpu) = NULL;
+
+- cpufreq_debug_enable_ratelimit();
+ return 0;
+ }
+
+diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
+index 00d73fc..7c7a1e4 100644
+--- a/drivers/cpufreq/cpufreq_stats.c
++++ b/drivers/cpufreq/cpufreq_stats.c
+@@ -165,17 +165,27 @@ static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq)
+ return -1;
+ }
+
++/* should be called late in the CPU removal sequence so that the stats
++ * memory is still available in case someone tries to use it.
++ */
+ static void cpufreq_stats_free_table(unsigned int cpu)
+ {
+ struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, cpu);
+- struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
+- if (policy && policy->cpu == cpu)
+- sysfs_remove_group(&policy->kobj, &stats_attr_group);
+ if (stat) {
+ kfree(stat->time_in_state);
+ kfree(stat);
+ }
+ per_cpu(cpufreq_stats_table, cpu) = NULL;
++}
++
++/* must be called early in the CPU removal sequence (before
++ * cpufreq_remove_dev) so that policy is still valid.
++ */
++static void cpufreq_stats_free_sysfs(unsigned int cpu)
++{
++ struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
++ if (policy && policy->cpu == cpu)
++ sysfs_remove_group(&policy->kobj, &stats_attr_group);
+ if (policy)
+ cpufreq_cpu_put(policy);
+ }
+@@ -316,6 +326,9 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
+ case CPU_ONLINE_FROZEN:
+ cpufreq_update_policy(cpu);
+ break;
++ case CPU_DOWN_PREPARE:
++ cpufreq_stats_free_sysfs(cpu);
++ break;
+ case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
+ cpufreq_stats_free_table(cpu);
+@@ -324,9 +337,11 @@ static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb,
+ return NOTIFY_OK;
+ }
+
++/* priority=1 so this will get called before cpufreq_remove_dev */
+ static struct notifier_block cpufreq_stat_cpu_notifier __refdata =
+ {
+ .notifier_call = cpufreq_stat_cpu_callback,
++ .priority = 1,
+ };
+
+ static struct notifier_block notifier_policy_block = {
+@@ -373,6 +388,7 @@ static void __exit cpufreq_stats_exit(void)
+ unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier);
+ for_each_online_cpu(cpu) {
+ cpufreq_stats_free_table(cpu);
++ cpufreq_stats_free_sysfs(cpu);
+ }
+ }
+
+diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
+index f508690..c47f3d0 100644
+--- a/drivers/cpuidle/governors/menu.c
++++ b/drivers/cpuidle/governors/menu.c
+@@ -237,6 +237,7 @@ static int menu_select(struct cpuidle_device *dev)
+ unsigned int power_usage = -1;
+ int i;
+ int multiplier;
++ struct timespec t;
+
+ if (data->needs_update) {
+ menu_update(dev);
+@@ -251,8 +252,9 @@ static int menu_select(struct cpuidle_device *dev)
+ return 0;
+
+ /* determine the expected residency time, round up */
++ t = ktime_to_timespec(tick_nohz_get_sleep_length());
+ data->expected_us =
+- DIV_ROUND_UP((u32)ktime_to_ns(tick_nohz_get_sleep_length()), 1000);
++ t.tv_sec * USEC_PER_SEC + t.tv_nsec / NSEC_PER_USEC;
+
+
+ data->bucket = which_bucket(data->expected_us);
+diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c
+index 23d1468..578d139 100644
+--- a/drivers/firewire/ohci.c
++++ b/drivers/firewire/ohci.c
+@@ -264,6 +264,7 @@ static char ohci_driver_name[] = KBUILD_MODNAME;
+ #define PCI_DEVICE_ID_AGERE_FW643 0x5901
+ #define PCI_DEVICE_ID_JMICRON_JMB38X_FW 0x2380
+ #define PCI_DEVICE_ID_TI_TSB12LV22 0x8009
++#define PCI_VENDOR_ID_PINNACLE_SYSTEMS 0x11bd
+
+ #define QUIRK_CYCLE_TIMER 1
+ #define QUIRK_RESET_PACKET 2
+@@ -3170,6 +3171,11 @@ static int __devinit pci_probe(struct pci_dev *dev,
+ int i, err;
+ size_t size;
+
++ if (dev->vendor == PCI_VENDOR_ID_PINNACLE_SYSTEMS) {
++ dev_err(&dev->dev, "Pinnacle MovieBoard is not yet supported\n");
++ return -ENOSYS;
++ }
++
+ ohci = kzalloc(sizeof(*ohci), GFP_KERNEL);
+ if (ohci == NULL) {
+ err = -ENOMEM;
+diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c
+index e1aee4f..b6a19cb 100644
+--- a/drivers/gpu/drm/drm_pci.c
++++ b/drivers/gpu/drm/drm_pci.c
+@@ -251,7 +251,7 @@ err:
+ }
+
+
+-int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
++static int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
+ {
+ if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
+ (p->busnum & 0xff) != dev->pdev->bus->number ||
+@@ -292,6 +292,7 @@ static struct drm_bus drm_pci_bus = {
+ .get_name = drm_pci_get_name,
+ .set_busid = drm_pci_set_busid,
+ .set_unique = drm_pci_set_unique,
++ .irq_by_busid = drm_pci_irq_by_busid,
+ .agp_init = drm_pci_agp_init,
+ };
+
+diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
+index 188b497..58c7f27 100644
+--- a/drivers/gpu/drm/i915/i915_irq.c
++++ b/drivers/gpu/drm/i915/i915_irq.c
+@@ -1567,6 +1567,17 @@ static void ironlake_irq_preinstall(struct drm_device *dev)
+ drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+
+ I915_WRITE(HWSTAM, 0xeffe);
++ if (IS_GEN6(dev)) {
++ /* Workaround stalls observed on Sandy Bridge GPUs by
++ * making the blitter command streamer generate a
++ * write to the Hardware Status Page for
++ * MI_USER_INTERRUPT. This appears to serialize the
++ * previous seqno write out before the interrupt
++ * happens.
++ */
++ I915_WRITE(GEN6_BLITTER_HWSTAM, ~GEN6_BLITTER_USER_INTERRUPT);
++ I915_WRITE(GEN6_BSD_HWSTAM, ~GEN6_BSD_USER_INTERRUPT);
++ }
+
+ /* XXX hotplug from PCH */
+
+diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
+index f39ac3a..5a96fd1 100644
+--- a/drivers/gpu/drm/i915/i915_reg.h
++++ b/drivers/gpu/drm/i915/i915_reg.h
+@@ -528,6 +528,7 @@
+ #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE 0
+ #define GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR (1 << 3)
+
++#define GEN6_BSD_HWSTAM 0x12098
+ #define GEN6_BSD_IMR 0x120a8
+ #define GEN6_BSD_USER_INTERRUPT (1 << 12)
+
+diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c
+index d3b903b..d98cee6 100644
+--- a/drivers/gpu/drm/i915/intel_i2c.c
++++ b/drivers/gpu/drm/i915/intel_i2c.c
+@@ -401,8 +401,7 @@ int intel_setup_gmbus(struct drm_device *dev)
+ bus->reg0 = i | GMBUS_RATE_100KHZ;
+
+ /* XXX force bit banging until GMBUS is fully debugged */
+- if (IS_GEN2(dev))
+- bus->force_bit = intel_gpio_create(dev_priv, i);
++ bus->force_bit = intel_gpio_create(dev_priv, i);
+ }
+
+ intel_i2c_reset(dev_priv->dev);
+diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
+index 67cb076..b28f7bd 100644
+--- a/drivers/gpu/drm/i915/intel_lvds.c
++++ b/drivers/gpu/drm/i915/intel_lvds.c
+@@ -727,6 +727,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
+ DMI_MATCH(DMI_PRODUCT_NAME, "U800"),
+ },
+ },
++ {
++ .callback = intel_no_lvds_dmi_callback,
++ .ident = "Asus EeeBox PC EB1007",
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
++ DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"),
++ },
++ },
+
+ { } /* terminating entry */
+ };
+diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
+index e9e6f71..c4504a2 100644
+--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
++++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
+@@ -666,12 +666,37 @@ gen6_ring_put_irq(struct intel_ring_buffer *ring, u32 gflag, u32 rflag)
+ static bool
+ bsd_ring_get_irq(struct intel_ring_buffer *ring)
+ {
+- return ring_get_irq(ring, GT_BSD_USER_INTERRUPT);
++ struct drm_device *dev = ring->dev;
++ drm_i915_private_t *dev_priv = dev->dev_private;
++
++ if (!dev->irq_enabled)
++ return false;
++
++ spin_lock(&ring->irq_lock);
++ if (ring->irq_refcount++ == 0) {
++ if (IS_G4X(dev))
++ i915_enable_irq(dev_priv, I915_BSD_USER_INTERRUPT);
++ else
++ ironlake_enable_irq(dev_priv, GT_BSD_USER_INTERRUPT);
++ }
++ spin_unlock(&ring->irq_lock);
++
++ return true;
+ }
+ static void
+ bsd_ring_put_irq(struct intel_ring_buffer *ring)
+ {
+- ring_put_irq(ring, GT_BSD_USER_INTERRUPT);
++ struct drm_device *dev = ring->dev;
++ drm_i915_private_t *dev_priv = dev->dev_private;
++
++ spin_lock(&ring->irq_lock);
++ if (--ring->irq_refcount == 0) {
++ if (IS_G4X(dev))
++ i915_disable_irq(dev_priv, I915_BSD_USER_INTERRUPT);
++ else
++ ironlake_disable_irq(dev_priv, GT_BSD_USER_INTERRUPT);
++ }
++ spin_unlock(&ring->irq_lock);
+ }
+
+ static int
+diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c
+index 529a3a7..02705c7 100644
+--- a/drivers/gpu/drm/radeon/atombios_crtc.c
++++ b/drivers/gpu/drm/radeon/atombios_crtc.c
+@@ -1011,7 +1011,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
+ uint64_t fb_location;
+ uint32_t fb_format, fb_pitch_pixels, tiling_flags;
+ u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE);
+- u32 tmp;
++ u32 tmp, viewport_w, viewport_h;
+ int r;
+
+ /* no fb bound */
+@@ -1137,8 +1137,10 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc,
+ y &= ~1;
+ WREG32(EVERGREEN_VIEWPORT_START + radeon_crtc->crtc_offset,
+ (x << 16) | y);
++ viewport_w = crtc->mode.hdisplay;
++ viewport_h = (crtc->mode.vdisplay + 1) & ~1;
+ WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
+- (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
++ (viewport_w << 16) | viewport_h);
+
+ /* pageflip setup */
+ /* make sure flip is at vb rather than hb */
+@@ -1179,7 +1181,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
+ uint64_t fb_location;
+ uint32_t fb_format, fb_pitch_pixels, tiling_flags;
+ u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE;
+- u32 tmp;
++ u32 tmp, viewport_w, viewport_h;
+ int r;
+
+ /* no fb bound */
+@@ -1304,8 +1306,10 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc,
+ y &= ~1;
+ WREG32(AVIVO_D1MODE_VIEWPORT_START + radeon_crtc->crtc_offset,
+ (x << 16) | y);
++ viewport_w = crtc->mode.hdisplay;
++ viewport_h = (crtc->mode.vdisplay + 1) & ~1;
+ WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
+- (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
++ (viewport_w << 16) | viewport_h);
+
+ /* pageflip setup */
+ /* make sure flip is at vb rather than hb */
+diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
+index 9073e3b..10e4e34 100644
+--- a/drivers/gpu/drm/radeon/evergreen.c
++++ b/drivers/gpu/drm/radeon/evergreen.c
+@@ -960,17 +960,19 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
+ {
+ save->vga_control[0] = RREG32(D1VGA_CONTROL);
+ save->vga_control[1] = RREG32(D2VGA_CONTROL);
+- save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL);
+- save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL);
+- save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL);
+- save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL);
+ save->vga_render_control = RREG32(VGA_RENDER_CONTROL);
+ save->vga_hdp_control = RREG32(VGA_HDP_CONTROL);
+ save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET);
+ save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET);
+- if (!(rdev->flags & RADEON_IS_IGP)) {
++ if (rdev->num_crtc >= 4) {
++ save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL);
++ save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL);
+ save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET);
+ save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET);
++ }
++ if (rdev->num_crtc >= 6) {
++ save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL);
++ save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL);
+ save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET);
+ save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET);
+ }
+@@ -979,35 +981,45 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav
+ WREG32(VGA_RENDER_CONTROL, 0);
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1);
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1);
+- if (!(rdev->flags & RADEON_IS_IGP)) {
++ if (rdev->num_crtc >= 4) {
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1);
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1);
++ }
++ if (rdev->num_crtc >= 6) {
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1);
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1);
+ }
+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
+- if (!(rdev->flags & RADEON_IS_IGP)) {
++ if (rdev->num_crtc >= 4) {
+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
++ }
++ if (rdev->num_crtc >= 6) {
+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+ }
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
+- if (!(rdev->flags & RADEON_IS_IGP)) {
++ if (rdev->num_crtc >= 4) {
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
++ }
++ if (rdev->num_crtc >= 6) {
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+ }
+
+ WREG32(D1VGA_CONTROL, 0);
+ WREG32(D2VGA_CONTROL, 0);
+- WREG32(EVERGREEN_D3VGA_CONTROL, 0);
+- WREG32(EVERGREEN_D4VGA_CONTROL, 0);
+- WREG32(EVERGREEN_D5VGA_CONTROL, 0);
+- WREG32(EVERGREEN_D6VGA_CONTROL, 0);
++ if (rdev->num_crtc >= 4) {
++ WREG32(EVERGREEN_D3VGA_CONTROL, 0);
++ WREG32(EVERGREEN_D4VGA_CONTROL, 0);
++ }
++ if (rdev->num_crtc >= 6) {
++ WREG32(EVERGREEN_D5VGA_CONTROL, 0);
++ WREG32(EVERGREEN_D6VGA_CONTROL, 0);
++ }
+ }
+
+ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save)
+@@ -1030,7 +1042,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET,
+ (u32)rdev->mc.vram_start);
+
+- if (!(rdev->flags & RADEON_IS_IGP)) {
++ if (rdev->num_crtc >= 4) {
+ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET,
+ upper_32_bits(rdev->mc.vram_start));
+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET,
+@@ -1048,7 +1060,8 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
+ (u32)rdev->mc.vram_start);
+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET,
+ (u32)rdev->mc.vram_start);
+-
++ }
++ if (rdev->num_crtc >= 6) {
+ WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET,
+ upper_32_bits(rdev->mc.vram_start));
+ WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET,
+@@ -1076,31 +1089,41 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s
+ /* Restore video state */
+ WREG32(D1VGA_CONTROL, save->vga_control[0]);
+ WREG32(D2VGA_CONTROL, save->vga_control[1]);
+- WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]);
+- WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]);
+- WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]);
+- WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]);
++ if (rdev->num_crtc >= 4) {
++ WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]);
++ WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]);
++ }
++ if (rdev->num_crtc >= 6) {
++ WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]);
++ WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]);
++ }
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1);
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1);
+- if (!(rdev->flags & RADEON_IS_IGP)) {
++ if (rdev->num_crtc >= 4) {
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1);
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1);
++ }
++ if (rdev->num_crtc >= 6) {
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1);
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1);
+ }
+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]);
+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]);
+- if (!(rdev->flags & RADEON_IS_IGP)) {
++ if (rdev->num_crtc >= 4) {
+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]);
+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]);
++ }
++ if (rdev->num_crtc >= 6) {
+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]);
+ WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]);
+ }
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
+- if (!(rdev->flags & RADEON_IS_IGP)) {
++ if (rdev->num_crtc >= 4) {
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
++ }
++ if (rdev->num_crtc >= 6) {
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
+ WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+ }
+@@ -1578,7 +1601,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
+ u32 sq_stack_resource_mgmt_2;
+ u32 sq_stack_resource_mgmt_3;
+ u32 vgt_cache_invalidation;
+- u32 hdp_host_path_cntl;
++ u32 hdp_host_path_cntl, tmp;
+ int i, j, num_shader_engines, ps_thread_count;
+
+ switch (rdev->family) {
+@@ -1900,7 +1923,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
+ gb_backend_map = 0x66442200;
+ break;
+ case CHIP_JUNIPER:
+- gb_backend_map = 0x00006420;
++ gb_backend_map = 0x00002200;
+ break;
+ default:
+ gb_backend_map =
+@@ -2141,6 +2164,10 @@ static void evergreen_gpu_init(struct radeon_device *rdev)
+ for (i = SQ_ALU_CONST_BUFFER_SIZE_HS_0; i < 0x29000; i += 4)
+ WREG32(i, 0);
+
++ tmp = RREG32(HDP_MISC_CNTL);
++ tmp |= HDP_FLUSH_INVALIDATE_CACHE;
++ WREG32(HDP_MISC_CNTL, tmp);
++
+ hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
+ WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
+
+@@ -2323,18 +2350,22 @@ void evergreen_disable_interrupt_state(struct radeon_device *rdev)
+ WREG32(GRBM_INT_CNTL, 0);
+ WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
+ WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
+- if (!(rdev->flags & RADEON_IS_IGP)) {
++ if (rdev->num_crtc >= 4) {
+ WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
+ WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
++ }
++ if (rdev->num_crtc >= 6) {
+ WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
+ WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+ }
+
+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0);
+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0);
+- if (!(rdev->flags & RADEON_IS_IGP)) {
++ if (rdev->num_crtc >= 4) {
+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0);
+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0);
++ }
++ if (rdev->num_crtc >= 6) {
+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0);
+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0);
+ }
+@@ -2453,19 +2484,25 @@ int evergreen_irq_set(struct radeon_device *rdev)
+
+ WREG32(INT_MASK + EVERGREEN_CRTC0_REGISTER_OFFSET, crtc1);
+ WREG32(INT_MASK + EVERGREEN_CRTC1_REGISTER_OFFSET, crtc2);
+- if (!(rdev->flags & RADEON_IS_IGP)) {
++ if (rdev->num_crtc >= 4) {
+ WREG32(INT_MASK + EVERGREEN_CRTC2_REGISTER_OFFSET, crtc3);
+ WREG32(INT_MASK + EVERGREEN_CRTC3_REGISTER_OFFSET, crtc4);
++ }
++ if (rdev->num_crtc >= 6) {
+ WREG32(INT_MASK + EVERGREEN_CRTC4_REGISTER_OFFSET, crtc5);
+ WREG32(INT_MASK + EVERGREEN_CRTC5_REGISTER_OFFSET, crtc6);
+ }
+
+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, grph1);
+ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, grph2);
+- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3);
+- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4);
+- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5);
+- WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6);
++ if (rdev->num_crtc >= 4) {
++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, grph3);
++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, grph4);
++ }
++ if (rdev->num_crtc >= 6) {
++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, grph5);
++ WREG32(GRPH_INT_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, grph6);
++ }
+
+ WREG32(DC_HPD1_INT_CONTROL, hpd1);
+ WREG32(DC_HPD2_INT_CONTROL, hpd2);
+@@ -2489,53 +2526,57 @@ static inline void evergreen_irq_ack(struct radeon_device *rdev)
+ rdev->irq.stat_regs.evergreen.disp_int_cont5 = RREG32(DISP_INTERRUPT_STATUS_CONTINUE5);
+ rdev->irq.stat_regs.evergreen.d1grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET);
+ rdev->irq.stat_regs.evergreen.d2grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET);
+- rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET);
+- rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET);
+- rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET);
+- rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
++ if (rdev->num_crtc >= 4) {
++ rdev->irq.stat_regs.evergreen.d3grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET);
++ rdev->irq.stat_regs.evergreen.d4grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET);
++ }
++ if (rdev->num_crtc >= 6) {
++ rdev->irq.stat_regs.evergreen.d5grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET);
++ rdev->irq.stat_regs.evergreen.d6grph_int = RREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET);
++ }
+
+ if (rdev->irq.stat_regs.evergreen.d1grph_int & GRPH_PFLIP_INT_OCCURRED)
+ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
+ if (rdev->irq.stat_regs.evergreen.d2grph_int & GRPH_PFLIP_INT_OCCURRED)
+ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
+- if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
+- WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
+- if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
+- WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
+- if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
+- WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
+- if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
+- WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
+-
+ if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VBLANK_INTERRUPT)
+ WREG32(VBLANK_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VBLANK_ACK);
+ if (rdev->irq.stat_regs.evergreen.disp_int & LB_D1_VLINE_INTERRUPT)
+ WREG32(VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, VLINE_ACK);
+-
+ if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VBLANK_INTERRUPT)
+ WREG32(VBLANK_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VBLANK_ACK);
+ if (rdev->irq.stat_regs.evergreen.disp_int_cont & LB_D2_VLINE_INTERRUPT)
+ WREG32(VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, VLINE_ACK);
+
+- if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
+- WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
+- if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
+- WREG32(VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VLINE_ACK);
+-
+- if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT)
+- WREG32(VBLANK_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VBLANK_ACK);
+- if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT)
+- WREG32(VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VLINE_ACK);
+-
+- if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
+- WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
+- if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
+- WREG32(VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VLINE_ACK);
+-
+- if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT)
+- WREG32(VBLANK_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VBLANK_ACK);
+- if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT)
+- WREG32(VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VLINE_ACK);
++ if (rdev->num_crtc >= 4) {
++ if (rdev->irq.stat_regs.evergreen.d3grph_int & GRPH_PFLIP_INT_OCCURRED)
++ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
++ if (rdev->irq.stat_regs.evergreen.d4grph_int & GRPH_PFLIP_INT_OCCURRED)
++ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
++ if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VBLANK_INTERRUPT)
++ WREG32(VBLANK_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VBLANK_ACK);
++ if (rdev->irq.stat_regs.evergreen.disp_int_cont2 & LB_D3_VLINE_INTERRUPT)
++ WREG32(VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, VLINE_ACK);
++ if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VBLANK_INTERRUPT)
++ WREG32(VBLANK_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VBLANK_ACK);
++ if (rdev->irq.stat_regs.evergreen.disp_int_cont3 & LB_D4_VLINE_INTERRUPT)
++ WREG32(VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, VLINE_ACK);
++ }
++
++ if (rdev->num_crtc >= 6) {
++ if (rdev->irq.stat_regs.evergreen.d5grph_int & GRPH_PFLIP_INT_OCCURRED)
++ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
++ if (rdev->irq.stat_regs.evergreen.d6grph_int & GRPH_PFLIP_INT_OCCURRED)
++ WREG32(GRPH_INT_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, GRPH_PFLIP_INT_CLEAR);
++ if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VBLANK_INTERRUPT)
++ WREG32(VBLANK_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VBLANK_ACK);
++ if (rdev->irq.stat_regs.evergreen.disp_int_cont4 & LB_D5_VLINE_INTERRUPT)
++ WREG32(VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, VLINE_ACK);
++ if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VBLANK_INTERRUPT)
++ WREG32(VBLANK_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VBLANK_ACK);
++ if (rdev->irq.stat_regs.evergreen.disp_int_cont5 & LB_D6_VLINE_INTERRUPT)
++ WREG32(VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET, VLINE_ACK);
++ }
+
+ if (rdev->irq.stat_regs.evergreen.disp_int & DC_HPD1_INTERRUPT) {
+ tmp = RREG32(DC_HPD1_INT_CONTROL);
+@@ -3146,6 +3187,7 @@ void evergreen_fini(struct radeon_device *rdev)
+ r700_cp_fini(rdev);
+ r600_irq_fini(rdev);
+ radeon_wb_fini(rdev);
++ radeon_ib_pool_fini(rdev);
+ radeon_irq_kms_fini(rdev);
+ evergreen_pcie_gart_fini(rdev);
+ radeon_gem_fini(rdev);
+diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h
+index fc40e0c..273e7e9 100644
+--- a/drivers/gpu/drm/radeon/evergreend.h
++++ b/drivers/gpu/drm/radeon/evergreend.h
+@@ -64,6 +64,8 @@
+ #define GB_BACKEND_MAP 0x98FC
+ #define DMIF_ADDR_CONFIG 0xBD4
+ #define HDP_ADDR_CONFIG 0x2F48
++#define HDP_MISC_CNTL 0x2F4C
++#define HDP_FLUSH_INVALIDATE_CACHE (1 << 0)
+
+ #define CC_SYS_RB_BACKEND_DISABLE 0x3F88
+ #define GC_USER_RB_BACKEND_DISABLE 0x9B7C
+@@ -458,7 +460,7 @@
+ #define IH_RB_WPTR_ADDR_LO 0x3e14
+ #define IH_CNTL 0x3e18
+ # define ENABLE_INTR (1 << 0)
+-# define IH_MC_SWAP(x) ((x) << 2)
++# define IH_MC_SWAP(x) ((x) << 1)
+ # define IH_MC_SWAP_NONE 0
+ # define IH_MC_SWAP_16BIT 1
+ # define IH_MC_SWAP_32BIT 2
+@@ -539,7 +541,7 @@
+ # define LB_D5_VBLANK_INTERRUPT (1 << 3)
+ # define DC_HPD5_INTERRUPT (1 << 17)
+ # define DC_HPD5_RX_INTERRUPT (1 << 18)
+-#define DISP_INTERRUPT_STATUS_CONTINUE5 0x6050
++#define DISP_INTERRUPT_STATUS_CONTINUE5 0x6150
+ # define LB_D6_VLINE_INTERRUPT (1 << 2)
+ # define LB_D6_VBLANK_INTERRUPT (1 << 3)
+ # define DC_HPD6_INTERRUPT (1 << 17)
+diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
+index 3d8a763..58f5070 100644
+--- a/drivers/gpu/drm/radeon/ni.c
++++ b/drivers/gpu/drm/radeon/ni.c
+@@ -417,7 +417,7 @@ static u32 cayman_get_tile_pipe_to_backend_map(struct radeon_device *rdev,
+ num_shader_engines = 1;
+ if (num_shader_engines > rdev->config.cayman.max_shader_engines)
+ num_shader_engines = rdev->config.cayman.max_shader_engines;
+- if (num_backends_per_asic > num_shader_engines)
++ if (num_backends_per_asic < num_shader_engines)
+ num_backends_per_asic = num_shader_engines;
+ if (num_backends_per_asic > (rdev->config.cayman.max_backends_per_se * num_shader_engines))
+ num_backends_per_asic = rdev->config.cayman.max_backends_per_se * num_shader_engines;
+@@ -829,7 +829,7 @@ static void cayman_gpu_init(struct radeon_device *rdev)
+ rdev->config.cayman.tile_config |=
+ ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4;
+ rdev->config.cayman.tile_config |=
+- (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT;
++ ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8;
+ rdev->config.cayman.tile_config |=
+ ((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12;
+
+@@ -931,6 +931,10 @@ static void cayman_gpu_init(struct radeon_device *rdev)
+ WREG32(CB_PERF_CTR3_SEL_0, 0);
+ WREG32(CB_PERF_CTR3_SEL_1, 0);
+
++ tmp = RREG32(HDP_MISC_CNTL);
++ tmp |= HDP_FLUSH_INVALIDATE_CACHE;
++ WREG32(HDP_MISC_CNTL, tmp);
++
+ hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
+ WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
+
+@@ -1580,6 +1584,7 @@ void cayman_fini(struct radeon_device *rdev)
+ cayman_cp_fini(rdev);
+ r600_irq_fini(rdev);
+ radeon_wb_fini(rdev);
++ radeon_ib_pool_fini(rdev);
+ radeon_irq_kms_fini(rdev);
+ cayman_pcie_gart_fini(rdev);
+ radeon_gem_fini(rdev);
+diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h
+index 0f9a08b..b2088c1 100644
+--- a/drivers/gpu/drm/radeon/nid.h
++++ b/drivers/gpu/drm/radeon/nid.h
+@@ -136,6 +136,8 @@
+ #define HDP_NONSURFACE_INFO 0x2C08
+ #define HDP_NONSURFACE_SIZE 0x2C0C
+ #define HDP_ADDR_CONFIG 0x2F48
++#define HDP_MISC_CNTL 0x2F4C
++#define HDP_FLUSH_INVALIDATE_CACHE (1 << 0)
+
+ #define CC_SYS_RB_BACKEND_DISABLE 0x3F88
+ #define GC_USER_SYS_RB_BACKEND_DISABLE 0x3F8C
+diff --git a/drivers/gpu/drm/radeon/r100_track.h b/drivers/gpu/drm/radeon/r100_track.h
+index 2fef9de..686f9dc 100644
+--- a/drivers/gpu/drm/radeon/r100_track.h
++++ b/drivers/gpu/drm/radeon/r100_track.h
+@@ -63,7 +63,7 @@ struct r100_cs_track {
+ unsigned num_arrays;
+ unsigned max_indx;
+ unsigned color_channel_mask;
+- struct r100_cs_track_array arrays[11];
++ struct r100_cs_track_array arrays[16];
+ struct r100_cs_track_cb cb[R300_MAX_CB];
+ struct r100_cs_track_cb zb;
+ struct r100_cs_track_cb aa;
+@@ -146,6 +146,12 @@ static inline int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,
+ ib = p->ib->ptr;
+ track = (struct r100_cs_track *)p->track;
+ c = radeon_get_ib_value(p, idx++) & 0x1F;
++ if (c > 16) {
++ DRM_ERROR("Only 16 vertex buffers are allowed %d\n",
++ pkt->opcode);
++ r100_cs_dump_packet(p, pkt);
++ return -EINVAL;
++ }
+ track->num_arrays = c;
+ for (i = 0; i < (c - 1); i+=2, idx+=3) {
+ r = r100_cs_packet_next_reloc(p, &reloc);
+diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
+index 6f27593..068cc85 100644
+--- a/drivers/gpu/drm/radeon/r600.c
++++ b/drivers/gpu/drm/radeon/r600.c
+@@ -2613,6 +2613,7 @@ void r600_fini(struct radeon_device *rdev)
+ r600_cp_fini(rdev);
+ r600_irq_fini(rdev);
+ radeon_wb_fini(rdev);
++ radeon_ib_pool_fini(rdev);
+ radeon_irq_kms_fini(rdev);
+ r600_pcie_gart_fini(rdev);
+ radeon_agp_fini(rdev);
+diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h
+index b2b944bc..e5eaef9 100644
+--- a/drivers/gpu/drm/radeon/r600d.h
++++ b/drivers/gpu/drm/radeon/r600d.h
+@@ -536,7 +536,7 @@
+ #define IH_RB_WPTR_ADDR_LO 0x3e14
+ #define IH_CNTL 0x3e18
+ # define ENABLE_INTR (1 << 0)
+-# define IH_MC_SWAP(x) ((x) << 2)
++# define IH_MC_SWAP(x) ((x) << 1)
+ # define IH_MC_SWAP_NONE 0
+ # define IH_MC_SWAP_16BIT 1
+ # define IH_MC_SWAP_32BIT 2
+diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c
+index ca57619..d948265 100644
+--- a/drivers/gpu/drm/radeon/radeon_asic.c
++++ b/drivers/gpu/drm/radeon/radeon_asic.c
+@@ -782,6 +782,7 @@ static struct radeon_asic evergreen_asic = {
+ .hpd_fini = &evergreen_hpd_fini,
+ .hpd_sense = &evergreen_hpd_sense,
+ .hpd_set_polarity = &evergreen_hpd_set_polarity,
++ .ioctl_wait_idle = r600_ioctl_wait_idle,
+ .gui_idle = &r600_gui_idle,
+ .pm_misc = &evergreen_pm_misc,
+ .pm_prepare = &evergreen_pm_prepare,
+@@ -828,6 +829,7 @@ static struct radeon_asic sumo_asic = {
+ .hpd_fini = &evergreen_hpd_fini,
+ .hpd_sense = &evergreen_hpd_sense,
+ .hpd_set_polarity = &evergreen_hpd_set_polarity,
++ .ioctl_wait_idle = r600_ioctl_wait_idle,
+ .gui_idle = &r600_gui_idle,
+ .pm_misc = &evergreen_pm_misc,
+ .pm_prepare = &evergreen_pm_prepare,
+@@ -874,6 +876,7 @@ static struct radeon_asic btc_asic = {
+ .hpd_fini = &evergreen_hpd_fini,
+ .hpd_sense = &evergreen_hpd_sense,
+ .hpd_set_polarity = &evergreen_hpd_set_polarity,
++ .ioctl_wait_idle = r600_ioctl_wait_idle,
+ .gui_idle = &r600_gui_idle,
+ .pm_misc = &evergreen_pm_misc,
+ .pm_prepare = &evergreen_pm_prepare,
+@@ -920,6 +923,7 @@ static struct radeon_asic cayman_asic = {
+ .hpd_fini = &evergreen_hpd_fini,
+ .hpd_sense = &evergreen_hpd_sense,
+ .hpd_set_polarity = &evergreen_hpd_set_polarity,
++ .ioctl_wait_idle = r600_ioctl_wait_idle,
+ .gui_idle = &r600_gui_idle,
+ .pm_misc = &evergreen_pm_misc,
+ .pm_prepare = &evergreen_pm_prepare,
+diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
+index 890217e..5d6ccc3 100644
+--- a/drivers/gpu/drm/radeon/radeon_device.c
++++ b/drivers/gpu/drm/radeon/radeon_device.c
+@@ -752,6 +752,7 @@ int radeon_device_init(struct radeon_device *rdev,
+ dma_bits = rdev->need_dma32 ? 32 : 40;
+ r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits));
+ if (r) {
++ rdev->need_dma32 = true;
+ printk(KERN_WARNING "radeon: No suitable DMA available.\n");
+ }
+
+diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
+index bdbab5c..2802c56 100644
+--- a/drivers/gpu/drm/radeon/radeon_display.c
++++ b/drivers/gpu/drm/radeon/radeon_display.c
+@@ -264,6 +264,8 @@ static void radeon_unpin_work_func(struct work_struct *__work)
+ radeon_bo_unreserve(work->old_rbo);
+ } else
+ DRM_ERROR("failed to reserve buffer after flip\n");
++
++ drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base);
+ kfree(work);
+ }
+
+@@ -371,6 +373,8 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
+ new_radeon_fb = to_radeon_framebuffer(fb);
+ /* schedule unpin of the old buffer */
+ obj = old_radeon_fb->obj;
++ /* take a reference to the old object */
++ drm_gem_object_reference(obj);
+ rbo = gem_to_radeon_bo(obj);
+ work->old_rbo = rbo;
+ INIT_WORK(&work->work, radeon_unpin_work_func);
+@@ -378,12 +382,9 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc,
+ /* We borrow the event spin lock for protecting unpin_work */
+ spin_lock_irqsave(&dev->event_lock, flags);
+ if (radeon_crtc->unpin_work) {
+- spin_unlock_irqrestore(&dev->event_lock, flags);
+- kfree(work);
+- radeon_fence_unref(&fence);
+-
+ DRM_DEBUG_DRIVER("flip queue: crtc already busy\n");
+- return -EBUSY;
++ r = -EBUSY;
++ goto unlock_free;
+ }
+ radeon_crtc->unpin_work = work;
+ radeon_crtc->deferred_flip_completion = 0;
+@@ -497,6 +498,8 @@ pflip_cleanup1:
+ pflip_cleanup:
+ spin_lock_irqsave(&dev->event_lock, flags);
+ radeon_crtc->unpin_work = NULL;
++unlock_free:
++ drm_gem_object_unreference_unlocked(old_radeon_fb->obj);
+ spin_unlock_irqrestore(&dev->event_lock, flags);
+ radeon_fence_unref(&fence);
+ kfree(work);
+diff --git a/drivers/gpu/drm/radeon/radeon_encoders.c b/drivers/gpu/drm/radeon/radeon_encoders.c
+index b427488..9423fba 100644
+--- a/drivers/gpu/drm/radeon/radeon_encoders.c
++++ b/drivers/gpu/drm/radeon/radeon_encoders.c
+@@ -1294,7 +1294,11 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
+ if (is_dig) {
+ switch (mode) {
+ case DRM_MODE_DPMS_ON:
+- atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
++ /* some early dce3.2 boards have a bug in their transmitter control table */
++ if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730))
++ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
++ else
++ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
+ if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
+ struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
+
+diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c
+index ef8a5ba..33b856b 100644
+--- a/drivers/gpu/drm/radeon/rv770.c
++++ b/drivers/gpu/drm/radeon/rv770.c
+@@ -572,6 +572,12 @@ static void rv770_program_channel_remap(struct radeon_device *rdev)
+ else
+ tcp_chan_steer = 0x00fac688;
+
++ /* RV770 CE has special chremap setup */
++ if (rdev->pdev->device == 0x944e) {
++ tcp_chan_steer = 0x00b08b08;
++ mc_shared_chremap = 0x00b08b08;
++ }
++
+ WREG32(TCP_CHAN_STEER, tcp_chan_steer);
+ WREG32(MC_SHARED_CHREMAP, mc_shared_chremap);
+ }
+@@ -1359,6 +1365,7 @@ void rv770_fini(struct radeon_device *rdev)
+ r700_cp_fini(rdev);
+ r600_irq_fini(rdev);
+ radeon_wb_fini(rdev);
++ radeon_ib_pool_fini(rdev);
+ radeon_irq_kms_fini(rdev);
+ rv770_pcie_gart_fini(rdev);
+ rv770_vram_scratch_fini(rdev);
+diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c
+index 0ec91c1..a5eda4c 100644
+--- a/drivers/hid/hid-magicmouse.c
++++ b/drivers/hid/hid-magicmouse.c
+@@ -501,9 +501,17 @@ static int magicmouse_probe(struct hid_device *hdev,
+ }
+ report->size = 6;
+
++ /*
++ * The device reponds with 'invalid report id' when feature
++ * report switching it into multitouch mode is sent to it.
++ *
++ * This results in -EIO from the _raw low-level transport callback,
++ * but there seems to be no other way of switching the mode.
++ * Thus the super-ugly hacky success check below.
++ */
+ ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature),
+ HID_FEATURE_REPORT);
+- if (ret != sizeof(feature)) {
++ if (ret != -EIO) {
+ hid_err(hdev, "unable to request touch data (%d)\n", ret);
+ goto err_stop_hw;
+ }
+diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
+index b5e8920..3462242 100644
+--- a/drivers/hwmon/asus_atk0110.c
++++ b/drivers/hwmon/asus_atk0110.c
+@@ -673,6 +673,7 @@ static int atk_debugfs_gitm_get(void *p, u64 *val)
+ else
+ err = -EIO;
+
++ ACPI_FREE(ret);
+ return err;
+ }
+
+diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
+index 194ca0a..08cea44 100644
+--- a/drivers/hwmon/coretemp.c
++++ b/drivers/hwmon/coretemp.c
+@@ -263,7 +263,7 @@ static int __devinit get_tjmax(struct cpuinfo_x86 *c, u32 id,
+ * If the TjMax is not plausible, an assumption
+ * will be used
+ */
+- if ((val > 80) && (val < 120)) {
++ if (val >= 70 && val <= 125) {
+ dev_info(dev, "TjMax is %d C.\n", val);
+ return val * 1000;
+ }
+@@ -271,24 +271,9 @@ static int __devinit get_tjmax(struct cpuinfo_x86 *c, u32 id,
+
+ /*
+ * An assumption is made for early CPUs and unreadable MSR.
+- * NOTE: the given value may not be correct.
++ * NOTE: the calculated value may not be correct.
+ */
+-
+- switch (c->x86_model) {
+- case 0xe:
+- case 0xf:
+- case 0x16:
+- case 0x1a:
+- dev_warn(dev, "TjMax is assumed as 100 C!\n");
+- return 100000;
+- case 0x17:
+- case 0x1c: /* Atom CPUs */
+- return adjust_tjmax(c, id, dev);
+- default:
+- dev_warn(dev, "CPU (model=0x%x) is not supported yet,"
+- " using default TjMax of 100C.\n", c->x86_model);
+- return 100000;
+- }
++ return adjust_tjmax(c, id, dev);
+ }
+
+ static void __devinit get_ucode_rev_on_cpu(void *edx)
+diff --git a/drivers/hwmon/ibmaem.c b/drivers/hwmon/ibmaem.c
+index bc6e2ab..affc17e 100644
+--- a/drivers/hwmon/ibmaem.c
++++ b/drivers/hwmon/ibmaem.c
+@@ -947,6 +947,7 @@ static int aem_register_sensors(struct aem_data *data,
+
+ /* Set up read-only sensors */
+ while (ro->label) {
++ sysfs_attr_init(&sensors->dev_attr.attr);
+ sensors->dev_attr.attr.name = ro->label;
+ sensors->dev_attr.attr.mode = S_IRUGO;
+ sensors->dev_attr.show = ro->show;
+@@ -963,6 +964,7 @@ static int aem_register_sensors(struct aem_data *data,
+
+ /* Set up read-write sensors */
+ while (rw->label) {
++ sysfs_attr_init(&sensors->dev_attr.attr);
+ sensors->dev_attr.attr.name = rw->label;
+ sensors->dev_attr.attr.mode = S_IRUGO | S_IWUSR;
+ sensors->dev_attr.show = rw->show;
+diff --git a/drivers/hwmon/ibmpex.c b/drivers/hwmon/ibmpex.c
+index 06d4eaf..41dbf81 100644
+--- a/drivers/hwmon/ibmpex.c
++++ b/drivers/hwmon/ibmpex.c
+@@ -358,6 +358,7 @@ static int create_sensor(struct ibmpex_bmc_data *data, int type,
+ else if (type == POWER_SENSOR)
+ sprintf(n, power_sensor_name_templates[func], "power", counter);
+
++ sysfs_attr_init(&data->sensors[sensor].attr[func].dev_attr.attr);
+ data->sensors[sensor].attr[func].dev_attr.attr.name = n;
+ data->sensors[sensor].attr[func].dev_attr.attr.mode = S_IRUGO;
+ data->sensors[sensor].attr[func].dev_attr.show = ibmpex_show_sensor;
+diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
+index 316b648..a8d2359 100644
+--- a/drivers/hwmon/it87.c
++++ b/drivers/hwmon/it87.c
+@@ -1535,7 +1535,7 @@ static struct attribute *it87_attributes_label[] = {
+ };
+
+ static const struct attribute_group it87_group_label = {
+- .attrs = it87_attributes_vid,
++ .attrs = it87_attributes_label,
+ };
+
+ /* SuperIO detection - will change isa_address if a chip is found */
+diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c
+index 1a6dfb6..d3b464b 100644
+--- a/drivers/hwmon/lm95241.c
++++ b/drivers/hwmon/lm95241.c
+@@ -98,11 +98,16 @@ struct lm95241_data {
+ };
+
+ /* Conversions */
+-static int TempFromReg(u8 val_h, u8 val_l)
++static int temp_from_reg_signed(u8 val_h, u8 val_l)
+ {
+- if (val_h & 0x80)
+- return val_h - 0x100;
+- return val_h * 1000 + val_l * 1000 / 256;
++ s16 val_hl = (val_h << 8) | val_l;
++ return val_hl * 1000 / 256;
++}
++
++static int temp_from_reg_unsigned(u8 val_h, u8 val_l)
++{
++ u16 val_hl = (val_h << 8) | val_l;
++ return val_hl * 1000 / 256;
+ }
+
+ static struct lm95241_data *lm95241_update_device(struct device *dev)
+@@ -135,10 +140,13 @@ static ssize_t show_input(struct device *dev, struct device_attribute *attr,
+ char *buf)
+ {
+ struct lm95241_data *data = lm95241_update_device(dev);
++ int index = to_sensor_dev_attr(attr)->index;
+
+ return snprintf(buf, PAGE_SIZE - 1, "%d\n",
+- TempFromReg(data->temp[to_sensor_dev_attr(attr)->index],
+- data->temp[to_sensor_dev_attr(attr)->index + 1]));
++ index == 0 || (data->config & (1 << (index / 2))) ?
++ temp_from_reg_signed(data->temp[index], data->temp[index + 1]) :
++ temp_from_reg_unsigned(data->temp[index],
++ data->temp[index + 1]));
+ }
+
+ static ssize_t show_type(struct device *dev, struct device_attribute *attr,
+@@ -339,7 +347,7 @@ static int lm95241_detect(struct i2c_client *new_client,
+ if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID)
+ == MANUFACTURER_ID)
+ && (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID)
+- >= DEFAULT_REVISION)) {
++ == DEFAULT_REVISION)) {
+ name = DEVNAME;
+ } else {
+ dev_dbg(&adapter->dev, "LM95241 detection failed at 0x%02x\n",
+diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c
+index 12a54aa..14335bb 100644
+--- a/drivers/hwmon/max1111.c
++++ b/drivers/hwmon/max1111.c
+@@ -40,6 +40,8 @@ struct max1111_data {
+ struct spi_transfer xfer[2];
+ uint8_t *tx_buf;
+ uint8_t *rx_buf;
++ struct mutex drvdata_lock;
++ /* protect msg, xfer and buffers from multiple access */
+ };
+
+ static int max1111_read(struct device *dev, int channel)
+@@ -48,6 +50,9 @@ static int max1111_read(struct device *dev, int channel)
+ uint8_t v1, v2;
+ int err;
+
++ /* writing to drvdata struct is not thread safe, wait on mutex */
++ mutex_lock(&data->drvdata_lock);
++
+ data->tx_buf[0] = (channel << MAX1111_CTRL_SEL_SH) |
+ MAX1111_CTRL_PD0 | MAX1111_CTRL_PD1 |
+ MAX1111_CTRL_SGL | MAX1111_CTRL_UNI | MAX1111_CTRL_STR;
+@@ -55,12 +60,15 @@ static int max1111_read(struct device *dev, int channel)
+ err = spi_sync(data->spi, &data->msg);
+ if (err < 0) {
+ dev_err(dev, "spi_sync failed with %d\n", err);
++ mutex_unlock(&data->drvdata_lock);
+ return err;
+ }
+
+ v1 = data->rx_buf[0];
+ v2 = data->rx_buf[1];
+
++ mutex_unlock(&data->drvdata_lock);
++
+ if ((v1 & 0xc0) || (v2 & 0x3f))
+ return -EINVAL;
+
+@@ -176,6 +184,8 @@ static int __devinit max1111_probe(struct spi_device *spi)
+ if (err)
+ goto err_free_data;
+
++ mutex_init(&data->drvdata_lock);
++
+ data->spi = spi;
+ spi_set_drvdata(spi, data);
+
+@@ -213,6 +223,7 @@ static int __devexit max1111_remove(struct spi_device *spi)
+
+ hwmon_device_unregister(data->hwmon_dev);
+ sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group);
++ mutex_destroy(&data->drvdata_lock);
+ kfree(data->rx_buf);
+ kfree(data->tx_buf);
+ kfree(data);
+diff --git a/drivers/hwmon/pmbus.c b/drivers/hwmon/pmbus.c
+index 98e2e28..9b1f0c3 100644
+--- a/drivers/hwmon/pmbus.c
++++ b/drivers/hwmon/pmbus.c
+@@ -47,22 +47,29 @@ static void pmbus_find_sensor_groups(struct i2c_client *client,
+ if (info->func[0]
+ && pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT))
+ info->func[0] |= PMBUS_HAVE_STATUS_INPUT;
+- if (pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) {
++ if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_12) &&
++ pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) {
+ info->func[0] |= PMBUS_HAVE_FAN12;
+ if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12))
+ info->func[0] |= PMBUS_HAVE_STATUS_FAN12;
+ }
+- if (pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) {
++ if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_34) &&
++ pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) {
+ info->func[0] |= PMBUS_HAVE_FAN34;
+ if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34))
+ info->func[0] |= PMBUS_HAVE_STATUS_FAN34;
+ }
+- if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) {
++ if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1))
+ info->func[0] |= PMBUS_HAVE_TEMP;
+- if (pmbus_check_byte_register(client, 0,
+- PMBUS_STATUS_TEMPERATURE))
++ if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2))
++ info->func[0] |= PMBUS_HAVE_TEMP2;
++ if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3))
++ info->func[0] |= PMBUS_HAVE_TEMP3;
++ if (info->func[0] & (PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2
++ | PMBUS_HAVE_TEMP3)
++ && pmbus_check_byte_register(client, 0,
++ PMBUS_STATUS_TEMPERATURE))
+ info->func[0] |= PMBUS_HAVE_STATUS_TEMP;
+- }
+
+ /* Sensors detected on all pages */
+ for (page = 0; page < info->pages; page++) {
+diff --git a/drivers/hwmon/pmbus_core.c b/drivers/hwmon/pmbus_core.c
+index 196ffaf..8217d19 100644
+--- a/drivers/hwmon/pmbus_core.c
++++ b/drivers/hwmon/pmbus_core.c
+@@ -355,8 +355,8 @@ static struct pmbus_data *pmbus_update_device(struct device *dev)
+ * Convert linear sensor values to milli- or micro-units
+ * depending on sensor type.
+ */
+-static int pmbus_reg2data_linear(struct pmbus_data *data,
+- struct pmbus_sensor *sensor)
++static long pmbus_reg2data_linear(struct pmbus_data *data,
++ struct pmbus_sensor *sensor)
+ {
+ s16 exponent;
+ s32 mantissa;
+@@ -390,15 +390,15 @@ static int pmbus_reg2data_linear(struct pmbus_data *data,
+ else
+ val >>= -exponent;
+
+- return (int)val;
++ return val;
+ }
+
+ /*
+ * Convert direct sensor values to milli- or micro-units
+ * depending on sensor type.
+ */
+-static int pmbus_reg2data_direct(struct pmbus_data *data,
+- struct pmbus_sensor *sensor)
++static long pmbus_reg2data_direct(struct pmbus_data *data,
++ struct pmbus_sensor *sensor)
+ {
+ long val = (s16) sensor->data;
+ long m, b, R;
+@@ -433,12 +433,12 @@ static int pmbus_reg2data_direct(struct pmbus_data *data,
+ R++;
+ }
+
+- return (int)((val - b) / m);
++ return (val - b) / m;
+ }
+
+-static int pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
++static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
+ {
+- int val;
++ long val;
+
+ if (data->info->direct[sensor->class])
+ val = pmbus_reg2data_direct(data, sensor);
+@@ -612,7 +612,7 @@ static int pmbus_get_boolean(struct pmbus_data *data, int index, int *val)
+ if (!s1 && !s2)
+ *val = !!regval;
+ else {
+- int v1, v2;
++ long v1, v2;
+ struct pmbus_sensor *sensor1, *sensor2;
+
+ sensor1 = &data->sensors[s1];
+@@ -654,7 +654,7 @@ static ssize_t pmbus_show_sensor(struct device *dev,
+ if (sensor->data < 0)
+ return sensor->data;
+
+- return snprintf(buf, PAGE_SIZE, "%d\n", pmbus_reg2data(data, sensor));
++ return snprintf(buf, PAGE_SIZE, "%ld\n", pmbus_reg2data(data, sensor));
+ }
+
+ static ssize_t pmbus_set_sensor(struct device *dev,
+@@ -700,6 +700,7 @@ do { \
+ struct sensor_device_attribute *a \
+ = &data->_type##s[data->num_##_type##s].attribute; \
+ BUG_ON(data->num_attributes >= data->max_attributes); \
++ sysfs_attr_init(&a->dev_attr.attr); \
+ a->dev_attr.attr.name = _name; \
+ a->dev_attr.attr.mode = _mode; \
+ a->dev_attr.show = _show; \
+@@ -1517,14 +1518,9 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
+ i2c_set_clientdata(client, data);
+ mutex_init(&data->update_lock);
+
+- /*
+- * Bail out if status register or PMBus revision register
+- * does not exist.
+- */
+- if (i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE) < 0
+- || i2c_smbus_read_byte_data(client, PMBUS_REVISION) < 0) {
+- dev_err(&client->dev,
+- "Status or revision register not found\n");
++ /* Bail out if PMBus status register does not exist. */
++ if (i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE) < 0) {
++ dev_err(&client->dev, "PMBus status register not found\n");
+ ret = -ENODEV;
+ goto out_data;
+ }
+diff --git a/drivers/hwmon/s3c-hwmon.c b/drivers/hwmon/s3c-hwmon.c
+index 92b42db..b39f52e 100644
+--- a/drivers/hwmon/s3c-hwmon.c
++++ b/drivers/hwmon/s3c-hwmon.c
+@@ -232,6 +232,7 @@ static int s3c_hwmon_create_attr(struct device *dev,
+
+ attr = &attrs->in;
+ attr->index = channel;
++ sysfs_attr_init(&attr->dev_attr.attr);
+ attr->dev_attr.attr.name = attrs->in_name;
+ attr->dev_attr.attr.mode = S_IRUGO;
+ attr->dev_attr.show = s3c_hwmon_ch_show;
+@@ -249,6 +250,7 @@ static int s3c_hwmon_create_attr(struct device *dev,
+
+ attr = &attrs->label;
+ attr->index = channel;
++ sysfs_attr_init(&attr->dev_attr.attr);
+ attr->dev_attr.attr.name = attrs->label_name;
+ attr->dev_attr.attr.mode = S_IRUGO;
+ attr->dev_attr.show = s3c_hwmon_label_show;
+diff --git a/drivers/i2c/busses/i2c-taos-evm.c b/drivers/i2c/busses/i2c-taos-evm.c
+index dd39c1e..26c352a 100644
+--- a/drivers/i2c/busses/i2c-taos-evm.c
++++ b/drivers/i2c/busses/i2c-taos-evm.c
+@@ -234,7 +234,7 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv)
+
+ if (taos->state != TAOS_STATE_IDLE) {
+ err = -ENODEV;
+- dev_dbg(&serio->dev, "TAOS EVM reset failed (state=%d, "
++ dev_err(&serio->dev, "TAOS EVM reset failed (state=%d, "
+ "pos=%d)\n", taos->state, taos->pos);
+ goto exit_close;
+ }
+@@ -255,7 +255,7 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv)
+ msecs_to_jiffies(250));
+ if (taos->state != TAOS_STATE_IDLE) {
+ err = -ENODEV;
+- dev_err(&adapter->dev, "Echo off failed "
++ dev_err(&serio->dev, "TAOS EVM echo off failed "
+ "(state=%d)\n", taos->state);
+ goto exit_close;
+ }
+@@ -263,7 +263,7 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv)
+ err = i2c_add_adapter(adapter);
+ if (err)
+ goto exit_close;
+- dev_dbg(&serio->dev, "Connected to TAOS EVM\n");
++ dev_info(&serio->dev, "Connected to TAOS EVM\n");
+
+ taos->client = taos_instantiate_device(adapter);
+ return 0;
+@@ -288,7 +288,7 @@ static void taos_disconnect(struct serio *serio)
+ serio_set_drvdata(serio, NULL);
+ kfree(taos);
+
+- dev_dbg(&serio->dev, "Disconnected from TAOS EVM\n");
++ dev_info(&serio->dev, "Disconnected from TAOS EVM\n");
+ }
+
+ static struct serio_device_id taos_serio_ids[] = {
+diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
+index b4ab39b..5f1b92c 100644
+--- a/drivers/i2c/busses/i2c-tegra.c
++++ b/drivers/i2c/busses/i2c-tegra.c
+@@ -330,6 +330,11 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
+ i2c_writel(i2c_dev, 0, I2C_INT_MASK);
+ clk_set_rate(i2c_dev->clk, i2c_dev->bus_clk_rate * 8);
+
++ if (!i2c_dev->is_dvc) {
++ u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG);
++ i2c_writel(i2c_dev, sl_cfg | I2C_SL_CNFG_NEWSL, I2C_SL_CNFG);
++ }
++
+ val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT |
+ 0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT;
+ i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
+diff --git a/drivers/i2c/muxes/pca954x.c b/drivers/i2c/muxes/pca954x.c
+index 54e1ce7..6f89536 100644
+--- a/drivers/i2c/muxes/pca954x.c
++++ b/drivers/i2c/muxes/pca954x.c
+@@ -201,10 +201,11 @@ static int pca954x_probe(struct i2c_client *client,
+
+ i2c_set_clientdata(client, data);
+
+- /* Read the mux register at addr to verify
+- * that the mux is in fact present.
++ /* Write the mux register at addr to verify
++ * that the mux is in fact present. This also
++ * initializes the mux to disconnected state.
+ */
+- if (i2c_smbus_read_byte(client) < 0) {
++ if (i2c_smbus_write_byte(client, 0) < 0) {
+ dev_warn(&client->dev, "probe failed\n");
+ goto exit_free;
+ }
+diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
+index a5ec5a7..9560822 100644
+--- a/drivers/ide/ide-cd.c
++++ b/drivers/ide/ide-cd.c
+@@ -1773,7 +1773,8 @@ static int ide_cd_probe(ide_drive_t *drive)
+
+ g->minors = 1;
+ g->driverfs_dev = &drive->gendev;
+- g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE;
++ g->flags = GENHD_FL_CD | GENHD_FL_REMOVABLE |
++ GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
+ if (ide_cdrom_setup(drive)) {
+ put_device(&info->dev);
+ goto failed;
+diff --git a/drivers/input/input.c b/drivers/input/input.c
+index ebbceed..e3c88fc 100644
+--- a/drivers/input/input.c
++++ b/drivers/input/input.c
+@@ -1757,7 +1757,7 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev)
+ } else if (test_bit(ABS_MT_TRACKING_ID, dev->absbit)) {
+ mt_slots = dev->absinfo[ABS_MT_TRACKING_ID].maximum -
+ dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1,
+- clamp(mt_slots, 2, 32);
++ mt_slots = clamp(mt_slots, 2, 32);
+ } else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
+ mt_slots = 2;
+ } else {
+diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
+index 7630273..f8ba7c9 100644
+--- a/drivers/input/mousedev.c
++++ b/drivers/input/mousedev.c
+@@ -187,7 +187,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
+ if (size == 0)
+ size = xres ? : 1;
+
+- clamp(value, min, max);
++ value = clamp(value, min, max);
+
+ mousedev->packet.x = ((value - min) * xres) / size;
+ mousedev->packet.abs_event = 1;
+@@ -201,7 +201,7 @@ static void mousedev_abs_event(struct input_dev *dev, struct mousedev *mousedev,
+ if (size == 0)
+ size = yres ? : 1;
+
+- clamp(value, min, max);
++ value = clamp(value, min, max);
+
+ mousedev->packet.y = yres - ((value - min) * yres) / size;
+ mousedev->packet.abs_event = 1;
+diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
+index 5c93627..70bd738 100644
+--- a/drivers/md/bitmap.c
++++ b/drivers/md/bitmap.c
+@@ -493,11 +493,11 @@ void bitmap_update_sb(struct bitmap *bitmap)
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ sb = kmap_atomic(bitmap->sb_page, KM_USER0);
+ sb->events = cpu_to_le64(bitmap->mddev->events);
+- if (bitmap->mddev->events < bitmap->events_cleared) {
++ if (bitmap->mddev->events < bitmap->events_cleared)
+ /* rocking back to read-only */
+ bitmap->events_cleared = bitmap->mddev->events;
+- sb->events_cleared = cpu_to_le64(bitmap->events_cleared);
+- }
++ sb->events_cleared = cpu_to_le64(bitmap->events_cleared);
++ sb->state = cpu_to_le32(bitmap->flags);
+ /* Just in case these have been changed via sysfs: */
+ sb->daemon_sleep = cpu_to_le32(bitmap->mddev->bitmap_info.daemon_sleep/HZ);
+ sb->write_behind = cpu_to_le32(bitmap->mddev->bitmap_info.max_write_behind);
+@@ -618,7 +618,7 @@ success:
+ if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN)
+ bitmap->flags |= BITMAP_HOSTENDIAN;
+ bitmap->events_cleared = le64_to_cpu(sb->events_cleared);
+- if (sb->state & cpu_to_le32(BITMAP_STALE))
++ if (bitmap->flags & BITMAP_STALE)
+ bitmap->events_cleared = bitmap->mddev->events;
+ err = 0;
+ out:
+@@ -652,9 +652,11 @@ static int bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
+ switch (op) {
+ case MASK_SET:
+ sb->state |= cpu_to_le32(bits);
++ bitmap->flags |= bits;
+ break;
+ case MASK_UNSET:
+ sb->state &= cpu_to_le32(~bits);
++ bitmap->flags &= ~bits;
+ break;
+ default:
+ BUG();
+diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
+index a550a05..aa4e570 100644
+--- a/drivers/md/dm-mpath.c
++++ b/drivers/md/dm-mpath.c
+@@ -1290,7 +1290,7 @@ static int do_end_io(struct multipath *m, struct request *clone,
+ if (!error && !clone->errors)
+ return 0; /* I/O complete */
+
+- if (error == -EOPNOTSUPP || error == -EREMOTEIO)
++ if (error == -EOPNOTSUPP || error == -EREMOTEIO || error == -EILSEQ)
+ return error;
+
+ if (mpio->pgpath)
+diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
+index cb8380c..53e603b 100644
+--- a/drivers/md/dm-table.c
++++ b/drivers/md/dm-table.c
+@@ -362,6 +362,7 @@ static void close_dev(struct dm_dev_internal *d, struct mapped_device *md)
+ static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev,
+ sector_t start, sector_t len, void *data)
+ {
++ struct request_queue *q;
+ struct queue_limits *limits = data;
+ struct block_device *bdev = dev->bdev;
+ sector_t dev_size =
+@@ -370,6 +371,22 @@ static int device_area_is_invalid(struct dm_target *ti, struct dm_dev *dev,
+ limits->logical_block_size >> SECTOR_SHIFT;
+ char b[BDEVNAME_SIZE];
+
++ /*
++ * Some devices exist without request functions,
++ * such as loop devices not yet bound to backing files.
++ * Forbid the use of such devices.
++ */
++ q = bdev_get_queue(bdev);
++ if (!q || !q->make_request_fn) {
++ DMWARN("%s: %s is not yet initialised: "
++ "start=%llu, len=%llu, dev_size=%llu",
++ dm_device_name(ti->table->md), bdevname(bdev, b),
++ (unsigned long long)start,
++ (unsigned long long)len,
++ (unsigned long long)dev_size);
++ return 1;
++ }
++
+ if (!dev_size)
+ return 0;
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 7d6f7f1..a7ed02c 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -2462,7 +2462,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
+ if (rdev->raid_disk == -1)
+ return -EEXIST;
+ /* personality does all needed checks */
+- if (rdev->mddev->pers->hot_add_disk == NULL)
++ if (rdev->mddev->pers->hot_remove_disk == NULL)
+ return -EINVAL;
+ err = rdev->mddev->pers->
+ hot_remove_disk(rdev->mddev, rdev->raid_disk);
+@@ -4347,13 +4347,19 @@ static int md_alloc(dev_t dev, char *name)
+ disk->fops = &md_fops;
+ disk->private_data = mddev;
+ disk->queue = mddev->queue;
++ blk_queue_flush(mddev->queue, REQ_FLUSH | REQ_FUA);
+ /* Allow extended partitions. This makes the
+ * 'mdp' device redundant, but we can't really
+ * remove it now.
+ */
+ disk->flags |= GENHD_FL_EXT_DEVT;
+- add_disk(disk);
+ mddev->gendisk = disk;
++ /* As soon as we call add_disk(), another thread could get
++ * through to md_open, so make sure it doesn't get too far
++ */
++ mutex_lock(&mddev->open_mutex);
++ add_disk(disk);
++
+ error = kobject_init_and_add(&mddev->kobj, &md_ktype,
+ &disk_to_dev(disk)->kobj, "%s", "md");
+ if (error) {
+@@ -4367,8 +4373,7 @@ static int md_alloc(dev_t dev, char *name)
+ if (mddev->kobj.sd &&
+ sysfs_create_group(&mddev->kobj, &md_bitmap_group))
+ printk(KERN_DEBUG "pointless warning\n");
+-
+- blk_queue_flush(mddev->queue, REQ_FLUSH | REQ_FUA);
++ mutex_unlock(&mddev->open_mutex);
+ abort:
+ mutex_unlock(&disks_mutex);
+ if (!error && mddev->kobj.sd) {
+@@ -7057,6 +7062,7 @@ static int remove_and_add_spares(mddev_t *mddev)
+ list_for_each_entry(rdev, &mddev->disks, same_set) {
+ if (rdev->raid_disk >= 0 &&
+ !test_bit(In_sync, &rdev->flags) &&
++ !test_bit(Faulty, &rdev->flags) &&
+ !test_bit(Blocked, &rdev->flags))
+ spares++;
+ if (rdev->raid_disk < 0
+diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
+index 49bf5f8..3d13d11 100644
+--- a/drivers/md/raid5.c
++++ b/drivers/md/raid5.c
+@@ -129,7 +129,7 @@ static inline int raid5_dec_bi_hw_segments(struct bio *bio)
+
+ static inline void raid5_set_bi_hw_segments(struct bio *bio, unsigned int cnt)
+ {
+- bio->bi_phys_segments = raid5_bi_phys_segments(bio) || (cnt << 16);
++ bio->bi_phys_segments = raid5_bi_phys_segments(bio) | (cnt << 16);
+ }
+
+ /* Find first data disk in a raid6 stripe */
+@@ -514,7 +514,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
+ bi = &sh->dev[i].req;
+
+ bi->bi_rw = rw;
+- if (rw == WRITE)
++ if (rw & WRITE)
+ bi->bi_end_io = raid5_end_write_request;
+ else
+ bi->bi_end_io = raid5_end_read_request;
+@@ -548,13 +548,13 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
+ bi->bi_io_vec[0].bv_offset = 0;
+ bi->bi_size = STRIPE_SIZE;
+ bi->bi_next = NULL;
+- if (rw == WRITE &&
++ if ((rw & WRITE) &&
+ test_bit(R5_ReWrite, &sh->dev[i].flags))
+ atomic_add(STRIPE_SECTORS,
+ &rdev->corrected_errors);
+ generic_make_request(bi);
+ } else {
+- if (rw == WRITE)
++ if (rw & WRITE)
+ set_bit(STRIPE_DEGRADED, &sh->state);
+ pr_debug("skip op %ld on disc %d for sector %llu\n",
+ bi->bi_rw, i, (unsigned long long)sh->sector);
+diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
+index af5263c..7b42ace 100644
+--- a/drivers/media/media-devnode.c
++++ b/drivers/media/media-devnode.c
+@@ -213,14 +213,14 @@ int __must_check media_devnode_register(struct media_devnode *mdev)
+
+ /* Part 1: Find a free minor number */
+ mutex_lock(&media_devnode_lock);
+- minor = find_next_zero_bit(media_devnode_nums, 0, MEDIA_NUM_DEVICES);
++ minor = find_next_zero_bit(media_devnode_nums, MEDIA_NUM_DEVICES, 0);
+ if (minor == MEDIA_NUM_DEVICES) {
+ mutex_unlock(&media_devnode_lock);
+ printk(KERN_ERR "could not get a free minor\n");
+ return -ENFILE;
+ }
+
+- set_bit(mdev->minor, media_devnode_nums);
++ set_bit(minor, media_devnode_nums);
+ mutex_unlock(&media_devnode_lock);
+
+ mdev->minor = minor;
+diff --git a/drivers/media/radio/si4713-i2c.c b/drivers/media/radio/si4713-i2c.c
+index deca2e0..c9f4a8e 100644
+--- a/drivers/media/radio/si4713-i2c.c
++++ b/drivers/media/radio/si4713-i2c.c
+@@ -1033,7 +1033,7 @@ static int si4713_write_econtrol_string(struct si4713_device *sdev,
+ char ps_name[MAX_RDS_PS_NAME + 1];
+
+ len = control->size - 1;
+- if (len > MAX_RDS_PS_NAME) {
++ if (len < 0 || len > MAX_RDS_PS_NAME) {
+ rval = -ERANGE;
+ goto exit;
+ }
+@@ -1057,7 +1057,7 @@ static int si4713_write_econtrol_string(struct si4713_device *sdev,
+ char radio_text[MAX_RDS_RADIO_TEXT + 1];
+
+ len = control->size - 1;
+- if (len > MAX_RDS_RADIO_TEXT) {
++ if (len < 0 || len > MAX_RDS_RADIO_TEXT) {
+ rval = -ERANGE;
+ goto exit;
+ }
+diff --git a/drivers/media/rc/ir-raw.c b/drivers/media/rc/ir-raw.c
+index 11c19d8..423ed45 100644
+--- a/drivers/media/rc/ir-raw.c
++++ b/drivers/media/rc/ir-raw.c
+@@ -114,18 +114,20 @@ int ir_raw_event_store_edge(struct rc_dev *dev, enum raw_event_type type)
+ s64 delta; /* ns */
+ DEFINE_IR_RAW_EVENT(ev);
+ int rc = 0;
++ int delay;
+
+ if (!dev->raw)
+ return -EINVAL;
+
+ now = ktime_get();
+ delta = ktime_to_ns(ktime_sub(now, dev->raw->last_event));
++ delay = MS_TO_NS(dev->input_dev->rep[REP_DELAY]);
+
+ /* Check for a long duration since last event or if we're
+ * being called for the first time, note that delta can't
+ * possibly be negative.
+ */
+- if (delta > IR_MAX_DURATION || !dev->raw->last_type)
++ if (delta > delay || !dev->raw->last_type)
+ type |= IR_START_EVENT;
+ else
+ ev.duration = delta;
+diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c
+index 43908a7..c1717bf 100644
+--- a/drivers/media/rc/ite-cir.c
++++ b/drivers/media/rc/ite-cir.c
+@@ -1357,6 +1357,7 @@ static const struct ite_dev_params ite_dev_descs[] = {
+ { /* 0: ITE8704 */
+ .model = "ITE8704 CIR transceiver",
+ .io_region_size = IT87_IOREG_LENGTH,
++ .io_rsrc_no = 0,
+ .hw_tx_capable = true,
+ .sample_period = (u32) (1000000000ULL / 115200),
+ .tx_carrier_freq = 38000,
+@@ -1381,6 +1382,7 @@ static const struct ite_dev_params ite_dev_descs[] = {
+ { /* 1: ITE8713 */
+ .model = "ITE8713 CIR transceiver",
+ .io_region_size = IT87_IOREG_LENGTH,
++ .io_rsrc_no = 0,
+ .hw_tx_capable = true,
+ .sample_period = (u32) (1000000000ULL / 115200),
+ .tx_carrier_freq = 38000,
+@@ -1405,6 +1407,7 @@ static const struct ite_dev_params ite_dev_descs[] = {
+ { /* 2: ITE8708 */
+ .model = "ITE8708 CIR transceiver",
+ .io_region_size = IT8708_IOREG_LENGTH,
++ .io_rsrc_no = 0,
+ .hw_tx_capable = true,
+ .sample_period = (u32) (1000000000ULL / 115200),
+ .tx_carrier_freq = 38000,
+@@ -1430,6 +1433,7 @@ static const struct ite_dev_params ite_dev_descs[] = {
+ { /* 3: ITE8709 */
+ .model = "ITE8709 CIR transceiver",
+ .io_region_size = IT8709_IOREG_LENGTH,
++ .io_rsrc_no = 2,
+ .hw_tx_capable = true,
+ .sample_period = (u32) (1000000000ULL / 115200),
+ .tx_carrier_freq = 38000,
+@@ -1471,6 +1475,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
+ struct rc_dev *rdev = NULL;
+ int ret = -ENOMEM;
+ int model_no;
++ int io_rsrc_no;
+
+ ite_dbg("%s called", __func__);
+
+@@ -1500,10 +1505,11 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
+
+ /* get the description for the device */
+ dev_desc = &ite_dev_descs[model_no];
++ io_rsrc_no = dev_desc->io_rsrc_no;
+
+ /* validate pnp resources */
+- if (!pnp_port_valid(pdev, 0) ||
+- pnp_port_len(pdev, 0) != dev_desc->io_region_size) {
++ if (!pnp_port_valid(pdev, io_rsrc_no) ||
++ pnp_port_len(pdev, io_rsrc_no) != dev_desc->io_region_size) {
+ dev_err(&pdev->dev, "IR PNP Port not valid!\n");
+ goto failure;
+ }
+@@ -1514,7 +1520,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
+ }
+
+ /* store resource values */
+- itdev->cir_addr = pnp_port_start(pdev, 0);
++ itdev->cir_addr = pnp_port_start(pdev, io_rsrc_no);
+ itdev->cir_irq = pnp_irq(pdev, 0);
+
+ /* initialize spinlocks */
+diff --git a/drivers/media/rc/ite-cir.h b/drivers/media/rc/ite-cir.h
+index 16a19f5..aa899a0 100644
+--- a/drivers/media/rc/ite-cir.h
++++ b/drivers/media/rc/ite-cir.h
+@@ -57,6 +57,9 @@ struct ite_dev_params {
+ /* size of the I/O region */
+ int io_region_size;
+
++ /* IR pnp I/O resource number */
++ int io_rsrc_no;
++
+ /* true if the hardware supports transmission */
+ bool hw_tx_capable;
+
+diff --git a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c
+index bb10ffe..8d558ae 100644
+--- a/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c
++++ b/drivers/media/rc/keymaps/rc-pinnacle-pctv-hd.c
+@@ -15,43 +15,39 @@
+ /* Pinnacle PCTV HD 800i mini remote */
+
+ static struct rc_map_table pinnacle_pctv_hd[] = {
+-
+- { 0x0f, KEY_1 },
+- { 0x15, KEY_2 },
+- { 0x10, KEY_3 },
+- { 0x18, KEY_4 },
+- { 0x1b, KEY_5 },
+- { 0x1e, KEY_6 },
+- { 0x11, KEY_7 },
+- { 0x21, KEY_8 },
+- { 0x12, KEY_9 },
+- { 0x27, KEY_0 },
+-
+- { 0x24, KEY_ZOOM },
+- { 0x2a, KEY_SUBTITLE },
+-
+- { 0x00, KEY_MUTE },
+- { 0x01, KEY_ENTER }, /* Pinnacle Logo */
+- { 0x39, KEY_POWER },
+-
+- { 0x03, KEY_VOLUMEUP },
+- { 0x09, KEY_VOLUMEDOWN },
+- { 0x06, KEY_CHANNELUP },
+- { 0x0c, KEY_CHANNELDOWN },
+-
+- { 0x2d, KEY_REWIND },
+- { 0x30, KEY_PLAYPAUSE },
+- { 0x33, KEY_FASTFORWARD },
+- { 0x3c, KEY_STOP },
+- { 0x36, KEY_RECORD },
+- { 0x3f, KEY_EPG }, /* Labeled "?" */
++ /* Key codes for the tiny Pinnacle remote*/
++ { 0x0700, KEY_MUTE },
++ { 0x0701, KEY_MENU }, /* Pinnacle logo */
++ { 0x0739, KEY_POWER },
++ { 0x0703, KEY_VOLUMEUP },
++ { 0x0709, KEY_VOLUMEDOWN },
++ { 0x0706, KEY_CHANNELUP },
++ { 0x070c, KEY_CHANNELDOWN },
++ { 0x070f, KEY_1 },
++ { 0x0715, KEY_2 },
++ { 0x0710, KEY_3 },
++ { 0x0718, KEY_4 },
++ { 0x071b, KEY_5 },
++ { 0x071e, KEY_6 },
++ { 0x0711, KEY_7 },
++ { 0x0721, KEY_8 },
++ { 0x0712, KEY_9 },
++ { 0x0727, KEY_0 },
++ { 0x0724, KEY_ZOOM }, /* 'Square' key */
++ { 0x072a, KEY_SUBTITLE }, /* 'T' key */
++ { 0x072d, KEY_REWIND },
++ { 0x0730, KEY_PLAYPAUSE },
++ { 0x0733, KEY_FASTFORWARD },
++ { 0x0736, KEY_RECORD },
++ { 0x073c, KEY_STOP },
++ { 0x073f, KEY_HELP }, /* '?' key */
+ };
+
+ static struct rc_map_list pinnacle_pctv_hd_map = {
+ .map = {
+ .scan = pinnacle_pctv_hd,
+ .size = ARRAY_SIZE(pinnacle_pctv_hd),
+- .rc_type = RC_TYPE_UNKNOWN, /* Legacy IR type */
++ .rc_type = RC_TYPE_RC5,
+ .name = RC_MAP_PINNACLE_PCTV_HD,
+ }
+ };
+diff --git a/drivers/media/video/bt8xx/bttv-driver.c b/drivers/media/video/bt8xx/bttv-driver.c
+index 91399c9..3ea1a5d 100644
+--- a/drivers/media/video/bt8xx/bttv-driver.c
++++ b/drivers/media/video/bt8xx/bttv-driver.c
+@@ -3474,7 +3474,7 @@ static int radio_s_tuner(struct file *file, void *priv,
+ if (0 != t->index)
+ return -EINVAL;
+
+- bttv_call_all(btv, tuner, g_tuner, t);
++ bttv_call_all(btv, tuner, s_tuner, t);
+ return 0;
+ }
+
+diff --git a/drivers/media/video/cx23885/cx23885-core.c b/drivers/media/video/cx23885/cx23885-core.c
+index 9933810..2a3fab1 100644
+--- a/drivers/media/video/cx23885/cx23885-core.c
++++ b/drivers/media/video/cx23885/cx23885-core.c
+@@ -2060,12 +2060,8 @@ static int __devinit cx23885_initdev(struct pci_dev *pci_dev,
+ goto fail_irq;
+ }
+
+- if (!pci_enable_msi(pci_dev))
+- err = request_irq(pci_dev->irq, cx23885_irq,
+- IRQF_DISABLED, dev->name, dev);
+- else
+- err = request_irq(pci_dev->irq, cx23885_irq,
+- IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
++ err = request_irq(pci_dev->irq, cx23885_irq,
++ IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
+ if (err < 0) {
+ printk(KERN_ERR "%s: can't get IRQ %d\n",
+ dev->name, pci_dev->irq);
+@@ -2114,7 +2110,6 @@ static void __devexit cx23885_finidev(struct pci_dev *pci_dev)
+
+ /* unregister stuff */
+ free_irq(pci_dev->irq, dev);
+- pci_disable_msi(pci_dev);
+
+ cx23885_dev_unregister(dev);
+ v4l2_device_unregister(v4l2_dev);
+diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c
+index bca307e..f637d34 100644
+--- a/drivers/media/video/cx88/cx88-blackbird.c
++++ b/drivers/media/video/cx88/cx88-blackbird.c
+@@ -1122,7 +1122,6 @@ static int mpeg_release(struct file *file)
+ mutex_lock(&dev->core->lock);
+ file->private_data = NULL;
+ kfree(fh);
+- mutex_unlock(&dev->core->lock);
+
+ /* Make sure we release the hardware */
+ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+@@ -1131,6 +1130,8 @@ static int mpeg_release(struct file *file)
+
+ atomic_dec(&dev->core->mpeg_users);
+
++ mutex_unlock(&dev->core->lock);
++
+ return 0;
+ }
+
+@@ -1334,11 +1335,9 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
+ blackbird_register_video(dev);
+
+ /* initial device configuration: needed ? */
+- mutex_lock(&dev->core->lock);
+ // init_controls(core);
+ cx88_set_tvnorm(core,core->tvnorm);
+ cx88_video_mux(core,0);
+- mutex_unlock(&dev->core->lock);
+
+ return 0;
+
+diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c
+index 7b8c9d3..c69df7e 100644
+--- a/drivers/media/video/cx88/cx88-dvb.c
++++ b/drivers/media/video/cx88/cx88-dvb.c
+@@ -133,6 +133,7 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
+ return -EINVAL;
+ }
+
++ mutex_lock(&dev->core->lock);
+ drv = cx8802_get_driver(dev, CX88_MPEG_DVB);
+ if (drv) {
+ if (acquire){
+@@ -143,6 +144,7 @@ static int cx88_dvb_bus_ctrl(struct dvb_frontend* fe, int acquire)
+ dev->frontends.active_fe_id = 0;
+ }
+ }
++ mutex_unlock(&dev->core->lock);
+
+ return ret;
+ }
+diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c
+index addf954..497f26f 100644
+--- a/drivers/media/video/cx88/cx88-mpeg.c
++++ b/drivers/media/video/cx88/cx88-mpeg.c
+@@ -624,13 +624,11 @@ static int cx8802_request_acquire(struct cx8802_driver *drv)
+
+ if (drv->advise_acquire)
+ {
+- mutex_lock(&drv->core->lock);
+ core->active_ref++;
+ if (core->active_type_id == CX88_BOARD_NONE) {
+ core->active_type_id = drv->type_id;
+ drv->advise_acquire(drv);
+ }
+- mutex_unlock(&drv->core->lock);
+
+ mpeg_dbg(1,"%s() Post acquire GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
+ }
+@@ -643,14 +641,12 @@ static int cx8802_request_release(struct cx8802_driver *drv)
+ {
+ struct cx88_core *core = drv->core;
+
+- mutex_lock(&drv->core->lock);
+ if (drv->advise_release && --core->active_ref == 0)
+ {
+ drv->advise_release(drv);
+ core->active_type_id = CX88_BOARD_NONE;
+ mpeg_dbg(1,"%s() Post release GPIO=%x\n", __func__, cx_read(MO_GP0_IO));
+ }
+- mutex_unlock(&drv->core->lock);
+
+ return 0;
+ }
+@@ -713,18 +709,17 @@ int cx8802_register_driver(struct cx8802_driver *drv)
+ drv->request_release = cx8802_request_release;
+ memcpy(driver, drv, sizeof(*driver));
+
++ mutex_lock(&drv->core->lock);
+ err = drv->probe(driver);
+ if (err == 0) {
+ i++;
+- mutex_lock(&drv->core->lock);
+ list_add_tail(&driver->drvlist, &dev->drvlist);
+- mutex_unlock(&drv->core->lock);
+ } else {
+ printk(KERN_ERR
+ "%s/2: cx8802 probe failed, err = %d\n",
+ dev->core->name, err);
+ }
+-
++ mutex_unlock(&drv->core->lock);
+ }
+
+ return i ? 0 : -ENODEV;
+@@ -748,6 +743,8 @@ int cx8802_unregister_driver(struct cx8802_driver *drv)
+ dev->pci->subsystem_device, dev->core->board.name,
+ dev->core->boardnr);
+
++ mutex_lock(&dev->core->lock);
++
+ list_for_each_entry_safe(d, dtmp, &dev->drvlist, drvlist) {
+ /* only unregister the correct driver type */
+ if (d->type_id != drv->type_id)
+@@ -755,15 +752,14 @@ int cx8802_unregister_driver(struct cx8802_driver *drv)
+
+ err = d->remove(d);
+ if (err == 0) {
+- mutex_lock(&drv->core->lock);
+ list_del(&d->drvlist);
+- mutex_unlock(&drv->core->lock);
+ kfree(d);
+ } else
+ printk(KERN_ERR "%s/2: cx8802 driver remove "
+ "failed (%d)\n", dev->core->name, err);
+ }
+
++ mutex_unlock(&dev->core->lock);
+ }
+
+ return err;
+@@ -827,6 +823,8 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev)
+
+ flush_request_modules(dev);
+
++ mutex_lock(&dev->core->lock);
++
+ if (!list_empty(&dev->drvlist)) {
+ struct cx8802_driver *drv, *tmp;
+ int err;
+@@ -838,9 +836,7 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev)
+ list_for_each_entry_safe(drv, tmp, &dev->drvlist, drvlist) {
+ err = drv->remove(drv);
+ if (err == 0) {
+- mutex_lock(&drv->core->lock);
+ list_del(&drv->drvlist);
+- mutex_unlock(&drv->core->lock);
+ } else
+ printk(KERN_ERR "%s/2: cx8802 driver remove "
+ "failed (%d)\n", dev->core->name, err);
+@@ -848,6 +844,8 @@ static void __devexit cx8802_remove(struct pci_dev *pci_dev)
+ }
+ }
+
++ mutex_unlock(&dev->core->lock);
++
+ /* Destroy any 8802 reference. */
+ dev->core->dvbdev = NULL;
+
+diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h
+index 9b3742a..3d32f4a 100644
+--- a/drivers/media/video/cx88/cx88.h
++++ b/drivers/media/video/cx88/cx88.h
+@@ -505,6 +505,8 @@ struct cx8802_driver {
+ int (*suspend)(struct pci_dev *pci_dev, pm_message_t state);
+ int (*resume)(struct pci_dev *pci_dev);
+
++ /* Callers to the following functions must hold core->lock */
++
+ /* MPEG 8802 -> mini driver - Driver probe and configuration */
+ int (*probe)(struct cx8802_driver *drv);
+ int (*remove)(struct cx8802_driver *drv);
+@@ -561,8 +563,9 @@ struct cx8802_dev {
+ /* for switching modulation types */
+ unsigned char ts_gen_cntrl;
+
+- /* List of attached drivers */
++ /* List of attached drivers; must hold core->lock to access */
+ struct list_head drvlist;
++
+ struct work_struct request_module_wk;
+ };
+
+@@ -685,6 +688,8 @@ int cx88_audio_thread(void *data);
+
+ int cx8802_register_driver(struct cx8802_driver *drv);
+ int cx8802_unregister_driver(struct cx8802_driver *drv);
++
++/* Caller must hold core->lock */
+ struct cx8802_driver * cx8802_get_driver(struct cx8802_dev *dev, enum cx88_board_type btype);
+
+ /* ----------------------------------------------------------- */
+diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+index 9d0dd08..e98d382 100644
+--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
++++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+@@ -3046,6 +3046,8 @@ static void pvr2_subdev_update(struct pvr2_hdw *hdw)
+ if (hdw->input_dirty || hdw->audiomode_dirty || hdw->force_dirty) {
+ struct v4l2_tuner vt;
+ memset(&vt, 0, sizeof(vt));
++ vt.type = (hdw->input_val == PVR2_CVAL_INPUT_RADIO) ?
++ V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+ vt.audmode = hdw->audiomode_val;
+ v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, s_tuner, &vt);
+ }
+@@ -5171,6 +5173,8 @@ void pvr2_hdw_status_poll(struct pvr2_hdw *hdw)
+ {
+ struct v4l2_tuner *vtp = &hdw->tuner_signal_info;
+ memset(vtp, 0, sizeof(*vtp));
++ vtp->type = (hdw->input_val == PVR2_CVAL_INPUT_RADIO) ?
++ V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+ hdw->tuner_signal_stale = 0;
+ /* Note: There apparently is no replacement for VIDIOC_CROPCAP
+ using v4l2-subdev - therefore we can't support that AT ALL right
+diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c
+index 9363ed9..1843fc2 100644
+--- a/drivers/media/video/tuner-core.c
++++ b/drivers/media/video/tuner-core.c
+@@ -724,19 +724,15 @@ static inline int check_mode(struct tuner *t, enum v4l2_tuner_type mode)
+ }
+
+ /**
+- * set_mode_freq - Switch tuner to other mode.
+- * @client: struct i2c_client pointer
++ * set_mode - Switch tuner to other mode.
+ * @t: a pointer to the module's internal struct_tuner
+ * @mode: enum v4l2_type (radio or TV)
+- * @freq: frequency to set (0 means to use the previous one)
+ *
+ * If tuner doesn't support the needed mode (radio or TV), prints a
+ * debug message and returns -EINVAL, changing its state to standby.
+- * Otherwise, changes the state and sets frequency to the last value, if
+- * the tuner can sleep or if it supports both Radio and TV.
++ * Otherwise, changes the mode and returns 0.
+ */
+-static int set_mode_freq(struct i2c_client *client, struct tuner *t,
+- enum v4l2_tuner_type mode, unsigned int freq)
++static int set_mode(struct tuner *t, enum v4l2_tuner_type mode)
+ {
+ struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
+
+@@ -752,17 +748,27 @@ static int set_mode_freq(struct i2c_client *client, struct tuner *t,
+ t->mode = mode;
+ tuner_dbg("Changing to mode %d\n", mode);
+ }
++ return 0;
++}
++
++/**
++ * set_freq - Set the tuner to the desired frequency.
++ * @t: a pointer to the module's internal struct_tuner
++ * @freq: frequency to set (0 means to use the current frequency)
++ */
++static void set_freq(struct tuner *t, unsigned int freq)
++{
++ struct i2c_client *client = v4l2_get_subdevdata(&t->sd);
++
+ if (t->mode == V4L2_TUNER_RADIO) {
+- if (freq)
+- t->radio_freq = freq;
+- set_radio_freq(client, t->radio_freq);
++ if (!freq)
++ freq = t->radio_freq;
++ set_radio_freq(client, freq);
+ } else {
+- if (freq)
+- t->tv_freq = freq;
+- set_tv_freq(client, t->tv_freq);
++ if (!freq)
++ freq = t->tv_freq;
++ set_tv_freq(client, freq);
+ }
+-
+- return 0;
+ }
+
+ /*
+@@ -1058,10 +1064,9 @@ static void tuner_status(struct dvb_frontend *fe)
+ static int tuner_s_radio(struct v4l2_subdev *sd)
+ {
+ struct tuner *t = to_tuner(sd);
+- struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+- if (set_mode_freq(client, t, V4L2_TUNER_RADIO, 0) == -EINVAL)
+- return 0;
++ if (set_mode(t, V4L2_TUNER_RADIO) == 0)
++ set_freq(t, 0);
+ return 0;
+ }
+
+@@ -1093,25 +1098,22 @@ static int tuner_s_power(struct v4l2_subdev *sd, int on)
+ static int tuner_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
+ {
+ struct tuner *t = to_tuner(sd);
+- struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+- if (set_mode_freq(client, t, V4L2_TUNER_ANALOG_TV, 0) == -EINVAL)
++ if (set_mode(t, V4L2_TUNER_ANALOG_TV))
+ return 0;
+
+ t->std = std;
+ tuner_fixup_std(t);
+-
++ set_freq(t, 0);
+ return 0;
+ }
+
+ static int tuner_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f)
+ {
+ struct tuner *t = to_tuner(sd);
+- struct i2c_client *client = v4l2_get_subdevdata(sd);
+-
+- if (set_mode_freq(client, t, f->type, f->frequency) == -EINVAL)
+- return 0;
+
++ if (set_mode(t, f->type) == 0)
++ set_freq(t, f->frequency);
+ return 0;
+ }
+
+@@ -1180,13 +1182,13 @@ static int tuner_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+ static int tuner_s_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
+ {
+ struct tuner *t = to_tuner(sd);
+- struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+- if (set_mode_freq(client, t, vt->type, 0) == -EINVAL)
++ if (set_mode(t, vt->type))
+ return 0;
+
+ if (t->mode == V4L2_TUNER_RADIO)
+ t->audmode = vt->audmode;
++ set_freq(t, 0);
+
+ return 0;
+ }
+@@ -1221,7 +1223,8 @@ static int tuner_resume(struct i2c_client *c)
+ tuner_dbg("resume\n");
+
+ if (!t->standby)
+- set_mode_freq(c, t, t->type, 0);
++ if (set_mode(t, t->mode) == 0)
++ set_freq(t, 0);
+
+ return 0;
+ }
+diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
+index f14581b..48c5c57 100644
+--- a/drivers/media/video/uvc/uvc_queue.c
++++ b/drivers/media/video/uvc/uvc_queue.c
+@@ -104,6 +104,8 @@ static int __uvc_free_buffers(struct uvc_video_queue *queue)
+ }
+
+ if (queue->count) {
++ uvc_queue_cancel(queue, 0);
++ INIT_LIST_HEAD(&queue->mainqueue);
+ vfree(queue->mem);
+ queue->count = 0;
+ }
+diff --git a/drivers/media/video/v4l2-ioctl.c b/drivers/media/video/v4l2-ioctl.c
+index 506edcc..a2e442a 100644
+--- a/drivers/media/video/v4l2-ioctl.c
++++ b/drivers/media/video/v4l2-ioctl.c
+@@ -1822,6 +1822,8 @@ static long __video_do_ioctl(struct file *file,
+ if (!ops->vidioc_g_tuner)
+ break;
+
++ p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
++ V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+ ret = ops->vidioc_g_tuner(file, fh, p);
+ if (!ret)
+ dbgarg(cmd, "index=%d, name=%s, type=%d, "
+@@ -1840,6 +1842,8 @@ static long __video_do_ioctl(struct file *file,
+
+ if (!ops->vidioc_s_tuner)
+ break;
++ p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
++ V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+ dbgarg(cmd, "index=%d, name=%s, type=%d, "
+ "capability=0x%x, rangelow=%d, "
+ "rangehigh=%d, signal=%d, afc=%d, "
+@@ -1858,6 +1862,8 @@ static long __video_do_ioctl(struct file *file,
+ if (!ops->vidioc_g_frequency)
+ break;
+
++ p->type = (vfd->vfl_type == VFL_TYPE_RADIO) ?
++ V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
+ ret = ops->vidioc_g_frequency(file, fh, p);
+ if (!ret)
+ dbgarg(cmd, "tuner=%d, type=%d, frequency=%d\n",
+diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
+index 3ab9ffa..55c5d47 100644
+--- a/drivers/mfd/omap-usb-host.c
++++ b/drivers/mfd/omap-usb-host.c
+@@ -994,22 +994,33 @@ static void usbhs_disable(struct device *dev)
+ dev_dbg(dev, "operation timed out\n");
+ }
+
+- if (pdata->ehci_data->phy_reset) {
+- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
+- gpio_free(pdata->ehci_data->reset_gpio_port[0]);
+-
+- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
+- gpio_free(pdata->ehci_data->reset_gpio_port[1]);
++ if (is_omap_usbhs_rev2(omap)) {
++ if (is_ehci_tll_mode(pdata->port_mode[0]))
++ clk_enable(omap->usbtll_p1_fck);
++ if (is_ehci_tll_mode(pdata->port_mode[1]))
++ clk_enable(omap->usbtll_p2_fck);
++ clk_disable(omap->utmi_p2_fck);
++ clk_disable(omap->utmi_p1_fck);
+ }
+
+- clk_disable(omap->utmi_p2_fck);
+- clk_disable(omap->utmi_p1_fck);
+ clk_disable(omap->usbtll_ick);
+ clk_disable(omap->usbtll_fck);
+ clk_disable(omap->usbhost_fs_fck);
+ clk_disable(omap->usbhost_hs_fck);
+ clk_disable(omap->usbhost_ick);
+
++ /* The gpio_free migh sleep; so unlock the spinlock */
++ spin_unlock_irqrestore(&omap->lock, flags);
++
++ if (pdata->ehci_data->phy_reset) {
++ if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
++ gpio_free(pdata->ehci_data->reset_gpio_port[0]);
++
++ if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
++ gpio_free(pdata->ehci_data->reset_gpio_port[1]);
++ }
++ return;
++
+ end_disble:
+ spin_unlock_irqrestore(&omap->lock, flags);
+ }
+diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
+index 81d7fa4..150cd70 100644
+--- a/drivers/misc/lkdtm.c
++++ b/drivers/misc/lkdtm.c
+@@ -120,6 +120,7 @@ static int recur_count = REC_NUM_DEFAULT;
+ static enum cname cpoint = CN_INVALID;
+ static enum ctype cptype = CT_NONE;
+ static int count = DEFAULT_COUNT;
++static DEFINE_SPINLOCK(count_lock);
+
+ module_param(recur_count, int, 0644);
+ MODULE_PARM_DESC(recur_count, " Recursion level for the stack overflow test, "\
+@@ -230,11 +231,14 @@ static const char *cp_name_to_str(enum cname name)
+ static int lkdtm_parse_commandline(void)
+ {
+ int i;
++ unsigned long flags;
+
+ if (cpoint_count < 1 || recur_count < 1)
+ return -EINVAL;
+
++ spin_lock_irqsave(&count_lock, flags);
+ count = cpoint_count;
++ spin_unlock_irqrestore(&count_lock, flags);
+
+ /* No special parameters */
+ if (!cpoint_type && !cpoint_name)
+@@ -349,6 +353,9 @@ static void lkdtm_do_action(enum ctype which)
+
+ static void lkdtm_handler(void)
+ {
++ unsigned long flags;
++
++ spin_lock_irqsave(&count_lock, flags);
+ count--;
+ printk(KERN_INFO "lkdtm: Crash point %s of type %s hit, trigger in %d rounds\n",
+ cp_name_to_str(cpoint), cp_type_to_str(cptype), count);
+@@ -357,6 +364,7 @@ static void lkdtm_handler(void)
+ lkdtm_do_action(cptype);
+ count = cpoint_count;
+ }
++ spin_unlock_irqrestore(&count_lock, flags);
+ }
+
+ static int lkdtm_register_cpoint(enum cname which)
+diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
+index a19967d..ba31abe 100644
+--- a/drivers/mmc/host/sdhci-esdhc-imx.c
++++ b/drivers/mmc/host/sdhci-esdhc-imx.c
+@@ -74,7 +74,7 @@ static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
+ if (boarddata && gpio_is_valid(boarddata->cd_gpio)
+ && gpio_get_value(boarddata->cd_gpio))
+ /* no card, if a valid gpio says so... */
+- val &= SDHCI_CARD_PRESENT;
++ val &= ~SDHCI_CARD_PRESENT;
+ else
+ /* ... in all other cases assume card is present */
+ val |= SDHCI_CARD_PRESENT;
+diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
+index 710339a..b98196c 100644
+--- a/drivers/mmc/host/tmio_mmc_pio.c
++++ b/drivers/mmc/host/tmio_mmc_pio.c
+@@ -760,8 +760,8 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc)
+ struct tmio_mmc_host *host = mmc_priv(mmc);
+ struct tmio_mmc_data *pdata = host->pdata;
+
+- return ((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) ||
+- !(sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT));
++ return !((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) ||
++ (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT));
+ }
+
+ static int tmio_mmc_get_cd(struct mmc_host *mmc)
+diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
+index 5060e60..e601672 100644
+--- a/drivers/mtd/mtdconcat.c
++++ b/drivers/mtd/mtdconcat.c
+@@ -319,7 +319,7 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
+ if (!(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+
+- ops->retlen = 0;
++ ops->retlen = ops->oobretlen = 0;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+@@ -334,7 +334,7 @@ concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
+ devops.len = subdev->size - to;
+
+ err = subdev->write_oob(subdev, to, &devops);
+- ops->retlen += devops.retlen;
++ ops->retlen += devops.oobretlen;
+ if (err)
+ return err;
+
+diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
+index c54a4cb..d1345fc 100644
+--- a/drivers/mtd/nand/nand_base.c
++++ b/drivers/mtd/nand/nand_base.c
+@@ -3112,6 +3112,8 @@ ident_done:
+ chip->chip_shift += 32 - 1;
+ }
+
++ chip->badblockbits = 8;
++
+ /* Set the bad block position */
+ if (mtd->writesize > 512 || (busw & NAND_BUSWIDTH_16))
+ chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
+diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
+index da9a351..2c8040f 100644
+--- a/drivers/mtd/nand/omap2.c
++++ b/drivers/mtd/nand/omap2.c
+@@ -263,11 +263,10 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
+ if (ret) {
+ /* PFPW engine is busy, use cpu copy method */
+ if (info->nand.options & NAND_BUSWIDTH_16)
+- omap_read_buf16(mtd, buf, len);
++ omap_read_buf16(mtd, (u_char *)p, len);
+ else
+- omap_read_buf8(mtd, buf, len);
++ omap_read_buf8(mtd, (u_char *)p, len);
+ } else {
+- p = (u32 *) buf;
+ do {
+ r_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+ r_count = r_count >> 2;
+@@ -293,7 +292,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
+ struct omap_nand_info, mtd);
+ uint32_t w_count = 0;
+ int i = 0, ret = 0;
+- u16 *p;
++ u16 *p = (u16 *)buf;
+ unsigned long tim, limit;
+
+ /* take care of subpage writes */
+@@ -309,11 +308,10 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
+ if (ret) {
+ /* PFPW engine is busy, use cpu copy method */
+ if (info->nand.options & NAND_BUSWIDTH_16)
+- omap_write_buf16(mtd, buf, len);
++ omap_write_buf16(mtd, (u_char *)p, len);
+ else
+- omap_write_buf8(mtd, buf, len);
++ omap_write_buf8(mtd, (u_char *)p, len);
+ } else {
+- p = (u16 *) buf;
+ while (len) {
+ w_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+ w_count = w_count >> 1;
+diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
+index ba71582..a20bfef 100644
+--- a/drivers/net/bonding/bond_alb.c
++++ b/drivers/net/bonding/bond_alb.c
+@@ -163,8 +163,6 @@ static int tlb_initialize(struct bonding *bond)
+ struct tlb_client_info *new_hashtbl;
+ int i;
+
+- spin_lock_init(&(bond_info->tx_hashtbl_lock));
+-
+ new_hashtbl = kzalloc(size, GFP_KERNEL);
+ if (!new_hashtbl) {
+ pr_err("%s: Error: Failed to allocate TLB hash table\n",
+@@ -764,8 +762,6 @@ static int rlb_initialize(struct bonding *bond)
+ int size = RLB_HASH_TABLE_SIZE * sizeof(struct rlb_client_info);
+ int i;
+
+- spin_lock_init(&(bond_info->rx_hashtbl_lock));
+-
+ new_hashtbl = kmalloc(size, GFP_KERNEL);
+ if (!new_hashtbl) {
+ pr_err("%s: Error: Failed to allocate RLB hash table\n",
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 16d6fe9..ffb0fde 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -1535,12 +1535,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
+ bond_dev->name, slave_dev->name);
+ }
+
+- /* bond must be initialized by bond_open() before enslaving */
+- if (!(bond_dev->flags & IFF_UP)) {
+- pr_warning("%s: master_dev is not up in bond_enslave\n",
+- bond_dev->name);
+- }
+-
+ /* already enslaved */
+ if (slave_dev->flags & IFF_SLAVE) {
+ pr_debug("Error, Device was already enslaved\n");
+@@ -4975,9 +4969,19 @@ static int bond_init(struct net_device *bond_dev)
+ {
+ struct bonding *bond = netdev_priv(bond_dev);
+ struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
++ struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond));
+
+ pr_debug("Begin bond_init for %s\n", bond_dev->name);
+
++ /*
++ * Initialize locks that may be required during
++ * en/deslave operations. All of the bond_open work
++ * (of which this is part) should really be moved to
++ * a phase prior to dev_open
++ */
++ spin_lock_init(&(bond_info->tx_hashtbl_lock));
++ spin_lock_init(&(bond_info->rx_hashtbl_lock));
++
+ bond->wq = create_singlethread_workqueue(bond_dev->name);
+ if (!bond->wq)
+ return -ENOMEM;
+diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
+index de87aea..8a2717e 100644
+--- a/drivers/net/bonding/bond_sysfs.c
++++ b/drivers/net/bonding/bond_sysfs.c
+@@ -227,12 +227,6 @@ static ssize_t bonding_store_slaves(struct device *d,
+ struct net_device *dev;
+ struct bonding *bond = to_bond(d);
+
+- /* Quick sanity check -- is the bond interface up? */
+- if (!(bond->dev->flags & IFF_UP)) {
+- pr_warning("%s: doing slave updates when interface is down.\n",
+- bond->dev->name);
+- }
+-
+ if (!rtnl_trylock())
+ return restart_syscall();
+
+diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c
+index 3e5d0b6..0d28378 100644
+--- a/drivers/net/hamradio/6pack.c
++++ b/drivers/net/hamradio/6pack.c
+@@ -692,10 +692,10 @@ static void sixpack_close(struct tty_struct *tty)
+ {
+ struct sixpack *sp;
+
+- write_lock(&disc_data_lock);
++ write_lock_bh(&disc_data_lock);
+ sp = tty->disc_data;
+ tty->disc_data = NULL;
+- write_unlock(&disc_data_lock);
++ write_unlock_bh(&disc_data_lock);
+ if (!sp)
+ return;
+
+diff --git a/drivers/net/hamradio/mkiss.c b/drivers/net/hamradio/mkiss.c
+index 4c62839..bc02968 100644
+--- a/drivers/net/hamradio/mkiss.c
++++ b/drivers/net/hamradio/mkiss.c
+@@ -813,10 +813,10 @@ static void mkiss_close(struct tty_struct *tty)
+ {
+ struct mkiss *ax;
+
+- write_lock(&disc_data_lock);
++ write_lock_bh(&disc_data_lock);
+ ax = tty->disc_data;
+ tty->disc_data = NULL;
+- write_unlock(&disc_data_lock);
++ write_unlock_bh(&disc_data_lock);
+
+ if (!ax)
+ return;
+diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
+index 0dfd1b9..0e3fccb 100644
+--- a/drivers/net/igb/igb_main.c
++++ b/drivers/net/igb/igb_main.c
+@@ -2372,6 +2372,9 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
+ }
+ #endif /* CONFIG_PCI_IOV */
+ adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus());
++ /* i350 cannot do RSS and SR-IOV at the same time */
++ if (hw->mac.type == e1000_i350 && adapter->vfs_allocated_count)
++ adapter->rss_queues = 1;
+
+ /*
+ * if rss_queues > 4 or vfs are going to be allocated with rss_queues
+diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
+index 78e34e9..6d357d6 100644
+--- a/drivers/net/macvlan.c
++++ b/drivers/net/macvlan.c
+@@ -598,8 +598,8 @@ static int macvlan_port_create(struct net_device *dev)
+ err = netdev_rx_handler_register(dev, macvlan_handle_frame, port);
+ if (err)
+ kfree(port);
+-
+- dev->priv_flags |= IFF_MACVLAN_PORT;
++ else
++ dev->priv_flags |= IFF_MACVLAN_PORT;
+ return err;
+ }
+
+diff --git a/drivers/net/pxa168_eth.c b/drivers/net/pxa168_eth.c
+index 89f7540..5f597ca 100644
+--- a/drivers/net/pxa168_eth.c
++++ b/drivers/net/pxa168_eth.c
+@@ -1273,7 +1273,7 @@ static int pxa168_eth_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ wmb();
+ wrl(pep, SDMA_CMD, SDMA_CMD_TXDH | SDMA_CMD_ERD);
+
+- stats->tx_bytes += skb->len;
++ stats->tx_bytes += length;
+ stats->tx_packets++;
+ dev->trans_start = jiffies;
+ if (pep->tx_ring_size - pep->tx_desc_count <= 1) {
+diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
+index 1033ef6..f2b974d 100644
+--- a/drivers/net/usb/cdc_ncm.c
++++ b/drivers/net/usb/cdc_ncm.c
+@@ -1254,6 +1254,7 @@ static struct usb_driver cdc_ncm_driver = {
+ .disconnect = cdc_ncm_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
++ .reset_resume = usbnet_resume,
+ .supports_autosuspend = 1,
+ };
+
+diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
+index 349a596..76d5089 100644
+--- a/drivers/net/wireless/ath/ath5k/base.c
++++ b/drivers/net/wireless/ath/ath5k/base.c
+@@ -72,6 +72,11 @@ static int modparam_all_channels;
+ module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO);
+ MODULE_PARM_DESC(all_channels, "Expose all channels the device can use.");
+
++static int modparam_fastchanswitch;
++module_param_named(fastchanswitch, modparam_fastchanswitch, bool, S_IRUGO);
++MODULE_PARM_DESC(fastchanswitch, "Enable fast channel switching for AR2413/AR5413 radios.");
++
++
+ /* Module info */
+ MODULE_AUTHOR("Jiri Slaby");
+ MODULE_AUTHOR("Nick Kossifidis");
+@@ -2644,6 +2649,7 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
+ struct ath5k_hw *ah = sc->ah;
+ struct ath_common *common = ath5k_hw_common(ah);
+ int ret, ani_mode;
++ bool fast;
+
+ ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n");
+
+@@ -2663,7 +2669,10 @@ ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan,
+ ath5k_drain_tx_buffs(sc);
+ if (chan)
+ sc->curchan = chan;
+- ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL,
++
++ fast = ((chan != NULL) && modparam_fastchanswitch) ? 1 : 0;
++
++ ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, fast,
+ skip_pcu);
+ if (ret) {
+ ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret);
+diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
+index efb672c..a33ae01 100644
+--- a/drivers/net/wireless/ath/ath5k/eeprom.c
++++ b/drivers/net/wireless/ath/ath5k/eeprom.c
+@@ -1565,14 +1565,12 @@ ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
+ if (!chinfo[pier].pd_curves)
+ continue;
+
+- for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
++ for (pdg = 0; pdg < AR5K_EEPROM_N_PD_CURVES; pdg++) {
+ struct ath5k_pdgain_info *pd =
+ &chinfo[pier].pd_curves[pdg];
+
+- if (pd != NULL) {
+- kfree(pd->pd_step);
+- kfree(pd->pd_pwr);
+- }
++ kfree(pd->pd_step);
++ kfree(pd->pd_pwr);
+ }
+
+ kfree(chinfo[pier].pd_curves);
+diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
+index 3c44689..2e251f6 100644
+--- a/drivers/net/wireless/ath/ath5k/pci.c
++++ b/drivers/net/wireless/ath/ath5k/pci.c
+@@ -265,7 +265,9 @@ ath5k_pci_remove(struct pci_dev *pdev)
+ #ifdef CONFIG_PM_SLEEP
+ static int ath5k_pci_suspend(struct device *dev)
+ {
+- struct ath5k_softc *sc = pci_get_drvdata(to_pci_dev(dev));
++ struct pci_dev *pdev = to_pci_dev(dev);
++ struct ieee80211_hw *hw = pci_get_drvdata(pdev);
++ struct ath5k_softc *sc = hw->priv;
+
+ ath5k_led_off(sc);
+ return 0;
+@@ -274,7 +276,8 @@ static int ath5k_pci_suspend(struct device *dev)
+ static int ath5k_pci_resume(struct device *dev)
+ {
+ struct pci_dev *pdev = to_pci_dev(dev);
+- struct ath5k_softc *sc = pci_get_drvdata(pdev);
++ struct ieee80211_hw *hw = pci_get_drvdata(pdev);
++ struct ath5k_softc *sc = hw->priv;
+
+ /*
+ * Suspend/Resume resets the PCI configuration space, so we have to
+diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
+index 8420689..6f53d2b 100644
+--- a/drivers/net/wireless/ath/ath5k/reset.c
++++ b/drivers/net/wireless/ath/ath5k/reset.c
+@@ -1119,8 +1119,11 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
+ /* Non fatal, can happen eg.
+ * on mode change */
+ ret = 0;
+- } else
++ } else {
++ ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_RESET,
++ "fast chan change successful\n");
+ return 0;
++ }
+ }
+
+ /*
+diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c
+index 929c68c..a073cdc 100644
+--- a/drivers/net/wireless/ath/ath5k/sysfs.c
++++ b/drivers/net/wireless/ath/ath5k/sysfs.c
+@@ -10,7 +10,8 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+ { \
+- struct ath5k_softc *sc = dev_get_drvdata(dev); \
++ struct ieee80211_hw *hw = dev_get_drvdata(dev); \
++ struct ath5k_softc *sc = hw->priv; \
+ return snprintf(buf, PAGE_SIZE, "%d\n", get); \
+ } \
+ \
+@@ -18,7 +19,8 @@ static ssize_t ath5k_attr_store_##name(struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, size_t count) \
+ { \
+- struct ath5k_softc *sc = dev_get_drvdata(dev); \
++ struct ieee80211_hw *hw = dev_get_drvdata(dev); \
++ struct ath5k_softc *sc = hw->priv; \
+ int val; \
+ \
+ val = (int)simple_strtoul(buf, NULL, 10); \
+@@ -33,7 +35,8 @@ static ssize_t ath5k_attr_show_##name(struct device *dev, \
+ struct device_attribute *attr, \
+ char *buf) \
+ { \
+- struct ath5k_softc *sc = dev_get_drvdata(dev); \
++ struct ieee80211_hw *hw = dev_get_drvdata(dev); \
++ struct ath5k_softc *sc = hw->priv; \
+ return snprintf(buf, PAGE_SIZE, "%d\n", get); \
+ } \
+ static DEVICE_ATTR(name, S_IRUGO, ath5k_attr_show_##name, NULL)
+diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+index 6eadf97..db4416c 100644
+--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+@@ -652,7 +652,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
+ .regDmn = { LE16(0), LE16(0x1f) },
+ .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */
+ .opCapFlags = {
+- .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A,
++ .opFlags = AR5416_OPFLAGS_11A,
+ .eepMisc = 0,
+ },
+ .rfSilent = 0,
+@@ -922,7 +922,7 @@ static const struct ar9300_eeprom ar9300_x113 = {
+ .db_stage2 = {3, 3, 3}, /* 3 chain */
+ .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */
+ .db_stage4 = {3, 3, 3}, /* don't exist for 2G */
+- .xpaBiasLvl = 0,
++ .xpaBiasLvl = 0xf,
+ .txFrameToDataStart = 0x0e,
+ .txFrameToPaOn = 0x0e,
+ .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */
+@@ -3994,6 +3994,16 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
+ POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)
+ );
+
++ /* Write the power for duplicated frames - HT40 */
++
++ /* dup40_cck (LSB), dup40_ofdm, ext20_cck, ext20_ofdm (MSB) */
++ REG_WRITE(ah, 0xa3e0,
++ POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
++ POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
++ POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
++ POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0)
++ );
++
+ /* Write the HT20 power per rate set */
+
+ /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
+@@ -4588,10 +4598,16 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
+ case 1:
+ break;
+ case 2:
+- scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
++ if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
++ scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
++ else
++ scaledPower = 0;
+ break;
+ case 3:
+- scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
++ if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
++ scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
++ else
++ scaledPower = 0;
+ break;
+ }
+
+diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
+index 8649581..fe3c10e 100644
+--- a/drivers/net/wireless/ath/ath9k/calib.c
++++ b/drivers/net/wireless/ath/ath9k/calib.c
+@@ -69,15 +69,21 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
+ int16_t *nfarray)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
++ struct ieee80211_conf *conf = &common->hw->conf;
+ struct ath_nf_limits *limit;
+ struct ath9k_nfcal_hist *h;
+ bool high_nf_mid = false;
++ u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+ int i;
+
+ h = cal->nfCalHist;
+ limit = ath9k_hw_get_nf_limits(ah, ah->curchan);
+
+ for (i = 0; i < NUM_NF_READINGS; i++) {
++ if (!(chainmask & (1 << i)) ||
++ ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
++ continue;
++
+ h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
+
+ if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
+@@ -225,6 +231,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
+ int32_t val;
+ u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
+ struct ath_common *common = ath9k_hw_common(ah);
++ struct ieee80211_conf *conf = &common->hw->conf;
+ s16 default_nf = ath9k_hw_get_default_nf(ah, chan);
+
+ if (ah->caldata)
+@@ -234,6 +241,9 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
+ if (chainmask & (1 << i)) {
+ s16 nfval;
+
++ if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))
++ continue;
++
+ if (h)
+ nfval = h[i].privNF;
+ else
+@@ -293,6 +303,9 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
+ ENABLE_REGWRITE_BUFFER(ah);
+ for (i = 0; i < NUM_NF_READINGS; i++) {
+ if (chainmask & (1 << i)) {
++ if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))
++ continue;
++
+ val = REG_READ(ah, ah->nf_regs[i]);
+ val &= 0xFFFFFE00;
+ val |= (((u32) (-50) << 1) & 0x1ff);
+diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+index 8cd8333..945e448 100644
+--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
++++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+@@ -522,10 +522,16 @@ static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
+ case 1:
+ break;
+ case 2:
+- scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
++ if (scaledPower > REDUCE_SCALED_POWER_BY_TWO_CHAIN)
++ scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN;
++ else
++ scaledPower = 0;
+ break;
+ case 3:
+- scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
++ if (scaledPower > REDUCE_SCALED_POWER_BY_THREE_CHAIN)
++ scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN;
++ else
++ scaledPower = 0;
+ break;
+ }
+ scaledPower = max((u16)0, scaledPower);
+diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
+index 1482fa6..846bb4f 100644
+--- a/drivers/net/wireless/ath/ath9k/main.c
++++ b/drivers/net/wireless/ath/ath9k/main.c
+@@ -633,7 +633,8 @@ void ath9k_tasklet(unsigned long data)
+ u32 status = sc->intrstatus;
+ u32 rxmask;
+
+- if (status & ATH9K_INT_FATAL) {
++ if ((status & ATH9K_INT_FATAL) ||
++ (status & ATH9K_INT_BB_WATCHDOG)) {
+ ath_reset(sc, true);
+ return;
+ }
+@@ -699,6 +700,7 @@ irqreturn_t ath_isr(int irq, void *dev)
+ {
+ #define SCHED_INTR ( \
+ ATH9K_INT_FATAL | \
++ ATH9K_INT_BB_WATCHDOG | \
+ ATH9K_INT_RXORN | \
+ ATH9K_INT_RXEOL | \
+ ATH9K_INT_RX | \
+diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
+index 9c65459..e137212 100644
+--- a/drivers/net/wireless/ath/ath9k/pci.c
++++ b/drivers/net/wireless/ath/ath9k/pci.c
+@@ -278,6 +278,12 @@ static int ath_pci_suspend(struct device *device)
+
+ ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
+
++ /* The device has to be moved to FULLSLEEP forcibly.
++ * Otherwise the chip never moved to full sleep,
++ * when no interface is up.
++ */
++ ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
++
+ return 0;
+ }
+
+diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
+index 4c0d36a..a39dfc4 100644
+--- a/drivers/net/wireless/ath/ath9k/rc.c
++++ b/drivers/net/wireless/ath/ath9k/rc.c
+@@ -689,7 +689,8 @@ static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table,
+
+ if (WLAN_RC_PHY_HT(rate_table->info[rix].phy)) {
+ rate->flags |= IEEE80211_TX_RC_MCS;
+- if (WLAN_RC_PHY_40(rate_table->info[rix].phy))
++ if (WLAN_RC_PHY_40(rate_table->info[rix].phy) &&
++ conf_is_ht40(&txrc->hw->conf))
+ rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+ if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy))
+ rate->flags |= IEEE80211_TX_RC_SHORT_GI;
+diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
+index 88fa7fd..4f2c8df 100644
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -662,7 +662,8 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
+ * TODO - this could be improved to be dependent on the rate.
+ * The hardware can keep up at lower rates, but not higher rates
+ */
+- if (fi->keyix != ATH9K_TXKEYIX_INVALID)
++ if ((fi->keyix != ATH9K_TXKEYIX_INVALID) &&
++ !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))
+ ndelim += ATH_AGGR_ENCRYPTDELIM;
+
+ /*
+diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
+index 2fb53d0..333b69e 100644
+--- a/drivers/net/wireless/ath/carl9170/usb.c
++++ b/drivers/net/wireless/ath/carl9170/usb.c
+@@ -112,6 +112,8 @@ static struct usb_device_id carl9170_usb_ids[] = {
+ { USB_DEVICE(0x04bb, 0x093f) },
+ /* NEC WL300NU-G */
+ { USB_DEVICE(0x0409, 0x0249) },
++ /* NEC WL300NU-AG */
++ { USB_DEVICE(0x0409, 0x02b4) },
+ /* AVM FRITZ!WLAN USB Stick N */
+ { USB_DEVICE(0x057c, 0x8401) },
+ /* AVM FRITZ!WLAN USB Stick N 2.4 */
+diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
+index 5a8a3cc..455f1f7 100644
+--- a/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
++++ b/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
+@@ -628,11 +628,11 @@ void iwl4965_rx_reply_rx(struct iwl_priv *priv,
+
+ /* rx_status carries information about the packet to mac80211 */
+ rx_status.mactime = le64_to_cpu(phy_res->timestamp);
++ rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
++ IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+ rx_status.freq =
+ ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel),
+ rx_status.band);
+- rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
+- IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+ rx_status.rate_idx =
+ iwl4965_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
+ rx_status.flag = 0;
+diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c
+index f5433c7..facc94e 100644
+--- a/drivers/net/wireless/iwlegacy/iwl-4965.c
++++ b/drivers/net/wireless/iwlegacy/iwl-4965.c
+@@ -1218,10 +1218,10 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c
+ * receive commit_rxon request
+ * abort any previous channel switch if still in process
+ */
+- if (priv->switch_rxon.switch_in_progress &&
+- (priv->switch_rxon.channel != ctx->staging.channel)) {
++ if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) &&
++ (priv->switch_channel != ctx->staging.channel)) {
+ IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
+- le16_to_cpu(priv->switch_rxon.channel));
++ le16_to_cpu(priv->switch_channel));
+ iwl_legacy_chswitch_done(priv, false);
+ }
+
+@@ -1237,7 +1237,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c
+
+ memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+ iwl_legacy_print_rx_config_cmd(priv, ctx);
+- return 0;
++ goto set_tx_power;
+ }
+
+ /* If we are currently associated and the new config requires
+@@ -1317,6 +1317,7 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *c
+
+ iwl4965_init_sensitivity(priv);
+
++set_tx_power:
+ /* If we issue a new RXON command which required a tune then we must
+ * send a new TXPOWER command or we won't be able to Tx any frames */
+ ret = iwl_legacy_set_tx_power(priv, priv->tx_power_next, true);
+@@ -1403,9 +1404,6 @@ static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
+ return rc;
+ }
+
+- priv->switch_rxon.channel = cmd.channel;
+- priv->switch_rxon.switch_in_progress = true;
+-
+ return iwl_legacy_send_cmd_pdu(priv,
+ REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
+ }
+@@ -1543,7 +1541,7 @@ static void iwl4965_temperature_calib(struct iwl_priv *priv)
+ s32 temp;
+
+ temp = iwl4965_hw_get_temperature(priv);
+- if (temp < 0)
++ if (IWL_TX_POWER_TEMPERATURE_OUT_OF_RANGE(temp))
+ return;
+
+ if (priv->temperature != temp) {
+diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c
+index 42db0fc..8ad7922 100644
+--- a/drivers/net/wireless/iwlegacy/iwl-core.c
++++ b/drivers/net/wireless/iwlegacy/iwl-core.c
+@@ -862,12 +862,8 @@ void iwl_legacy_chswitch_done(struct iwl_priv *priv, bool is_success)
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+- if (priv->switch_rxon.switch_in_progress) {
++ if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+ ieee80211_chswitch_done(ctx->vif, is_success);
+- mutex_lock(&priv->mutex);
+- priv->switch_rxon.switch_in_progress = false;
+- mutex_unlock(&priv->mutex);
+- }
+ }
+ EXPORT_SYMBOL(iwl_legacy_chswitch_done);
+
+@@ -879,19 +875,19 @@ void iwl_legacy_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+ struct iwl_legacy_rxon_cmd *rxon = (void *)&ctx->active;
+
+- if (priv->switch_rxon.switch_in_progress) {
+- if (!le32_to_cpu(csa->status) &&
+- (csa->channel == priv->switch_rxon.channel)) {
+- rxon->channel = csa->channel;
+- ctx->staging.channel = csa->channel;
+- IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
+- le16_to_cpu(csa->channel));
+- iwl_legacy_chswitch_done(priv, true);
+- } else {
+- IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
++ if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
++ return;
++
++ if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) {
++ rxon->channel = csa->channel;
++ ctx->staging.channel = csa->channel;
++ IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
+ le16_to_cpu(csa->channel));
+- iwl_legacy_chswitch_done(priv, false);
+- }
++ iwl_legacy_chswitch_done(priv, true);
++ } else {
++ IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
++ le16_to_cpu(csa->channel));
++ iwl_legacy_chswitch_done(priv, false);
+ }
+ }
+ EXPORT_SYMBOL(iwl_legacy_rx_csa);
+diff --git a/drivers/net/wireless/iwlegacy/iwl-core.h b/drivers/net/wireless/iwlegacy/iwl-core.h
+index f03b463..e49176a 100644
+--- a/drivers/net/wireless/iwlegacy/iwl-core.h
++++ b/drivers/net/wireless/iwlegacy/iwl-core.h
+@@ -561,7 +561,7 @@ void iwl_legacy_free_geos(struct iwl_priv *priv);
+ #define STATUS_SCAN_HW 15
+ #define STATUS_POWER_PMI 16
+ #define STATUS_FW_ERROR 17
+-
++#define STATUS_CHANNEL_SWITCH_PENDING 18
+
+ static inline int iwl_legacy_is_ready(struct iwl_priv *priv)
+ {
+diff --git a/drivers/net/wireless/iwlegacy/iwl-dev.h b/drivers/net/wireless/iwlegacy/iwl-dev.h
+index f43ac1e..54f89b4 100644
+--- a/drivers/net/wireless/iwlegacy/iwl-dev.h
++++ b/drivers/net/wireless/iwlegacy/iwl-dev.h
+@@ -854,17 +854,6 @@ struct traffic_stats {
+ };
+
+ /*
+- * iwl_switch_rxon: "channel switch" structure
+- *
+- * @ switch_in_progress: channel switch in progress
+- * @ channel: new channel
+- */
+-struct iwl_switch_rxon {
+- bool switch_in_progress;
+- __le16 channel;
+-};
+-
+-/*
+ * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds
+ * to perform continuous uCode event logging operation if enabled
+ */
+@@ -1115,7 +1104,7 @@ struct iwl_priv {
+
+ struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX];
+
+- struct iwl_switch_rxon switch_rxon;
++ __le16 switch_channel;
+
+ /* 1st responses from initialize and runtime uCode images.
+ * _4965's initialize alive response contains some calibration data. */
+diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c
+index a62fe24..d654876 100644
+--- a/drivers/net/wireless/iwlegacy/iwl4965-base.c
++++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c
+@@ -2851,16 +2851,13 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
+ goto out_exit;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+- test_bit(STATUS_SCANNING, &priv->status))
++ test_bit(STATUS_SCANNING, &priv->status) ||
++ test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+ goto out_exit;
+
+ if (!iwl_legacy_is_associated_ctx(ctx))
+ goto out_exit;
+
+- /* channel switch in progress */
+- if (priv->switch_rxon.switch_in_progress == true)
+- goto out_exit;
+-
+ mutex_lock(&priv->mutex);
+ if (priv->cfg->ops->lib->set_channel_switch) {
+
+@@ -2910,16 +2907,20 @@ void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
+ * at this point, staging_rxon has the
+ * configuration for channel switch
+ */
++ set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
++ priv->switch_channel = cpu_to_le16(ch);
+ if (priv->cfg->ops->lib->set_channel_switch(priv,
+- ch_switch))
+- priv->switch_rxon.switch_in_progress = false;
++ ch_switch)) {
++ clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
++ &priv->status);
++ priv->switch_channel = 0;
++ ieee80211_chswitch_done(ctx->vif, false);
++ }
+ }
+ }
+ out:
+ mutex_unlock(&priv->mutex);
+ out_exit:
+- if (!priv->switch_rxon.switch_in_progress)
+- ieee80211_chswitch_done(ctx->vif, false);
+ IWL_DEBUG_MAC80211(priv, "leave\n");
+ }
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c
+index d7b6126..d474cf3 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-2000.c
++++ b/drivers/net/wireless/iwlwifi/iwl-2000.c
+@@ -181,79 +181,6 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
+ return 0;
+ }
+
+-static int iwl2030_hw_channel_switch(struct iwl_priv *priv,
+- struct ieee80211_channel_switch *ch_switch)
+-{
+- /*
+- * MULTI-FIXME
+- * See iwl_mac_channel_switch.
+- */
+- struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+- struct iwl6000_channel_switch_cmd cmd;
+- const struct iwl_channel_info *ch_info;
+- u32 switch_time_in_usec, ucode_switch_time;
+- u16 ch;
+- u32 tsf_low;
+- u8 switch_count;
+- u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
+- struct ieee80211_vif *vif = ctx->vif;
+- struct iwl_host_cmd hcmd = {
+- .id = REPLY_CHANNEL_SWITCH,
+- .len = sizeof(cmd),
+- .flags = CMD_SYNC,
+- .data = &cmd,
+- };
+-
+- cmd.band = priv->band == IEEE80211_BAND_2GHZ;
+- ch = ch_switch->channel->hw_value;
+- IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
+- ctx->active.channel, ch);
+- cmd.channel = cpu_to_le16(ch);
+- cmd.rxon_flags = ctx->staging.flags;
+- cmd.rxon_filter_flags = ctx->staging.filter_flags;
+- switch_count = ch_switch->count;
+- tsf_low = ch_switch->timestamp & 0x0ffffffff;
+- /*
+- * calculate the ucode channel switch time
+- * adding TSF as one of the factor for when to switch
+- */
+- if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
+- if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
+- beacon_interval)) {
+- switch_count -= (priv->ucode_beacon_time -
+- tsf_low) / beacon_interval;
+- } else
+- switch_count = 0;
+- }
+- if (switch_count <= 1)
+- cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
+- else {
+- switch_time_in_usec =
+- vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
+- ucode_switch_time = iwl_usecs_to_beacons(priv,
+- switch_time_in_usec,
+- beacon_interval);
+- cmd.switch_time = iwl_add_beacon_time(priv,
+- priv->ucode_beacon_time,
+- ucode_switch_time,
+- beacon_interval);
+- }
+- IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
+- cmd.switch_time);
+- ch_info = iwl_get_channel_info(priv, priv->band, ch);
+- if (ch_info)
+- cmd.expect_beacon = is_channel_radar(ch_info);
+- else {
+- IWL_ERR(priv, "invalid channel switch from %u to %u\n",
+- ctx->active.channel, ch);
+- return -EFAULT;
+- }
+- priv->switch_rxon.channel = cmd.channel;
+- priv->switch_rxon.switch_in_progress = true;
+-
+- return iwl_send_cmd_sync(priv, &hcmd);
+-}
+-
+ static struct iwl_lib_ops iwl2000_lib = {
+ .set_hw_params = iwl2000_hw_set_hw_params,
+ .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
+@@ -277,7 +204,6 @@ static struct iwl_lib_ops iwl2000_lib = {
+ .alive_notify = iwlagn_alive_notify,
+ .send_tx_power = iwlagn_send_tx_power,
+ .update_chain_flags = iwl_update_chain_flags,
+- .set_channel_switch = iwl2030_hw_channel_switch,
+ .apm_ops = {
+ .init = iwl_apm_init,
+ .config = iwl2000_nic_config,
+diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
+index 22e045b..dcf40e8 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
++++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
+@@ -337,8 +337,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
+ ctx->active.channel, ch);
+ return -EFAULT;
+ }
+- priv->switch_rxon.channel = cmd.channel;
+- priv->switch_rxon.switch_in_progress = true;
+
+ return iwl_send_cmd_sync(priv, &hcmd);
+ }
+@@ -513,7 +511,6 @@ static struct iwl_base_params iwl5000_base_params = {
+ };
+ static struct iwl_ht_params iwl5000_ht_params = {
+ .ht_greenfield_support = true,
+- .use_rts_for_aggregation = true, /* use rts/cts protection */
+ };
+
+ #define IWL_DEVICE_5000 \
+diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
+index a745b01..9035255 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
++++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
+@@ -277,8 +277,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
+ ctx->active.channel, ch);
+ return -EFAULT;
+ }
+- priv->switch_rxon.channel = cmd.channel;
+- priv->switch_rxon.switch_in_progress = true;
+
+ return iwl_send_cmd_sync(priv, &hcmd);
+ }
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
+index 41543ad..129a551 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
+@@ -217,17 +217,9 @@ static void iwlagn_tx_cmd_protection(struct iwl_priv *priv,
+ __le16 fc, __le32 *tx_flags)
+ {
+ if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS ||
+- info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
++ info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT ||
++ info->flags & IEEE80211_TX_CTL_AMPDU)
+ *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
+- return;
+- }
+-
+- if (priv->cfg->ht_params &&
+- priv->cfg->ht_params->use_rts_for_aggregation &&
+- info->flags & IEEE80211_TX_CTL_AMPDU) {
+- *tx_flags |= TX_CMD_FLG_PROT_REQUIRE_MSK;
+- return;
+- }
+ }
+
+ /* Calc max signal level (dBm) among 3 possible receivers */
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+index fbbde07..7c0f80c 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+@@ -173,6 +173,14 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+ return 0;
+ }
+
++ /*
++ * force CTS-to-self frames protection if RTS-CTS is not preferred
++ * one aggregation protection method
++ */
++ if (!(priv->cfg->ht_params &&
++ priv->cfg->ht_params->use_rts_for_aggregation))
++ ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
++
+ if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
+ !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK))
+ ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+@@ -189,10 +197,10 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+ * receive commit_rxon request
+ * abort any previous channel switch if still in process
+ */
+- if (priv->switch_rxon.switch_in_progress &&
+- (priv->switch_rxon.channel != ctx->staging.channel)) {
++ if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) &&
++ (priv->switch_channel != ctx->staging.channel)) {
+ IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
+- le16_to_cpu(priv->switch_rxon.channel));
++ le16_to_cpu(priv->switch_channel));
+ iwl_chswitch_done(priv, false);
+ }
+
+@@ -210,6 +218,11 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+
+ memcpy(active, &ctx->staging, sizeof(*active));
+ iwl_print_rx_config_cmd(priv, ctx);
++ /*
++ * We do not commit tx power settings while channel changing,
++ * do it now if after settings changed.
++ */
++ iwl_set_tx_power(priv, priv->tx_power_next, false);
+ return 0;
+ }
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
+index 321b18b..5941e61 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
++++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
+@@ -3461,16 +3461,13 @@ void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
+ goto out_exit;
+
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+- test_bit(STATUS_SCANNING, &priv->status))
++ test_bit(STATUS_SCANNING, &priv->status) ||
++ test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+ goto out_exit;
+
+ if (!iwl_is_associated_ctx(ctx))
+ goto out_exit;
+
+- /* channel switch in progress */
+- if (priv->switch_rxon.switch_in_progress == true)
+- goto out_exit;
+-
+ mutex_lock(&priv->mutex);
+ if (priv->cfg->ops->lib->set_channel_switch) {
+
+@@ -3520,16 +3517,20 @@ void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
+ * at this point, staging_rxon has the
+ * configuration for channel switch
+ */
++ set_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status);
++ priv->switch_channel = cpu_to_le16(ch);
+ if (priv->cfg->ops->lib->set_channel_switch(priv,
+- ch_switch))
+- priv->switch_rxon.switch_in_progress = false;
++ ch_switch)) {
++ clear_bit(STATUS_CHANNEL_SWITCH_PENDING,
++ &priv->status);
++ priv->switch_channel = 0;
++ ieee80211_chswitch_done(ctx->vif, false);
++ }
+ }
+ }
+ out:
+ mutex_unlock(&priv->mutex);
+ out_exit:
+- if (!priv->switch_rxon.switch_in_progress)
+- ieee80211_chswitch_done(ctx->vif, false);
+ IWL_DEBUG_MAC80211(priv, "leave\n");
+ }
+
+diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
+index bafbe57..7fd7fe6 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-core.c
++++ b/drivers/net/wireless/iwlwifi/iwl-core.c
+@@ -861,12 +861,8 @@ void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
+ if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+ return;
+
+- if (priv->switch_rxon.switch_in_progress) {
++ if (test_and_clear_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
+ ieee80211_chswitch_done(ctx->vif, is_success);
+- mutex_lock(&priv->mutex);
+- priv->switch_rxon.switch_in_progress = false;
+- mutex_unlock(&priv->mutex);
+- }
+ }
+
+ #ifdef CONFIG_IWLWIFI_DEBUG
+@@ -1776,6 +1772,7 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct iwl_priv *priv = hw->priv;
+ struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
+ struct iwl_rxon_context *tmp;
++ enum nl80211_iftype newviftype = newtype;
+ u32 interface_modes;
+ int err;
+
+@@ -1783,6 +1780,15 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+
+ mutex_lock(&priv->mutex);
+
++ if (!ctx->vif || !iwl_is_ready_rf(priv)) {
++ /*
++ * Huh? But wait ... this can maybe happen when
++ * we're in the middle of a firmware restart!
++ */
++ err = -EBUSY;
++ goto out;
++ }
++
+ interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;
+
+ if (!(interface_modes & BIT(newtype))) {
+@@ -1809,7 +1815,8 @@ int iwl_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+
+ /* success */
+ iwl_teardown_interface(priv, vif, true);
+- vif->type = newtype;
++ vif->type = newviftype;
++ vif->p2p = newp2p;
+ err = iwl_setup_interface(priv, ctx);
+ WARN_ON(err);
+ /*
+diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
+index b316d83..92f65b6 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-core.h
++++ b/drivers/net/wireless/iwlwifi/iwl-core.h
+@@ -662,7 +662,7 @@ void iwlcore_free_geos(struct iwl_priv *priv);
+ #define STATUS_SCAN_HW 15
+ #define STATUS_POWER_PMI 16
+ #define STATUS_FW_ERROR 17
+-
++#define STATUS_CHANNEL_SWITCH_PENDING 19
+
+ static inline int iwl_is_ready(struct iwl_priv *priv)
+ {
+diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
+index 68b953f..65a16ae 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
++++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
+@@ -1037,17 +1037,6 @@ struct traffic_stats {
+ };
+
+ /*
+- * iwl_switch_rxon: "channel switch" structure
+- *
+- * @ switch_in_progress: channel switch in progress
+- * @ channel: new channel
+- */
+-struct iwl_switch_rxon {
+- bool switch_in_progress;
+- __le16 channel;
+-};
+-
+-/*
+ * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds
+ * to perform continuous uCode event logging operation if enabled
+ */
+@@ -1344,7 +1333,7 @@ struct iwl_priv {
+
+ struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX];
+
+- struct iwl_switch_rxon switch_rxon;
++ __le16 switch_channel;
+
+ /* 1st responses from initialize and runtime uCode images.
+ * _agn's initialize alive response contains some calibration data. */
+@@ -1658,21 +1647,24 @@ iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif)
+ ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++) \
+ if (priv->valid_contexts & BIT(ctx->ctxid))
+
+-static inline int iwl_is_associated(struct iwl_priv *priv,
+- enum iwl_rxon_context_id ctxid)
++static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx)
+ {
+- return (priv->contexts[ctxid].active.filter_flags &
+- RXON_FILTER_ASSOC_MSK) ? 1 : 0;
++ return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
+ }
+
+-static inline int iwl_is_any_associated(struct iwl_priv *priv)
++static inline int iwl_is_associated(struct iwl_priv *priv,
++ enum iwl_rxon_context_id ctxid)
+ {
+- return iwl_is_associated(priv, IWL_RXON_CTX_BSS);
++ return iwl_is_associated_ctx(&priv->contexts[ctxid]);
+ }
+
+-static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx)
++static inline int iwl_is_any_associated(struct iwl_priv *priv)
+ {
+- return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
++ struct iwl_rxon_context *ctx;
++ for_each_context(priv, ctx)
++ if (iwl_is_associated_ctx(ctx))
++ return true;
++ return false;
+ }
+
+ static inline int is_channel_valid(const struct iwl_channel_info *ch_info)
+diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
+index 6f9a2fa..8055910 100644
+--- a/drivers/net/wireless/iwlwifi/iwl-rx.c
++++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
+@@ -299,19 +299,19 @@ static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+ struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
+
+- if (priv->switch_rxon.switch_in_progress) {
+- if (!le32_to_cpu(csa->status) &&
+- (csa->channel == priv->switch_rxon.channel)) {
+- rxon->channel = csa->channel;
+- ctx->staging.channel = csa->channel;
+- IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
+- le16_to_cpu(csa->channel));
+- iwl_chswitch_done(priv, true);
+- } else {
+- IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
++ if (!test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status))
++ return;
++
++ if (!le32_to_cpu(csa->status) && csa->channel == priv->switch_channel) {
++ rxon->channel = csa->channel;
++ ctx->staging.channel = csa->channel;
++ IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
+ le16_to_cpu(csa->channel));
+- iwl_chswitch_done(priv, false);
+- }
++ iwl_chswitch_done(priv, true);
++ } else {
++ IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
++ le16_to_cpu(csa->channel));
++ iwl_chswitch_done(priv, false);
+ }
+ }
+
+diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c
+index e183587..a8f3bc7 100644
+--- a/drivers/net/wireless/p54/p54usb.c
++++ b/drivers/net/wireless/p54/p54usb.c
+@@ -82,6 +82,7 @@ static struct usb_device_id p54u_table[] __devinitdata = {
+ {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */
+ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */
+ {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 */
+ {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */
+ {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */
+diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+index 71244a3..91bf182 100644
+--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
++++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+@@ -278,6 +278,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = {
+ {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/
+ {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
+ {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
++ {RTL_USB_DEVICE(0x0846, 0x9041, rtl92cu_hal_cfg)}, /*NetGear WNA1000M*/
+ {RTL_USB_DEVICE(0x0Df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
+ {RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/
+ /* HP - Lite-On ,8188CUS Slim Combo */
+diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
+index ab607bb..13c0c77 100644
+--- a/drivers/net/wireless/zd1211rw/zd_usb.c
++++ b/drivers/net/wireless/zd1211rw/zd_usb.c
+@@ -1533,6 +1533,31 @@ static void __exit usb_exit(void)
+ module_init(usb_init);
+ module_exit(usb_exit);
+
++static int zd_ep_regs_out_msg(struct usb_device *udev, void *data, int len,
++ int *actual_length, int timeout)
++{
++ /* In USB 2.0 mode EP_REGS_OUT endpoint is interrupt type. However in
++ * USB 1.1 mode endpoint is bulk. Select correct type URB by endpoint
++ * descriptor.
++ */
++ struct usb_host_endpoint *ep;
++ unsigned int pipe;
++
++ pipe = usb_sndintpipe(udev, EP_REGS_OUT);
++ ep = usb_pipe_endpoint(udev, pipe);
++ if (!ep)
++ return -EINVAL;
++
++ if (usb_endpoint_xfer_int(&ep->desc)) {
++ return usb_interrupt_msg(udev, pipe, data, len,
++ actual_length, timeout);
++ } else {
++ pipe = usb_sndbulkpipe(udev, EP_REGS_OUT);
++ return usb_bulk_msg(udev, pipe, data, len, actual_length,
++ timeout);
++ }
++}
++
+ static int usb_int_regs_length(unsigned int count)
+ {
+ return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data);
+@@ -1648,15 +1673,14 @@ int zd_usb_ioread16v(struct zd_usb *usb, u16 *values,
+
+ udev = zd_usb_to_usbdev(usb);
+ prepare_read_regs_int(usb);
+- r = usb_interrupt_msg(udev, usb_sndintpipe(udev, EP_REGS_OUT),
+- req, req_len, &actual_req_len, 50 /* ms */);
++ r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);
+ if (r) {
+ dev_dbg_f(zd_usb_dev(usb),
+- "error in usb_interrupt_msg(). Error number %d\n", r);
++ "error in zd_ep_regs_out_msg(). Error number %d\n", r);
+ goto error;
+ }
+ if (req_len != actual_req_len) {
+- dev_dbg_f(zd_usb_dev(usb), "error in usb_interrupt_msg()\n"
++ dev_dbg_f(zd_usb_dev(usb), "error in zd_ep_regs_out_msg()\n"
+ " req_len %d != actual_req_len %d\n",
+ req_len, actual_req_len);
+ r = -EIO;
+@@ -1818,9 +1842,17 @@ int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
+ rw->value = cpu_to_le16(ioreqs[i].value);
+ }
+
+- usb_fill_int_urb(urb, udev, usb_sndintpipe(udev, EP_REGS_OUT),
+- req, req_len, iowrite16v_urb_complete, usb,
+- ep->desc.bInterval);
++ /* In USB 2.0 mode endpoint is interrupt type. However in USB 1.1 mode
++ * endpoint is bulk. Select correct type URB by endpoint descriptor.
++ */
++ if (usb_endpoint_xfer_int(&ep->desc))
++ usb_fill_int_urb(urb, udev, usb_sndintpipe(udev, EP_REGS_OUT),
++ req, req_len, iowrite16v_urb_complete, usb,
++ ep->desc.bInterval);
++ else
++ usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_REGS_OUT),
++ req, req_len, iowrite16v_urb_complete, usb);
++
+ urb->transfer_flags |= URB_FREE_BUFFER;
+
+ /* Submit previous URB */
+@@ -1924,15 +1956,14 @@ int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits)
+ }
+
+ udev = zd_usb_to_usbdev(usb);
+- r = usb_interrupt_msg(udev, usb_sndintpipe(udev, EP_REGS_OUT),
+- req, req_len, &actual_req_len, 50 /* ms */);
++ r = zd_ep_regs_out_msg(udev, req, req_len, &actual_req_len, 50 /*ms*/);
+ if (r) {
+ dev_dbg_f(zd_usb_dev(usb),
+- "error in usb_interrupt_msg(). Error number %d\n", r);
++ "error in zd_ep_regs_out_msg(). Error number %d\n", r);
+ goto out;
+ }
+ if (req_len != actual_req_len) {
+- dev_dbg_f(zd_usb_dev(usb), "error in usb_interrupt_msg()"
++ dev_dbg_f(zd_usb_dev(usb), "error in zd_ep_regs_out_msg()"
+ " req_len %d != actual_req_len %d\n",
+ req_len, actual_req_len);
+ r = -EIO;
+diff --git a/drivers/oprofile/buffer_sync.c b/drivers/oprofile/buffer_sync.c
+index a3984f4..f34b5b2 100644
+--- a/drivers/oprofile/buffer_sync.c
++++ b/drivers/oprofile/buffer_sync.c
+@@ -141,6 +141,13 @@ static struct notifier_block module_load_nb = {
+ .notifier_call = module_load_notify,
+ };
+
++static void free_all_tasks(void)
++{
++ /* make sure we don't leak task structs */
++ process_task_mortuary();
++ process_task_mortuary();
++}
++
+ int sync_start(void)
+ {
+ int err;
+@@ -148,8 +155,6 @@ int sync_start(void)
+ if (!zalloc_cpumask_var(&marked_cpus, GFP_KERNEL))
+ return -ENOMEM;
+
+- mutex_lock(&buffer_mutex);
+-
+ err = task_handoff_register(&task_free_nb);
+ if (err)
+ goto out1;
+@@ -166,7 +171,6 @@ int sync_start(void)
+ start_cpu_work();
+
+ out:
+- mutex_unlock(&buffer_mutex);
+ return err;
+ out4:
+ profile_event_unregister(PROFILE_MUNMAP, &munmap_nb);
+@@ -174,6 +178,7 @@ out3:
+ profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb);
+ out2:
+ task_handoff_unregister(&task_free_nb);
++ free_all_tasks();
+ out1:
+ free_cpumask_var(marked_cpus);
+ goto out;
+@@ -182,20 +187,16 @@ out1:
+
+ void sync_stop(void)
+ {
+- /* flush buffers */
+- mutex_lock(&buffer_mutex);
+ end_cpu_work();
+ unregister_module_notifier(&module_load_nb);
+ profile_event_unregister(PROFILE_MUNMAP, &munmap_nb);
+ profile_event_unregister(PROFILE_TASK_EXIT, &task_exit_nb);
+ task_handoff_unregister(&task_free_nb);
+- mutex_unlock(&buffer_mutex);
+- flush_cpu_work();
++ barrier(); /* do all of the above first */
+
+- /* make sure we don't leak task structs */
+- process_task_mortuary();
+- process_task_mortuary();
++ flush_cpu_work();
+
++ free_all_tasks();
+ free_cpumask_var(marked_cpus);
+ }
+
+diff --git a/drivers/pci/hotplug/pcihp_slot.c b/drivers/pci/hotplug/pcihp_slot.c
+index 80b461c..749fdf0 100644
+--- a/drivers/pci/hotplug/pcihp_slot.c
++++ b/drivers/pci/hotplug/pcihp_slot.c
+@@ -158,6 +158,47 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
+ */
+ }
+
++/* Program PCIE MaxPayload setting on device: ensure parent maxpayload <= device */
++static int pci_set_payload(struct pci_dev *dev)
++{
++ int pos, ppos;
++ u16 pctl, psz;
++ u16 dctl, dsz, dcap, dmax;
++ struct pci_dev *parent;
++
++ parent = dev->bus->self;
++ pos = pci_find_capability(dev, PCI_CAP_ID_EXP);
++ if (!pos)
++ return 0;
++
++ /* Read Device MaxPayload capability and setting */
++ pci_read_config_word(dev, pos + PCI_EXP_DEVCTL, &dctl);
++ pci_read_config_word(dev, pos + PCI_EXP_DEVCAP, &dcap);
++ dsz = (dctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
++ dmax = (dcap & PCI_EXP_DEVCAP_PAYLOAD);
++
++ /* Read Parent MaxPayload setting */
++ ppos = pci_find_capability(parent, PCI_CAP_ID_EXP);
++ if (!ppos)
++ return 0;
++ pci_read_config_word(parent, ppos + PCI_EXP_DEVCTL, &pctl);
++ psz = (pctl & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
++
++ /* If parent payload > device max payload -> error
++ * If parent payload > device payload -> set speed
++ * If parent payload <= device payload -> do nothing
++ */
++ if (psz > dmax)
++ return -1;
++ else if (psz > dsz) {
++ dev_info(&dev->dev, "Setting MaxPayload to %d\n", 128 << psz);
++ pci_write_config_word(dev, pos + PCI_EXP_DEVCTL,
++ (dctl & ~PCI_EXP_DEVCTL_PAYLOAD) +
++ (psz << 5));
++ }
++ return 0;
++}
++
+ void pci_configure_slot(struct pci_dev *dev)
+ {
+ struct pci_dev *cdev;
+@@ -169,6 +210,10 @@ void pci_configure_slot(struct pci_dev *dev)
+ (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI)))
+ return;
+
++ ret = pci_set_payload(dev);
++ if (ret)
++ dev_warn(&dev->dev, "could not set device max payload\n");
++
+ memset(&hpp, 0, sizeof(hpp));
+ ret = pci_get_hp_params(dev, &hpp);
+ if (ret)
+diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c
+index d552d2c..5db70c7 100644
+--- a/drivers/pci/intel-iommu.c
++++ b/drivers/pci/intel-iommu.c
+@@ -46,6 +46,8 @@
+ #define ROOT_SIZE VTD_PAGE_SIZE
+ #define CONTEXT_SIZE VTD_PAGE_SIZE
+
++#define IS_BRIDGE_HOST_DEVICE(pdev) \
++ ((pdev->class >> 8) == PCI_CLASS_BRIDGE_HOST)
+ #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
+ #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
+ #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
+@@ -1416,6 +1418,10 @@ static void domain_exit(struct dmar_domain *domain)
+ if (!domain)
+ return;
+
++ /* Flush any lazy unmaps that may reference this domain */
++ if (!intel_iommu_strict)
++ flush_unmaps_timeout(0);
++
+ domain_remove_dev_info(domain);
+ /* destroy iovas */
+ put_iova_domain(&domain->iovad);
+@@ -2105,10 +2111,10 @@ static int identity_mapping(struct pci_dev *pdev)
+ if (likely(!iommu_identity_mapping))
+ return 0;
+
++ info = pdev->dev.archdata.iommu;
++ if (info && info != DUMMY_DEVICE_DOMAIN_INFO)
++ return (info->domain == si_domain);
+
+- list_for_each_entry(info, &si_domain->devices, link)
+- if (info->dev == pdev)
+- return 1;
+ return 0;
+ }
+
+@@ -2186,8 +2192,19 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup)
+ * Assume that they will -- if they turn out not to be, then we can
+ * take them out of the 1:1 domain later.
+ */
+- if (!startup)
+- return pdev->dma_mask > DMA_BIT_MASK(32);
++ if (!startup) {
++ /*
++ * If the device's dma_mask is less than the system's memory
++ * size then this is not a candidate for identity mapping.
++ */
++ u64 dma_mask = pdev->dma_mask;
++
++ if (pdev->dev.coherent_dma_mask &&
++ pdev->dev.coherent_dma_mask < dma_mask)
++ dma_mask = pdev->dev.coherent_dma_mask;
++
++ return dma_mask >= dma_get_required_mask(&pdev->dev);
++ }
+
+ return 1;
+ }
+@@ -2202,6 +2219,9 @@ static int __init iommu_prepare_static_identity_mapping(int hw)
+ return -EFAULT;
+
+ for_each_pci_dev(pdev) {
++ /* Skip Host/PCI Bridge devices */
++ if (IS_BRIDGE_HOST_DEVICE(pdev))
++ continue;
+ if (iommu_should_identity_map(pdev, 1)) {
+ printk(KERN_INFO "IOMMU: %s identity mapping for device %s\n",
+ hw ? "hardware" : "software", pci_name(pdev));
+@@ -2591,8 +2611,7 @@ static dma_addr_t __intel_map_single(struct device *hwdev, phys_addr_t paddr,
+ iommu = domain_get_iommu(domain);
+ size = aligned_nrpages(paddr, size);
+
+- iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size),
+- pdev->dma_mask);
++ iova = intel_alloc_iova(hwdev, domain, dma_to_mm_pfn(size), dma_mask);
+ if (!iova)
+ goto error;
+
+@@ -3379,8 +3398,8 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
+ spin_lock_irqsave(&device_domain_lock, flags);
+ list_for_each_safe(entry, tmp, &domain->devices) {
+ info = list_entry(entry, struct device_domain_info, link);
+- /* No need to compare PCI domain; it has to be the same */
+- if (info->bus == pdev->bus->number &&
++ if (info->segment == pci_domain_nr(pdev->bus) &&
++ info->bus == pdev->bus->number &&
+ info->devfn == pdev->devfn) {
+ list_del(&info->link);
+ list_del(&info->global);
+@@ -3418,10 +3437,13 @@ static void domain_remove_one_dev_info(struct dmar_domain *domain,
+ domain_update_iommu_cap(domain);
+ spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
+
+- spin_lock_irqsave(&iommu->lock, tmp_flags);
+- clear_bit(domain->id, iommu->domain_ids);
+- iommu->domains[domain->id] = NULL;
+- spin_unlock_irqrestore(&iommu->lock, tmp_flags);
++ if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
++ !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY)) {
++ spin_lock_irqsave(&iommu->lock, tmp_flags);
++ clear_bit(domain->id, iommu->domain_ids);
++ iommu->domains[domain->id] = NULL;
++ spin_unlock_irqrestore(&iommu->lock, tmp_flags);
++ }
+ }
+
+ spin_unlock_irqrestore(&device_domain_lock, flags);
+diff --git a/drivers/pci/iova.c b/drivers/pci/iova.c
+index 9606e59..c5c274a 100644
+--- a/drivers/pci/iova.c
++++ b/drivers/pci/iova.c
+@@ -63,8 +63,16 @@ __cached_rbnode_delete_update(struct iova_domain *iovad, struct iova *free)
+ curr = iovad->cached32_node;
+ cached_iova = container_of(curr, struct iova, node);
+
+- if (free->pfn_lo >= cached_iova->pfn_lo)
+- iovad->cached32_node = rb_next(&free->node);
++ if (free->pfn_lo >= cached_iova->pfn_lo) {
++ struct rb_node *node = rb_next(&free->node);
++ struct iova *iova = container_of(node, struct iova, node);
++
++ /* only cache if it's below 32bit pfn */
++ if (node && iova->pfn_lo < iovad->dma_32bit_pfn)
++ iovad->cached32_node = node;
++ else
++ iovad->cached32_node = NULL;
++ }
+ }
+
+ /* Computes the padding size required, to make the
+diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
+index 135df16..46767c5 100644
+--- a/drivers/pci/pci-driver.c
++++ b/drivers/pci/pci-driver.c
+@@ -624,7 +624,7 @@ static int pci_pm_prepare(struct device *dev)
+ * system from the sleep state, we'll have to prevent it from signaling
+ * wake-up.
+ */
+- pm_runtime_resume(dev);
++ pm_runtime_get_sync(dev);
+
+ if (drv && drv->pm && drv->pm->prepare)
+ error = drv->pm->prepare(dev);
+@@ -638,6 +638,8 @@ static void pci_pm_complete(struct device *dev)
+
+ if (drv && drv->pm && drv->pm->complete)
+ drv->pm->complete(dev);
++
++ pm_runtime_put_sync(dev);
+ }
+
+ #else /* !CONFIG_PM_SLEEP */
+diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
+index 5129ed6..362e3b3 100644
+--- a/drivers/pci/quirks.c
++++ b/drivers/pci/quirks.c
+@@ -2755,9 +2755,34 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev)
+
+ dev_notice(&dev->dev, "proprietary Ricoh MMC controller disabled (via firewire function)\n");
+ dev_notice(&dev->dev, "MMC cards are now supported by standard SDHCI controller\n");
++
++ /*
++ * RICOH 0xe823 SD/MMC card reader fails to recognize
++ * certain types of SD/MMC cards. Lowering the SD base
++ * clock frequency from 200Mhz to 50Mhz fixes this issue.
++ *
++ * 0x150 - SD2.0 mode enable for changing base clock
++ * frequency to 50Mhz
++ * 0xe1 - Base clock frequency
++ * 0x32 - 50Mhz new clock frequency
++ * 0xf9 - Key register for 0x150
++ * 0xfc - key register for 0xe1
++ */
++ if (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);
++ pci_write_config_byte(dev, 0xfc, 0x01);
++ pci_write_config_byte(dev, 0xe1, 0x32);
++ pci_write_config_byte(dev, 0xfc, 0x00);
++
++ dev_notice(&dev->dev, "MMC controller base frequency changed to 50Mhz.\n");
++ }
+ }
+ 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_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*/
+
+ #if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP)
+@@ -2784,6 +2809,16 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x342e, vtd_mask_spec_errors);
+ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x3c28, vtd_mask_spec_errors);
+ #endif
+
++static void __devinit fixup_ti816x_class(struct pci_dev* dev)
++{
++ /* TI 816x devices do not have class code set when in PCIe boot mode */
++ if (dev->class == PCI_CLASS_NOT_DEFINED) {
++ dev_info(&dev->dev, "Setting PCI class for 816x PCIe device\n");
++ dev->class = PCI_CLASS_MULTIMEDIA_VIDEO;
++ }
++}
++DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_TI, 0xb800, fixup_ti816x_class);
++
+ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f,
+ struct pci_fixup *end)
+ {
+diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
+index 832a3fd7..c8c9842 100644
+--- a/drivers/platform/x86/asus-wmi.c
++++ b/drivers/platform/x86/asus-wmi.c
+@@ -1223,7 +1223,7 @@ static int asus_wmi_sysfs_init(struct platform_device *device)
+ /*
+ * Platform device
+ */
+-static int __init asus_wmi_platform_init(struct asus_wmi *asus)
++static int asus_wmi_platform_init(struct asus_wmi *asus)
+ {
+ int rv;
+
+diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
+index de301aa8..fdfb9e7 100644
+--- a/drivers/platform/x86/dell-laptop.c
++++ b/drivers/platform/x86/dell-laptop.c
+@@ -290,12 +290,9 @@ static int dell_rfkill_set(void *data, bool blocked)
+ dell_send_request(buffer, 17, 11);
+
+ /* If the hardware switch controls this radio, and the hardware
+- switch is disabled, don't allow changing the software state.
+- If the hardware switch is reported as not supported, always
+- fire the SMI to toggle the killswitch. */
++ switch is disabled, don't allow changing the software state */
+ if ((hwswitch_state & BIT(hwswitch_bit)) &&
+- !(buffer->output[1] & BIT(16)) &&
+- (buffer->output[1] & BIT(0))) {
++ !(buffer->output[1] & BIT(16))) {
+ ret = -EINVAL;
+ goto out;
+ }
+@@ -401,23 +398,6 @@ static const struct file_operations dell_debugfs_fops = {
+
+ static void dell_update_rfkill(struct work_struct *ignored)
+ {
+- int status;
+-
+- get_buffer();
+- dell_send_request(buffer, 17, 11);
+- status = buffer->output[1];
+- release_buffer();
+-
+- /* if hardware rfkill is not supported, set it explicitly */
+- if (!(status & BIT(0))) {
+- if (wifi_rfkill)
+- dell_rfkill_set((void *)1, !((status & BIT(17)) >> 17));
+- if (bluetooth_rfkill)
+- dell_rfkill_set((void *)2, !((status & BIT(18)) >> 18));
+- if (wwan_rfkill)
+- dell_rfkill_set((void *)3, !((status & BIT(19)) >> 19));
+- }
+-
+ if (wifi_rfkill)
+ dell_rfkill_query(wifi_rfkill, (void *)1);
+ if (bluetooth_rfkill)
+diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c
+index f0b8951..a8a2b6b 100644
+--- a/drivers/scsi/bnx2i/bnx2i_hwi.c
++++ b/drivers/scsi/bnx2i/bnx2i_hwi.c
+@@ -1274,6 +1274,7 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba)
+ iscsi_init.dummy_buffer_addr_hi =
+ (u32) ((u64) hba->dummy_buf_dma >> 32);
+
++ hba->num_ccell = hba->max_sqes >> 1;
+ hba->ctx_ccell_tasks =
+ ((hba->num_ccell & 0xFFFF) | (hba->max_sqes << 16));
+ iscsi_init.num_ccells_per_conn = hba->num_ccell;
+diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c
+index 1d24a28..6adbdc3 100644
+--- a/drivers/scsi/bnx2i/bnx2i_init.c
++++ b/drivers/scsi/bnx2i/bnx2i_init.c
+@@ -244,7 +244,7 @@ void bnx2i_stop(void *handle)
+ wait_event_interruptible_timeout(hba->eh_wait,
+ (list_empty(&hba->ep_ofld_list) &&
+ list_empty(&hba->ep_destroy_list)),
+- 10 * HZ);
++ 2 * HZ);
+ /* Wait for all endpoints to be torn down, Chip will be reset once
+ * control returns to network driver. So it is required to cleanup and
+ * release all connection resources before returning from this routine.
+diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+index 1809f9c..51a970f 100644
+--- a/drivers/scsi/bnx2i/bnx2i_iscsi.c
++++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c
+@@ -858,7 +858,7 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic)
+ mutex_init(&hba->net_dev_lock);
+ init_waitqueue_head(&hba->eh_wait);
+ if (test_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type)) {
+- hba->hba_shutdown_tmo = 20 * HZ;
++ hba->hba_shutdown_tmo = 30 * HZ;
+ hba->conn_teardown_tmo = 20 * HZ;
+ hba->conn_ctx_destroy_tmo = 6 * HZ;
+ } else { /* 5706/5708/5709 */
+@@ -1208,6 +1208,9 @@ static int bnx2i_task_xmit(struct iscsi_task *task)
+ struct bnx2i_cmd *cmd = task->dd_data;
+ struct iscsi_cmd *hdr = (struct iscsi_cmd *) task->hdr;
+
++ if (bnx2i_conn->ep->num_active_cmds + 1 > hba->max_sqes)
++ return -ENOMEM;
++
+ /*
+ * If there is no scsi_cmnd this must be a mgmt task
+ */
+diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+index d2064a0..9aab26a 100644
+--- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
+@@ -113,6 +113,7 @@ struct sense_info {
+ };
+
+
++#define MPT2SAS_TURN_ON_FAULT_LED (0xFFFC)
+ #define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF)
+
+ /**
+@@ -121,6 +122,7 @@ struct sense_info {
+ * @work: work object (ioc->fault_reset_work_q)
+ * @cancel_pending_work: flag set during reset handling
+ * @ioc: per adapter object
++ * @device_handle: device handle
+ * @VF_ID: virtual function id
+ * @VP_ID: virtual port id
+ * @ignore: flag meaning this event has been marked to ignore
+@@ -134,6 +136,7 @@ struct fw_event_work {
+ u8 cancel_pending_work;
+ struct delayed_work delayed_work;
+ struct MPT2SAS_ADAPTER *ioc;
++ u16 device_handle;
+ u8 VF_ID;
+ u8 VP_ID;
+ u8 ignore;
+@@ -3708,17 +3711,75 @@ _scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
+ #endif
+
+ /**
+- * _scsih_smart_predicted_fault - illuminate Fault LED
++ * _scsih_turn_on_fault_led - illuminate Fault LED
+ * @ioc: per adapter object
+ * @handle: device handle
++ * Context: process
+ *
+ * Return nothing.
+ */
+ static void
+-_scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle)
++_scsih_turn_on_fault_led(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+ {
+ Mpi2SepReply_t mpi_reply;
+ Mpi2SepRequest_t mpi_request;
++
++ memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
++ mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
++ mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
++ mpi_request.SlotStatus =
++ cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
++ mpi_request.DevHandle = cpu_to_le16(handle);
++ mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS;
++ if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
++ &mpi_request)) != 0) {
++ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name,
++ __FILE__, __LINE__, __func__);
++ return;
++ }
++
++ if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
++ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "enclosure_processor: "
++ "ioc_status (0x%04x), loginfo(0x%08x)\n", ioc->name,
++ le16_to_cpu(mpi_reply.IOCStatus),
++ le32_to_cpu(mpi_reply.IOCLogInfo)));
++ return;
++ }
++}
++
++/**
++ * _scsih_send_event_to_turn_on_fault_led - fire delayed event
++ * @ioc: per adapter object
++ * @handle: device handle
++ * Context: interrupt.
++ *
++ * Return nothing.
++ */
++static void
++_scsih_send_event_to_turn_on_fault_led(struct MPT2SAS_ADAPTER *ioc, u16 handle)
++{
++ struct fw_event_work *fw_event;
++
++ fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
++ if (!fw_event)
++ return;
++ fw_event->event = MPT2SAS_TURN_ON_FAULT_LED;
++ fw_event->device_handle = handle;
++ fw_event->ioc = ioc;
++ _scsih_fw_event_add(ioc, fw_event);
++}
++
++/**
++ * _scsih_smart_predicted_fault - process smart errors
++ * @ioc: per adapter object
++ * @handle: device handle
++ * Context: interrupt.
++ *
++ * Return nothing.
++ */
++static void
++_scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle)
++{
+ struct scsi_target *starget;
+ struct MPT2SAS_TARGET *sas_target_priv_data;
+ Mpi2EventNotificationReply_t *event_reply;
+@@ -3745,30 +3806,8 @@ _scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+ starget_printk(KERN_WARNING, starget, "predicted fault\n");
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+- if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) {
+- memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
+- mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
+- mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
+- mpi_request.SlotStatus =
+- cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT);
+- mpi_request.DevHandle = cpu_to_le16(handle);
+- mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS;
+- if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
+- &mpi_request)) != 0) {
+- printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+- ioc->name, __FILE__, __LINE__, __func__);
+- return;
+- }
+-
+- if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
+- dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
+- "enclosure_processor: ioc_status (0x%04x), "
+- "loginfo(0x%08x)\n", ioc->name,
+- le16_to_cpu(mpi_reply.IOCStatus),
+- le32_to_cpu(mpi_reply.IOCLogInfo)));
+- return;
+- }
+- }
++ if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
++ _scsih_send_event_to_turn_on_fault_led(ioc, handle);
+
+ /* insert into event log */
+ sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
+@@ -6330,6 +6369,9 @@ _firmware_event_work(struct work_struct *work)
+ }
+
+ switch (fw_event->event) {
++ case MPT2SAS_TURN_ON_FAULT_LED:
++ _scsih_turn_on_fault_led(ioc, fw_event->device_handle);
++ break;
+ case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
+ _scsih_sas_topology_change_event(ioc, fw_event);
+ break;
+diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
+index d3e58d7..c52a0a2 100644
+--- a/drivers/scsi/qla2xxx/qla_attr.c
++++ b/drivers/scsi/qla2xxx/qla_attr.c
+@@ -1877,14 +1877,15 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
+
+ scsi_remove_host(vha->host);
+
++ /* Allow timer to run to drain queued items, when removing vp */
++ qla24xx_deallocate_vp_id(vha);
++
+ if (vha->timer_active) {
+ qla2x00_vp_stop_timer(vha);
+ DEBUG15(printk(KERN_INFO "scsi(%ld): timer for the vport[%d]"
+ " = %p has stopped\n", vha->host_no, vha->vp_idx, vha));
+ }
+
+- qla24xx_deallocate_vp_id(vha);
+-
+ /* No pending activities shall be there on the vha now */
+ DEBUG(msleep(random32()%10)); /* Just to see if something falls on
+ * the net we have placed below */
+diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
+index f5ba09c..5223c1d 100644
+--- a/drivers/scsi/qla2xxx/qla_fw.h
++++ b/drivers/scsi/qla2xxx/qla_fw.h
+@@ -416,8 +416,7 @@ struct cmd_type_6 {
+ uint8_t vp_index;
+
+ uint32_t fcp_data_dseg_address[2]; /* Data segment address. */
+- uint16_t fcp_data_dseg_len; /* Data segment length. */
+- uint16_t reserved_1; /* MUST be set to 0. */
++ uint32_t fcp_data_dseg_len; /* Data segment length. */
+ };
+
+ #define COMMAND_TYPE_7 0x18 /* Command Type 7 entry */
+diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
+index 455fe13..eb31213 100644
+--- a/drivers/scsi/qla2xxx/qla_nx.c
++++ b/drivers/scsi/qla2xxx/qla_nx.c
+@@ -2548,11 +2548,11 @@ qla2xx_build_scsi_type_6_iocbs(srb_t *sp, struct cmd_type_6 *cmd_pkt,
+ dsd_seg = (uint32_t *)&cmd_pkt->fcp_data_dseg_address;
+ *dsd_seg++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
+ *dsd_seg++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
+- cmd_pkt->fcp_data_dseg_len = dsd_list_len;
++ *dsd_seg++ = cpu_to_le32(dsd_list_len);
+ } else {
+ *cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
+ *cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
+- *cur_dsd++ = dsd_list_len;
++ *cur_dsd++ = cpu_to_le32(dsd_list_len);
+ }
+ cur_dsd = (uint32_t *)next_dsd;
+ while (avail_dsds) {
+diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
+index aa77475..4c3f5e8 100644
+--- a/drivers/scsi/qla2xxx/qla_os.c
++++ b/drivers/scsi/qla2xxx/qla_os.c
+@@ -2360,21 +2360,26 @@ qla2x00_remove_one(struct pci_dev *pdev)
+ base_vha = pci_get_drvdata(pdev);
+ ha = base_vha->hw;
+
+- spin_lock_irqsave(&ha->vport_slock, flags);
+- list_for_each_entry(vha, &ha->vp_list, list) {
+- atomic_inc(&vha->vref_count);
++ mutex_lock(&ha->vport_lock);
++ while (ha->cur_vport_count) {
++ struct Scsi_Host *scsi_host;
+
+- if (vha->fc_vport) {
+- spin_unlock_irqrestore(&ha->vport_slock, flags);
++ spin_lock_irqsave(&ha->vport_slock, flags);
+
+- fc_vport_terminate(vha->fc_vport);
++ BUG_ON(base_vha->list.next == &ha->vp_list);
++ /* This assumes first entry in ha->vp_list is always base vha */
++ vha = list_first_entry(&base_vha->list, scsi_qla_host_t, list);
++ scsi_host = scsi_host_get(vha->host);
+
+- spin_lock_irqsave(&ha->vport_slock, flags);
+- }
++ spin_unlock_irqrestore(&ha->vport_slock, flags);
++ mutex_unlock(&ha->vport_lock);
++
++ fc_vport_terminate(vha->fc_vport);
++ scsi_host_put(vha->host);
+
+- atomic_dec(&vha->vref_count);
++ mutex_lock(&ha->vport_lock);
+ }
+- spin_unlock_irqrestore(&ha->vport_slock, flags);
++ mutex_unlock(&ha->vport_lock);
+
+ set_bit(UNLOADING, &base_vha->dpc_flags);
+
+@@ -3604,7 +3609,8 @@ qla2x00_timer(scsi_qla_host_t *vha)
+ if (!pci_channel_offline(ha->pdev))
+ pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
+
+- if (IS_QLA82XX(ha)) {
++ /* Make sure qla82xx_watchdog is run only for physical port */
++ if (!vha->vp_idx && IS_QLA82XX(ha)) {
+ if (test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags))
+ start_dpc++;
+ qla82xx_watchdog(vha);
+@@ -3675,8 +3681,8 @@ qla2x00_timer(scsi_qla_host_t *vha)
+ atomic_read(&vha->loop_down_timer)));
+ }
+
+- /* Check if beacon LED needs to be blinked */
+- if (ha->beacon_blink_led == 1) {
++ /* Check if beacon LED needs to be blinked for physical host only */
++ if (!vha->vp_idx && (ha->beacon_blink_led == 1)) {
+ set_bit(BEACON_BLINK_NEEDED, &vha->dpc_flags);
+ start_dpc++;
+ }
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+index 58584dc..44e8ca3 100644
+--- a/drivers/scsi/scsi_scan.c
++++ b/drivers/scsi/scsi_scan.c
+@@ -297,7 +297,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
+ kfree(sdev);
+ goto out;
+ }
+-
++ blk_get_queue(sdev->request_queue);
+ sdev->request_queue->queuedata = sdev;
+ scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
+
+diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
+index e639125..e0bd3f7 100644
+--- a/drivers/scsi/scsi_sysfs.c
++++ b/drivers/scsi/scsi_sysfs.c
+@@ -322,6 +322,7 @@ static void scsi_device_dev_release_usercontext(struct work_struct *work)
+ kfree(evt);
+ }
+
++ blk_put_queue(sdev->request_queue);
+ /* NULL queue means the device can't be used */
+ sdev->request_queue = NULL;
+
+diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
+index 95019c7..4778e27 100644
+--- a/drivers/scsi/sr.c
++++ b/drivers/scsi/sr.c
+@@ -636,7 +636,7 @@ static int sr_probe(struct device *dev)
+ disk->first_minor = minor;
+ sprintf(disk->disk_name, "sr%d", minor);
+ disk->fops = &sr_bdops;
+- disk->flags = GENHD_FL_CD;
++ disk->flags = GENHD_FL_CD | GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE;
+ disk->events = DISK_EVENT_MEDIA_CHANGE | DISK_EVENT_EJECT_REQUEST;
+
+ blk_queue_rq_timeout(sdev->request_queue, SR_TIMEOUT);
+diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c
+index 9f4b58b..7e22b73 100644
+--- a/drivers/scsi/ultrastor.c
++++ b/drivers/scsi/ultrastor.c
+@@ -307,7 +307,7 @@ static inline int find_and_clear_bit_16(unsigned long *field)
+ "0: bsfw %1,%w0\n\t"
+ "btr %0,%1\n\t"
+ "jnc 0b"
+- : "=&r" (rv), "=m" (*field) :);
++ : "=&r" (rv), "+m" (*field) :);
+
+ return rv;
+ }
+diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
+index 6172335..82dd6fb 100644
+--- a/drivers/sh/clk/cpg.c
++++ b/drivers/sh/clk/cpg.c
+@@ -105,7 +105,7 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
+
+ /* Rebuild the frequency table */
+ clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
+- table, &clk->arch_flags);
++ table, NULL);
+
+ return 0;
+ }
+diff --git a/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c b/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c
+index f008659..f7bff4e 100644
+--- a/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c
++++ b/drivers/staging/brcm80211/brcmsmac/wlc_ampdu.c
+@@ -1123,21 +1123,12 @@ wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
+ ini->txretry[index] = 0;
+
+ /* ampdu_ack_len: number of acked aggregated frames */
+- /* ampdu_ack_map: block ack bit map for the aggregation */
+ /* ampdu_len: number of aggregated frames */
+ rate_status(wlc, tx_info, txs, mcs);
+ tx_info->flags |= IEEE80211_TX_STAT_ACK;
+ tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
+-
+- /* XXX TODO: Make these accurate. */
+ tx_info->status.ampdu_ack_len =
+- (txs->
+- status & TX_STATUS_FRM_RTX_MASK) >>
+- TX_STATUS_FRM_RTX_SHIFT;
+- tx_info->status.ampdu_len =
+- (txs->
+- status & TX_STATUS_FRM_RTX_MASK) >>
+- TX_STATUS_FRM_RTX_SHIFT;
++ tx_info->status.ampdu_len = 1;
+
+ skb_pull(p, D11_PHY_HDR_LEN);
+ skb_pull(p, D11_TXH_LEN);
+@@ -1163,6 +1154,8 @@ wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
+ /* Retry timeout */
+ ini->tx_in_transit--;
+ ieee80211_tx_info_clear_status(tx_info);
++ tx_info->status.ampdu_ack_len = 0;
++ tx_info->status.ampdu_len = 1;
+ tx_info->flags |=
+ IEEE80211_TX_STAT_AMPDU_NO_BACK;
+ skb_pull(p, D11_PHY_HDR_LEN);
+diff --git a/drivers/staging/gma500/psb_fb.c b/drivers/staging/gma500/psb_fb.c
+index f67f53b..1b96199 100644
+--- a/drivers/staging/gma500/psb_fb.c
++++ b/drivers/staging/gma500/psb_fb.c
+@@ -489,6 +489,16 @@ static int psbfb_create(struct psb_fbdev *fbdev,
+ info->screen_size = size;
+ memset(info->screen_base, 0, size);
+
++ if (dev_priv->pg->stolen_size) {
++ info->apertures = alloc_apertures(1);
++ if (!info->apertures) {
++ ret = -ENOMEM;
++ goto out_err0;
++ }
++ info->apertures->ranges[0].base = dev->mode_config.fb_base;
++ info->apertures->ranges[0].size = dev_priv->pg->stolen_size;
++ }
++
+ drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
+ drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
+ sizes->fb_width, sizes->fb_height);
+diff --git a/drivers/staging/lirc/lirc_zilog.c b/drivers/staging/lirc/lirc_zilog.c
+index dd6a57c..4e051f6 100644
+--- a/drivers/staging/lirc/lirc_zilog.c
++++ b/drivers/staging/lirc/lirc_zilog.c
+@@ -475,14 +475,14 @@ static int lirc_thread(void *arg)
+ dprintk("poll thread started\n");
+
+ while (!kthread_should_stop()) {
++ set_current_state(TASK_INTERRUPTIBLE);
++
+ /* if device not opened, we can sleep half a second */
+ if (atomic_read(&ir->open_count) == 0) {
+ schedule_timeout(HZ/2);
+ continue;
+ }
+
+- set_current_state(TASK_INTERRUPTIBLE);
+-
+ /*
+ * This is ~113*2 + 24 + jitter (2*repeat gap + code length).
+ * We use this interval as the chip resets every time you poll
+diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c
+index 8b1451d..8486eb1 100644
+--- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c
++++ b/drivers/staging/rtl8712/rtl871x_ioctl_set.c
+@@ -68,7 +68,10 @@ static u8 do_join(struct _adapter *padapter)
+ pmlmepriv->fw_state |= _FW_UNDER_LINKING;
+ pmlmepriv->pscanned = plist;
+ pmlmepriv->to_join = true;
+- if (_queue_empty(queue) == true) {
++
++ /* adhoc mode will start with an empty queue, but skip checking */
++ if (!check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) &&
++ _queue_empty(queue)) {
+ if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
+ pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
+ /* when set_ssid/set_bssid for do_join(), but scanning queue
+diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c
+index 7b1fe45..37b650b 100644
+--- a/drivers/staging/usbip/usbip_common.c
++++ b/drivers/staging/usbip/usbip_common.c
+@@ -604,7 +604,7 @@ static void correct_endian_ret_submit(struct usbip_header_ret_submit *pdu,
+ be32_to_cpus(&pdu->status);
+ be32_to_cpus(&pdu->actual_length);
+ be32_to_cpus(&pdu->start_frame);
+- cpu_to_be32s(&pdu->number_of_packets);
++ be32_to_cpus(&pdu->number_of_packets);
+ be32_to_cpus(&pdu->error_count);
+ }
+ }
+diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c
+index d25e208..fc10ed4 100644
+--- a/drivers/target/target_core_device.c
++++ b/drivers/target/target_core_device.c
+@@ -150,13 +150,13 @@ out:
+
+ {
+ struct se_device *dev = se_lun->lun_se_dev;
+- spin_lock(&dev->stats_lock);
++ spin_lock_irq(&dev->stats_lock);
+ dev->num_cmds++;
+ if (se_cmd->data_direction == DMA_TO_DEVICE)
+ dev->write_bytes += se_cmd->data_length;
+ else if (se_cmd->data_direction == DMA_FROM_DEVICE)
+ dev->read_bytes += se_cmd->data_length;
+- spin_unlock(&dev->stats_lock);
++ spin_unlock_irq(&dev->stats_lock);
+ }
+
+ /*
+diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c
+index 4a10983..59b8b9c 100644
+--- a/drivers/target/target_core_tmr.c
++++ b/drivers/target/target_core_tmr.c
+@@ -55,7 +55,8 @@ struct se_tmr_req *core_tmr_alloc_req(
+ {
+ struct se_tmr_req *tmr;
+
+- tmr = kmem_cache_zalloc(se_tmr_req_cache, GFP_KERNEL);
++ tmr = kmem_cache_zalloc(se_tmr_req_cache, (in_interrupt()) ?
++ GFP_ATOMIC : GFP_KERNEL);
+ if (!(tmr)) {
+ printk(KERN_ERR "Unable to allocate struct se_tmr_req\n");
+ return ERR_PTR(-ENOMEM);
+@@ -398,9 +399,9 @@ int core_tmr_lun_reset(
+ printk(KERN_INFO "LUN_RESET: SCSI-2 Released reservation\n");
+ }
+
+- spin_lock(&dev->stats_lock);
++ spin_lock_irq(&dev->stats_lock);
+ dev->num_resets++;
+- spin_unlock(&dev->stats_lock);
++ spin_unlock_irq(&dev->stats_lock);
+
+ DEBUG_LR("LUN_RESET: %s for [%s] Complete\n",
+ (preempt_and_abort_list) ? "Preempt" : "TMR",
+diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
+index 9583b23..beaf8fa 100644
+--- a/drivers/target/target_core_transport.c
++++ b/drivers/target/target_core_transport.c
+@@ -762,7 +762,6 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd)
+ transport_all_task_dev_remove_state(cmd);
+ spin_unlock_irqrestore(&T_TASK(cmd)->t_state_lock, flags);
+
+- transport_free_dev_tasks(cmd);
+
+ check_lun:
+ spin_lock_irqsave(&lun->lun_cmd_lock, flags);
+@@ -1195,6 +1194,7 @@ transport_get_task_from_execute_queue(struct se_device *dev)
+ break;
+
+ list_del(&task->t_execute_list);
++ atomic_set(&task->task_execute_queue, 0);
+ atomic_dec(&dev->execute_tasks);
+
+ return task;
+@@ -1210,8 +1210,14 @@ void transport_remove_task_from_execute_queue(
+ {
+ unsigned long flags;
+
++ if (atomic_read(&task->task_execute_queue) == 0) {
++ dump_stack();
++ return;
++ }
++
+ spin_lock_irqsave(&dev->execute_task_lock, flags);
+ list_del(&task->t_execute_list);
++ atomic_set(&task->task_execute_queue, 0);
+ atomic_dec(&dev->execute_tasks);
+ spin_unlock_irqrestore(&dev->execute_task_lock, flags);
+ }
+@@ -2058,6 +2064,13 @@ int transport_generic_handle_tmr(
+ }
+ EXPORT_SYMBOL(transport_generic_handle_tmr);
+
++void transport_generic_free_cmd_intr(
++ struct se_cmd *cmd)
++{
++ transport_add_cmd_to_queue(cmd, TRANSPORT_FREE_CMD_INTR);
++}
++EXPORT_SYMBOL(transport_generic_free_cmd_intr);
++
+ static int transport_stop_tasks_for_cmd(struct se_cmd *cmd)
+ {
+ struct se_task *task, *task_tmp;
+@@ -4776,18 +4789,20 @@ void transport_do_task_sg_chain(struct se_cmd *cmd)
+ sg_end_cur->page_link &= ~0x02;
+
+ sg_chain(sg_head, task_sg_num, sg_head_cur);
+- sg_count += (task->task_sg_num + 1);
+- } else
+ sg_count += task->task_sg_num;
++ task_sg_num = (task->task_sg_num + 1);
++ } else {
++ sg_chain(sg_head, task_sg_num, sg_head_cur);
++ sg_count += task->task_sg_num;
++ task_sg_num = task->task_sg_num;
++ }
+
+ sg_head = sg_head_cur;
+ sg_link = sg_link_cur;
+- task_sg_num = task->task_sg_num;
+ continue;
+ }
+ sg_head = sg_first = &task->task_sg[0];
+ sg_link = &task->task_sg[task->task_sg_num];
+- task_sg_num = task->task_sg_num;
+ /*
+ * Check for single task..
+ */
+@@ -4798,9 +4813,12 @@ void transport_do_task_sg_chain(struct se_cmd *cmd)
+ */
+ sg_end = &task->task_sg[task->task_sg_num - 1];
+ sg_end->page_link &= ~0x02;
+- sg_count += (task->task_sg_num + 1);
+- } else
+ sg_count += task->task_sg_num;
++ task_sg_num = (task->task_sg_num + 1);
++ } else {
++ sg_count += task->task_sg_num;
++ task_sg_num = task->task_sg_num;
++ }
+ }
+ /*
+ * Setup the starting pointer and total t_tasks_sg_linked_no including
+@@ -4809,21 +4827,20 @@ void transport_do_task_sg_chain(struct se_cmd *cmd)
+ T_TASK(cmd)->t_tasks_sg_chained = sg_first;
+ T_TASK(cmd)->t_tasks_sg_chained_no = sg_count;
+
+- DEBUG_CMD_M("Setup T_TASK(cmd)->t_tasks_sg_chained: %p and"
+- " t_tasks_sg_chained_no: %u\n", T_TASK(cmd)->t_tasks_sg_chained,
++ DEBUG_CMD_M("Setup cmd: %p T_TASK(cmd)->t_tasks_sg_chained: %p and"
++ " t_tasks_sg_chained_no: %u\n", cmd, T_TASK(cmd)->t_tasks_sg_chained,
+ T_TASK(cmd)->t_tasks_sg_chained_no);
+
+ for_each_sg(T_TASK(cmd)->t_tasks_sg_chained, sg,
+ T_TASK(cmd)->t_tasks_sg_chained_no, i) {
+
+- DEBUG_CMD_M("SG: %p page: %p length: %d offset: %d\n",
+- sg, sg_page(sg), sg->length, sg->offset);
++ DEBUG_CMD_M("SG[%d]: %p page: %p length: %d offset: %d, magic: 0x%08x\n",
++ i, sg, sg_page(sg), sg->length, sg->offset, sg->sg_magic);
+ if (sg_is_chain(sg))
+ DEBUG_CMD_M("SG: %p sg_is_chain=1\n", sg);
+ if (sg_is_last(sg))
+ DEBUG_CMD_M("SG: %p sg_is_last=1\n", sg);
+ }
+-
+ }
+ EXPORT_SYMBOL(transport_do_task_sg_chain);
+
+@@ -5297,6 +5314,8 @@ void transport_generic_free_cmd(
+ if (wait_for_tasks && cmd->transport_wait_for_tasks)
+ cmd->transport_wait_for_tasks(cmd, 0, 0);
+
++ transport_free_dev_tasks(cmd);
++
+ transport_generic_remove(cmd, release_to_pool,
+ session_reinstatement);
+ }
+@@ -6132,6 +6151,9 @@ get_cmd:
+ case TRANSPORT_REMOVE:
+ transport_generic_remove(cmd, 1, 0);
+ break;
++ case TRANSPORT_FREE_CMD_INTR:
++ transport_generic_free_cmd(cmd, 0, 1, 0);
++ break;
+ case TRANSPORT_PROCESS_TMR:
+ transport_generic_do_tmr(cmd);
+ break;
+diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c
+index 26403b8..da9270e 100644
+--- a/drivers/tty/serial/pch_uart.c
++++ b/drivers/tty/serial/pch_uart.c
+@@ -1392,6 +1392,7 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
+ int fifosize, base_baud;
+ int port_type;
+ struct pch_uart_driver_data *board;
++ const char *board_name;
+
+ board = &drv_dat[id->driver_data];
+ port_type = board->port_type;
+@@ -1407,7 +1408,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev,
+ base_baud = 1843200; /* 1.8432MHz */
+
+ /* quirk for CM-iTC board */
+- if (strstr(dmi_get_system_info(DMI_BOARD_NAME), "CM-iTC"))
++ board_name = dmi_get_system_info(DMI_BOARD_NAME);
++ if (board_name && strstr(board_name, "CM-iTC"))
+ base_baud = 192000000; /* 192.0MHz */
+
+ switch (port_type) {
+diff --git a/drivers/tty/serial/s5pv210.c b/drivers/tty/serial/s5pv210.c
+index 6ebccd7..453e5b7 100644
+--- a/drivers/tty/serial/s5pv210.c
++++ b/drivers/tty/serial/s5pv210.c
+@@ -31,7 +31,7 @@ static int s5pv210_serial_setsource(struct uart_port *port,
+ struct s3c2410_uartcfg *cfg = port->dev->platform_data;
+ unsigned long ucon = rd_regl(port, S3C2410_UCON);
+
+- if ((cfg->clocks_size) == 1)
++ if (cfg->flags & NO_NEED_CHECK_CLKSRC)
+ return 0;
+
+ if (strcmp(clk->name, "pclk") == 0)
+@@ -56,7 +56,7 @@ static int s5pv210_serial_getsource(struct uart_port *port,
+
+ clk->divisor = 1;
+
+- if ((cfg->clocks_size) == 1)
++ if (cfg->flags & NO_NEED_CHECK_CLKSRC)
+ return 0;
+
+ switch (ucon & S5PV210_UCON_CLKMASK) {
+diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
+index 733fe8e..d4bee1b 100644
+--- a/drivers/tty/serial/serial_core.c
++++ b/drivers/tty/serial/serial_core.c
+@@ -172,12 +172,16 @@ static int uart_startup(struct tty_struct *tty, struct uart_state *state, int in
+
+ retval = uport->ops->startup(uport);
+ if (retval == 0) {
+- if (init_hw) {
+- /*
+- * Initialise the hardware port settings.
+- */
+- uart_change_speed(tty, state, NULL);
++ if (uart_console(uport) && uport->cons->cflag) {
++ tty->termios->c_cflag = uport->cons->cflag;
++ uport->cons->cflag = 0;
++ }
++ /*
++ * Initialise the hardware port settings.
++ */
++ uart_change_speed(tty, state, NULL);
+
++ if (init_hw) {
+ /*
+ * Setup the RTS and DTR signals once the
+ * port is open and ready to respond.
+@@ -1466,45 +1470,6 @@ static void uart_hangup(struct tty_struct *tty)
+ mutex_unlock(&port->mutex);
+ }
+
+-/**
+- * uart_update_termios - update the terminal hw settings
+- * @tty: tty associated with UART
+- * @state: UART to update
+- *
+- * Copy across the serial console cflag setting into the termios settings
+- * for the initial open of the port. This allows continuity between the
+- * kernel settings, and the settings init adopts when it opens the port
+- * for the first time.
+- */
+-static void uart_update_termios(struct tty_struct *tty,
+- struct uart_state *state)
+-{
+- struct uart_port *port = state->uart_port;
+-
+- if (uart_console(port) && port->cons->cflag) {
+- tty->termios->c_cflag = port->cons->cflag;
+- port->cons->cflag = 0;
+- }
+-
+- /*
+- * If the device failed to grab its irq resources,
+- * or some other error occurred, don't try to talk
+- * to the port hardware.
+- */
+- if (!(tty->flags & (1 << TTY_IO_ERROR))) {
+- /*
+- * Make termios settings take effect.
+- */
+- uart_change_speed(tty, state, NULL);
+-
+- /*
+- * And finally enable the RTS and DTR signals.
+- */
+- if (tty->termios->c_cflag & CBAUD)
+- uart_set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+- }
+-}
+-
+ static int uart_carrier_raised(struct tty_port *port)
+ {
+ struct uart_state *state = container_of(port, struct uart_state, port);
+@@ -1524,16 +1489,8 @@ static void uart_dtr_rts(struct tty_port *port, int onoff)
+ struct uart_state *state = container_of(port, struct uart_state, port);
+ struct uart_port *uport = state->uart_port;
+
+- if (onoff) {
++ if (onoff)
+ uart_set_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
+-
+- /*
+- * If this is the first open to succeed,
+- * adjust things to suit.
+- */
+- if (!test_and_set_bit(ASYNCB_NORMAL_ACTIVE, &port->flags))
+- uart_update_termios(port->tty, state);
+- }
+ else
+ uart_clear_mctrl(uport, TIOCM_DTR | TIOCM_RTS);
+ }
+diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
+index e19e136..1104c9d 100644
+--- a/drivers/tty/tty_ldisc.c
++++ b/drivers/tty/tty_ldisc.c
+@@ -555,7 +555,7 @@ static void tty_ldisc_flush_works(struct tty_struct *tty)
+ static int tty_ldisc_wait_idle(struct tty_struct *tty)
+ {
+ int ret;
+- ret = wait_event_interruptible_timeout(tty_ldisc_idle,
++ ret = wait_event_timeout(tty_ldisc_idle,
+ atomic_read(&tty->ldisc->users) == 1, 5 * HZ);
+ if (ret < 0)
+ return ret;
+@@ -763,6 +763,8 @@ static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
+ if (IS_ERR(ld))
+ return -1;
+
++ WARN_ON_ONCE(tty_ldisc_wait_idle(tty));
++
+ tty_ldisc_close(tty, tty->ldisc);
+ tty_ldisc_put(tty->ldisc);
+ tty->ldisc = NULL;
+diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
+index e057e53..d0b84ff 100644
+--- a/drivers/usb/class/cdc-acm.c
++++ b/drivers/usb/class/cdc-acm.c
+@@ -946,7 +946,7 @@ static int acm_probe(struct usb_interface *intf,
+ u8 ac_management_function = 0;
+ u8 call_management_function = 0;
+ int call_interface_num = -1;
+- int data_interface_num;
++ int data_interface_num = -1;
+ unsigned long quirks;
+ int num_rx_buf;
+ int i;
+@@ -1030,7 +1030,11 @@ next_desc:
+ if (!union_header) {
+ if (call_interface_num > 0) {
+ dev_dbg(&intf->dev, "No union descriptor, using call management descriptor\n");
+- data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num));
++ /* quirks for Droids MuIn LCD */
++ if (quirks & NO_DATA_INTERFACE)
++ data_interface = usb_ifnum_to_if(usb_dev, 0);
++ else
++ data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num));
+ control_interface = intf;
+ } else {
+ if (intf->cur_altsetting->desc.bNumEndpoints != 3) {
+@@ -1613,6 +1617,8 @@ static const struct usb_device_id acm_ids[] = {
+ { NOKIA_PCSUITE_ACM_INFO(0x04ce), }, /* Nokia E90 */
+ { NOKIA_PCSUITE_ACM_INFO(0x01d4), }, /* Nokia E55 */
+ { NOKIA_PCSUITE_ACM_INFO(0x0302), }, /* Nokia N8 */
++ { NOKIA_PCSUITE_ACM_INFO(0x0335), }, /* Nokia E7 */
++ { NOKIA_PCSUITE_ACM_INFO(0x03cd), }, /* Nokia C7 */
+ { SAMSUNG_PCSUITE_ACM_INFO(0x6651), }, /* Samsung GTi8510 (INNOV8) */
+
+ /* NOTE: non-Nokia COMM/ACM/0xff is likely MSFT RNDIS... NOT a modem! */
+@@ -1622,6 +1628,11 @@ static const struct usb_device_id acm_ids[] = {
+ .driver_info = NOT_A_MODEM,
+ },
+
++ /* Support for Droids MuIn LCD */
++ { USB_DEVICE(0x04d8, 0x000b),
++ .driver_info = NO_DATA_INTERFACE,
++ },
++
+ /* control interfaces without any protocol set */
+ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+ USB_CDC_PROTO_NONE) },
+diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
+index b4ea54d..683104a 100644
+--- a/drivers/usb/class/cdc-acm.h
++++ b/drivers/usb/class/cdc-acm.h
+@@ -137,3 +137,4 @@ struct acm {
+ #define SINGLE_RX_URB 2
+ #define NO_CAP_LINE 4
+ #define NOT_A_MODEM 8
++#define NO_DATA_INTERFACE 16
+diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
+index e35a176..34e3da5 100644
+--- a/drivers/usb/core/driver.c
++++ b/drivers/usb/core/driver.c
+@@ -375,7 +375,7 @@ static int usb_unbind_interface(struct device *dev)
+ * Just re-enable it without affecting the endpoint toggles.
+ */
+ usb_enable_interface(udev, intf, false);
+- } else if (!error && !intf->dev.power.in_suspend) {
++ } else if (!error && !intf->dev.power.is_prepared) {
+ r = usb_set_interface(udev, intf->altsetting[0].
+ desc.bInterfaceNumber, 0);
+ if (r < 0)
+@@ -960,7 +960,7 @@ void usb_rebind_intf(struct usb_interface *intf)
+ }
+
+ /* Try to rebind the interface */
+- if (!intf->dev.power.in_suspend) {
++ if (!intf->dev.power.is_prepared) {
+ intf->needs_binding = 0;
+ rc = device_attach(&intf->dev);
+ if (rc < 0)
+@@ -1107,7 +1107,7 @@ static int usb_resume_interface(struct usb_device *udev,
+ if (intf->condition == USB_INTERFACE_UNBOUND) {
+
+ /* Carry out a deferred switch to altsetting 0 */
+- if (intf->needs_altsetting0 && !intf->dev.power.in_suspend) {
++ if (intf->needs_altsetting0 && !intf->dev.power.is_prepared) {
+ usb_set_interface(udev, intf->altsetting[0].
+ desc.bInterfaceNumber, 0);
+ intf->needs_altsetting0 = 0;
+@@ -1187,13 +1187,22 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
+ for (i = n - 1; i >= 0; --i) {
+ intf = udev->actconfig->interface[i];
+ status = usb_suspend_interface(udev, intf, msg);
++
++ /* Ignore errors during system sleep transitions */
++ if (!(msg.event & PM_EVENT_AUTO))
++ status = 0;
+ if (status != 0)
+ break;
+ }
+ }
+- if (status == 0)
++ if (status == 0) {
+ status = usb_suspend_device(udev, msg);
+
++ /* Again, ignore errors during system sleep transitions */
++ if (!(msg.event & PM_EVENT_AUTO))
++ status = 0;
++ }
++
+ /* If the suspend failed, resume interfaces that did get suspended */
+ if (status != 0) {
+ msg.event ^= (PM_EVENT_SUSPEND | PM_EVENT_RESUME);
+diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
+index 77a7fae..cddc533 100644
+--- a/drivers/usb/core/hcd.c
++++ b/drivers/usb/core/hcd.c
+@@ -986,7 +986,7 @@ static int register_root_hub(struct usb_hcd *hcd)
+ spin_unlock_irq (&hcd_root_hub_lock);
+
+ /* Did the HC die before the root hub was registered? */
+- if (HCD_DEAD(hcd) || hcd->state == HC_STATE_HALT)
++ if (HCD_DEAD(hcd))
+ usb_hc_died (hcd); /* This time clean up */
+ }
+
+@@ -2128,9 +2128,6 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)
+ set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
+ if (hcd->shared_hcd)
+ set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);
+-
+- if (unlikely(hcd->state == HC_STATE_HALT))
+- usb_hc_died(hcd);
+ rc = IRQ_HANDLED;
+ }
+
+diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
+index 93720bd..64edb30 100644
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -339,7 +339,8 @@ static int get_hub_status(struct usb_device *hdev,
+ {
+ int i, status = -ETIMEDOUT;
+
+- for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) {
++ for (i = 0; i < USB_STS_RETRIES &&
++ (status == -ETIMEDOUT || status == -EPIPE); i++) {
+ status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
+ USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_HUB, 0, 0,
+ data, sizeof(*data), USB_STS_TIMEOUT);
+@@ -355,7 +356,8 @@ static int get_port_status(struct usb_device *hdev, int port1,
+ {
+ int i, status = -ETIMEDOUT;
+
+- for (i = 0; i < USB_STS_RETRIES && status == -ETIMEDOUT; i++) {
++ for (i = 0; i < USB_STS_RETRIES &&
++ (status == -ETIMEDOUT || status == -EPIPE); i++) {
+ status = usb_control_msg(hdev, usb_rcvctrlpipe(hdev, 0),
+ USB_REQ_GET_STATUS, USB_DIR_IN | USB_RT_PORT, 0, port1,
+ data, sizeof(*data), USB_STS_TIMEOUT);
+@@ -1641,6 +1643,7 @@ void usb_disconnect(struct usb_device **pdev)
+ {
+ struct usb_device *udev = *pdev;
+ int i;
++ struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+
+ if (!udev) {
+ pr_debug ("%s nodev\n", __func__);
+@@ -1668,7 +1671,9 @@ void usb_disconnect(struct usb_device **pdev)
+ * so that the hardware is now fully quiesced.
+ */
+ dev_dbg (&udev->dev, "unregistering device\n");
++ mutex_lock(hcd->bandwidth_mutex);
+ usb_disable_device(udev, 0);
++ mutex_unlock(hcd->bandwidth_mutex);
+ usb_hcd_synchronize_unlinks(udev);
+
+ usb_remove_ep_devs(&udev->ep0);
+@@ -2306,6 +2311,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
+ USB_DEVICE_REMOTE_WAKEUP, 0,
+ NULL, 0,
+ USB_CTRL_SET_TIMEOUT);
++
++ /* System sleep transitions should never fail */
++ if (!(msg.event & PM_EVENT_AUTO))
++ status = 0;
+ } else {
+ /* device has up to 10 msec to fully suspend */
+ dev_dbg(&udev->dev, "usb %ssuspend\n",
+@@ -2544,16 +2553,15 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
+ struct usb_device *hdev = hub->hdev;
+ unsigned port1;
+
+- /* fail if children aren't already suspended */
++ /* Warn if children aren't already suspended */
+ for (port1 = 1; port1 <= hdev->maxchild; port1++) {
+ struct usb_device *udev;
+
+ udev = hdev->children [port1-1];
+ if (udev && udev->can_submit) {
+- if (!(msg.event & PM_EVENT_AUTO))
+- dev_dbg(&intf->dev, "port %d nyet suspended\n",
+- port1);
+- return -EBUSY;
++ dev_warn(&intf->dev, "port %d nyet suspended\n", port1);
++ if (msg.event & PM_EVENT_AUTO)
++ return -EBUSY;
+ }
+ }
+
+diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
+index 5701e85..0b5ec23 100644
+--- a/drivers/usb/core/message.c
++++ b/drivers/usb/core/message.c
+@@ -1135,15 +1135,26 @@ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf,
+ * Deallocates hcd/hardware state for the endpoints (nuking all or most
+ * pending urbs) and usbcore state for the interfaces, so that usbcore
+ * must usb_set_configuration() before any interfaces could be used.
++ *
++ * Must be called with hcd->bandwidth_mutex held.
+ */
+ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ {
+ int i;
++ struct usb_hcd *hcd = bus_to_hcd(dev->bus);
+
+ /* getting rid of interfaces will disconnect
+ * any drivers bound to them (a key side effect)
+ */
+ if (dev->actconfig) {
++ /*
++ * FIXME: In order to avoid self-deadlock involving the
++ * bandwidth_mutex, we have to mark all the interfaces
++ * before unregistering any of them.
++ */
++ for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++)
++ dev->actconfig->interface[i]->unregistering = 1;
++
+ for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
+ struct usb_interface *interface;
+
+@@ -1153,7 +1164,6 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+ continue;
+ dev_dbg(&dev->dev, "unregistering interface %s\n",
+ dev_name(&interface->dev));
+- interface->unregistering = 1;
+ remove_intf_ep_devs(interface);
+ device_del(&interface->dev);
+ }
+@@ -1172,6 +1182,16 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
+
+ dev_dbg(&dev->dev, "%s nuking %s URBs\n", __func__,
+ skip_ep0 ? "non-ep0" : "all");
++ if (hcd->driver->check_bandwidth) {
++ /* First pass: Cancel URBs, leave endpoint pointers intact. */
++ for (i = skip_ep0; i < 16; ++i) {
++ usb_disable_endpoint(dev, i, false);
++ usb_disable_endpoint(dev, i + USB_DIR_IN, false);
++ }
++ /* Remove endpoints from the host controller internal state */
++ usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL);
++ /* Second pass: remove endpoint pointers */
++ }
+ for (i = skip_ep0; i < 16; ++i) {
+ usb_disable_endpoint(dev, i, true);
+ usb_disable_endpoint(dev, i + USB_DIR_IN, true);
+@@ -1273,6 +1293,8 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
+ interface);
+ return -EINVAL;
+ }
++ if (iface->unregistering)
++ return -ENODEV;
+
+ alt = usb_altnum_to_altsetting(iface, alternate);
+ if (!alt) {
+@@ -1727,6 +1749,7 @@ free_interfaces:
+ /* if it's already configured, clear out old state first.
+ * getting rid of old interfaces means unbinding their drivers.
+ */
++ mutex_lock(hcd->bandwidth_mutex);
+ if (dev->state != USB_STATE_ADDRESS)
+ usb_disable_device(dev, 1); /* Skip ep0 */
+
+@@ -1739,7 +1762,6 @@ free_interfaces:
+ * host controller will not allow submissions to dropped endpoints. If
+ * this call fails, the device state is unchanged.
+ */
+- mutex_lock(hcd->bandwidth_mutex);
+ ret = usb_hcd_alloc_bandwidth(dev, cp, NULL, NULL);
+ if (ret < 0) {
+ mutex_unlock(hcd->bandwidth_mutex);
+diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c
+index 882484a..fa12ec8 100644
+--- a/drivers/usb/gadget/f_rndis.c
++++ b/drivers/usb/gadget/f_rndis.c
+@@ -420,8 +420,7 @@ rndis_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+ */
+ case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
+ | USB_CDC_SEND_ENCAPSULATED_COMMAND:
+- if (w_length > req->length || w_value
+- || w_index != rndis->ctrl_id)
++ if (w_value || w_index != rndis->ctrl_id)
+ goto invalid;
+ /* read the request; process it later */
+ value = w_length;
+diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
+index 78561d1..c606b02 100644
+--- a/drivers/usb/host/ehci-hcd.c
++++ b/drivers/usb/host/ehci-hcd.c
+@@ -777,8 +777,9 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ goto dead;
+ }
+
++ /* Shared IRQ? */
+ masked_status = status & INTR_MASK;
+- if (!masked_status) { /* irq sharing? */
++ if (!masked_status || unlikely(hcd->state == HC_STATE_HALT)) {
+ spin_unlock(&ehci->lock);
+ return IRQ_NONE;
+ }
+@@ -873,6 +874,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
+ dead:
+ ehci_reset(ehci);
+ ehci_writel(ehci, 0, &ehci->regs->configured_flag);
++ usb_hc_died(hcd);
+ /* generic layer kills/unlinks all urbs, then
+ * uses ehci_stop to clean up the rest
+ */
+diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c
+index 1543c83..d12426f 100644
+--- a/drivers/usb/host/ehci-sched.c
++++ b/drivers/usb/host/ehci-sched.c
+@@ -471,8 +471,10 @@ static int enable_periodic (struct ehci_hcd *ehci)
+ */
+ status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
+ STS_PSS, 0, 9 * 125);
+- if (status)
++ if (status) {
++ usb_hc_died(ehci_to_hcd(ehci));
+ return status;
++ }
+
+ cmd = ehci_readl(ehci, &ehci->regs->command) | CMD_PSE;
+ ehci_writel(ehci, cmd, &ehci->regs->command);
+@@ -510,8 +512,10 @@ static int disable_periodic (struct ehci_hcd *ehci)
+ */
+ status = handshake_on_error_set_halt(ehci, &ehci->regs->status,
+ STS_PSS, STS_PSS, 9 * 125);
+- if (status)
++ if (status) {
++ usb_hc_died(ehci_to_hcd(ehci));
+ return status;
++ }
+
+ cmd = ehci_readl(ehci, &ehci->regs->command) & ~CMD_PSE;
+ ehci_writel(ehci, cmd, &ehci->regs->command);
+diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
+index c0e22f2..baae4cc 100644
+--- a/drivers/usb/host/isp116x-hcd.c
++++ b/drivers/usb/host/isp116x-hcd.c
+@@ -612,6 +612,7 @@ static irqreturn_t isp116x_irq(struct usb_hcd *hcd)
+ /* IRQ's are off, we do no DMA,
+ perfectly ready to die ... */
+ hcd->state = HC_STATE_HALT;
++ usb_hc_died(hcd);
+ ret = IRQ_HANDLED;
+ goto done;
+ }
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index d557235..c001fff 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -764,6 +764,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ if (ints == ~(u32)0) {
+ disable (ohci);
+ ohci_dbg (ohci, "device removed!\n");
++ usb_hc_died(hcd);
+ return IRQ_HANDLED;
+ }
+
+@@ -771,7 +772,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ ints &= ohci_readl(ohci, &regs->intrenable);
+
+ /* interrupt for some other device? */
+- if (ints == 0)
++ if (ints == 0 || unlikely(hcd->state == HC_STATE_HALT))
+ return IRQ_NOTMINE;
+
+ if (ints & OHCI_INTR_UE) {
+@@ -788,6 +789,7 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
+ } else {
+ disable (ohci);
+ ohci_err (ohci, "OHCI Unrecoverable Error, disabled\n");
++ usb_hc_died(hcd);
+ }
+
+ ohci_dump (ohci, 1);
+diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
+index d84d6f0..ad8166c 100644
+--- a/drivers/usb/host/ohci-pci.c
++++ b/drivers/usb/host/ohci-pci.c
+@@ -181,10 +181,18 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd)
+ */
+ static int ohci_quirk_nvidia_shutdown(struct usb_hcd *hcd)
+ {
++ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+
+- ohci->flags |= OHCI_QUIRK_SHUTDOWN;
+- ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
++ /* Evidently nVidia fixed their later hardware; this is a guess at
++ * the changeover point.
++ */
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB 0x026d
++
++ if (pdev->device < PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_USB) {
++ ohci->flags |= OHCI_QUIRK_SHUTDOWN;
++ ohci_dbg(ohci, "enabled nVidia shutdown quirk\n");
++ }
+
+ return 0;
+ }
+diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
+index 4a771f6..5fbe997 100644
+--- a/drivers/usb/host/oxu210hp-hcd.c
++++ b/drivers/usb/host/oxu210hp-hcd.c
+@@ -1884,6 +1884,7 @@ static int enable_periodic(struct oxu_hcd *oxu)
+ status = handshake(oxu, &oxu->regs->status, STS_PSS, 0, 9 * 125);
+ if (status != 0) {
+ oxu_to_hcd(oxu)->state = HC_STATE_HALT;
++ usb_hc_died(oxu_to_hcd(oxu));
+ return status;
+ }
+
+@@ -1909,6 +1910,7 @@ static int disable_periodic(struct oxu_hcd *oxu)
+ status = handshake(oxu, &oxu->regs->status, STS_PSS, STS_PSS, 9 * 125);
+ if (status != 0) {
+ oxu_to_hcd(oxu)->state = HC_STATE_HALT;
++ usb_hc_died(oxu_to_hcd(oxu));
+ return status;
+ }
+
+@@ -2449,8 +2451,9 @@ static irqreturn_t oxu210_hcd_irq(struct usb_hcd *hcd)
+ goto dead;
+ }
+
++ /* Shared IRQ? */
+ status &= INTR_MASK;
+- if (!status) { /* irq sharing? */
++ if (!status || unlikely(hcd->state == HC_STATE_HALT)) {
+ spin_unlock(&oxu->lock);
+ return IRQ_NONE;
+ }
+@@ -2516,6 +2519,7 @@ static irqreturn_t oxu210_hcd_irq(struct usb_hcd *hcd)
+ dead:
+ ehci_reset(oxu);
+ writel(0, &oxu->regs->configured_flag);
++ usb_hc_died(hcd);
+ /* generic layer kills/unlinks all urbs, then
+ * uses oxu_stop to clean up the rest
+ */
+diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c
+index 0231814..ff00bd8 100644
+--- a/drivers/usb/host/xhci-dbg.c
++++ b/drivers/usb/host/xhci-dbg.c
+@@ -437,13 +437,13 @@ char *xhci_get_slot_state(struct xhci_hcd *xhci,
+ struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);
+
+ switch (GET_SLOT_STATE(slot_ctx->dev_state)) {
+- case 0:
++ case SLOT_STATE_ENABLED:
+ return "enabled/disabled";
+- case 1:
++ case SLOT_STATE_DEFAULT:
+ return "default";
+- case 2:
++ case SLOT_STATE_ADDRESSED:
+ return "addressed";
+- case 3:
++ case SLOT_STATE_CONFIGURED:
+ return "configured";
+ default:
+ return "reserved";
+diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
+index 627f343..976422a 100644
+--- a/drivers/usb/host/xhci-mem.c
++++ b/drivers/usb/host/xhci-mem.c
+@@ -207,14 +207,13 @@ void xhci_free_or_cache_endpoint_ring(struct xhci_hcd *xhci,
+
+ rings_cached = virt_dev->num_rings_cached;
+ if (rings_cached < XHCI_MAX_RINGS_CACHED) {
+- virt_dev->num_rings_cached++;
+- rings_cached = virt_dev->num_rings_cached;
+ virt_dev->ring_cache[rings_cached] =
+ virt_dev->eps[ep_index].ring;
++ virt_dev->num_rings_cached++;
+ xhci_dbg(xhci, "Cached old ring, "
+ "%d ring%s cached\n",
+- rings_cached,
+- (rings_cached > 1) ? "s" : "");
++ virt_dev->num_rings_cached,
++ (virt_dev->num_rings_cached > 1) ? "s" : "");
+ } else {
+ xhci_ring_free(xhci, virt_dev->eps[ep_index].ring);
+ xhci_dbg(xhci, "Ring cache full (%d rings), "
+@@ -987,9 +986,19 @@ static unsigned int xhci_parse_exponent_interval(struct usb_device *udev,
+ interval = clamp_val(ep->desc.bInterval, 1, 16) - 1;
+ if (interval != ep->desc.bInterval - 1)
+ dev_warn(&udev->dev,
+- "ep %#x - rounding interval to %d microframes\n",
++ "ep %#x - rounding interval to %d %sframes\n",
+ ep->desc.bEndpointAddress,
+- 1 << interval);
++ 1 << interval,
++ udev->speed == USB_SPEED_FULL ? "" : "micro");
++
++ if (udev->speed == USB_SPEED_FULL) {
++ /*
++ * Full speed isoc endpoints specify interval in frames,
++ * not microframes. We are using microframes everywhere,
++ * so adjust accordingly.
++ */
++ interval += 3; /* 1 frame = 2^3 uframes */
++ }
+
+ return interval;
+ }
+@@ -1046,12 +1055,12 @@ static unsigned int xhci_get_endpoint_interval(struct usb_device *udev,
+ break;
+
+ case USB_SPEED_FULL:
+- if (usb_endpoint_xfer_int(&ep->desc)) {
++ if (usb_endpoint_xfer_isoc(&ep->desc)) {
+ interval = xhci_parse_exponent_interval(udev, ep);
+ break;
+ }
+ /*
+- * Fall through for isochronous endpoint interval decoding
++ * Fall through for interrupt endpoint interval decoding
+ * since it uses the same rules as low speed interrupt
+ * endpoints.
+ */
+diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
+index a10494c..6fce318 100644
+--- a/drivers/usb/host/xhci-pci.c
++++ b/drivers/usb/host/xhci-pci.c
+@@ -28,6 +28,9 @@
+ #define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
+ #define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
+
++#define PCI_VENDOR_ID_ETRON 0x1b6f
++#define PCI_DEVICE_ID_ASROCK_P67 0x7023
++
+ static const char hcd_name[] = "xhci_hcd";
+
+ /* called after powerup, by probe or system-pm "wakeup" */
+@@ -105,12 +108,27 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
+
+ /* Look for vendor-specific quirks */
+ if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC &&
+- pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK &&
+- pdev->revision == 0x0) {
++ pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK) {
++ if (pdev->revision == 0x0) {
+ xhci->quirks |= XHCI_RESET_EP_QUIRK;
+ xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure"
+ " endpoint cmd after reset endpoint\n");
++ }
++ /* Fresco Logic confirms: all revisions of this chip do not
++ * support MSI, even though some of them claim to in their PCI
++ * capabilities.
++ */
++ xhci->quirks |= XHCI_BROKEN_MSI;
++ xhci_dbg(xhci, "QUIRK: Fresco Logic revision %u "
++ "has broken MSI implementation\n",
++ pdev->revision);
+ }
++ if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
++ pdev->device == PCI_DEVICE_ID_ASROCK_P67) {
++ xhci->quirks |= XHCI_RESET_ON_RESUME;
++ xhci_dbg(xhci, "QUIRK: Resetting on resume\n");
++ }
++
+ if (pdev->vendor == PCI_VENDOR_ID_NEC)
+ xhci->quirks |= XHCI_NEC_HOST;
+
+diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
+index 7437386..a5e96cb 100644
+--- a/drivers/usb/host/xhci-ring.c
++++ b/drivers/usb/host/xhci-ring.c
+@@ -1632,6 +1632,9 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ else
+ *status = 0;
+ break;
++ case COMP_STOP_INVAL:
++ case COMP_STOP:
++ return finish_td(xhci, td, event_trb, event, ep, status, false);
+ default:
+ if (!xhci_requires_manual_halt_cleanup(xhci,
+ ep_ctx, trb_comp_code))
+@@ -1676,15 +1679,12 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ }
+ } else {
+ /* Maybe the event was for the data stage? */
+- if (trb_comp_code != COMP_STOP_INVAL) {
+- /* We didn't stop on a link TRB in the middle */
+- td->urb->actual_length =
+- td->urb->transfer_buffer_length -
+- TRB_LEN(event->transfer_len);
+- xhci_dbg(xhci, "Waiting for status "
+- "stage event\n");
+- return 0;
+- }
++ td->urb->actual_length =
++ td->urb->transfer_buffer_length -
++ TRB_LEN(le32_to_cpu(event->transfer_len));
++ xhci_dbg(xhci, "Waiting for status "
++ "stage event\n");
++ return 0;
+ }
+ }
+
+@@ -1768,9 +1768,6 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ }
+ }
+
+- if ((idx == urb_priv->length - 1) && *status == -EINPROGRESS)
+- *status = 0;
+-
+ return finish_td(xhci, td, event_trb, event, ep, status, false);
+ }
+
+@@ -1788,8 +1785,7 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ idx = urb_priv->td_cnt;
+ frame = &td->urb->iso_frame_desc[idx];
+
+- /* The transfer is partly done */
+- *status = -EXDEV;
++ /* The transfer is partly done. */
+ frame->status = -EXDEV;
+
+ /* calc actual length */
+@@ -2139,6 +2135,11 @@ cleanup:
+ "status = %d\n",
+ urb, urb->actual_length, status);
+ spin_unlock(&xhci->lock);
++ /* EHCI, UHCI, and OHCI always unconditionally set the
++ * urb->status of an isochronous endpoint to 0.
++ */
++ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS)
++ status = 0;
+ usb_hcd_giveback_urb(bus_to_hcd(urb->dev->bus), urb, status);
+ spin_lock(&xhci->lock);
+ }
+diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
+index 81b976e..4209b02 100644
+--- a/drivers/usb/host/xhci.c
++++ b/drivers/usb/host/xhci.c
+@@ -430,12 +430,19 @@ int xhci_run(struct usb_hcd *hcd)
+ free_irq(hcd->irq, hcd);
+ hcd->irq = -1;
+
++ /* Some Fresco Logic host controllers advertise MSI, but fail to
++ * generate interrupts. Don't even try to enable MSI.
++ */
++ if (xhci->quirks & XHCI_BROKEN_MSI)
++ goto legacy_irq;
++
+ ret = xhci_setup_msix(xhci);
+ if (ret)
+ /* fall back to msi*/
+ ret = xhci_setup_msi(xhci);
+
+ if (ret) {
++legacy_irq:
+ /* fall back to legacy interrupt*/
+ ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
+ hcd->irq_descr, hcd);
+@@ -752,6 +759,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
+ msleep(100);
+
+ spin_lock_irq(&xhci->lock);
++ if (xhci->quirks & XHCI_RESET_ON_RESUME)
++ hibernated = true;
+
+ if (!hibernated) {
+ /* step 1: restore register */
+@@ -1389,6 +1398,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
+ u32 added_ctxs;
+ unsigned int last_ctx;
+ u32 new_add_flags, new_drop_flags, new_slot_info;
++ struct xhci_virt_device *virt_dev;
+ int ret = 0;
+
+ ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
+@@ -1411,11 +1421,25 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
+ return 0;
+ }
+
+- in_ctx = xhci->devs[udev->slot_id]->in_ctx;
+- out_ctx = xhci->devs[udev->slot_id]->out_ctx;
++ virt_dev = xhci->devs[udev->slot_id];
++ in_ctx = virt_dev->in_ctx;
++ out_ctx = virt_dev->out_ctx;
+ ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
+ ep_index = xhci_get_endpoint_index(&ep->desc);
+ ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
++
++ /* If this endpoint is already in use, and the upper layers are trying
++ * to add it again without dropping it, reject the addition.
++ */
++ if (virt_dev->eps[ep_index].ring &&
++ !(le32_to_cpu(ctrl_ctx->drop_flags) &
++ xhci_get_endpoint_flag(&ep->desc))) {
++ xhci_warn(xhci, "Trying to add endpoint 0x%x "
++ "without dropping it.\n",
++ (unsigned int) ep->desc.bEndpointAddress);
++ return -EINVAL;
++ }
++
+ /* If the HCD has already noted the endpoint is enabled,
+ * ignore this request.
+ */
+@@ -1430,8 +1454,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
+ * process context, not interrupt context (or so documenation
+ * for usb_set_interface() and usb_set_configuration() claim).
+ */
+- if (xhci_endpoint_init(xhci, xhci->devs[udev->slot_id],
+- udev, ep, GFP_NOIO) < 0) {
++ if (xhci_endpoint_init(xhci, virt_dev, udev, ep, GFP_NOIO) < 0) {
+ dev_dbg(&udev->dev, "%s - could not initialize ep %#x\n",
+ __func__, ep->desc.bEndpointAddress);
+ return -ENOMEM;
+@@ -1692,8 +1715,17 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
+ xhci_dbg_ctx(xhci, virt_dev->out_ctx,
+ LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
+
++ /* Free any rings that were dropped, but not changed. */
++ for (i = 1; i < 31; ++i) {
++ if ((ctrl_ctx->drop_flags & (1 << (i + 1))) &&
++ !(ctrl_ctx->add_flags & (1 << (i + 1))))
++ xhci_free_or_cache_endpoint_ring(xhci, virt_dev, i);
++ }
+ xhci_zero_in_ctx(xhci, virt_dev);
+- /* Install new rings and free or cache any old rings */
++ /*
++ * Install any rings for completely new endpoints or changed endpoints,
++ * and free or cache any old rings from changed endpoints.
++ */
+ for (i = 1; i < 31; ++i) {
+ if (!virt_dev->eps[i].new_ring)
+ continue;
+@@ -2275,6 +2307,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
+ struct xhci_command *reset_device_cmd;
+ int timeleft;
+ int last_freed_endpoint;
++ struct xhci_slot_ctx *slot_ctx;
+
+ ret = xhci_check_args(hcd, udev, NULL, 0, false, __func__);
+ if (ret <= 0)
+@@ -2307,6 +2340,12 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
+ return -EINVAL;
+ }
+
++ /* If device is not setup, there is no point in resetting it */
++ slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
++ if (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state)) ==
++ SLOT_STATE_DISABLED)
++ return 0;
++
+ xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id);
+ /* Allocate the command structure that holds the struct completion.
+ * Assume we're in process context, since the normal device reset
+diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
+index ba1be6b..1e52d5e 100644
+--- a/drivers/usb/host/xhci.h
++++ b/drivers/usb/host/xhci.h
+@@ -560,6 +560,11 @@ struct xhci_slot_ctx {
+ #define SLOT_STATE (0x1f << 27)
+ #define GET_SLOT_STATE(p) (((p) & (0x1f << 27)) >> 27)
+
++#define SLOT_STATE_DISABLED 0
++#define SLOT_STATE_ENABLED SLOT_STATE_DISABLED
++#define SLOT_STATE_DEFAULT 1
++#define SLOT_STATE_ADDRESSED 2
++#define SLOT_STATE_CONFIGURED 3
+
+ /**
+ * struct xhci_ep_ctx
+@@ -1281,6 +1286,8 @@ struct xhci_hcd {
+ #define XHCI_RESET_EP_QUIRK (1 << 1)
+ #define XHCI_NEC_HOST (1 << 2)
+ #define XHCI_AMD_PLL_FIX (1 << 3)
++#define XHCI_BROKEN_MSI (1 << 6)
++#define XHCI_RESET_ON_RESUME (1 << 7)
+ /* There are two roothubs to keep track of bus suspend info for */
+ struct xhci_bus_state bus_state[2];
+ /* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */
+diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
+index 0f11afd..ebeccb7 100644
+--- a/drivers/usb/serial/cp210x.c
++++ b/drivers/usb/serial/cp210x.c
+@@ -112,6 +112,10 @@ static const struct usb_device_id id_table[] = {
+ { USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */
+ { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
+ { USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */
++ { USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */
++ { USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */
++ { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */
++ { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
+ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
+ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
+ { USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
+diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
+index 4de6ef0..2e06b90 100644
+--- a/drivers/usb/serial/ftdi_sio.c
++++ b/drivers/usb/serial/ftdi_sio.c
+@@ -179,6 +179,7 @@ static struct usb_device_id id_table_combined [] = {
+ { USB_DEVICE(FTDI_VID, FTDI_232RL_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_8U2232C_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_4232H_PID) },
++ { USB_DEVICE(FTDI_VID, FTDI_232H_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) },
+@@ -566,6 +567,7 @@ static struct usb_device_id id_table_combined [] = {
+ { USB_DEVICE(FTDI_VID, FTDI_IBS_APP70_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) },
++ { USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) },
+ /*
+ * ELV devices:
+ */
+@@ -646,6 +648,7 @@ static struct usb_device_id id_table_combined [] = {
+ { USB_DEVICE(FTDI_VID, EVER_ECO_PRO_CDS) },
+ { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_1_PID) },
+ { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_2_PID) },
++ { USB_DEVICE(FTDI_VID, FTDI_4N_GALAXY_DE_3_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_0_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_1_PID) },
+ { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_2_PID) },
+@@ -846,7 +849,8 @@ static const char *ftdi_chip_name[] = {
+ [FT2232C] = "FT2232C",
+ [FT232RL] = "FT232RL",
+ [FT2232H] = "FT2232H",
+- [FT4232H] = "FT4232H"
++ [FT4232H] = "FT4232H",
++ [FT232H] = "FT232H"
+ };
+
+
+@@ -1166,6 +1170,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty,
+ break;
+ case FT2232H: /* FT2232H chip */
+ case FT4232H: /* FT4232H chip */
++ case FT232H: /* FT232H chip */
+ if ((baud <= 12000000) & (baud >= 1200)) {
+ div_value = ftdi_2232h_baud_to_divisor(baud);
+ } else if (baud < 1200) {
+@@ -1427,9 +1432,12 @@ static void ftdi_determine_type(struct usb_serial_port *port)
+ } else if (version < 0x600) {
+ /* Assume it's an FT232BM (or FT245BM) */
+ priv->chip_type = FT232BM;
+- } else {
+- /* Assume it's an FT232R */
++ } else if (version < 0x900) {
++ /* Assume it's an FT232RL */
+ priv->chip_type = FT232RL;
++ } else {
++ /* Assume it's an FT232H */
++ priv->chip_type = FT232H;
+ }
+ dev_info(&udev->dev, "Detected %s\n", ftdi_chip_name[priv->chip_type]);
+ }
+@@ -1557,7 +1565,8 @@ static int create_sysfs_attrs(struct usb_serial_port *port)
+ priv->chip_type == FT2232C ||
+ priv->chip_type == FT232RL ||
+ priv->chip_type == FT2232H ||
+- priv->chip_type == FT4232H)) {
++ priv->chip_type == FT4232H ||
++ priv->chip_type == FT232H)) {
+ retval = device_create_file(&port->dev,
+ &dev_attr_latency_timer);
+ }
+@@ -1578,7 +1587,8 @@ static void remove_sysfs_attrs(struct usb_serial_port *port)
+ priv->chip_type == FT2232C ||
+ priv->chip_type == FT232RL ||
+ priv->chip_type == FT2232H ||
+- priv->chip_type == FT4232H) {
++ priv->chip_type == FT4232H ||
++ priv->chip_type == FT232H) {
+ device_remove_file(&port->dev, &dev_attr_latency_timer);
+ }
+ }
+@@ -2210,6 +2220,7 @@ static int ftdi_tiocmget(struct tty_struct *tty)
+ case FT232RL:
+ case FT2232H:
+ case FT4232H:
++ case FT232H:
+ len = 2;
+ break;
+ default:
+diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h
+index 213fe3d..19584fa 100644
+--- a/drivers/usb/serial/ftdi_sio.h
++++ b/drivers/usb/serial/ftdi_sio.h
+@@ -156,7 +156,8 @@ enum ftdi_chip_type {
+ FT2232C = 4,
+ FT232RL = 5,
+ FT2232H = 6,
+- FT4232H = 7
++ FT4232H = 7,
++ FT232H = 8
+ };
+
+ enum ftdi_sio_baudrate {
+diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
+index efffc23..19156d1 100644
+--- a/drivers/usb/serial/ftdi_sio_ids.h
++++ b/drivers/usb/serial/ftdi_sio_ids.h
+@@ -22,6 +22,7 @@
+ #define FTDI_8U232AM_ALT_PID 0x6006 /* FTDI's alternate PID for above */
+ #define FTDI_8U2232C_PID 0x6010 /* Dual channel device */
+ #define FTDI_4232H_PID 0x6011 /* Quad channel hi-speed device */
++#define FTDI_232H_PID 0x6014 /* Single channel hi-speed device */
+ #define FTDI_SIO_PID 0x8372 /* Product Id SIO application of 8U100AX */
+ #define FTDI_232RL_PID 0xFBFA /* Product ID for FT232RL */
+
+@@ -351,6 +352,7 @@
+ */
+ #define FTDI_4N_GALAXY_DE_1_PID 0xF3C0
+ #define FTDI_4N_GALAXY_DE_2_PID 0xF3C1
++#define FTDI_4N_GALAXY_DE_3_PID 0xF3C2
+
+ /*
+ * Linx Technologies product ids
+@@ -491,6 +493,11 @@
+ /* www.canusb.com Lawicel CANUSB device (FTDI_VID) */
+ #define FTDI_CANUSB_PID 0xFFA8 /* Product Id */
+
++/*
++ * TavIR AVR product ids (FTDI_VID)
++ */
++#define FTDI_TAVIR_STK500_PID 0xFA33 /* STK500 AVR programmer */
++
+
+
+ /********************************/
+diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c
+index 26710b1..456447e033 100644
+--- a/drivers/usb/serial/garmin_gps.c
++++ b/drivers/usb/serial/garmin_gps.c
+@@ -1,7 +1,7 @@
+ /*
+ * Garmin GPS driver
+ *
+- * Copyright (C) 2006-2009 Hermann Kneissel herkne@users.sourceforge.net
++ * Copyright (C) 2006-2011 Hermann Kneissel herkne@gmx.de
+ *
+ * The latest version of the driver can be found at
+ * http://sourceforge.net/projects/garmin-gps/
+@@ -51,7 +51,7 @@ static int debug;
+ */
+
+ #define VERSION_MAJOR 0
+-#define VERSION_MINOR 33
++#define VERSION_MINOR 36
+
+ #define _STR(s) #s
+ #define _DRIVER_VERSION(a, b) "v" _STR(a) "." _STR(b)
+@@ -410,6 +410,7 @@ static int gsp_send_ack(struct garmin_data *garmin_data_p, __u8 pkt_id)
+ */
+ static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count)
+ {
++ unsigned long flags;
+ const __u8 *recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET;
+ __le32 *usbdata = (__le32 *) garmin_data_p->inbuffer;
+
+@@ -458,7 +459,9 @@ static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count)
+ /* if this was an abort-transfer command, flush all
+ queued data. */
+ if (isAbortTrfCmnd(garmin_data_p->inbuffer)) {
++ spin_lock_irqsave(&garmin_data_p->lock, flags);
+ garmin_data_p->flags |= FLAGS_DROP_DATA;
++ spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+ pkt_clear(garmin_data_p);
+ }
+
+@@ -943,7 +946,7 @@ static int garmin_open(struct tty_struct *tty, struct usb_serial_port *port)
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
+ garmin_data_p->mode = initial_mode;
+ garmin_data_p->count = 0;
+- garmin_data_p->flags = 0;
++ garmin_data_p->flags &= FLAGS_SESSION_REPLY1_SEEN;
+ spin_unlock_irqrestore(&garmin_data_p->lock, flags);
+
+ /* shutdown any bulk reads that might be going on */
+@@ -1178,7 +1181,8 @@ static int garmin_write_room(struct tty_struct *tty)
+
+
+ static void garmin_read_process(struct garmin_data *garmin_data_p,
+- unsigned char *data, unsigned data_length)
++ unsigned char *data, unsigned data_length,
++ int bulk_data)
+ {
+ unsigned long flags;
+
+@@ -1193,7 +1197,8 @@ static void garmin_read_process(struct garmin_data *garmin_data_p,
+ send it directly to the tty port */
+ if (garmin_data_p->flags & FLAGS_QUEUING) {
+ pkt_add(garmin_data_p, data, data_length);
+- } else if (getLayerId(data) == GARMIN_LAYERID_APPL) {
++ } else if (bulk_data ||
++ getLayerId(data) == GARMIN_LAYERID_APPL) {
+
+ spin_lock_irqsave(&garmin_data_p->lock, flags);
+ garmin_data_p->flags |= APP_RESP_SEEN;
+@@ -1237,7 +1242,7 @@ static void garmin_read_bulk_callback(struct urb *urb)
+ usb_serial_debug_data(debug, &port->dev,
+ __func__, urb->actual_length, data);
+
+- garmin_read_process(garmin_data_p, data, urb->actual_length);
++ garmin_read_process(garmin_data_p, data, urb->actual_length, 1);
+
+ if (urb->actual_length == 0 &&
+ 0 != (garmin_data_p->flags & FLAGS_BULK_IN_RESTART)) {
+@@ -1346,7 +1351,7 @@ static void garmin_read_int_callback(struct urb *urb)
+ __func__, garmin_data_p->serial_num);
+ }
+
+- garmin_read_process(garmin_data_p, data, urb->actual_length);
++ garmin_read_process(garmin_data_p, data, urb->actual_length, 0);
+
+ port->interrupt_in_urb->dev = port->serial->dev;
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+@@ -1461,6 +1466,7 @@ static int garmin_attach(struct usb_serial *serial)
+ garmin_data_p->timer.function = timeout_handler;
+ garmin_data_p->port = port;
+ garmin_data_p->state = 0;
++ garmin_data_p->flags = 0;
+ garmin_data_p->count = 0;
+ usb_set_serial_port_data(port, garmin_data_p);
+
+diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c
+index 653465f..e2bfecc 100644
+--- a/drivers/usb/serial/moto_modem.c
++++ b/drivers/usb/serial/moto_modem.c
+@@ -25,6 +25,7 @@ static const struct usb_device_id id_table[] = {
+ { USB_DEVICE(0x05c6, 0x3197) }, /* unknown Motorola phone */
+ { USB_DEVICE(0x0c44, 0x0022) }, /* unknown Mororola phone */
+ { USB_DEVICE(0x22b8, 0x2a64) }, /* Motorola KRZR K1m */
++ { USB_DEVICE(0x22b8, 0x2c84) }, /* Motorola VE240 phone */
+ { USB_DEVICE(0x22b8, 0x2c64) }, /* Motorola V950 phone */
+ { },
+ };
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index d77ff04..60b25d8 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -149,6 +149,7 @@ static void option_instat_callback(struct urb *urb);
+ #define HUAWEI_PRODUCT_K3765 0x1465
+ #define HUAWEI_PRODUCT_E14AC 0x14AC
+ #define HUAWEI_PRODUCT_ETS1220 0x1803
++#define HUAWEI_PRODUCT_E353 0x1506
+
+ #define QUANTA_VENDOR_ID 0x0408
+ #define QUANTA_PRODUCT_Q101 0xEA02
+@@ -310,10 +311,6 @@ static void option_instat_callback(struct urb *urb);
+ #define ZTE_PRODUCT_AC2726 0xfff5
+ #define ZTE_PRODUCT_AC8710T 0xffff
+
+-/* ZTE PRODUCTS -- alternate vendor ID */
+-#define ZTE_VENDOR_ID2 0x1d6b
+-#define ZTE_PRODUCT_MF_330 0x0002
+-
+ #define BENQ_VENDOR_ID 0x04a5
+ #define BENQ_PRODUCT_H10 0x4068
+
+@@ -339,11 +336,12 @@ static void option_instat_callback(struct urb *urb);
+ #define TOSHIBA_PRODUCT_G450 0x0d45
+
+ #define ALINK_VENDOR_ID 0x1e0e
++#define ALINK_PRODUCT_PH300 0x9100
+ #define ALINK_PRODUCT_3GU 0x9200
+
+ /* ALCATEL PRODUCTS */
+ #define ALCATEL_VENDOR_ID 0x1bbb
+-#define ALCATEL_PRODUCT_X060S 0x0000
++#define ALCATEL_PRODUCT_X060S_X200 0x0000
+
+ #define PIRELLI_VENDOR_ID 0x1266
+ #define PIRELLI_PRODUCT_C100_1 0x1002
+@@ -378,6 +376,9 @@ static void option_instat_callback(struct urb *urb);
+ * It seems to contain a Qualcomm QSC6240/6290 chipset */
+ #define FOUR_G_SYSTEMS_PRODUCT_W14 0x9603
+
++/* Zoom */
++#define ZOOM_PRODUCT_4597 0x9607
++
+ /* Haier products */
+ #define HAIER_VENDOR_ID 0x201e
+ #define HAIER_PRODUCT_CE100 0x2009
+@@ -431,6 +432,20 @@ static const struct option_blacklist_info four_g_w14_blacklist = {
+ .reason = OPTION_BLACKLIST_SENDSETUP
+ };
+
++static const u8 alcatel_x200_no_sendsetup[] = { 0, 1 };
++static const struct option_blacklist_info alcatel_x200_blacklist = {
++ .infolen = ARRAY_SIZE(alcatel_x200_no_sendsetup),
++ .ifaceinfo = alcatel_x200_no_sendsetup,
++ .reason = OPTION_BLACKLIST_SENDSETUP
++};
++
++static const u8 zte_k3765_z_no_sendsetup[] = { 0, 1, 2 };
++static const struct option_blacklist_info zte_k3765_z_blacklist = {
++ .infolen = ARRAY_SIZE(zte_k3765_z_no_sendsetup),
++ .ifaceinfo = zte_k3765_z_no_sendsetup,
++ .reason = OPTION_BLACKLIST_SENDSETUP
++};
++
+ static const struct usb_device_id option_ids[] = {
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
+ { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
+@@ -532,6 +547,7 @@ static const struct usb_device_id option_ids[] = {
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) },
++ { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) },
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) },
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) },
+ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) },
+@@ -914,13 +930,13 @@ static const struct usb_device_id option_ids[] = {
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) },
+- { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff) },
++ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff,
++ 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710T, 0xff, 0xff, 0xff) },
+- { USB_DEVICE(ZTE_VENDOR_ID2, ZTE_PRODUCT_MF_330) },
+ { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
+ { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
+ { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */
+@@ -933,13 +949,17 @@ static const struct usb_device_id option_ids[] = {
+ { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) },
+ { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */
+ { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) },
++ { USB_DEVICE(ALINK_VENDOR_ID, ALINK_PRODUCT_PH300) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
+- { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
++ { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200),
++ .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
++ },
+ { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
+ { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
+ { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
+ .driver_info = (kernel_ulong_t)&four_g_w14_blacklist
+ },
++ { USB_DEVICE(LONGCHEER_VENDOR_ID, ZOOM_PRODUCT_4597) },
+ { USB_DEVICE(HAIER_VENDOR_ID, HAIER_PRODUCT_CE100) },
+ /* Pirelli */
+ { USB_DEVICE(PIRELLI_VENDOR_ID, PIRELLI_PRODUCT_C100_1)},
+@@ -972,7 +992,7 @@ static const struct usb_device_id option_ids[] = {
+ { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) },
+ { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */
+ { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */
+- { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730/GT-B3710 LTE USB modem.*/
++ { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/
+ { } /* Terminating entry */
+ };
+ MODULE_DEVICE_TABLE(usb, option_ids);
+@@ -1109,6 +1129,12 @@ static int option_probe(struct usb_serial *serial,
+ serial->interface->cur_altsetting->desc.bInterfaceNumber == 1)
+ return -ENODEV;
+
++ /* Don't bind network interface on Samsung GT-B3730, it is handled by a separate module */
++ if (serial->dev->descriptor.idVendor == SAMSUNG_VENDOR_ID &&
++ serial->dev->descriptor.idProduct == SAMSUNG_PRODUCT_GT_B3730 &&
++ serial->interface->cur_altsetting->desc.bInterfaceClass != USB_CLASS_CDC_DATA)
++ return -ENODEV;
++
+ data = serial->private = kzalloc(sizeof(struct usb_wwan_intf_private), GFP_KERNEL);
+
+ if (!data)
+diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
+index 30461fc..0c20831 100644
+--- a/drivers/usb/serial/pl2303.c
++++ b/drivers/usb/serial/pl2303.c
+@@ -91,6 +91,7 @@ static const struct usb_device_id id_table[] = {
+ { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
+ { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) },
+ { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) },
++ { USB_DEVICE(WINCHIPHEAD_VENDOR_ID, WINCHIPHEAD_USBSER_PRODUCT_ID) },
+ { } /* Terminating entry */
+ };
+
+diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h
+index 1b025f7..ca0d237 100644
+--- a/drivers/usb/serial/pl2303.h
++++ b/drivers/usb/serial/pl2303.h
+@@ -144,3 +144,7 @@
+ /* ADLINK ND-6530 RS232,RS485 and RS422 adapter */
+ #define ADLINK_VENDOR_ID 0x0b63
+ #define ADLINK_ND6530_PRODUCT_ID 0x6530
++
++/* WinChipHead USB->RS 232 adapter */
++#define WINCHIPHEAD_VENDOR_ID 0x4348
++#define WINCHIPHEAD_USBSER_PRODUCT_ID 0x5523
+diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
+index 0041899..e8ae21b 100644
+--- a/drivers/usb/storage/transport.c
++++ b/drivers/usb/storage/transport.c
+@@ -819,6 +819,35 @@ Retry_Sense:
+ }
+ }
+
++ /*
++ * Some devices don't work or return incorrect data the first
++ * time they get a READ(10) command, or for the first READ(10)
++ * after a media change. If the INITIAL_READ10 flag is set,
++ * keep track of whether READ(10) commands succeed. If the
++ * previous one succeeded and this one failed, set the REDO_READ10
++ * flag to force a retry.
++ */
++ if (unlikely((us->fflags & US_FL_INITIAL_READ10) &&
++ srb->cmnd[0] == READ_10)) {
++ if (srb->result == SAM_STAT_GOOD) {
++ set_bit(US_FLIDX_READ10_WORKED, &us->dflags);
++ } else if (test_bit(US_FLIDX_READ10_WORKED, &us->dflags)) {
++ clear_bit(US_FLIDX_READ10_WORKED, &us->dflags);
++ set_bit(US_FLIDX_REDO_READ10, &us->dflags);
++ }
++
++ /*
++ * Next, if the REDO_READ10 flag is set, return a result
++ * code that will cause the SCSI core to retry the READ(10)
++ * command immediately.
++ */
++ if (test_bit(US_FLIDX_REDO_READ10, &us->dflags)) {
++ clear_bit(US_FLIDX_REDO_READ10, &us->dflags);
++ srb->result = DID_IMM_RETRY << 16;
++ srb->sense_buffer[0] = 0;
++ }
++ }
++
+ /* Did we transfer less than the minimum amount required? */
+ if ((srb->result == SAM_STAT_GOOD || srb->sense_buffer[2] == 0) &&
+ scsi_bufflen(srb) - scsi_get_resid(srb) < srb->underflow)
+diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
+index c1602b8..ccff348 100644
+--- a/drivers/usb/storage/unusual_devs.h
++++ b/drivers/usb/storage/unusual_devs.h
+@@ -1114,6 +1114,16 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_FIX_CAPACITY ),
+
++/* Reported by Paul Hartman <paul.hartman+linux@gmail.com>
++ * This card reader returns "Illegal Request, Logical Block Address
++ * Out of Range" for the first READ(10) after a new card is inserted.
++ */
++UNUSUAL_DEV( 0x090c, 0x6000, 0x0100, 0x0100,
++ "Feiya",
++ "SD/SDHC Card Reader",
++ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
++ US_FL_INITIAL_READ10 ),
++
+ /* This Pentax still camera is not conformant
+ * to the USB storage specification: -
+ * - It does not like the INQUIRY command. So we must handle this command
+@@ -1888,6 +1898,15 @@ UNUSUAL_DEV( 0x1908, 0x3335, 0x0200, 0x0200,
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_NO_READ_DISC_INFO ),
+
++/* Reported by Sven Geggus <sven-usbst@geggus.net>
++ * This encrypted pen drive returns bogus data for the initial READ(10).
++ */
++UNUSUAL_DEV( 0x1b1c, 0x1ab5, 0x0200, 0x0200,
++ "Corsair",
++ "Padlock v2",
++ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
++ US_FL_INITIAL_READ10 ),
++
+ /* Patch by Richard Schütz <r.schtz@t-online.de>
+ * This external hard drive enclosure uses a JMicron chip which
+ * needs the US_FL_IGNORE_RESIDUE flag to work properly. */
+diff --git a/drivers/usb/storage/unusual_realtek.h b/drivers/usb/storage/unusual_realtek.h
+index 3236e03..e41f50c 100644
+--- a/drivers/usb/storage/unusual_realtek.h
++++ b/drivers/usb/storage/unusual_realtek.h
+@@ -23,19 +23,19 @@
+ #if defined(CONFIG_USB_STORAGE_REALTEK) || \
+ defined(CONFIG_USB_STORAGE_REALTEK_MODULE)
+
+-UNUSUAL_DEV(0x0bda, 0x0159, 0x0000, 0x9999,
++UNUSUAL_DEV(0x0bda, 0x0138, 0x0000, 0x9999,
+ "Realtek",
+ "USB Card Reader",
+- USB_SC_SCSI, USB_PR_BULK, init_realtek_cr, 0),
++ USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0),
+
+ UNUSUAL_DEV(0x0bda, 0x0158, 0x0000, 0x9999,
+ "Realtek",
+ "USB Card Reader",
+- USB_SC_SCSI, USB_PR_BULK, init_realtek_cr, 0),
++ USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0),
+
+-UNUSUAL_DEV(0x0bda, 0x0138, 0x0000, 0x9999,
++UNUSUAL_DEV(0x0bda, 0x0159, 0x0000, 0x9999,
+ "Realtek",
+ "USB Card Reader",
+- USB_SC_SCSI, USB_PR_BULK, init_realtek_cr, 0),
++ USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0),
+
+ #endif /* defined(CONFIG_USB_STORAGE_REALTEK) || ... */
+diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
+index 4219c19..07d6d73 100644
+--- a/drivers/usb/storage/usb.c
++++ b/drivers/usb/storage/usb.c
+@@ -439,7 +439,8 @@ static void adjust_quirks(struct us_data *us)
+ US_FL_CAPACITY_HEURISTICS | US_FL_IGNORE_DEVICE |
+ US_FL_NOT_LOCKABLE | US_FL_MAX_SECTORS_64 |
+ US_FL_CAPACITY_OK | US_FL_IGNORE_RESIDUE |
+- US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT);
++ US_FL_SINGLE_LUN | US_FL_NO_WP_DETECT |
++ US_FL_INITIAL_READ10);
+
+ p = quirks;
+ while (*p) {
+@@ -483,6 +484,9 @@ static void adjust_quirks(struct us_data *us)
+ case 'm':
+ f |= US_FL_MAX_SECTORS_64;
+ break;
++ case 'n':
++ f |= US_FL_INITIAL_READ10;
++ break;
+ case 'o':
+ f |= US_FL_CAPACITY_OK;
+ break;
+@@ -946,6 +950,13 @@ int usb_stor_probe2(struct us_data *us)
+ if (result)
+ goto BadDevice;
+
++ /*
++ * If the device returns invalid data for the first READ(10)
++ * command, indicate the command should be retried.
++ */
++ if (us->fflags & US_FL_INITIAL_READ10)
++ set_bit(US_FLIDX_REDO_READ10, &us->dflags);
++
+ /* Acquire all the other resources and add the host */
+ result = usb_stor_acquire_resources(us);
+ if (result)
+diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
+index 89d3bff..7b0f211 100644
+--- a/drivers/usb/storage/usb.h
++++ b/drivers/usb/storage/usb.h
+@@ -73,6 +73,8 @@ struct us_unusual_dev {
+ #define US_FLIDX_RESETTING 4 /* device reset in progress */
+ #define US_FLIDX_TIMED_OUT 5 /* SCSI midlayer timed out */
+ #define US_FLIDX_DONT_SCAN 6 /* don't scan (disconnect) */
++#define US_FLIDX_REDO_READ10 7 /* redo READ(10) command */
++#define US_FLIDX_READ10_WORKED 8 /* previous READ(10) succeeded */
+
+ #define USB_STOR_STRING_LEN 32
+
+diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c
+index 53b2c5a..305c975 100644
+--- a/drivers/video/vga16fb.c
++++ b/drivers/video/vga16fb.c
+@@ -1265,9 +1265,11 @@ static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image
+
+ static void vga16fb_destroy(struct fb_info *info)
+ {
++ struct platform_device *dev = container_of(info->device, struct platform_device, dev);
+ iounmap(info->screen_base);
+ fb_dealloc_cmap(&info->cmap);
+ /* XXX unshare VGA regions */
++ platform_set_drvdata(dev, NULL);
+ framebuffer_release(info);
+ }
+
+diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c
+index 5ec5ac1..befbe80 100644
+--- a/drivers/watchdog/mtx-1_wdt.c
++++ b/drivers/watchdog/mtx-1_wdt.c
+@@ -211,6 +211,12 @@ static int __devinit mtx1_wdt_probe(struct platform_device *pdev)
+ int ret;
+
+ mtx1_wdt_device.gpio = pdev->resource[0].start;
++ ret = gpio_request_one(mtx1_wdt_device.gpio,
++ GPIOF_OUT_INIT_HIGH, "mtx1-wdt");
++ if (ret < 0) {
++ dev_err(&pdev->dev, "failed to request gpio");
++ return ret;
++ }
+
+ spin_lock_init(&mtx1_wdt_device.lock);
+ init_completion(&mtx1_wdt_device.stop);
+@@ -236,6 +242,8 @@ static int __devexit mtx1_wdt_remove(struct platform_device *pdev)
+ mtx1_wdt_device.queue = 0;
+ wait_for_completion(&mtx1_wdt_device.stop);
+ }
++
++ gpio_free(mtx1_wdt_device.gpio);
+ misc_deregister(&mtx1_wdt_misc);
+ return 0;
+ }
+diff --git a/fs/block_dev.c b/fs/block_dev.c
+index 257b00e..610e8e0 100644
+--- a/fs/block_dev.c
++++ b/fs/block_dev.c
+@@ -762,7 +762,19 @@ static struct block_device *bd_start_claiming(struct block_device *bdev,
+ if (!disk)
+ return ERR_PTR(-ENXIO);
+
+- whole = bdget_disk(disk, 0);
++ /*
++ * Normally, @bdev should equal what's returned from bdget_disk()
++ * if partno is 0; however, some drivers (floppy) use multiple
++ * bdev's for the same physical device and @bdev may be one of the
++ * aliases. Keep @bdev if partno is 0. This means claimer
++ * tracking is broken for those devices but it has always been that
++ * way.
++ */
++ if (partno)
++ whole = bdget_disk(disk, 0);
++ else
++ whole = bdgrab(bdev);
++
+ module_put(disk->fops->owner);
+ put_disk(disk);
+ if (!whole)
+@@ -1120,6 +1132,15 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
+ goto restart;
+ }
+ }
++
++ if (!ret && !bdev->bd_openers) {
++ bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);
++ bdi = blk_get_backing_dev_info(bdev);
++ if (bdi == NULL)
++ bdi = &default_backing_dev_info;
++ bdev_inode_switch_bdi(bdev->bd_inode, bdi);
++ }
++
+ /*
+ * If the device is invalidated, rescan partition
+ * if open succeeded or failed with -ENOMEDIUM.
+@@ -1130,14 +1151,6 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
+ rescan_partitions(disk, bdev);
+ if (ret)
+ goto out_clear;
+-
+- if (!bdev->bd_openers) {
+- bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);
+- bdi = blk_get_backing_dev_info(bdev);
+- if (bdi == NULL)
+- bdi = &default_backing_dev_info;
+- bdev_inode_switch_bdi(bdev->bd_inode, bdi);
+- }
+ } else {
+ struct block_device *whole;
+ whole = bdget_disk(disk, 0);
+@@ -1237,6 +1250,8 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
+ res = __blkdev_get(bdev, mode, 0);
+
+ if (whole) {
++ struct gendisk *disk = whole->bd_disk;
++
+ /* finish claiming */
+ mutex_lock(&bdev->bd_mutex);
+ spin_lock(&bdev_lock);
+@@ -1263,15 +1278,16 @@ int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder)
+ spin_unlock(&bdev_lock);
+
+ /*
+- * Block event polling for write claims. Any write
+- * holder makes the write_holder state stick until all
+- * are released. This is good enough and tracking
+- * individual writeable reference is too fragile given
+- * the way @mode is used in blkdev_get/put().
++ * Block event polling for write claims if requested. Any
++ * write holder makes the write_holder state stick until
++ * all are released. This is good enough and tracking
++ * individual writeable reference is too fragile given the
++ * way @mode is used in blkdev_get/put().
+ */
+- if (!res && (mode & FMODE_WRITE) && !bdev->bd_write_holder) {
++ if (!res && (mode & FMODE_WRITE) && !bdev->bd_write_holder &&
++ (disk->flags & GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE)) {
+ bdev->bd_write_holder = true;
+- disk_block_events(bdev->bd_disk);
++ disk_block_events(disk);
+ }
+
+ mutex_unlock(&bdev->bd_mutex);
+diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
+index d1a016b..ba3d95b 100644
+--- a/fs/cifs/cifsencrypt.c
++++ b/fs/cifs/cifsencrypt.c
+@@ -184,7 +184,7 @@ int cifs_verify_signature(struct smb_hdr *cifs_pdu,
+ if (cifs_pdu == NULL || server == NULL)
+ return -EINVAL;
+
+- if (cifs_pdu->Command == SMB_COM_NEGOTIATE)
++ if (!server->session_estab)
+ return 0;
+
+ if (cifs_pdu->Command == SMB_COM_LOCKING_ANDX) {
+diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
+index 277262a..01db14c 100644
+--- a/fs/cifs/connect.c
++++ b/fs/cifs/connect.c
+@@ -199,7 +199,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
+ }
+ spin_unlock(&GlobalMid_Lock);
+
+- while (server->tcpStatus == CifsNeedReconnect) {
++ do {
+ try_to_freeze();
+
+ /* we should try only the port we connected to before */
+@@ -214,7 +214,7 @@ cifs_reconnect(struct TCP_Server_Info *server)
+ server->tcpStatus = CifsNeedNegotiate;
+ spin_unlock(&GlobalMid_Lock);
+ }
+- }
++ } while (server->tcpStatus == CifsNeedReconnect);
+
+ return rc;
+ }
+@@ -2447,7 +2447,7 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
+
+ if (!CIFSSMBQFSUnixInfo(xid, tcon)) {
+ __u64 cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
+-
++ cFYI(1, "unix caps which server supports %lld", cap);
+ /* check for reconnect case in which we do not
+ want to change the mount behavior if we can avoid it */
+ if (vol_info == NULL) {
+@@ -2465,6 +2465,9 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
+ }
+ }
+
++ if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
++ cERROR(1, "per-share encryption not supported yet");
++
+ cap &= CIFS_UNIX_CAP_MASK;
+ if (vol_info && vol_info->no_psx_acl)
+ cap &= ~CIFS_UNIX_POSIX_ACL_CAP;
+@@ -2513,6 +2516,10 @@ void reset_cifs_unix_caps(int xid, struct cifsTconInfo *tcon,
+ cFYI(1, "very large read cap");
+ if (cap & CIFS_UNIX_LARGE_WRITE_CAP)
+ cFYI(1, "very large write cap");
++ if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_CAP)
++ cFYI(1, "transport encryption cap");
++ if (cap & CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)
++ cFYI(1, "mandatory transport encryption cap");
+ #endif /* CIFS_DEBUG2 */
+ if (CIFSSMBSetFSUnixInfo(xid, tcon, cap)) {
+ if (vol_info == NULL) {
+@@ -2564,23 +2571,6 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
+ else /* default */
+ cifs_sb->rsize = CIFSMaxBufSize;
+
+- if (pvolume_info->wsize > PAGEVEC_SIZE * PAGE_CACHE_SIZE) {
+- cERROR(1, "wsize %d too large, using 4096 instead",
+- pvolume_info->wsize);
+- cifs_sb->wsize = 4096;
+- } else if (pvolume_info->wsize)
+- cifs_sb->wsize = pvolume_info->wsize;
+- else
+- cifs_sb->wsize = min_t(const int,
+- PAGEVEC_SIZE * PAGE_CACHE_SIZE,
+- 127*1024);
+- /* old default of CIFSMaxBufSize was too small now
+- that SMB Write2 can send multiple pages in kvec.
+- RFC1001 does not describe what happens when frame
+- bigger than 128K is sent so use that as max in
+- conjunction with 52K kvec constraint on arch with 4K
+- page size */
+-
+ if (cifs_sb->rsize < 2048) {
+ cifs_sb->rsize = 2048;
+ /* Windows ME may prefer this */
+@@ -2658,6 +2648,48 @@ static void setup_cifs_sb(struct smb_vol *pvolume_info,
+ "mount option supported");
+ }
+
++/* Prior to 3.0, cifs couldn't handle writes larger than this */
++#define CIFS_MAX_WSIZE (PAGEVEC_SIZE * PAGE_CACHE_SIZE)
++
++/*
++ * When the server doesn't allow large posix writes, only allow a wsize of
++ * 128k minus the size of the WRITE_AND_X header. That allows for a write up
++ * to the maximum size described by RFC1002.
++ */
++#define CIFS_MAX_RFC1002_WSIZE (128 * 1024 - sizeof(WRITE_REQ) + 4)
++
++/* Make the default the same as the max */
++#define CIFS_DEFAULT_WSIZE CIFS_MAX_WSIZE
++
++static unsigned int
++cifs_negotiate_wsize(struct cifsTconInfo *tcon, struct smb_vol *pvolume_info)
++{
++ __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability);
++ struct TCP_Server_Info *server = tcon->ses->server;
++ unsigned int wsize = pvolume_info->wsize ? pvolume_info->wsize :
++ CIFS_DEFAULT_WSIZE;
++
++ /* can server support 24-bit write sizes? (via UNIX extensions) */
++ if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP))
++ wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE);
++
++ /*
++ * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set?
++ * Limit it to max buffer offered by the server, minus the size of the
++ * WRITEX header, not including the 4 byte RFC1001 length.
++ */
++ if (!(server->capabilities & CAP_LARGE_WRITE_X) ||
++ (!(server->capabilities & CAP_UNIX) &&
++ (server->secMode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED))))
++ wsize = min_t(unsigned int, wsize,
++ server->maxBuf - sizeof(WRITE_REQ) + 4);
++
++ /* hard limit of CIFS_MAX_WSIZE */
++ wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE);
++
++ return wsize;
++}
++
+ static int
+ is_path_accessible(int xid, struct cifsTconInfo *tcon,
+ struct cifs_sb_info *cifs_sb, const char *full_path)
+@@ -2831,20 +2863,26 @@ try_mount_again:
+ goto remote_path_check;
+ }
+
+- /* do not care if following two calls succeed - informational */
+- if (!tcon->ipc) {
+- CIFSSMBQFSDeviceInfo(xid, tcon);
+- CIFSSMBQFSAttributeInfo(xid, tcon);
+- }
+-
+ /* tell server which Unix caps we support */
+- if (tcon->ses->capabilities & CAP_UNIX)
++ if (tcon->ses->capabilities & CAP_UNIX) {
+ /* reset of caps checks mount to see if unix extensions
+ disabled for just this mount */
+ reset_cifs_unix_caps(xid, tcon, sb, volume_info);
+- else
++ if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) &&
++ (le64_to_cpu(tcon->fsUnixInfo.Capability) &
++ CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) {
++ rc = -EACCES;
++ goto mount_fail_check;
++ }
++ } else
+ tcon->unix_ext = 0; /* server does not support them */
+
++ /* do not care if following two calls succeed - informational */
++ if (!tcon->ipc) {
++ CIFSSMBQFSDeviceInfo(xid, tcon);
++ CIFSSMBQFSAttributeInfo(xid, tcon);
++ }
++
+ /* convert forward to back slashes in prepath here if needed */
+ if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
+ convert_delimiter(cifs_sb->prepath, CIFS_DIR_SEP(cifs_sb));
+@@ -2853,13 +2891,12 @@ try_mount_again:
+ cifs_sb->rsize = 1024 * 127;
+ cFYI(DBG2, "no very large read support, rsize now 127K");
+ }
+- if (!(tcon->ses->capabilities & CAP_LARGE_WRITE_X))
+- cifs_sb->wsize = min(cifs_sb->wsize,
+- (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
+ if (!(tcon->ses->capabilities & CAP_LARGE_READ_X))
+ cifs_sb->rsize = min(cifs_sb->rsize,
+ (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE));
+
++ cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info);
++
+ remote_path_check:
+ /* check if a whole path (including prepath) is not remote */
+ if (!rc && tcon) {
+@@ -3195,7 +3232,7 @@ int cifs_negotiate_protocol(unsigned int xid, struct cifsSesInfo *ses)
+ }
+ if (rc == 0) {
+ spin_lock(&GlobalMid_Lock);
+- if (server->tcpStatus != CifsExiting)
++ if (server->tcpStatus == CifsNeedNegotiate)
+ server->tcpStatus = CifsGood;
+ else
+ rc = -EHOSTDOWN;
+diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c
+index 297a43d..05268cf 100644
+--- a/fs/cifs/fscache.c
++++ b/fs/cifs/fscache.c
+@@ -94,6 +94,7 @@ static void cifs_fscache_disable_inode_cookie(struct inode *inode)
+ if (cifsi->fscache) {
+ cFYI(1, "CIFS disabling inode cookie (0x%p)",
+ cifsi->fscache);
++ fscache_uncache_all_inode_pages(cifsi->fscache, inode);
+ fscache_relinquish_cookie(cifsi->fscache, 1);
+ cifsi->fscache = NULL;
+ }
+diff --git a/fs/dcookies.c b/fs/dcookies.c
+index a21cabd..dda0dc7 100644
+--- a/fs/dcookies.c
++++ b/fs/dcookies.c
+@@ -178,6 +178,8 @@ SYSCALL_DEFINE(lookup_dcookie)(u64 cookie64, char __user * buf, size_t len)
+ /* FIXME: (deleted) ? */
+ path = d_path(&dcs->path, kbuf, PAGE_SIZE);
+
++ mutex_unlock(&dcookie_mutex);
++
+ if (IS_ERR(path)) {
+ err = PTR_ERR(path);
+ goto out_free;
+@@ -194,6 +196,7 @@ SYSCALL_DEFINE(lookup_dcookie)(u64 cookie64, char __user * buf, size_t len)
+
+ out_free:
+ kfree(kbuf);
++ return err;
+ out:
+ mutex_unlock(&dcookie_mutex);
+ return err;
+diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c
+index 4d4cc6a..94ab3c0 100644
+--- a/fs/ecryptfs/inode.c
++++ b/fs/ecryptfs/inode.c
+@@ -527,6 +527,8 @@ static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry)
+ dget(lower_dentry);
+ rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry);
+ dput(lower_dentry);
++ if (!rc && dentry->d_inode)
++ clear_nlink(dentry->d_inode);
+ fsstack_copy_attr_times(dir, lower_dir_dentry->d_inode);
+ dir->i_nlink = lower_dir_dentry->d_inode->i_nlink;
+ unlock_dir(lower_dir_dentry);
+diff --git a/fs/ecryptfs/keystore.c b/fs/ecryptfs/keystore.c
+index 03e609c..27a7fef 100644
+--- a/fs/ecryptfs/keystore.c
++++ b/fs/ecryptfs/keystore.c
+@@ -599,8 +599,8 @@ struct ecryptfs_write_tag_70_packet_silly_stack {
+ struct mutex *tfm_mutex;
+ char *block_aligned_filename;
+ struct ecryptfs_auth_tok *auth_tok;
+- struct scatterlist src_sg;
+- struct scatterlist dst_sg;
++ struct scatterlist src_sg[2];
++ struct scatterlist dst_sg[2];
+ struct blkcipher_desc desc;
+ char iv[ECRYPTFS_MAX_IV_BYTES];
+ char hash[ECRYPTFS_TAG_70_DIGEST_SIZE];
+@@ -816,23 +816,21 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
+ memcpy(&s->block_aligned_filename[s->num_rand_bytes], filename,
+ filename_size);
+ rc = virt_to_scatterlist(s->block_aligned_filename,
+- s->block_aligned_filename_size, &s->src_sg, 1);
+- if (rc != 1) {
++ s->block_aligned_filename_size, s->src_sg, 2);
++ if (rc < 1) {
+ printk(KERN_ERR "%s: Internal error whilst attempting to "
+- "convert filename memory to scatterlist; "
+- "expected rc = 1; got rc = [%d]. "
++ "convert filename memory to scatterlist; rc = [%d]. "
+ "block_aligned_filename_size = [%zd]\n", __func__, rc,
+ s->block_aligned_filename_size);
+ goto out_release_free_unlock;
+ }
+ rc = virt_to_scatterlist(&dest[s->i], s->block_aligned_filename_size,
+- &s->dst_sg, 1);
+- if (rc != 1) {
++ s->dst_sg, 2);
++ if (rc < 1) {
+ printk(KERN_ERR "%s: Internal error whilst attempting to "
+ "convert encrypted filename memory to scatterlist; "
+- "expected rc = 1; got rc = [%d]. "
+- "block_aligned_filename_size = [%zd]\n", __func__, rc,
+- s->block_aligned_filename_size);
++ "rc = [%d]. block_aligned_filename_size = [%zd]\n",
++ __func__, rc, s->block_aligned_filename_size);
+ goto out_release_free_unlock;
+ }
+ /* The characters in the first block effectively do the job
+@@ -855,7 +853,7 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes,
+ mount_crypt_stat->global_default_fn_cipher_key_bytes);
+ goto out_release_free_unlock;
+ }
+- rc = crypto_blkcipher_encrypt_iv(&s->desc, &s->dst_sg, &s->src_sg,
++ rc = crypto_blkcipher_encrypt_iv(&s->desc, s->dst_sg, s->src_sg,
+ s->block_aligned_filename_size);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to encrypt filename; "
+@@ -891,8 +889,8 @@ struct ecryptfs_parse_tag_70_packet_silly_stack {
+ struct mutex *tfm_mutex;
+ char *decrypted_filename;
+ struct ecryptfs_auth_tok *auth_tok;
+- struct scatterlist src_sg;
+- struct scatterlist dst_sg;
++ struct scatterlist src_sg[2];
++ struct scatterlist dst_sg[2];
+ struct blkcipher_desc desc;
+ char fnek_sig_hex[ECRYPTFS_SIG_SIZE_HEX + 1];
+ char iv[ECRYPTFS_MAX_IV_BYTES];
+@@ -1008,13 +1006,12 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
+ }
+ mutex_lock(s->tfm_mutex);
+ rc = virt_to_scatterlist(&data[(*packet_size)],
+- s->block_aligned_filename_size, &s->src_sg, 1);
+- if (rc != 1) {
++ s->block_aligned_filename_size, s->src_sg, 2);
++ if (rc < 1) {
+ printk(KERN_ERR "%s: Internal error whilst attempting to "
+ "convert encrypted filename memory to scatterlist; "
+- "expected rc = 1; got rc = [%d]. "
+- "block_aligned_filename_size = [%zd]\n", __func__, rc,
+- s->block_aligned_filename_size);
++ "rc = [%d]. block_aligned_filename_size = [%zd]\n",
++ __func__, rc, s->block_aligned_filename_size);
+ goto out_unlock;
+ }
+ (*packet_size) += s->block_aligned_filename_size;
+@@ -1028,13 +1025,12 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
+ goto out_unlock;
+ }
+ rc = virt_to_scatterlist(s->decrypted_filename,
+- s->block_aligned_filename_size, &s->dst_sg, 1);
+- if (rc != 1) {
++ s->block_aligned_filename_size, s->dst_sg, 2);
++ if (rc < 1) {
+ printk(KERN_ERR "%s: Internal error whilst attempting to "
+ "convert decrypted filename memory to scatterlist; "
+- "expected rc = 1; got rc = [%d]. "
+- "block_aligned_filename_size = [%zd]\n", __func__, rc,
+- s->block_aligned_filename_size);
++ "rc = [%d]. block_aligned_filename_size = [%zd]\n",
++ __func__, rc, s->block_aligned_filename_size);
+ goto out_free_unlock;
+ }
+ /* The characters in the first block effectively do the job of
+@@ -1065,7 +1061,7 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size,
+ mount_crypt_stat->global_default_fn_cipher_key_bytes);
+ goto out_free_unlock;
+ }
+- rc = crypto_blkcipher_decrypt_iv(&s->desc, &s->dst_sg, &s->src_sg,
++ rc = crypto_blkcipher_decrypt_iv(&s->desc, s->dst_sg, s->src_sg,
+ s->block_aligned_filename_size);
+ if (rc) {
+ printk(KERN_ERR "%s: Error attempting to decrypt filename; "
+diff --git a/fs/exec.c b/fs/exec.c
+index 5e62d26..0c3682d 100644
+--- a/fs/exec.c
++++ b/fs/exec.c
+@@ -1046,6 +1046,7 @@ int flush_old_exec(struct linux_binprm * bprm)
+
+ bprm->mm = NULL; /* We're using it now */
+
++ set_fs(USER_DS);
+ current->flags &= ~(PF_RANDOMIZE | PF_KTHREAD);
+ flush_thread();
+ current->personality &= ~bprm->per_clear;
+@@ -1310,10 +1311,6 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
+ if (retval)
+ return retval;
+
+- /* kernel module loader fixup */
+- /* so we don't try to load run modprobe in kernel space. */
+- set_fs(USER_DS);
+-
+ retval = audit_bprm(bprm);
+ if (retval)
+ return retval;
+diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c
+index 32f3b86..93f9fd0 100644
+--- a/fs/ext3/namei.c
++++ b/fs/ext3/namei.c
+@@ -1416,10 +1416,19 @@ static int make_indexed_dir(handle_t *handle, struct dentry *dentry,
+ frame->at = entries;
+ frame->bh = bh;
+ bh = bh2;
++ /*
++ * Mark buffers dirty here so that if do_split() fails we write a
++ * consistent set of buffers to disk.
++ */
++ ext3_journal_dirty_metadata(handle, frame->bh);
++ ext3_journal_dirty_metadata(handle, bh);
+ de = do_split(handle,dir, &bh, frame, &hinfo, &retval);
+- dx_release (frames);
+- if (!(de))
++ if (!de) {
++ ext3_mark_inode_dirty(handle, dir);
++ dx_release(frames);
+ return retval;
++ }
++ dx_release(frames);
+
+ return add_dirent_to_buf(handle, dentry, inode, de, bh);
+ }
+diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
+index 4daaf2b..1e37c09 100644
+--- a/fs/ext4/ext4.h
++++ b/fs/ext4/ext4.h
+@@ -1590,12 +1590,8 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,
+ */
+ struct ext4_lazy_init {
+ unsigned long li_state;
+-
+- wait_queue_head_t li_wait_daemon;
+ wait_queue_head_t li_wait_task;
+- struct timer_list li_timer;
+ struct task_struct *li_task;
+-
+ struct list_head li_request_list;
+ struct mutex li_list_mtx;
+ };
+diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
+index d8a16ee..15bfa44 100644
+--- a/fs/ext4/mballoc.c
++++ b/fs/ext4/mballoc.c
+@@ -1273,6 +1273,8 @@ repeat_load_buddy:
+ return 0;
+
+ err:
++ if (page)
++ page_cache_release(page);
+ if (e4b->bd_bitmap_page)
+ page_cache_release(e4b->bd_bitmap_page);
+ if (e4b->bd_buddy_page)
+diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
+index b6dbd05..7bb8f76 100644
+--- a/fs/ext4/page-io.c
++++ b/fs/ext4/page-io.c
+@@ -203,46 +203,29 @@ static void ext4_end_bio(struct bio *bio, int error)
+ for (i = 0; i < io_end->num_io_pages; i++) {
+ struct page *page = io_end->pages[i]->p_page;
+ struct buffer_head *bh, *head;
+- int partial_write = 0;
++ loff_t offset;
++ loff_t io_end_offset;
+
+- head = page_buffers(page);
+- if (error)
++ if (error) {
+ SetPageError(page);
+- BUG_ON(!head);
+- if (head->b_size != PAGE_CACHE_SIZE) {
+- loff_t offset;
+- loff_t io_end_offset = io_end->offset + io_end->size;
++ set_bit(AS_EIO, &page->mapping->flags);
++ head = page_buffers(page);
++ BUG_ON(!head);
++
++ io_end_offset = io_end->offset + io_end->size;
+
+ offset = (sector_t) page->index << PAGE_CACHE_SHIFT;
+ bh = head;
+ do {
+ if ((offset >= io_end->offset) &&
+- (offset+bh->b_size <= io_end_offset)) {
+- if (error)
+- buffer_io_error(bh);
+-
+- }
+- if (buffer_delay(bh))
+- partial_write = 1;
+- else if (!buffer_mapped(bh))
+- clear_buffer_dirty(bh);
+- else if (buffer_dirty(bh))
+- partial_write = 1;
++ (offset+bh->b_size <= io_end_offset))
++ buffer_io_error(bh);
++
+ offset += bh->b_size;
+ bh = bh->b_this_page;
+ } while (bh != head);
+ }
+
+- /*
+- * If this is a partial write which happened to make
+- * all buffers uptodate then we can optimize away a
+- * bogus readpage() for the next read(). Here we
+- * 'discover' whether the page went uptodate as a
+- * result of this (potentially partial) write.
+- */
+- if (!partial_write)
+- SetPageUptodate(page);
+-
+ put_io_page(io_end->pages[i]);
+ }
+ io_end->num_io_pages = 0;
+diff --git a/fs/ext4/super.c b/fs/ext4/super.c
+index 8553dfb..e6ea384 100644
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -2659,12 +2659,6 @@ static void print_daily_error_info(unsigned long arg)
+ mod_timer(&sbi->s_err_report, jiffies + 24*60*60*HZ); /* Once a day */
+ }
+
+-static void ext4_lazyinode_timeout(unsigned long data)
+-{
+- struct task_struct *p = (struct task_struct *)data;
+- wake_up_process(p);
+-}
+-
+ /* Find next suitable group and run ext4_init_inode_table */
+ static int ext4_run_li_request(struct ext4_li_request *elr)
+ {
+@@ -2712,7 +2706,7 @@ static int ext4_run_li_request(struct ext4_li_request *elr)
+
+ /*
+ * Remove lr_request from the list_request and free the
+- * request tructure. Should be called with li_list_mtx held
++ * request structure. Should be called with li_list_mtx held
+ */
+ static void ext4_remove_li_request(struct ext4_li_request *elr)
+ {
+@@ -2730,14 +2724,16 @@ static void ext4_remove_li_request(struct ext4_li_request *elr)
+
+ static void ext4_unregister_li_request(struct super_block *sb)
+ {
+- struct ext4_li_request *elr = EXT4_SB(sb)->s_li_request;
+-
+- if (!ext4_li_info)
++ mutex_lock(&ext4_li_mtx);
++ if (!ext4_li_info) {
++ mutex_unlock(&ext4_li_mtx);
+ return;
++ }
+
+ mutex_lock(&ext4_li_info->li_list_mtx);
+- ext4_remove_li_request(elr);
++ ext4_remove_li_request(EXT4_SB(sb)->s_li_request);
+ mutex_unlock(&ext4_li_info->li_list_mtx);
++ mutex_unlock(&ext4_li_mtx);
+ }
+
+ static struct task_struct *ext4_lazyinit_task;
+@@ -2756,14 +2752,10 @@ static int ext4_lazyinit_thread(void *arg)
+ struct ext4_lazy_init *eli = (struct ext4_lazy_init *)arg;
+ struct list_head *pos, *n;
+ struct ext4_li_request *elr;
+- unsigned long next_wakeup;
+- DEFINE_WAIT(wait);
++ unsigned long next_wakeup, cur;
+
+ BUG_ON(NULL == eli);
+
+- eli->li_timer.data = (unsigned long)current;
+- eli->li_timer.function = ext4_lazyinode_timeout;
+-
+ eli->li_task = current;
+ wake_up(&eli->li_wait_task);
+
+@@ -2797,19 +2789,15 @@ cont_thread:
+ if (freezing(current))
+ refrigerator();
+
+- if ((time_after_eq(jiffies, next_wakeup)) ||
++ cur = jiffies;
++ if ((time_after_eq(cur, next_wakeup)) ||
+ (MAX_JIFFY_OFFSET == next_wakeup)) {
+ cond_resched();
+ continue;
+ }
+
+- eli->li_timer.expires = next_wakeup;
+- add_timer(&eli->li_timer);
+- prepare_to_wait(&eli->li_wait_daemon, &wait,
+- TASK_INTERRUPTIBLE);
+- if (time_before(jiffies, next_wakeup))
+- schedule();
+- finish_wait(&eli->li_wait_daemon, &wait);
++ schedule_timeout_interruptible(next_wakeup - cur);
++
+ if (kthread_should_stop()) {
+ ext4_clear_request_list();
+ goto exit_thread;
+@@ -2833,12 +2821,10 @@ exit_thread:
+ goto cont_thread;
+ }
+ mutex_unlock(&eli->li_list_mtx);
+- del_timer_sync(&ext4_li_info->li_timer);
+ eli->li_task = NULL;
+ wake_up(&eli->li_wait_task);
+
+ kfree(ext4_li_info);
+- ext4_lazyinit_task = NULL;
+ ext4_li_info = NULL;
+ mutex_unlock(&ext4_li_mtx);
+
+@@ -2866,7 +2852,6 @@ static int ext4_run_lazyinit_thread(void)
+ if (IS_ERR(ext4_lazyinit_task)) {
+ int err = PTR_ERR(ext4_lazyinit_task);
+ ext4_clear_request_list();
+- del_timer_sync(&ext4_li_info->li_timer);
+ kfree(ext4_li_info);
+ ext4_li_info = NULL;
+ printk(KERN_CRIT "EXT4: error %d creating inode table "
+@@ -2915,9 +2900,7 @@ static int ext4_li_info_new(void)
+ INIT_LIST_HEAD(&eli->li_request_list);
+ mutex_init(&eli->li_list_mtx);
+
+- init_waitqueue_head(&eli->li_wait_daemon);
+ init_waitqueue_head(&eli->li_wait_task);
+- init_timer(&eli->li_timer);
+ eli->li_state |= EXT4_LAZYINIT_QUIT;
+
+ ext4_li_info = eli;
+@@ -4652,6 +4635,9 @@ static int ext4_quota_off(struct super_block *sb, int type)
+ if (test_opt(sb, DELALLOC))
+ sync_filesystem(sb);
+
++ if (!inode)
++ goto out;
++
+ /* Update modification times of quota files when userspace can
+ * start looking at them */
+ handle = ext4_journal_start(inode, 1);
+diff --git a/fs/fat/file.c b/fs/fat/file.c
+index 7257752..7018e1d 100644
+--- a/fs/fat/file.c
++++ b/fs/fat/file.c
+@@ -102,7 +102,7 @@ static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr)
+ if (attr & ATTR_SYS)
+ inode->i_flags |= S_IMMUTABLE;
+ else
+- inode->i_flags &= S_IMMUTABLE;
++ inode->i_flags &= ~S_IMMUTABLE;
+ }
+
+ fat_save_attrs(inode, attr);
+diff --git a/fs/fscache/page.c b/fs/fscache/page.c
+index 41c441c..fd03b0e 100644
+--- a/fs/fscache/page.c
++++ b/fs/fscache/page.c
+@@ -967,3 +967,43 @@ void fscache_mark_pages_cached(struct fscache_retrieval *op,
+ pagevec_reinit(pagevec);
+ }
+ EXPORT_SYMBOL(fscache_mark_pages_cached);
++
++/*
++ * Uncache all the pages in an inode that are marked PG_fscache, assuming them
++ * to be associated with the given cookie.
++ */
++void __fscache_uncache_all_inode_pages(struct fscache_cookie *cookie,
++ struct inode *inode)
++{
++ struct address_space *mapping = inode->i_mapping;
++ struct pagevec pvec;
++ pgoff_t next;
++ int i;
++
++ _enter("%p,%p", cookie, inode);
++
++ if (!mapping || mapping->nrpages == 0) {
++ _leave(" [no pages]");
++ return;
++ }
++
++ pagevec_init(&pvec, 0);
++ next = 0;
++ do {
++ if (!pagevec_lookup(&pvec, mapping, next, PAGEVEC_SIZE))
++ break;
++ for (i = 0; i < pagevec_count(&pvec); i++) {
++ struct page *page = pvec.pages[i];
++ next = page->index;
++ if (PageFsCache(page)) {
++ __fscache_wait_on_page_write(cookie, page);
++ __fscache_uncache_page(cookie, page);
++ }
++ }
++ pagevec_release(&pvec);
++ cond_resched();
++ } while (++next);
++
++ _leave("");
++}
++EXPORT_SYMBOL(__fscache_uncache_all_inode_pages);
+diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c
+index e483108..418728f 100644
+--- a/fs/gfs2/file.c
++++ b/fs/gfs2/file.c
+@@ -826,6 +826,7 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
+ loff_t bytes, max_bytes;
+ struct gfs2_alloc *al;
+ int error;
++ loff_t bsize_mask = ~((loff_t)sdp->sd_sb.sb_bsize - 1);
+ loff_t next = (offset + len - 1) >> sdp->sd_sb.sb_bsize_shift;
+ next = (next + 1) << sdp->sd_sb.sb_bsize_shift;
+
+@@ -833,13 +834,15 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
+ if (mode & ~FALLOC_FL_KEEP_SIZE)
+ return -EOPNOTSUPP;
+
+- offset = (offset >> sdp->sd_sb.sb_bsize_shift) <<
+- sdp->sd_sb.sb_bsize_shift;
++ offset &= bsize_mask;
+
+ len = next - offset;
+ bytes = sdp->sd_max_rg_data * sdp->sd_sb.sb_bsize / 2;
+ if (!bytes)
+ bytes = UINT_MAX;
++ bytes &= bsize_mask;
++ if (bytes == 0)
++ bytes = sdp->sd_sb.sb_bsize;
+
+ gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &ip->i_gh);
+ error = gfs2_glock_nq(&ip->i_gh);
+@@ -870,6 +873,9 @@ retry:
+ if (error) {
+ if (error == -ENOSPC && bytes > sdp->sd_sb.sb_bsize) {
+ bytes >>= 1;
++ bytes &= bsize_mask;
++ if (bytes == 0)
++ bytes = sdp->sd_sb.sb_bsize;
+ goto retry;
+ }
+ goto out_qunlock;
+diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c
+index 3031d81..4ac88ff 100644
+--- a/fs/hfsplus/wrapper.c
++++ b/fs/hfsplus/wrapper.c
+@@ -36,6 +36,7 @@ int hfsplus_submit_bio(struct block_device *bdev, sector_t sector,
+ {
+ DECLARE_COMPLETION_ONSTACK(wait);
+ struct bio *bio;
++ int ret = 0;
+
+ bio = bio_alloc(GFP_NOIO, 1);
+ bio->bi_sector = sector;
+@@ -54,8 +55,10 @@ int hfsplus_submit_bio(struct block_device *bdev, sector_t sector,
+ wait_for_completion(&wait);
+
+ if (!bio_flagged(bio, BIO_UPTODATE))
+- return -EIO;
+- return 0;
++ ret = -EIO;
++
++ bio_put(bio);
++ return ret;
+ }
+
+ static int hfsplus_read_mdb(void *bufptr, struct hfsplus_wd *wd)
+diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c
+index 69b1804..f486ff6 100644
+--- a/fs/jbd/commit.c
++++ b/fs/jbd/commit.c
+@@ -722,8 +722,13 @@ wait_for_iobuf:
+ required. */
+ JBUFFER_TRACE(jh, "file as BJ_Forget");
+ journal_file_buffer(jh, commit_transaction, BJ_Forget);
+- /* Wake up any transactions which were waiting for this
+- IO to complete */
++ /*
++ * Wake up any transactions which were waiting for this
++ * IO to complete. The barrier must be here so that changes
++ * by journal_file_buffer() take effect before wake_up_bit()
++ * does the waitqueue check.
++ */
++ smp_mb();
+ wake_up_bit(&bh->b_state, BH_Unshadow);
+ JBUFFER_TRACE(jh, "brelse shadowed buffer");
+ __brelse(bh);
+diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
+index b3713af..e2d4285 100644
+--- a/fs/jbd/journal.c
++++ b/fs/jbd/journal.c
+@@ -437,9 +437,12 @@ int __log_space_left(journal_t *journal)
+ int __log_start_commit(journal_t *journal, tid_t target)
+ {
+ /*
+- * Are we already doing a recent enough commit?
++ * The only transaction we can possibly wait upon is the
++ * currently running transaction (if it exists). Otherwise,
++ * the target tid must be an old one.
+ */
+- if (!tid_geq(journal->j_commit_request, target)) {
++ if (journal->j_running_transaction &&
++ journal->j_running_transaction->t_tid == target) {
+ /*
+ * We want a new commit: OK, mark the request and wakeup the
+ * commit thread. We do _not_ do the commit ourselves.
+@@ -451,7 +454,14 @@ int __log_start_commit(journal_t *journal, tid_t target)
+ journal->j_commit_sequence);
+ wake_up(&journal->j_wait_commit);
+ return 1;
+- }
++ } else if (!tid_geq(journal->j_commit_request, target))
++ /* This should never happen, but if it does, preserve
++ the evidence before kjournald goes into a loop and
++ increments j_commit_sequence beyond all recognition. */
++ WARN_ONCE(1, "jbd: bad log_start_commit: %u %u %u %u\n",
++ journal->j_commit_request, journal->j_commit_sequence,
++ target, journal->j_running_transaction ?
++ journal->j_running_transaction->t_tid : 0);
+ return 0;
+ }
+
+diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c
+index adb45ec..e374050 100644
+--- a/fs/lockd/clntproc.c
++++ b/fs/lockd/clntproc.c
+@@ -708,7 +708,13 @@ static void nlmclnt_unlock_callback(struct rpc_task *task, void *data)
+
+ if (task->tk_status < 0) {
+ dprintk("lockd: unlock failed (err = %d)\n", -task->tk_status);
+- goto retry_rebind;
++ switch (task->tk_status) {
++ case -EACCES:
++ case -EIO:
++ goto die;
++ default:
++ goto retry_rebind;
++ }
+ }
+ if (status == NLM_LCK_DENIED_GRACE_PERIOD) {
+ rpc_delay(task, NLMCLNT_GRACE_WAIT);
+diff --git a/fs/locks.c b/fs/locks.c
+index 0a4f50d..b286539 100644
+--- a/fs/locks.c
++++ b/fs/locks.c
+@@ -160,10 +160,28 @@ EXPORT_SYMBOL_GPL(unlock_flocks);
+
+ static struct kmem_cache *filelock_cache __read_mostly;
+
++static void locks_init_lock_always(struct file_lock *fl)
++{
++ fl->fl_next = NULL;
++ fl->fl_fasync = NULL;
++ fl->fl_owner = NULL;
++ fl->fl_pid = 0;
++ fl->fl_nspid = NULL;
++ fl->fl_file = NULL;
++ fl->fl_flags = 0;
++ fl->fl_type = 0;
++ fl->fl_start = fl->fl_end = 0;
++}
++
+ /* Allocate an empty lock structure. */
+ struct file_lock *locks_alloc_lock(void)
+ {
+- return kmem_cache_alloc(filelock_cache, GFP_KERNEL);
++ struct file_lock *fl = kmem_cache_alloc(filelock_cache, GFP_KERNEL);
++
++ if (fl)
++ locks_init_lock_always(fl);
++
++ return fl;
+ }
+ EXPORT_SYMBOL_GPL(locks_alloc_lock);
+
+@@ -200,17 +218,9 @@ void locks_init_lock(struct file_lock *fl)
+ INIT_LIST_HEAD(&fl->fl_link);
+ INIT_LIST_HEAD(&fl->fl_block);
+ init_waitqueue_head(&fl->fl_wait);
+- fl->fl_next = NULL;
+- fl->fl_fasync = NULL;
+- fl->fl_owner = NULL;
+- fl->fl_pid = 0;
+- fl->fl_nspid = NULL;
+- fl->fl_file = NULL;
+- fl->fl_flags = 0;
+- fl->fl_type = 0;
+- fl->fl_start = fl->fl_end = 0;
+ fl->fl_ops = NULL;
+ fl->fl_lmops = NULL;
++ locks_init_lock_always(fl);
+ }
+
+ EXPORT_SYMBOL(locks_init_lock);
+diff --git a/fs/namei.c b/fs/namei.c
+index e3c4f11..732a754 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1013,7 +1013,6 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
+ * Don't forget we might have a non-mountpoint managed dentry
+ * that wants to block transit.
+ */
+- *inode = path->dentry->d_inode;
+ if (!reverse_transit &&
+ unlikely(managed_dentry_might_block(path->dentry)))
+ return false;
+@@ -1027,6 +1026,12 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
+ path->mnt = mounted;
+ path->dentry = mounted->mnt_root;
+ nd->seq = read_seqcount_begin(&path->dentry->d_seq);
++ /*
++ * Update the inode too. We don't need to re-check the
++ * dentry sequence number here after this d_inode read,
++ * because a mount-point is always pinned.
++ */
++ *inode = path->dentry->d_inode;
+ }
+
+ if (unlikely(path->dentry->d_flags & DCACHE_NEED_AUTOMOUNT))
+@@ -1378,12 +1383,12 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd)
+ {
+ int res;
+
+- BUG_ON(nd->depth >= MAX_NESTED_LINKS);
+ if (unlikely(current->link_count >= MAX_NESTED_LINKS)) {
+ path_put_conditional(path, nd);
+ path_put(&nd->path);
+ return -ELOOP;
+ }
++ BUG_ON(nd->depth >= MAX_NESTED_LINKS);
+
+ nd->depth++;
+ current->link_count++;
+diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
+index ce153a6..419119c 100644
+--- a/fs/nfs/fscache.c
++++ b/fs/nfs/fscache.c
+@@ -259,12 +259,10 @@ static void nfs_fscache_disable_inode_cookie(struct inode *inode)
+ dfprintk(FSCACHE,
+ "NFS: nfsi 0x%p turning cache off\n", NFS_I(inode));
+
+- /* Need to invalidate any mapped pages that were read in before
+- * turning off the cache.
++ /* Need to uncache any pages attached to this inode that
++ * fscache knows about before turning off the cache.
+ */
+- if (inode->i_mapping && inode->i_mapping->nrpages)
+- invalidate_inode_pages2(inode->i_mapping);
+-
++ fscache_uncache_all_inode_pages(NFS_I(inode)->fscache, inode);
+ nfs_fscache_zap_inode_cookie(inode);
+ }
+ }
+diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
+index 57bb31a..19877db 100644
+--- a/fs/nfs/inode.c
++++ b/fs/nfs/inode.c
+@@ -256,7 +256,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
+
+ nfs_attr_check_mountpoint(sb, fattr);
+
+- if ((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0 && (fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0)
++ if (((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0) &&
++ !nfs_attr_use_mounted_on_fileid(fattr))
+ goto out_no_inode;
+ if ((fattr->valid & NFS_ATTR_FATTR_TYPE) == 0)
+ goto out_no_inode;
+@@ -1294,7 +1295,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
+ if (new_isize != cur_isize) {
+ /* Do we perhaps have any outstanding writes, or has
+ * the file grown beyond our last write? */
+- if (nfsi->npages == 0 || new_isize > cur_isize) {
++ if ((nfsi->npages == 0 && !test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) ||
++ new_isize > cur_isize) {
+ i_size_write(inode, new_isize);
+ invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA;
+ }
+diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
+index ce118ce..d10eb7e 100644
+--- a/fs/nfs/internal.h
++++ b/fs/nfs/internal.h
+@@ -45,6 +45,17 @@ static inline void nfs_attr_check_mountpoint(struct super_block *parent, struct
+ fattr->valid |= NFS_ATTR_FATTR_MOUNTPOINT;
+ }
+
++static inline int nfs_attr_use_mounted_on_fileid(struct nfs_fattr *fattr)
++{
++ if (((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) == 0) ||
++ (((fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0) &&
++ ((fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) == 0)))
++ return 0;
++
++ fattr->fileid = fattr->mounted_on_fileid;
++ return 1;
++}
++
+ struct nfs_clone_mount {
+ const struct super_block *sb;
+ const struct dentry *dentry;
+diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
+index be79dc9..590c09c 100644
+--- a/fs/nfs/nfs4filelayout.c
++++ b/fs/nfs/nfs4filelayout.c
+@@ -554,13 +554,18 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
+ __func__, nfl_util, fl->num_fh, fl->first_stripe_index,
+ fl->pattern_offset);
+
+- if (!fl->num_fh)
++ /* Note that a zero value for num_fh is legal for STRIPE_SPARSE.
++ * Futher checking is done in filelayout_check_layout */
++ if (fl->num_fh < 0 || fl->num_fh >
++ max(NFS4_PNFS_MAX_STRIPE_CNT, NFS4_PNFS_MAX_MULTI_CNT))
+ goto out_err;
+
+- fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
+- gfp_flags);
+- if (!fl->fh_array)
+- goto out_err;
++ if (fl->num_fh > 0) {
++ fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *),
++ gfp_flags);
++ if (!fl->fh_array)
++ goto out_err;
++ }
+
+ for (i = 0; i < fl->num_fh; i++) {
+ /* Do we want to use a mempool here? */
+diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
+index cf1b339..d348326 100644
+--- a/fs/nfs/nfs4proc.c
++++ b/fs/nfs/nfs4proc.c
+@@ -267,9 +267,11 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc
+ break;
+ nfs4_schedule_stateid_recovery(server, state);
+ goto wait_on_recovery;
++ case -NFS4ERR_EXPIRED:
++ if (state != NULL)
++ nfs4_schedule_stateid_recovery(server, state);
+ case -NFS4ERR_STALE_STATEID:
+ case -NFS4ERR_STALE_CLIENTID:
+- case -NFS4ERR_EXPIRED:
+ nfs4_schedule_lease_recovery(clp);
+ goto wait_on_recovery;
+ #if defined(CONFIG_NFS_V4_1)
+@@ -2263,12 +2265,14 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
+ return nfs4_map_errors(status);
+ }
+
++static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr);
+ /*
+ * Get locations and (maybe) other attributes of a referral.
+ * Note that we'll actually follow the referral later when
+ * we detect fsid mismatch in inode revalidation
+ */
+-static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct nfs_fattr *fattr, struct nfs_fh *fhandle)
++static int nfs4_get_referral(struct inode *dir, const struct qstr *name,
++ struct nfs_fattr *fattr, struct nfs_fh *fhandle)
+ {
+ int status = -ENOMEM;
+ struct page *page = NULL;
+@@ -2286,15 +2290,16 @@ static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct
+ goto out;
+ /* Make sure server returned a different fsid for the referral */
+ if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) {
+- dprintk("%s: server did not return a different fsid for a referral at %s\n", __func__, name->name);
++ dprintk("%s: server did not return a different fsid for"
++ " a referral at %s\n", __func__, name->name);
+ status = -EIO;
+ goto out;
+ }
++ /* Fixup attributes for the nfs_lookup() call to nfs_fhget() */
++ nfs_fixup_referral_attributes(&locations->fattr);
+
++ /* replace the lookup nfs_fattr with the locations nfs_fattr */
+ memcpy(fattr, &locations->fattr, sizeof(struct nfs_fattr));
+- fattr->valid |= NFS_ATTR_FATTR_V4_REFERRAL;
+- if (!fattr->mode)
+- fattr->mode = S_IFDIR;
+ memset(fhandle, 0, sizeof(struct nfs_fh));
+ out:
+ if (page)
+@@ -3670,9 +3675,11 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
+ break;
+ nfs4_schedule_stateid_recovery(server, state);
+ goto wait_on_recovery;
++ case -NFS4ERR_EXPIRED:
++ if (state != NULL)
++ nfs4_schedule_stateid_recovery(server, state);
+ case -NFS4ERR_STALE_STATEID:
+ case -NFS4ERR_STALE_CLIENTID:
+- case -NFS4ERR_EXPIRED:
+ nfs4_schedule_lease_recovery(clp);
+ goto wait_on_recovery;
+ #if defined(CONFIG_NFS_V4_1)
+@@ -4543,6 +4550,7 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl)
+ case -ESTALE:
+ goto out;
+ case -NFS4ERR_EXPIRED:
++ nfs4_schedule_stateid_recovery(server, state);
+ case -NFS4ERR_STALE_CLIENTID:
+ case -NFS4ERR_STALE_STATEID:
+ nfs4_schedule_lease_recovery(server->nfs_client);
+@@ -4652,11 +4660,15 @@ static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list,
+ return len;
+ }
+
++/*
++ * nfs_fhget will use either the mounted_on_fileid or the fileid
++ */
+ static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr)
+ {
+- if (!((fattr->valid & NFS_ATTR_FATTR_FILEID) &&
+- (fattr->valid & NFS_ATTR_FATTR_FSID) &&
+- (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)))
++ if (!(((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) ||
++ (fattr->valid & NFS_ATTR_FATTR_FILEID)) &&
++ (fattr->valid & NFS_ATTR_FATTR_FSID) &&
++ (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL)))
+ return;
+
+ fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE |
+@@ -4671,7 +4683,6 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
+ struct nfs_server *server = NFS_SERVER(dir);
+ u32 bitmask[2] = {
+ [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS,
+- [1] = FATTR4_WORD1_MOUNTED_ON_FILEID,
+ };
+ struct nfs4_fs_locations_arg args = {
+ .dir_fh = NFS_FH(dir),
+@@ -4690,11 +4701,18 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name,
+ int status;
+
+ dprintk("%s: start\n", __func__);
++
++ /* Ask for the fileid of the absent filesystem if mounted_on_fileid
++ * is not supported */
++ if (NFS_SERVER(dir)->attr_bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
++ bitmask[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID;
++ else
++ bitmask[0] |= FATTR4_WORD0_FILEID;
++
+ nfs_fattr_init(&fs_locations->fattr);
+ fs_locations->server = server;
+ fs_locations->nlocations = 0;
+ status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0);
+- nfs_fixup_referral_attributes(&fs_locations->fattr);
+ dprintk("%s: returned status = %d\n", __func__, status);
+ return status;
+ }
+diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
+index 036f5ad..e97dd21 100644
+--- a/fs/nfs/nfs4state.c
++++ b/fs/nfs/nfs4state.c
+@@ -1466,7 +1466,10 @@ static int nfs4_reclaim_lease(struct nfs_client *clp)
+ #ifdef CONFIG_NFS_V4_1
+ void nfs4_schedule_session_recovery(struct nfs4_session *session)
+ {
+- nfs4_schedule_lease_recovery(session->clp);
++ struct nfs_client *clp = session->clp;
++
++ set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
++ nfs4_schedule_lease_recovery(clp);
+ }
+ EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery);
+
+@@ -1549,6 +1552,7 @@ static int nfs4_reset_session(struct nfs_client *clp)
+ status = nfs4_recovery_handle_error(clp, status);
+ goto out;
+ }
++ clear_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
+ /* create_session negotiated new slot table */
+ clear_bit(NFS4CLNT_RECALL_SLOT, &clp->cl_state);
+
+diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
+index c3ccd2c..a58bd56 100644
+--- a/fs/nfs/nfs4xdr.c
++++ b/fs/nfs/nfs4xdr.c
+@@ -91,7 +91,7 @@ static int nfs4_stat_to_errno(int);
+ #define encode_getfh_maxsz (op_encode_hdr_maxsz)
+ #define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \
+ ((3+NFS4_FHSIZE) >> 2))
+-#define nfs4_fattr_bitmap_maxsz 3
++#define nfs4_fattr_bitmap_maxsz 4
+ #define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
+ #define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2))
+ #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2))
+@@ -3030,7 +3030,7 @@ out_overflow:
+ return -EIO;
+ }
+
+-static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap)
++static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res)
+ {
+ __be32 *p;
+
+@@ -3041,7 +3041,7 @@ static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap)
+ if (unlikely(!p))
+ goto out_overflow;
+ bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
+- return -be32_to_cpup(p);
++ *res = -be32_to_cpup(p);
+ }
+ return 0;
+ out_overflow:
+@@ -4002,6 +4002,7 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
+ int status;
+ umode_t fmode = 0;
+ uint32_t type;
++ int32_t err;
+
+ status = decode_attr_type(xdr, bitmap, &type);
+ if (status < 0)
+@@ -4027,13 +4028,12 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
+ goto xdr_error;
+ fattr->valid |= status;
+
+- status = decode_attr_error(xdr, bitmap);
+- if (status == -NFS4ERR_WRONGSEC) {
+- nfs_fixup_secinfo_attributes(fattr, fh);
+- status = 0;
+- }
++ err = 0;
++ status = decode_attr_error(xdr, bitmap, &err);
+ if (status < 0)
+ goto xdr_error;
++ if (err == -NFS4ERR_WRONGSEC)
++ nfs_fixup_secinfo_attributes(fattr, fh);
+
+ status = decode_attr_filehandle(xdr, bitmap, fh);
+ if (status < 0)
+diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
+index f57f528..101c85a 100644
+--- a/fs/nfs/pnfs.c
++++ b/fs/nfs/pnfs.c
+@@ -1009,7 +1009,7 @@ void
+ pnfs_set_layoutcommit(struct nfs_write_data *wdata)
+ {
+ struct nfs_inode *nfsi = NFS_I(wdata->inode);
+- loff_t end_pos = wdata->args.offset + wdata->res.count;
++ loff_t end_pos = wdata->mds_offset + wdata->res.count;
+ bool mark_as_dirty = false;
+
+ spin_lock(&nfsi->vfs_inode.i_lock);
+diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig
+index 18b3e89..fbb2a5e 100644
+--- a/fs/nfsd/Kconfig
++++ b/fs/nfsd/Kconfig
+@@ -82,6 +82,7 @@ config NFSD_V4
+ select NFSD_V3
+ select FS_POSIX_ACL
+ select SUNRPC_GSS
++ select CRYPTO
+ help
+ This option enables support in your system's NFS server for
+ version 4 of the NFS protocol (RFC 3530).
+diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
+index 1f5eae4..2b1449d 100644
+--- a/fs/nfsd/nfsctl.c
++++ b/fs/nfsd/nfsctl.c
+@@ -13,6 +13,7 @@
+ #include <linux/lockd/lockd.h>
+ #include <linux/sunrpc/clnt.h>
+ #include <linux/sunrpc/gss_api.h>
++#include <linux/sunrpc/gss_krb5_enctypes.h>
+
+ #include "idmap.h"
+ #include "nfsd.h"
+@@ -189,18 +190,10 @@ static struct file_operations export_features_operations = {
+ .release = single_release,
+ };
+
+-#ifdef CONFIG_SUNRPC_GSS
++#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
+ static int supported_enctypes_show(struct seq_file *m, void *v)
+ {
+- struct gss_api_mech *k5mech;
+-
+- k5mech = gss_mech_get_by_name("krb5");
+- if (k5mech == NULL)
+- goto out;
+- if (k5mech->gm_upcall_enctypes != NULL)
+- seq_printf(m, k5mech->gm_upcall_enctypes);
+- gss_mech_put(k5mech);
+-out:
++ seq_printf(m, KRB5_SUPPORTED_ENCTYPES);
+ return 0;
+ }
+
+@@ -215,7 +208,7 @@ static struct file_operations supported_enctypes_ops = {
+ .llseek = seq_lseek,
+ .release = single_release,
+ };
+-#endif /* CONFIG_SUNRPC_GSS */
++#endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
+
+ extern int nfsd_pool_stats_open(struct inode *inode, struct file *file);
+ extern int nfsd_pool_stats_release(struct inode *inode, struct file *file);
+@@ -1427,9 +1420,9 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
+ [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR},
+ [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO},
+ [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO},
+-#ifdef CONFIG_SUNRPC_GSS
++#if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE)
+ [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO},
+-#endif /* CONFIG_SUNRPC_GSS */
++#endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */
+ #ifdef CONFIG_NFSD_V4
+ [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR},
+ [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR},
+diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
+index 129f3c9..d80b2d8 100644
+--- a/fs/nfsd/vfs.c
++++ b/fs/nfsd/vfs.c
+@@ -699,7 +699,15 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor
+ }
+ #endif /* CONFIG_NFSD_V3 */
+
++static int nfsd_open_break_lease(struct inode *inode, int access)
++{
++ unsigned int mode;
+
++ if (access & NFSD_MAY_NOT_BREAK_LEASE)
++ return 0;
++ mode = (access & NFSD_MAY_WRITE) ? O_WRONLY : O_RDONLY;
++ return break_lease(inode, mode | O_NONBLOCK);
++}
+
+ /*
+ * Open an existing file or directory.
+@@ -747,12 +755,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
+ if (!inode->i_fop)
+ goto out;
+
+- /*
+- * Check to see if there are any leases on this file.
+- * This may block while leases are broken.
+- */
+- if (!(access & NFSD_MAY_NOT_BREAK_LEASE))
+- host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? O_WRONLY : 0));
++ host_err = nfsd_open_break_lease(inode, access);
+ if (host_err) /* NOMEM or WOULDBLOCK */
+ goto out_nfserr;
+
+@@ -1653,8 +1656,10 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp,
+ if (!dold->d_inode)
+ goto out_drop_write;
+ host_err = nfsd_break_lease(dold->d_inode);
+- if (host_err)
++ if (host_err) {
++ err = nfserrno(host_err);
+ goto out_drop_write;
++ }
+ host_err = vfs_link(dold, dirp, dnew);
+ if (!host_err) {
+ err = nfserrno(commit_metadata(ffhp));
+diff --git a/fs/partitions/efi.c b/fs/partitions/efi.c
+index 19d6750..6296b40 100644
+--- a/fs/partitions/efi.c
++++ b/fs/partitions/efi.c
+@@ -310,6 +310,15 @@ static int is_gpt_valid(struct parsed_partitions *state, u64 lba,
+ goto fail;
+ }
+
++ /* Check the GUID Partition Table header size */
++ if (le32_to_cpu((*gpt)->header_size) >
++ bdev_logical_block_size(state->bdev)) {
++ pr_debug("GUID Partition Table Header size is wrong: %u > %u\n",
++ le32_to_cpu((*gpt)->header_size),
++ bdev_logical_block_size(state->bdev));
++ goto fail;
++ }
++
+ /* Check the GUID Partition Table CRC */
+ origcrc = le32_to_cpu((*gpt)->header_crc32);
+ (*gpt)->header_crc32 = 0;
+diff --git a/fs/partitions/ldm.c b/fs/partitions/ldm.c
+index ce4f624..a29d5cc 100644
+--- a/fs/partitions/ldm.c
++++ b/fs/partitions/ldm.c
+@@ -1335,6 +1335,11 @@ static bool ldm_frag_add (const u8 *data, int size, struct list_head *frags)
+
+ list_add_tail (&f->list, frags);
+ found:
++ if (rec >= f->num) {
++ ldm_error("REC value (%d) exceeds NUM value (%d)", rec, f->num);
++ return false;
++ }
++
+ if (f->map & (1 << rec)) {
+ ldm_error ("Duplicate VBLK, part %d.", rec);
+ f->map &= 0x7F; /* Mark the group as broken */
+diff --git a/fs/proc/base.c b/fs/proc/base.c
+index dfa5327..0352336 100644
+--- a/fs/proc/base.c
++++ b/fs/proc/base.c
+@@ -2762,6 +2762,9 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole)
+ struct task_io_accounting acct = task->ioac;
+ unsigned long flags;
+
++ if (!ptrace_may_access(task, PTRACE_MODE_READ))
++ return -EACCES;
++
+ if (whole && lock_task_sighand(task, &flags)) {
+ struct task_struct *t = task;
+
+@@ -2892,7 +2895,7 @@ static const struct pid_entry tgid_base_stuff[] = {
+ REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations),
+ #endif
+ #ifdef CONFIG_TASK_IO_ACCOUNTING
+- INF("io", S_IRUGO, proc_tgid_io_accounting),
++ INF("io", S_IRUSR, proc_tgid_io_accounting),
+ #endif
+ };
+
+@@ -3230,7 +3233,7 @@ static const struct pid_entry tid_base_stuff[] = {
+ REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
+ #endif
+ #ifdef CONFIG_TASK_IO_ACCOUNTING
+- INF("io", S_IRUGO, proc_tid_io_accounting),
++ INF("io", S_IRUSR, proc_tid_io_accounting),
+ #endif
+ };
+
+diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
+index aed25e8..e5cb2ce 100644
+--- a/fs/ubifs/journal.c
++++ b/fs/ubifs/journal.c
+@@ -666,6 +666,7 @@ out_free:
+
+ out_release:
+ release_head(c, BASEHD);
++ kfree(dent);
+ out_ro:
+ ubifs_ro_mode(c, err);
+ if (last_reference)
+diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
+index bf31b47..cad60b5 100644
+--- a/fs/ubifs/sb.c
++++ b/fs/ubifs/sb.c
+@@ -475,7 +475,8 @@ failed:
+ * @c: UBIFS file-system description object
+ *
+ * This function returns a pointer to the superblock node or a negative error
+- * code.
++ * code. Note, the user of this function is responsible of kfree()'ing the
++ * returned superblock buffer.
+ */
+ struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c)
+ {
+diff --git a/fs/ubifs/shrinker.c b/fs/ubifs/shrinker.c
+index 46961c0..d8f5d0f 100644
+--- a/fs/ubifs/shrinker.c
++++ b/fs/ubifs/shrinker.c
+@@ -283,7 +283,11 @@ int ubifs_shrinker(struct shrinker *shrink, int nr, gfp_t gfp_mask)
+ long clean_zn_cnt = atomic_long_read(&ubifs_clean_zn_cnt);
+
+ if (nr == 0)
+- return clean_zn_cnt;
++ /*
++ * Due to the way UBIFS updates the clean znode counter it may
++ * temporarily be negative.
++ */
++ return clean_zn_cnt >= 0 ? clean_zn_cnt : 1;
+
+ if (!clean_zn_cnt) {
+ /*
+diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
+index 04ad07f..328e6fc 100644
+--- a/fs/ubifs/super.c
++++ b/fs/ubifs/super.c
+@@ -1584,6 +1584,7 @@ static int ubifs_remount_rw(struct ubifs_info *c)
+ }
+ sup->leb_cnt = cpu_to_le32(c->leb_cnt);
+ err = ubifs_write_sb_node(c, sup);
++ kfree(sup);
+ if (err)
+ goto out;
+ }
+diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
+index 27d64d7..a892ed9 100644
+--- a/fs/xfs/xfs_alloc.c
++++ b/fs/xfs/xfs_alloc.c
+@@ -2610,6 +2610,12 @@ restart:
+ new->bno + new->length) -
+ min(busyp->bno, new->bno);
+ new->bno = min(busyp->bno, new->bno);
++ /*
++ * Start the search over from the tree root, because
++ * erasing the node can rearrange the tree topology.
++ */
++ spin_unlock(&pag->pagb_lock);
++ goto restart;
+ } else
+ busyp = NULL;
+
+diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h
+index e5a3f58..dfb0ec6 100644
+--- a/include/asm-generic/bug.h
++++ b/include/asm-generic/bug.h
+@@ -162,9 +162,6 @@ extern void warn_slowpath_null(const char *file, const int line);
+ unlikely(__ret_warn_once); \
+ })
+
+-#define WARN_ON_RATELIMIT(condition, state) \
+- WARN_ON((condition) && __ratelimit(state))
+-
+ /*
+ * WARN_ON_SMP() is for cases that the warning is either
+ * meaningless for !SMP or may even cause failures.
+diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h
+index f04b2a3..06cd510 100644
+--- a/include/drm/drm_pciids.h
++++ b/include/drm/drm_pciids.h
+@@ -182,6 +182,7 @@
+ {0x1002, 0x6750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6758, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6759, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
++ {0x1002, 0x675F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6760, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6761, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6762, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
+@@ -192,6 +193,7 @@
+ {0x1002, 0x6767, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6768, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6770, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
++ {0x1002, 0x6778, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6779, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6880, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \
+ {0x1002, 0x6888, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYPRESS|RADEON_NEW_MEMMAP}, \
+diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h
+index be50d9e..acdb143 100644
+--- a/include/linux/blk_types.h
++++ b/include/linux/blk_types.h
+@@ -168,7 +168,7 @@ enum rq_flag_bits {
+ (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER)
+ #define REQ_COMMON_MASK \
+ (REQ_WRITE | REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_DISCARD | \
+- REQ_NOIDLE | REQ_FLUSH | REQ_FUA)
++ REQ_NOIDLE | REQ_FLUSH | REQ_FUA | REQ_SECURE)
+ #define REQ_CLONE_MASK REQ_COMMON_MASK
+
+ #define REQ_RAHEAD (1 << __REQ_RAHEAD)
+diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
+index 2ad95fa..ae9091a 100644
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -257,7 +257,7 @@ struct queue_limits {
+ unsigned char misaligned;
+ unsigned char discard_misaligned;
+ unsigned char cluster;
+- signed char discard_zeroes_data;
++ unsigned char discard_zeroes_data;
+ };
+
+ struct request_queue
+@@ -364,6 +364,8 @@ struct request_queue
+ * for flush operations
+ */
+ unsigned int flush_flags;
++ unsigned int flush_not_queueable:1;
++ unsigned int flush_queue_delayed:1;
+ unsigned int flush_pending_idx:1;
+ unsigned int flush_running_idx:1;
+ unsigned long flush_pending_since;
+@@ -843,6 +845,7 @@ extern void blk_queue_softirq_done(struct request_queue *, softirq_done_fn *);
+ extern void blk_queue_rq_timed_out(struct request_queue *, rq_timed_out_fn *);
+ extern void blk_queue_rq_timeout(struct request_queue *, unsigned int);
+ extern void blk_queue_flush(struct request_queue *q, unsigned int flush);
++extern void blk_queue_flush_queueable(struct request_queue *q, bool queueable);
+ extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
+
+ extern int blk_rq_map_sg(struct request_queue *, struct request *, struct scatterlist *);
+@@ -1066,13 +1069,16 @@ static inline int queue_limit_discard_alignment(struct queue_limits *lim, sector
+ {
+ unsigned int alignment = (sector << 9) & (lim->discard_granularity - 1);
+
++ if (!lim->max_discard_sectors)
++ return 0;
++
+ return (lim->discard_granularity + lim->discard_alignment - alignment)
+ & (lim->discard_granularity - 1);
+ }
+
+ static inline unsigned int queue_discard_zeroes_data(struct request_queue *q)
+ {
+- if (q->limits.discard_zeroes_data == 1)
++ if (q->limits.max_discard_sectors && q->limits.discard_zeroes_data == 1)
+ return 1;
+
+ return 0;
+@@ -1111,6 +1117,11 @@ static inline unsigned int block_size(struct block_device *bdev)
+ return bdev->bd_block_size;
+ }
+
++static inline bool queue_flush_queueable(struct request_queue *q)
++{
++ return !q->flush_not_queueable;
++}
++
+ typedef struct {struct page *v;} Sector;
+
+ unsigned char *read_dev_sector(struct block_device *, sector_t, Sector *);
+diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
+index c37b21a..24e2932 100644
+--- a/include/linux/clocksource.h
++++ b/include/linux/clocksource.h
+@@ -192,6 +192,7 @@ struct clocksource {
+ #ifdef CONFIG_CLOCKSOURCE_WATCHDOG
+ /* Watchdog related data, used by the framework */
+ struct list_head wd_list;
++ cycle_t cs_last;
+ cycle_t wd_last;
+ #endif
+ };
+diff --git a/include/linux/connector.h b/include/linux/connector.h
+index 7c60d09..f696bcc 100644
+--- a/include/linux/connector.h
++++ b/include/linux/connector.h
+@@ -44,7 +44,7 @@
+ #define CN_VAL_DRBD 0x1
+ #define CN_KVP_IDX 0x9 /* HyperV KVP */
+
+-#define CN_NETLINK_USERS 9
++#define CN_NETLINK_USERS 10 /* Highest index + 1 */
+
+ /*
+ * Maximum connector's message size.
+diff --git a/include/linux/device.h b/include/linux/device.h
+index d08399d..779e860 100644
+--- a/include/linux/device.h
++++ b/include/linux/device.h
+@@ -506,13 +506,13 @@ static inline int device_is_registered(struct device *dev)
+
+ static inline void device_enable_async_suspend(struct device *dev)
+ {
+- if (!dev->power.in_suspend)
++ if (!dev->power.is_prepared)
+ dev->power.async_suspend = true;
+ }
+
+ static inline void device_disable_async_suspend(struct device *dev)
+ {
+- if (!dev->power.in_suspend)
++ if (!dev->power.is_prepared)
+ dev->power.async_suspend = false;
+ }
+
+diff --git a/include/linux/fscache.h b/include/linux/fscache.h
+index 7c4d72f..9ec20de 100644
+--- a/include/linux/fscache.h
++++ b/include/linux/fscache.h
+@@ -204,6 +204,8 @@ extern bool __fscache_check_page_write(struct fscache_cookie *, struct page *);
+ extern void __fscache_wait_on_page_write(struct fscache_cookie *, struct page *);
+ extern bool __fscache_maybe_release_page(struct fscache_cookie *, struct page *,
+ gfp_t);
++extern void __fscache_uncache_all_inode_pages(struct fscache_cookie *,
++ struct inode *);
+
+ /**
+ * fscache_register_netfs - Register a filesystem as desiring caching services
+@@ -643,4 +645,23 @@ bool fscache_maybe_release_page(struct fscache_cookie *cookie,
+ return false;
+ }
+
++/**
++ * fscache_uncache_all_inode_pages - Uncache all an inode's pages
++ * @cookie: The cookie representing the inode's cache object.
++ * @inode: The inode to uncache pages from.
++ *
++ * Uncache all the pages in an inode that are marked PG_fscache, assuming them
++ * to be associated with the given cookie.
++ *
++ * This function may sleep. It will wait for pages that are being written out
++ * and will wait whilst the PG_fscache mark is removed by the cache.
++ */
++static inline
++void fscache_uncache_all_inode_pages(struct fscache_cookie *cookie,
++ struct inode *inode)
++{
++ if (fscache_cookie_valid(cookie))
++ __fscache_uncache_all_inode_pages(cookie, inode);
++}
++
+ #endif /* _LINUX_FSCACHE_H */
+diff --git a/include/linux/genhd.h b/include/linux/genhd.h
+index d764a42..300d758 100644
+--- a/include/linux/genhd.h
++++ b/include/linux/genhd.h
+@@ -127,6 +127,7 @@ struct hd_struct {
+ #define GENHD_FL_SUPPRESS_PARTITION_INFO 32
+ #define GENHD_FL_EXT_DEVT 64 /* allow extended devt */
+ #define GENHD_FL_NATIVE_CAPACITY 128
++#define GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE 256
+
+ enum {
+ DISK_EVENT_MEDIA_CHANGE = 1 << 0, /* media changed */
+diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h
+index 72bfa5a..8e37fba 100644
+--- a/include/linux/if_packet.h
++++ b/include/linux/if_packet.h
+@@ -62,6 +62,7 @@ struct tpacket_auxdata {
+ __u16 tp_mac;
+ __u16 tp_net;
+ __u16 tp_vlan_tci;
++ __u16 tp_padding;
+ };
+
+ /* Rx ring - header status */
+@@ -100,6 +101,7 @@ struct tpacket2_hdr {
+ __u32 tp_sec;
+ __u32 tp_nsec;
+ __u16 tp_vlan_tci;
++ __u16 tp_padding;
+ };
+
+ #define TPACKET2_HDRLEN (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll))
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index 0249fe7..66b22bf 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -1680,9 +1680,12 @@ static inline int skb_gro_header_hard(struct sk_buff *skb, unsigned int hlen)
+ static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen,
+ unsigned int offset)
+ {
++ if (!pskb_may_pull(skb, hlen))
++ return NULL;
++
+ NAPI_GRO_CB(skb)->frag0 = NULL;
+ NAPI_GRO_CB(skb)->frag0_len = 0;
+- return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL;
++ return skb->data + offset;
+ }
+
+ static inline void *skb_gro_mac_header(struct sk_buff *skb)
+diff --git a/include/linux/netfilter/ipset/ip_set_ahash.h b/include/linux/netfilter/ipset/ip_set_ahash.h
+index a0196ac..ac3c822 100644
+--- a/include/linux/netfilter/ipset/ip_set_ahash.h
++++ b/include/linux/netfilter/ipset/ip_set_ahash.h
+@@ -839,7 +839,7 @@ type_pf_tdel(struct ip_set *set, void *value, u32 timeout)
+ struct htable *t = h->table;
+ const struct type_pf_elem *d = value;
+ struct hbucket *n;
+- int i, ret = 0;
++ int i;
+ struct type_pf_elem *data;
+ u32 key;
+
+@@ -850,7 +850,7 @@ type_pf_tdel(struct ip_set *set, void *value, u32 timeout)
+ if (!type_pf_data_equal(data, d))
+ continue;
+ if (type_pf_data_expired(data))
+- ret = -IPSET_ERR_EXIST;
++ return -IPSET_ERR_EXIST;
+ if (i != n->pos - 1)
+ /* Not last one */
+ type_pf_data_copy(data, ahash_tdata(n, n->pos - 1));
+diff --git a/include/linux/netfilter/ipset/ip_set_timeout.h b/include/linux/netfilter/ipset/ip_set_timeout.h
+index 9f30c5f..bb773c1 100644
+--- a/include/linux/netfilter/ipset/ip_set_timeout.h
++++ b/include/linux/netfilter/ipset/ip_set_timeout.h
+@@ -45,7 +45,7 @@ ip_set_timeout_test(unsigned long timeout)
+ {
+ return timeout != IPSET_ELEM_UNSET &&
+ (timeout == IPSET_ELEM_PERMANENT ||
+- time_after(timeout, jiffies));
++ time_is_after_jiffies(timeout));
+ }
+
+ static inline bool
+@@ -53,7 +53,7 @@ ip_set_timeout_expired(unsigned long timeout)
+ {
+ return timeout != IPSET_ELEM_UNSET &&
+ timeout != IPSET_ELEM_PERMANENT &&
+- time_before(timeout, jiffies);
++ time_is_before_jiffies(timeout);
+ }
+
+ static inline unsigned long
+@@ -64,7 +64,7 @@ ip_set_timeout_set(u32 timeout)
+ if (!timeout)
+ return IPSET_ELEM_PERMANENT;
+
+- t = timeout * HZ + jiffies;
++ t = msecs_to_jiffies(timeout * 1000) + jiffies;
+ if (t == IPSET_ELEM_UNSET || t == IPSET_ELEM_PERMANENT)
+ /* Bingo! */
+ t++;
+@@ -75,7 +75,8 @@ ip_set_timeout_set(u32 timeout)
+ static inline u32
+ ip_set_timeout_get(unsigned long timeout)
+ {
+- return timeout == IPSET_ELEM_PERMANENT ? 0 : (timeout - jiffies)/HZ;
++ return timeout == IPSET_ELEM_PERMANENT ? 0 :
++ jiffies_to_msecs(timeout - jiffies)/1000;
+ }
+
+ #else
+@@ -89,14 +90,14 @@ static inline bool
+ ip_set_timeout_test(unsigned long timeout)
+ {
+ return timeout == IPSET_ELEM_PERMANENT ||
+- time_after(timeout, jiffies);
++ time_is_after_jiffies(timeout);
+ }
+
+ static inline bool
+ ip_set_timeout_expired(unsigned long timeout)
+ {
+ return timeout != IPSET_ELEM_PERMANENT &&
+- time_before(timeout, jiffies);
++ time_is_before_jiffies(timeout);
+ }
+
+ static inline unsigned long
+@@ -107,7 +108,7 @@ ip_set_timeout_set(u32 timeout)
+ if (!timeout)
+ return IPSET_ELEM_PERMANENT;
+
+- t = timeout * HZ + jiffies;
++ t = msecs_to_jiffies(timeout * 1000) + jiffies;
+ if (t == IPSET_ELEM_PERMANENT)
+ /* Bingo! :-) */
+ t++;
+@@ -118,7 +119,8 @@ ip_set_timeout_set(u32 timeout)
+ static inline u32
+ ip_set_timeout_get(unsigned long timeout)
+ {
+- return timeout == IPSET_ELEM_PERMANENT ? 0 : (timeout - jiffies)/HZ;
++ return timeout == IPSET_ELEM_PERMANENT ? 0 :
++ jiffies_to_msecs(timeout - jiffies)/1000;
+ }
+ #endif /* ! IP_SET_BITMAP_TIMEOUT */
+
+diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
+index 8abe8d7..d041a4a 100644
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -608,6 +608,8 @@
+ #define PCI_DEVICE_ID_MATROX_G550 0x2527
+ #define PCI_DEVICE_ID_MATROX_VIA 0x4536
+
++#define PCI_VENDOR_ID_MOBILITY_ELECTRONICS 0x14f2
++
+ #define PCI_VENDOR_ID_CT 0x102c
+ #define PCI_DEVICE_ID_CT_69000 0x00c0
+ #define PCI_DEVICE_ID_CT_65545 0x00d8
+@@ -1535,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_R5CE823 0xe823
+ #define PCI_DEVICE_ID_RICOH_R5C832 0x0832
+ #define PCI_DEVICE_ID_RICOH_R5C843 0x0843
+
+diff --git a/include/linux/pm.h b/include/linux/pm.h
+index 512e091..fffb12f 100644
+--- a/include/linux/pm.h
++++ b/include/linux/pm.h
+@@ -425,7 +425,8 @@ struct dev_pm_info {
+ pm_message_t power_state;
+ unsigned int can_wakeup:1;
+ unsigned int async_suspend:1;
+- unsigned int in_suspend:1; /* Owned by the PM core */
++ bool is_prepared:1; /* Owned by the PM core */
++ bool is_suspended:1; /* Ditto */
+ spinlock_t lock;
+ #ifdef CONFIG_PM_SLEEP
+ struct list_head entry;
+diff --git a/include/linux/pm_qos_params.h b/include/linux/pm_qos_params.h
+index 77cbddb..a7d87f9 100644
+--- a/include/linux/pm_qos_params.h
++++ b/include/linux/pm_qos_params.h
+@@ -16,6 +16,10 @@
+ #define PM_QOS_NUM_CLASSES 4
+ #define PM_QOS_DEFAULT_VALUE -1
+
++#define PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC)
++#define PM_QOS_NETWORK_LAT_DEFAULT_VALUE (2000 * USEC_PER_SEC)
++#define PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE 0
++
+ struct pm_qos_request_list {
+ struct plist_node list;
+ int pm_qos_class;
+diff --git a/include/linux/ratelimit.h b/include/linux/ratelimit.h
+index 03ff67b..2f00715 100644
+--- a/include/linux/ratelimit.h
++++ b/include/linux/ratelimit.h
+@@ -41,4 +41,44 @@ extern struct ratelimit_state printk_ratelimit_state;
+ extern int ___ratelimit(struct ratelimit_state *rs, const char *func);
+ #define __ratelimit(state) ___ratelimit(state, __func__)
+
++#ifdef CONFIG_PRINTK
++
++#define WARN_ON_RATELIMIT(condition, state) \
++ WARN_ON((condition) && __ratelimit(state))
++
++#define __WARN_RATELIMIT(condition, state, format...) \
++({ \
++ int rtn = 0; \
++ if (unlikely(__ratelimit(state))) \
++ rtn = WARN(condition, format); \
++ rtn; \
++})
++
++#define WARN_RATELIMIT(condition, format...) \
++({ \
++ static DEFINE_RATELIMIT_STATE(_rs, \
++ DEFAULT_RATELIMIT_INTERVAL, \
++ DEFAULT_RATELIMIT_BURST); \
++ __WARN_RATELIMIT(condition, &_rs, format); \
++})
++
++#else
++
++#define WARN_ON_RATELIMIT(condition, state) \
++ WARN_ON(condition)
++
++#define __WARN_RATELIMIT(condition, state, format...) \
++({ \
++ int rtn = WARN(condition, format); \
++ rtn; \
++})
++
++#define WARN_RATELIMIT(condition, format...) \
++({ \
++ int rtn = WARN(condition, format); \
++ rtn; \
++})
++
++#endif
++
+ #endif /* _LINUX_RATELIMIT_H */
+diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
+index e98cd2e..06d6964 100644
+--- a/include/linux/seqlock.h
++++ b/include/linux/seqlock.h
+@@ -88,12 +88,12 @@ static __always_inline unsigned read_seqbegin(const seqlock_t *sl)
+ unsigned ret;
+
+ repeat:
+- ret = sl->sequence;
+- smp_rmb();
++ ret = ACCESS_ONCE(sl->sequence);
+ if (unlikely(ret & 1)) {
+ cpu_relax();
+ goto repeat;
+ }
++ smp_rmb();
+
+ return ret;
+ }
+diff --git a/include/linux/sunrpc/gss_krb5_enctypes.h b/include/linux/sunrpc/gss_krb5_enctypes.h
+new file mode 100644
+index 0000000..ec6234e
+--- /dev/null
++++ b/include/linux/sunrpc/gss_krb5_enctypes.h
+@@ -0,0 +1,4 @@
++/*
++ * Dumb way to share this static piece of information with nfsd
++ */
++#define KRB5_SUPPORTED_ENCTYPES "18,17,16,23,3,1,2"
+diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
+index f73c482..fe2d8e6 100644
+--- a/include/linux/sunrpc/sched.h
++++ b/include/linux/sunrpc/sched.h
+@@ -84,7 +84,8 @@ struct rpc_task {
+ #endif
+ unsigned char tk_priority : 2,/* Task priority */
+ tk_garb_retry : 2,
+- tk_cred_retry : 2;
++ tk_cred_retry : 2,
++ tk_rebind_retry : 2;
+ };
+ #define tk_xprt tk_client->cl_xprt
+
+diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h
+index 71693d4..17df360 100644
+--- a/include/linux/usb_usual.h
++++ b/include/linux/usb_usual.h
+@@ -62,7 +62,9 @@
+ US_FLAG(NO_READ_DISC_INFO, 0x00040000) \
+ /* cannot handle READ_DISC_INFO */ \
+ US_FLAG(NO_READ_CAPACITY_16, 0x00080000) \
+- /* cannot handle READ_CAPACITY_16 */
++ /* cannot handle READ_CAPACITY_16 */ \
++ US_FLAG(INITIAL_READ10, 0x00100000) \
++ /* Initial READ(10) (and others) must be retried */
+
+ #define US_FLAG(name, value) US_FL_##name = value ,
+ enum { US_DO_ALL_FLAGS };
+diff --git a/include/net/dst.h b/include/net/dst.h
+index 75b95df..b3ad020 100644
+--- a/include/net/dst.h
++++ b/include/net/dst.h
+@@ -120,6 +120,8 @@ static inline u32 *dst_metrics_write_ptr(struct dst_entry *dst)
+ {
+ unsigned long p = dst->_metrics;
+
++ BUG_ON(!p);
++
+ if (p & DST_METRICS_READ_ONLY)
+ return dst->ops->cow_metrics(dst, p);
+ return __DST_METRICS_PTR(p);
+diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
+index 86aefed..e5bf4c8 100644
+--- a/include/net/ip_vs.h
++++ b/include/net/ip_vs.h
+@@ -802,7 +802,8 @@ struct netns_ipvs {
+ struct list_head rs_table[IP_VS_RTAB_SIZE];
+ /* ip_vs_app */
+ struct list_head app_list;
+-
++ /* ip_vs_ftp */
++ struct ip_vs_app *ftp_app;
+ /* ip_vs_proto */
+ #define IP_VS_PROTO_TAB_SIZE 32 /* must be power of 2 */
+ struct ip_vs_proto_data *proto_data_table[IP_VS_PROTO_TAB_SIZE];
+diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
+index 1d3b5b2..561ac99 100644
+--- a/include/target/target_core_base.h
++++ b/include/target/target_core_base.h
+@@ -98,6 +98,7 @@ enum transport_state_table {
+ TRANSPORT_REMOVE = 14,
+ TRANSPORT_FREE = 15,
+ TRANSPORT_NEW_CMD_MAP = 16,
++ TRANSPORT_FREE_CMD_INTR = 17,
+ };
+
+ /* Used for struct se_cmd->se_cmd_flags */
+diff --git a/include/target/target_core_transport.h b/include/target/target_core_transport.h
+index 59aa464..24a1c6c 100644
+--- a/include/target/target_core_transport.h
++++ b/include/target/target_core_transport.h
+@@ -172,6 +172,7 @@ extern int transport_generic_handle_cdb_map(struct se_cmd *);
+ extern int transport_generic_handle_data(struct se_cmd *);
+ extern void transport_new_cmd_failure(struct se_cmd *);
+ extern int transport_generic_handle_tmr(struct se_cmd *);
++extern void transport_generic_free_cmd_intr(struct se_cmd *);
+ extern void __transport_stop_task_timer(struct se_task *, unsigned long *);
+ extern unsigned char transport_asciihex_to_binaryhex(unsigned char val[2]);
+ extern int transport_generic_map_mem_to_cmd(struct se_cmd *cmd, struct scatterlist *, u32,
+diff --git a/init/calibrate.c b/init/calibrate.c
+index 76ac919..30a44cd 100644
+--- a/init/calibrate.c
++++ b/init/calibrate.c
+@@ -185,30 +185,32 @@ recalibrate:
+
+ void __cpuinit calibrate_delay(void)
+ {
++ unsigned long lpj;
+ static bool printed;
+
+ if (preset_lpj) {
+- loops_per_jiffy = preset_lpj;
++ lpj = preset_lpj;
+ if (!printed)
+ pr_info("Calibrating delay loop (skipped) "
+ "preset value.. ");
+ } else if ((!printed) && lpj_fine) {
+- loops_per_jiffy = lpj_fine;
++ lpj = lpj_fine;
+ pr_info("Calibrating delay loop (skipped), "
+ "value calculated using timer frequency.. ");
+- } else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) {
++ } else if ((lpj = calibrate_delay_direct()) != 0) {
+ if (!printed)
+ pr_info("Calibrating delay using timer "
+ "specific routine.. ");
+ } else {
+ if (!printed)
+ pr_info("Calibrating delay loop... ");
+- loops_per_jiffy = calibrate_delay_converge();
++ lpj = calibrate_delay_converge();
+ }
+ if (!printed)
+ pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
+- loops_per_jiffy/(500000/HZ),
+- (loops_per_jiffy/(5000/HZ)) % 100, loops_per_jiffy);
++ lpj/(500000/HZ),
++ (lpj/(5000/HZ)) % 100, lpj);
+
++ loops_per_jiffy = lpj;
+ printed = true;
+ }
+diff --git a/init/main.c b/init/main.c
+index 4a9479e..48df882 100644
+--- a/init/main.c
++++ b/init/main.c
+@@ -580,8 +580,8 @@ asmlinkage void __init start_kernel(void)
+ #endif
+ page_cgroup_init();
+ enable_debug_pagealloc();
+- kmemleak_init();
+ debug_objects_mem_init();
++ kmemleak_init();
+ setup_per_cpu_pageset();
+ numa_policy_init();
+ if (late_time_init)
+diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
+index 2c039c9..51e4944 100644
+--- a/kernel/irq/irqdesc.c
++++ b/kernel/irq/irqdesc.c
+@@ -257,13 +257,11 @@ int __init early_irq_init(void)
+ count = ARRAY_SIZE(irq_desc);
+
+ for (i = 0; i < count; i++) {
+- desc[i].irq_data.irq = i;
+- desc[i].irq_data.chip = &no_irq_chip;
+ desc[i].kstat_irqs = alloc_percpu(unsigned int);
+- irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS);
+- alloc_masks(desc + i, GFP_KERNEL, node);
+- desc_smp_init(desc + i, node);
++ alloc_masks(&desc[i], GFP_KERNEL, node);
++ raw_spin_lock_init(&desc[i].lock);
+ lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
++ desc_set_defaults(i, &desc[i], node);
+ }
+ return arch_early_irq_init();
+ }
+diff --git a/kernel/lockdep.c b/kernel/lockdep.c
+index 53a6895..49452a7 100644
+--- a/kernel/lockdep.c
++++ b/kernel/lockdep.c
+@@ -3242,7 +3242,7 @@ int lock_is_held(struct lockdep_map *lock)
+ int ret = 0;
+
+ if (unlikely(current->lockdep_recursion))
+- return ret;
++ return 1; /* avoid false negative lockdep_assert_held() */
+
+ raw_local_irq_save(flags);
+ check_flags(flags);
+diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
+index 0da058b..a9582ef 100644
+--- a/kernel/pm_qos_params.c
++++ b/kernel/pm_qos_params.c
+@@ -53,11 +53,17 @@ enum pm_qos_type {
+ PM_QOS_MIN /* return the smallest value */
+ };
+
++/*
++ * Note: The lockless read path depends on the CPU accessing
++ * target_value atomically. Atomic access is only guaranteed on all CPU
++ * types linux supports for 32 bit quantites
++ */
+ struct pm_qos_object {
+ struct plist_head requests;
+ struct blocking_notifier_head *notifiers;
+ struct miscdevice pm_qos_power_miscdev;
+ char *name;
++ s32 target_value; /* Do not change to 64 bit */
+ s32 default_value;
+ enum pm_qos_type type;
+ };
+@@ -70,7 +76,8 @@ static struct pm_qos_object cpu_dma_pm_qos = {
+ .requests = PLIST_HEAD_INIT(cpu_dma_pm_qos.requests, pm_qos_lock),
+ .notifiers = &cpu_dma_lat_notifier,
+ .name = "cpu_dma_latency",
+- .default_value = 2000 * USEC_PER_SEC,
++ .target_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE,
++ .default_value = PM_QOS_CPU_DMA_LAT_DEFAULT_VALUE,
+ .type = PM_QOS_MIN,
+ };
+
+@@ -79,7 +86,8 @@ static struct pm_qos_object network_lat_pm_qos = {
+ .requests = PLIST_HEAD_INIT(network_lat_pm_qos.requests, pm_qos_lock),
+ .notifiers = &network_lat_notifier,
+ .name = "network_latency",
+- .default_value = 2000 * USEC_PER_SEC,
++ .target_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE,
++ .default_value = PM_QOS_NETWORK_LAT_DEFAULT_VALUE,
+ .type = PM_QOS_MIN
+ };
+
+@@ -89,7 +97,8 @@ static struct pm_qos_object network_throughput_pm_qos = {
+ .requests = PLIST_HEAD_INIT(network_throughput_pm_qos.requests, pm_qos_lock),
+ .notifiers = &network_throughput_notifier,
+ .name = "network_throughput",
+- .default_value = 0,
++ .target_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE,
++ .default_value = PM_QOS_NETWORK_THROUGHPUT_DEFAULT_VALUE,
+ .type = PM_QOS_MAX,
+ };
+
+@@ -135,6 +144,16 @@ static inline int pm_qos_get_value(struct pm_qos_object *o)
+ }
+ }
+
++static inline s32 pm_qos_read_value(struct pm_qos_object *o)
++{
++ return o->target_value;
++}
++
++static inline void pm_qos_set_value(struct pm_qos_object *o, s32 value)
++{
++ o->target_value = value;
++}
++
+ static void update_target(struct pm_qos_object *o, struct plist_node *node,
+ int del, int value)
+ {
+@@ -159,6 +178,7 @@ static void update_target(struct pm_qos_object *o, struct plist_node *node,
+ plist_add(node, &o->requests);
+ }
+ curr_value = pm_qos_get_value(o);
++ pm_qos_set_value(o, curr_value);
+ spin_unlock_irqrestore(&pm_qos_lock, flags);
+
+ if (prev_value != curr_value)
+@@ -193,18 +213,11 @@ static int find_pm_qos_object_by_minor(int minor)
+ * pm_qos_request - returns current system wide qos expectation
+ * @pm_qos_class: identification of which qos value is requested
+ *
+- * This function returns the current target value in an atomic manner.
++ * This function returns the current target value.
+ */
+ int pm_qos_request(int pm_qos_class)
+ {
+- unsigned long flags;
+- int value;
+-
+- spin_lock_irqsave(&pm_qos_lock, flags);
+- value = pm_qos_get_value(pm_qos_array[pm_qos_class]);
+- spin_unlock_irqrestore(&pm_qos_lock, flags);
+-
+- return value;
++ return pm_qos_read_value(pm_qos_array[pm_qos_class]);
+ }
+ EXPORT_SYMBOL_GPL(pm_qos_request);
+
+diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
+index ca0aacc..1a78c1a 100644
+--- a/kernel/power/snapshot.c
++++ b/kernel/power/snapshot.c
+@@ -1199,7 +1199,11 @@ static void free_unnecessary_pages(void)
+ to_free_highmem = alloc_highmem - save;
+ } else {
+ to_free_highmem = 0;
+- to_free_normal -= save - alloc_highmem;
++ save -= alloc_highmem;
++ if (to_free_normal > save)
++ to_free_normal -= save;
++ else
++ to_free_normal = 0;
+ }
+
+ memory_bm_position_reset(&copy_bm);
+diff --git a/kernel/power/user.c b/kernel/power/user.c
+index 7d02d33..42ddbc6 100644
+--- a/kernel/power/user.c
++++ b/kernel/power/user.c
+@@ -113,8 +113,10 @@ static int snapshot_open(struct inode *inode, struct file *filp)
+ if (error)
+ pm_notifier_call_chain(PM_POST_RESTORE);
+ }
+- if (error)
++ if (error) {
++ free_basic_memory_bitmaps();
+ atomic_inc(&snapshot_device_available);
++ }
+ data->frozen = 0;
+ data->ready = 0;
+ data->platform_support = 0;
+diff --git a/kernel/taskstats.c b/kernel/taskstats.c
+index 9ffea36..fc0f220 100644
+--- a/kernel/taskstats.c
++++ b/kernel/taskstats.c
+@@ -285,16 +285,18 @@ ret:
+ static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd)
+ {
+ struct listener_list *listeners;
+- struct listener *s, *tmp;
++ struct listener *s, *tmp, *s2;
+ unsigned int cpu;
+
+ if (!cpumask_subset(mask, cpu_possible_mask))
+ return -EINVAL;
+
++ s = NULL;
+ if (isadd == REGISTER) {
+ for_each_cpu(cpu, mask) {
+- s = kmalloc_node(sizeof(struct listener), GFP_KERNEL,
+- cpu_to_node(cpu));
++ if (!s)
++ s = kmalloc_node(sizeof(struct listener),
++ GFP_KERNEL, cpu_to_node(cpu));
+ if (!s)
+ goto cleanup;
+ s->pid = pid;
+@@ -303,9 +305,16 @@ static int add_del_listener(pid_t pid, const struct cpumask *mask, int isadd)
+
+ listeners = &per_cpu(listener_array, cpu);
+ down_write(&listeners->sem);
++ list_for_each_entry_safe(s2, tmp, &listeners->list, list) {
++ if (s2->pid == pid)
++ goto next_cpu;
++ }
+ list_add(&s->list, &listeners->list);
++ s = NULL;
++next_cpu:
+ up_write(&listeners->sem);
+ }
++ kfree(s);
+ return 0;
+ }
+
+diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
+index 0e17c10..727da92 100644
+--- a/kernel/time/clocksource.c
++++ b/kernel/time/clocksource.c
+@@ -185,7 +185,6 @@ static struct clocksource *watchdog;
+ static struct timer_list watchdog_timer;
+ static DECLARE_WORK(watchdog_work, clocksource_watchdog_work);
+ static DEFINE_SPINLOCK(watchdog_lock);
+-static cycle_t watchdog_last;
+ static int watchdog_running;
+
+ static int clocksource_watchdog_kthread(void *data);
+@@ -254,11 +253,6 @@ static void clocksource_watchdog(unsigned long data)
+ if (!watchdog_running)
+ goto out;
+
+- wdnow = watchdog->read(watchdog);
+- wd_nsec = clocksource_cyc2ns((wdnow - watchdog_last) & watchdog->mask,
+- watchdog->mult, watchdog->shift);
+- watchdog_last = wdnow;
+-
+ list_for_each_entry(cs, &watchdog_list, wd_list) {
+
+ /* Clocksource already marked unstable? */
+@@ -268,19 +262,28 @@ static void clocksource_watchdog(unsigned long data)
+ continue;
+ }
+
++ local_irq_disable();
+ csnow = cs->read(cs);
++ wdnow = watchdog->read(watchdog);
++ local_irq_enable();
+
+ /* Clocksource initialized ? */
+ if (!(cs->flags & CLOCK_SOURCE_WATCHDOG)) {
+ cs->flags |= CLOCK_SOURCE_WATCHDOG;
+- cs->wd_last = csnow;
++ cs->wd_last = wdnow;
++ cs->cs_last = csnow;
+ continue;
+ }
+
+- /* Check the deviation from the watchdog clocksource. */
+- cs_nsec = clocksource_cyc2ns((csnow - cs->wd_last) &
++ wd_nsec = clocksource_cyc2ns((wdnow - cs->wd_last) & watchdog->mask,
++ watchdog->mult, watchdog->shift);
++
++ cs_nsec = clocksource_cyc2ns((csnow - cs->cs_last) &
+ cs->mask, cs->mult, cs->shift);
+- cs->wd_last = csnow;
++ cs->cs_last = csnow;
++ cs->wd_last = wdnow;
++
++ /* Check the deviation from the watchdog clocksource. */
+ if (abs(cs_nsec - wd_nsec) > WATCHDOG_THRESHOLD) {
+ clocksource_unstable(cs, cs_nsec - wd_nsec);
+ continue;
+@@ -318,7 +321,6 @@ static inline void clocksource_start_watchdog(void)
+ return;
+ init_timer(&watchdog_timer);
+ watchdog_timer.function = clocksource_watchdog;
+- watchdog_last = watchdog->read(watchdog);
+ watchdog_timer.expires = jiffies + WATCHDOG_INTERVAL;
+ add_timer_on(&watchdog_timer, cpumask_first(cpu_online_mask));
+ watchdog_running = 1;
+diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
+index ee24fa1..666880d 100644
+--- a/kernel/trace/ftrace.c
++++ b/kernel/trace/ftrace.c
+@@ -2413,14 +2413,16 @@ ftrace_regex_release(struct inode *inode, struct file *file, int enable)
+ ftrace_match_records(parser->buffer, parser->idx, enable);
+ }
+
+- mutex_lock(&ftrace_lock);
+- if (ftrace_start_up && ftrace_enabled)
+- ftrace_run_update_code(FTRACE_ENABLE_CALLS);
+- mutex_unlock(&ftrace_lock);
+-
+ trace_parser_put(parser);
+ kfree(iter);
+
++ if (file->f_mode & FMODE_WRITE) {
++ mutex_lock(&ftrace_lock);
++ if (ftrace_start_up && ftrace_enabled)
++ ftrace_run_update_code(FTRACE_ENABLE_CALLS);
++ mutex_unlock(&ftrace_lock);
++ }
++
+ mutex_unlock(&ftrace_regex_lock);
+ return 0;
+ }
+diff --git a/lib/debugobjects.c b/lib/debugobjects.c
+index 9d86e45..a78b7c6 100644
+--- a/lib/debugobjects.c
++++ b/lib/debugobjects.c
+@@ -198,7 +198,7 @@ static void free_object(struct debug_obj *obj)
+ * initialized:
+ */
+ if (obj_pool_free > ODEBUG_POOL_SIZE && obj_cache)
+- sched = !work_pending(&debug_obj_work);
++ sched = keventd_up() && !work_pending(&debug_obj_work);
+ hlist_add_head(&obj->node, &obj_pool);
+ obj_pool_free++;
+ obj_pool_used--;
+diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
+index 619313e..507a22f 100644
+--- a/lib/locking-selftest.c
++++ b/lib/locking-selftest.c
+@@ -144,7 +144,7 @@ static void init_shared_classes(void)
+
+ #define HARDIRQ_ENTER() \
+ local_irq_disable(); \
+- irq_enter(); \
++ __irq_enter(); \
+ WARN_ON(!in_irq());
+
+ #define HARDIRQ_EXIT() \
+diff --git a/mm/compaction.c b/mm/compaction.c
+index 021a296..e4e0166 100644
+--- a/mm/compaction.c
++++ b/mm/compaction.c
+@@ -144,9 +144,20 @@ static void isolate_freepages(struct zone *zone,
+ int nr_freepages = cc->nr_freepages;
+ struct list_head *freelist = &cc->freepages;
+
++ /*
++ * Initialise the free scanner. The starting point is where we last
++ * scanned from (or the end of the zone if starting). The low point
++ * is the end of the pageblock the migration scanner is using.
++ */
+ pfn = cc->free_pfn;
+ low_pfn = cc->migrate_pfn + pageblock_nr_pages;
+- high_pfn = low_pfn;
++
++ /*
++ * Take care that if the migration scanner is at the end of the zone
++ * that the free scanner does not accidentally move to the next zone
++ * in the next isolation cycle.
++ */
++ high_pfn = min(low_pfn, pfn);
+
+ /*
+ * Isolate free pages until enough are available to migrate the
+@@ -240,11 +251,18 @@ static bool too_many_isolated(struct zone *zone)
+ return isolated > (inactive + active) / 2;
+ }
+
++/* possible outcome of isolate_migratepages */
++typedef enum {
++ ISOLATE_ABORT, /* Abort compaction now */
++ ISOLATE_NONE, /* No pages isolated, continue scanning */
++ ISOLATE_SUCCESS, /* Pages isolated, migrate */
++} isolate_migrate_t;
++
+ /*
+ * Isolate all pages that can be migrated from the block pointed to by
+ * the migrate scanner within compact_control.
+ */
+-static unsigned long isolate_migratepages(struct zone *zone,
++static isolate_migrate_t isolate_migratepages(struct zone *zone,
+ struct compact_control *cc)
+ {
+ unsigned long low_pfn, end_pfn;
+@@ -261,7 +279,7 @@ static unsigned long isolate_migratepages(struct zone *zone,
+ /* Do not cross the free scanner or scan within a memory hole */
+ if (end_pfn > cc->free_pfn || !pfn_valid(low_pfn)) {
+ cc->migrate_pfn = end_pfn;
+- return 0;
++ return ISOLATE_NONE;
+ }
+
+ /*
+@@ -270,10 +288,14 @@ static unsigned long isolate_migratepages(struct zone *zone,
+ * delay for some time until fewer pages are isolated
+ */
+ while (unlikely(too_many_isolated(zone))) {
++ /* async migration should just abort */
++ if (!cc->sync)
++ return ISOLATE_ABORT;
++
+ congestion_wait(BLK_RW_ASYNC, HZ/10);
+
+ if (fatal_signal_pending(current))
+- return 0;
++ return ISOLATE_ABORT;
+ }
+
+ /* Time to isolate some pages for migration */
+@@ -358,7 +380,7 @@ static unsigned long isolate_migratepages(struct zone *zone,
+
+ trace_mm_compaction_isolate_migratepages(nr_scanned, nr_isolated);
+
+- return cc->nr_migratepages;
++ return ISOLATE_SUCCESS;
+ }
+
+ /*
+@@ -522,8 +544,15 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
+ unsigned long nr_migrate, nr_remaining;
+ int err;
+
+- if (!isolate_migratepages(zone, cc))
++ switch (isolate_migratepages(zone, cc)) {
++ case ISOLATE_ABORT:
++ ret = COMPACT_PARTIAL;
++ goto out;
++ case ISOLATE_NONE:
+ continue;
++ case ISOLATE_SUCCESS:
++ ;
++ }
+
+ nr_migrate = cc->nr_migratepages;
+ err = migrate_pages(&cc->migratepages, compaction_alloc,
+@@ -547,6 +576,7 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
+
+ }
+
++out:
+ /* Release free pages and check accounting */
+ cc->nr_freepages -= release_freepages(&cc->freepages);
+ VM_BUG_ON(cc->nr_freepages != 0);
+diff --git a/mm/hugetlb.c b/mm/hugetlb.c
+index 8ee3bd8..f7c32fb 100644
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -1033,10 +1033,10 @@ static struct page *alloc_huge_page(struct vm_area_struct *vma,
+ */
+ chg = vma_needs_reservation(h, vma, addr);
+ if (chg < 0)
+- return ERR_PTR(chg);
++ return ERR_PTR(-VM_FAULT_OOM);
+ if (chg)
+ if (hugetlb_get_quota(inode->i_mapping, chg))
+- return ERR_PTR(-ENOSPC);
++ return ERR_PTR(-VM_FAULT_SIGBUS);
+
+ spin_lock(&hugetlb_lock);
+ page = dequeue_huge_page_vma(h, vma, addr, avoid_reserve);
+@@ -1111,6 +1111,14 @@ static void __init gather_bootmem_prealloc(void)
+ WARN_ON(page_count(page) != 1);
+ prep_compound_huge_page(page, h->order);
+ prep_new_huge_page(h, page, page_to_nid(page));
++ /*
++ * If we had gigantic hugepages allocated at boot time, we need
++ * to restore the 'stolen' pages to totalram_pages in order to
++ * fix confusing memory reports from free(1) and another
++ * side-effects, like CommitLimit going negative.
++ */
++ if (h->order > (MAX_ORDER - 1))
++ totalram_pages += 1 << h->order;
+ }
+ }
+
+diff --git a/mm/kmemleak.c b/mm/kmemleak.c
+index c1d5867..aacee45 100644
+--- a/mm/kmemleak.c
++++ b/mm/kmemleak.c
+@@ -1414,9 +1414,12 @@ static void *kmemleak_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+ ++(*pos);
+
+ list_for_each_continue_rcu(n, &object_list) {
+- next_obj = list_entry(n, struct kmemleak_object, object_list);
+- if (get_object(next_obj))
++ struct kmemleak_object *obj =
++ list_entry(n, struct kmemleak_object, object_list);
++ if (get_object(obj)) {
++ next_obj = obj;
+ break;
++ }
+ }
+
+ put_object(prev_obj);
+diff --git a/mm/ksm.c b/mm/ksm.c
+index 942dfc7..e48c86e 100644
+--- a/mm/ksm.c
++++ b/mm/ksm.c
+@@ -1301,6 +1301,12 @@ static struct rmap_item *scan_get_next_rmap_item(struct page **page)
+ slot = list_entry(slot->mm_list.next, struct mm_slot, mm_list);
+ ksm_scan.mm_slot = slot;
+ spin_unlock(&ksm_mmlist_lock);
++ /*
++ * Although we tested list_empty() above, a racing __ksm_exit
++ * of the last mm on the list may have removed it since then.
++ */
++ if (slot == &ksm_mm_head)
++ return NULL;
+ next_mm:
+ ksm_scan.address = 0;
+ ksm_scan.rmap_list = &slot->rmap_list;
+diff --git a/mm/memory-failure.c b/mm/memory-failure.c
+index 2b9a5ee..9568e0b 100644
+--- a/mm/memory-failure.c
++++ b/mm/memory-failure.c
+@@ -52,6 +52,7 @@
+ #include <linux/swapops.h>
+ #include <linux/hugetlb.h>
+ #include <linux/memory_hotplug.h>
++#include <linux/mm_inline.h>
+ #include "internal.h"
+
+ int sysctl_memory_failure_early_kill __read_mostly = 0;
+@@ -1463,7 +1464,8 @@ int soft_offline_page(struct page *page, int flags)
+ ret = isolate_lru_page(page);
+ if (!ret) {
+ LIST_HEAD(pagelist);
+-
++ inc_zone_page_state(page, NR_ISOLATED_ANON +
++ page_is_file_cache(page));
+ list_add(&page->lru, &pagelist);
+ ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL,
+ 0, true);
+diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
+index 9ca1d60..fc5e0ba 100644
+--- a/mm/memory_hotplug.c
++++ b/mm/memory_hotplug.c
+@@ -518,7 +518,7 @@ int mem_online_node(int nid)
+
+ lock_memory_hotplug();
+ pgdat = hotadd_new_pgdat(nid, 0);
+- if (pgdat) {
++ if (!pgdat) {
+ ret = -ENOMEM;
+ goto out;
+ }
+diff --git a/mm/migrate.c b/mm/migrate.c
+index 34132f8..3179891 100644
+--- a/mm/migrate.c
++++ b/mm/migrate.c
+@@ -288,7 +288,7 @@ static int migrate_page_move_mapping(struct address_space *mapping,
+ */
+ __dec_zone_page_state(page, NR_FILE_PAGES);
+ __inc_zone_page_state(newpage, NR_FILE_PAGES);
+- if (PageSwapBacked(page)) {
++ if (!PageSwapCache(page) && PageSwapBacked(page)) {
+ __dec_zone_page_state(page, NR_SHMEM);
+ __inc_zone_page_state(newpage, NR_SHMEM);
+ }
+diff --git a/mm/nommu.c b/mm/nommu.c
+index c4c542c..0376a4c 100644
+--- a/mm/nommu.c
++++ b/mm/nommu.c
+@@ -1819,10 +1819,13 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
+ return NULL;
+ }
+
+-int remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+- unsigned long to, unsigned long size, pgprot_t prot)
++int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,
++ unsigned long pfn, unsigned long size, pgprot_t prot)
+ {
+- vma->vm_start = vma->vm_pgoff << PAGE_SHIFT;
++ if (addr != (pfn << PAGE_SHIFT))
++ return -EINVAL;
++
++ vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
+ return 0;
+ }
+ EXPORT_SYMBOL(remap_pfn_range);
+diff --git a/mm/oom_kill.c b/mm/oom_kill.c
+index f52e85c..5299cb8 100644
+--- a/mm/oom_kill.c
++++ b/mm/oom_kill.c
+@@ -285,7 +285,7 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
+ do_each_thread(g, p) {
+ unsigned int points;
+
+- if (!p->mm)
++ if (p->exit_state)
+ continue;
+ if (oom_unkillable_task(p, mem, nodemask))
+ continue;
+@@ -301,6 +301,8 @@ static struct task_struct *select_bad_process(unsigned int *ppoints,
+ */
+ if (test_tsk_thread_flag(p, TIF_MEMDIE))
+ return ERR_PTR(-1UL);
++ if (!p->mm)
++ continue;
+
+ if (p->flags & PF_EXITING) {
+ /*
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index 3f8bce2..e78b324 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -2064,6 +2064,7 @@ restart:
+ first_zones_zonelist(zonelist, high_zoneidx, NULL,
+ &preferred_zone);
+
++rebalance:
+ /* This is the last chance, in general, before the goto nopage. */
+ page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist,
+ high_zoneidx, alloc_flags & ~ALLOC_NO_WATERMARKS,
+@@ -2071,7 +2072,6 @@ restart:
+ if (page)
+ goto got_pg;
+
+-rebalance:
+ /* Allocate without watermarks if the context allows */
+ if (alloc_flags & ALLOC_NO_WATERMARKS) {
+ page = __alloc_pages_high_priority(gfp_mask, order,
+diff --git a/mm/shmem.c b/mm/shmem.c
+index dfc7069..ba12be4 100644
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -916,11 +916,12 @@ static int shmem_unuse_inode(struct shmem_inode_info *info, swp_entry_t entry, s
+ if (size > ENTRIES_PER_PAGE)
+ size = ENTRIES_PER_PAGE;
+ offset = shmem_find_swp(entry, ptr, ptr+size);
++ shmem_swp_unmap(ptr);
+ if (offset >= 0) {
+ shmem_dir_unmap(dir);
++ ptr = shmem_swp_map(subdir);
+ goto found;
+ }
+- shmem_swp_unmap(ptr);
+ }
+ }
+ lost1:
+@@ -1100,8 +1101,8 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
+ delete_from_page_cache(page);
+ shmem_swp_set(info, entry, swap.val);
+ shmem_swp_unmap(entry);
+- spin_unlock(&info->lock);
+ swap_shmem_alloc(swap);
++ spin_unlock(&info->lock);
+ BUG_ON(page_mapped(page));
+ swap_writepage(page, wbc);
+ return 0;
+diff --git a/mm/slub.c b/mm/slub.c
+index 9d2e5e4..f6cb6cd 100644
+--- a/mm/slub.c
++++ b/mm/slub.c
+@@ -261,6 +261,18 @@ static inline void *get_freepointer(struct kmem_cache *s, void *object)
+ return *(void **)(object + s->offset);
+ }
+
++static inline void *get_freepointer_safe(struct kmem_cache *s, void *object)
++{
++ void *p;
++
++#ifdef CONFIG_DEBUG_PAGEALLOC
++ probe_kernel_read(&p, (void **)(object + s->offset), sizeof(p));
++#else
++ p = get_freepointer(s, object);
++#endif
++ return p;
++}
++
+ static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)
+ {
+ *(void **)(object + s->offset) = fp;
+@@ -1943,7 +1955,7 @@ redo:
+ if (unlikely(!irqsafe_cpu_cmpxchg_double(
+ s->cpu_slab->freelist, s->cpu_slab->tid,
+ object, tid,
+- get_freepointer(s, object), next_tid(tid)))) {
++ get_freepointer_safe(s, object), next_tid(tid)))) {
+
+ note_cmpxchg_failure("slab_alloc", s, tid);
+ goto redo;
+diff --git a/mm/vmscan.c b/mm/vmscan.c
+index 8bfd450..7f3270f 100644
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -230,8 +230,11 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
+ if (scanned == 0)
+ scanned = SWAP_CLUSTER_MAX;
+
+- if (!down_read_trylock(&shrinker_rwsem))
+- return 1; /* Assume we'll be able to shrink next time */
++ if (!down_read_trylock(&shrinker_rwsem)) {
++ /* Assume we'll be able to shrink next time */
++ ret = 1;
++ goto out;
++ }
+
+ list_for_each_entry(shrinker, &shrinker_list, list) {
+ unsigned long long delta;
+@@ -282,6 +285,8 @@ unsigned long shrink_slab(unsigned long scanned, gfp_t gfp_mask,
+ shrinker->nr += total_scan;
+ }
+ up_read(&shrinker_rwsem);
++out:
++ cond_resched();
+ return ret;
+ }
+
+@@ -1109,8 +1114,20 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
+ nr_lumpy_dirty++;
+ scan++;
+ } else {
+- /* the page is freed already. */
+- if (!page_count(cursor_page))
++ /*
++ * Check if the page is freed already.
++ *
++ * We can't use page_count() as that
++ * requires compound_head and we don't
++ * have a pin on the page here. If a
++ * page is tail, we may or may not
++ * have isolated the head, so assume
++ * it's not free, it'd be tricky to
++ * track the head status without a
++ * page pin.
++ */
++ if (!PageTail(cursor_page) &&
++ !atomic_read(&cursor_page->_count))
+ continue;
+ break;
+ }
+@@ -2240,7 +2257,8 @@ static bool pgdat_balanced(pg_data_t *pgdat, unsigned long balanced_pages,
+ for (i = 0; i <= classzone_idx; i++)
+ present_pages += pgdat->node_zones[i].present_pages;
+
+- return balanced_pages > (present_pages >> 2);
++ /* A special case here: if zone has no page, we think it's balanced */
++ return balanced_pages >= (present_pages >> 2);
+ }
+
+ /* is kswapd sleeping prematurely? */
+@@ -2256,7 +2274,7 @@ static bool sleeping_prematurely(pg_data_t *pgdat, int order, long remaining,
+ return true;
+
+ /* Check the watermark levels */
+- for (i = 0; i < pgdat->nr_zones; i++) {
++ for (i = 0; i <= classzone_idx; i++) {
+ struct zone *zone = pgdat->node_zones + i;
+
+ if (!populated_zone(zone))
+@@ -2274,7 +2292,7 @@ static bool sleeping_prematurely(pg_data_t *pgdat, int order, long remaining,
+ }
+
+ if (!zone_watermark_ok_safe(zone, order, high_wmark_pages(zone),
+- classzone_idx, 0))
++ i, 0))
+ all_zones_ok = false;
+ else
+ balanced += zone->present_pages;
+@@ -2286,7 +2304,7 @@ static bool sleeping_prematurely(pg_data_t *pgdat, int order, long remaining,
+ * must be balanced
+ */
+ if (order)
+- return pgdat_balanced(pgdat, balanced, classzone_idx);
++ return !pgdat_balanced(pgdat, balanced, classzone_idx);
+ else
+ return !all_zones_ok;
+ }
+@@ -2376,7 +2394,6 @@ loop_again:
+ if (!zone_watermark_ok_safe(zone, order,
+ high_wmark_pages(zone), 0, 0)) {
+ end_zone = i;
+- *classzone_idx = i;
+ break;
+ }
+ }
+@@ -2431,19 +2448,19 @@ loop_again:
+ KSWAPD_ZONE_BALANCE_GAP_RATIO);
+ if (!zone_watermark_ok_safe(zone, order,
+ high_wmark_pages(zone) + balance_gap,
+- end_zone, 0))
++ end_zone, 0)) {
+ shrink_zone(priority, zone, &sc);
+- reclaim_state->reclaimed_slab = 0;
+- nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL,
+- lru_pages);
+- sc.nr_reclaimed += reclaim_state->reclaimed_slab;
+- total_scanned += sc.nr_scanned;
+
+- if (zone->all_unreclaimable)
+- continue;
+- if (nr_slab == 0 &&
+- !zone_reclaimable(zone))
+- zone->all_unreclaimable = 1;
++ reclaim_state->reclaimed_slab = 0;
++ nr_slab = shrink_slab(sc.nr_scanned, GFP_KERNEL,
++ lru_pages);
++ sc.nr_reclaimed += reclaim_state->reclaimed_slab;
++ total_scanned += sc.nr_scanned;
++
++ if (nr_slab == 0 && !zone_reclaimable(zone))
++ zone->all_unreclaimable = 1;
++ }
++
+ /*
+ * If we've done a decent amount of scanning and
+ * the reclaim ratio is low, start doing writepage
+@@ -2453,6 +2470,12 @@ loop_again:
+ total_scanned > sc.nr_reclaimed + sc.nr_reclaimed / 2)
+ sc.may_writepage = 1;
+
++ if (zone->all_unreclaimable) {
++ if (end_zone && end_zone == i)
++ end_zone--;
++ continue;
++ }
++
+ if (!zone_watermark_ok_safe(zone, order,
+ high_wmark_pages(zone), end_zone, 0)) {
+ all_zones_ok = 0;
+@@ -2631,8 +2654,8 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order, int classzone_idx)
+ */
+ static int kswapd(void *p)
+ {
+- unsigned long order;
+- int classzone_idx;
++ unsigned long order, new_order;
++ int classzone_idx, new_classzone_idx;
+ pg_data_t *pgdat = (pg_data_t*)p;
+ struct task_struct *tsk = current;
+
+@@ -2662,17 +2685,23 @@ static int kswapd(void *p)
+ tsk->flags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD;
+ set_freezable();
+
+- order = 0;
+- classzone_idx = MAX_NR_ZONES - 1;
++ order = new_order = 0;
++ classzone_idx = new_classzone_idx = pgdat->nr_zones - 1;
+ for ( ; ; ) {
+- unsigned long new_order;
+- int new_classzone_idx;
+ int ret;
+
+- new_order = pgdat->kswapd_max_order;
+- new_classzone_idx = pgdat->classzone_idx;
+- pgdat->kswapd_max_order = 0;
+- pgdat->classzone_idx = MAX_NR_ZONES - 1;
++ /*
++ * If the last balance_pgdat was unsuccessful it's unlikely a
++ * new request of a similar or harder type will succeed soon
++ * so consider going to sleep on the basis we reclaimed at
++ */
++ if (classzone_idx >= new_classzone_idx && order == new_order) {
++ new_order = pgdat->kswapd_max_order;
++ new_classzone_idx = pgdat->classzone_idx;
++ pgdat->kswapd_max_order = 0;
++ pgdat->classzone_idx = pgdat->nr_zones - 1;
++ }
++
+ if (order < new_order || classzone_idx > new_classzone_idx) {
+ /*
+ * Don't sleep if someone wants a larger 'order'
+@@ -2685,7 +2714,7 @@ static int kswapd(void *p)
+ order = pgdat->kswapd_max_order;
+ classzone_idx = pgdat->classzone_idx;
+ pgdat->kswapd_max_order = 0;
+- pgdat->classzone_idx = MAX_NR_ZONES - 1;
++ pgdat->classzone_idx = pgdat->nr_zones - 1;
+ }
+
+ ret = try_to_freeze();
+diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
+index b2ff6c8..f11e61e 100644
+--- a/net/8021q/vlan_dev.c
++++ b/net/8021q/vlan_dev.c
+@@ -338,7 +338,7 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,
+ u64_stats_update_begin(&stats->syncp);
+ stats->tx_packets++;
+ stats->tx_bytes += len;
+- u64_stats_update_begin(&stats->syncp);
++ u64_stats_update_end(&stats->syncp);
+ } else {
+ this_cpu_inc(vlan_dev_info(dev)->vlan_pcpu_stats->tx_dropped);
+ }
+diff --git a/net/atm/atm_sysfs.c b/net/atm/atm_sysfs.c
+index f7fa67c..f49da58 100644
+--- a/net/atm/atm_sysfs.c
++++ b/net/atm/atm_sysfs.c
+@@ -59,6 +59,14 @@ static ssize_t show_atmaddress(struct device *cdev,
+ return pos - buf;
+ }
+
++static ssize_t show_atmindex(struct device *cdev,
++ struct device_attribute *attr, char *buf)
++{
++ struct atm_dev *adev = to_atm_dev(cdev);
++
++ return sprintf(buf, "%d\n", adev->number);
++}
++
+ static ssize_t show_carrier(struct device *cdev,
+ struct device_attribute *attr, char *buf)
+ {
+@@ -99,6 +107,7 @@ static ssize_t show_link_rate(struct device *cdev,
+
+ static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
+ static DEVICE_ATTR(atmaddress, S_IRUGO, show_atmaddress, NULL);
++static DEVICE_ATTR(atmindex, S_IRUGO, show_atmindex, NULL);
+ static DEVICE_ATTR(carrier, S_IRUGO, show_carrier, NULL);
+ static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
+ static DEVICE_ATTR(link_rate, S_IRUGO, show_link_rate, NULL);
+@@ -106,6 +115,7 @@ static DEVICE_ATTR(link_rate, S_IRUGO, show_link_rate, NULL);
+ static struct device_attribute *atm_attrs[] = {
+ &dev_attr_atmaddress,
+ &dev_attr_address,
++ &dev_attr_atmindex,
+ &dev_attr_carrier,
+ &dev_attr_type,
+ &dev_attr_link_rate,
+diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
+index 74ef4d4..ecaaa00 100644
+--- a/net/bridge/br_netfilter.c
++++ b/net/bridge/br_netfilter.c
+@@ -104,10 +104,16 @@ static void fake_update_pmtu(struct dst_entry *dst, u32 mtu)
+ {
+ }
+
++static u32 *fake_cow_metrics(struct dst_entry *dst, unsigned long old)
++{
++ return NULL;
++}
++
+ static struct dst_ops fake_dst_ops = {
+ .family = AF_INET,
+ .protocol = cpu_to_be16(ETH_P_IP),
+ .update_pmtu = fake_update_pmtu,
++ .cow_metrics = fake_cow_metrics,
+ };
+
+ /*
+@@ -117,6 +123,10 @@ static struct dst_ops fake_dst_ops = {
+ * ipt_REJECT needs it. Future netfilter modules might
+ * require us to fill additional fields.
+ */
++static const u32 br_dst_default_metrics[RTAX_MAX] = {
++ [RTAX_MTU - 1] = 1500,
++};
++
+ void br_netfilter_rtable_init(struct net_bridge *br)
+ {
+ struct rtable *rt = &br->fake_rtable;
+@@ -124,7 +134,7 @@ void br_netfilter_rtable_init(struct net_bridge *br)
+ atomic_set(&rt->dst.__refcnt, 1);
+ rt->dst.dev = br->dev;
+ rt->dst.path = &rt->dst;
+- dst_metric_set(&rt->dst, RTAX_MTU, 1500);
++ dst_init_metrics(&rt->dst, br_dst_default_metrics, true);
+ rt->dst.flags = DST_NOXFRM;
+ rt->dst.ops = &fake_dst_ops;
+ }
+diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
+index 387013d..5e9ae57 100644
+--- a/net/bridge/br_private.h
++++ b/net/bridge/br_private.h
+@@ -123,6 +123,7 @@ struct net_bridge_port
+ bridge_id designated_bridge;
+ u32 path_cost;
+ u32 designated_cost;
++ unsigned long designated_age;
+
+ struct timer_list forward_delay_timer;
+ struct timer_list hold_timer;
+diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c
+index 7370d14..c24ae0d 100644
+--- a/net/bridge/br_stp.c
++++ b/net/bridge/br_stp.c
+@@ -164,8 +164,7 @@ void br_transmit_config(struct net_bridge_port *p)
+ else {
+ struct net_bridge_port *root
+ = br_get_port(br, br->root_port);
+- bpdu.message_age = br->max_age
+- - (root->message_age_timer.expires - jiffies)
++ bpdu.message_age = (jiffies - root->designated_age)
+ + MESSAGE_AGE_INCR;
+ }
+ bpdu.max_age = br->max_age;
+@@ -189,6 +188,7 @@ static inline void br_record_config_information(struct net_bridge_port *p,
+ p->designated_cost = bpdu->root_path_cost;
+ p->designated_bridge = bpdu->bridge_id;
+ p->designated_port = bpdu->port_id;
++ p->designated_age = jiffies + bpdu->message_age;
+
+ mod_timer(&p->message_age_timer, jiffies
+ + (p->br->max_age - bpdu->message_age));
+diff --git a/net/core/dev.c b/net/core/dev.c
+index b624fe4..acd7423 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -1007,7 +1007,7 @@ rollback:
+ }
+
+ write_lock_bh(&dev_base_lock);
+- hlist_del(&dev->name_hlist);
++ hlist_del_rcu(&dev->name_hlist);
+ write_unlock_bh(&dev_base_lock);
+
+ synchronize_rcu();
+@@ -5258,7 +5258,7 @@ void netdev_update_features(struct net_device *dev)
+ if (dev->features == features)
+ return;
+
+- netdev_info(dev, "Features changed: 0x%08x -> 0x%08x\n",
++ netdev_dbg(dev, "Features changed: 0x%08x -> 0x%08x\n",
+ dev->features, features);
+
+ if (dev->netdev_ops->ndo_set_features)
+diff --git a/net/core/dst.c b/net/core/dst.c
+index 91104d3..b71b7a3 100644
+--- a/net/core/dst.c
++++ b/net/core/dst.c
+@@ -314,7 +314,7 @@ void __dst_destroy_metrics_generic(struct dst_entry *dst, unsigned long old)
+ {
+ unsigned long prev, new;
+
+- new = (unsigned long) dst_default_metrics;
++ new = ((unsigned long) dst_default_metrics) | DST_METRICS_READ_ONLY;
+ prev = cmpxchg(&dst->_metrics, old, new);
+ if (prev == old)
+ kfree(__DST_METRICS_PTR(old));
+diff --git a/net/core/ethtool.c b/net/core/ethtool.c
+index 74ead9e..76ed645 100644
+--- a/net/core/ethtool.c
++++ b/net/core/ethtool.c
+@@ -231,6 +231,29 @@ static int ethtool_set_feature_compat(struct net_device *dev,
+ return 1;
+ }
+
++static int ethtool_set_flags_compat(struct net_device *dev,
++ int (*legacy_set)(struct net_device *, u32),
++ struct ethtool_set_features_block *features, u32 mask)
++{
++ u32 value;
++
++ if (!legacy_set)
++ return 0;
++
++ if (!(features[0].valid & mask))
++ return 0;
++
++ value = dev->features & ~features[0].valid;
++ value |= features[0].requested;
++
++ features[0].valid &= ~mask;
++
++ if (legacy_set(dev, value & mask) < 0)
++ netdev_info(dev, "Legacy flags change failed\n");
++
++ return 1;
++}
++
+ static int ethtool_set_features_compat(struct net_device *dev,
+ struct ethtool_set_features_block *features)
+ {
+@@ -247,7 +270,7 @@ static int ethtool_set_features_compat(struct net_device *dev,
+ features, NETIF_F_ALL_TSO);
+ compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_rx_csum,
+ features, NETIF_F_RXCSUM);
+- compat |= ethtool_set_feature_compat(dev, dev->ethtool_ops->set_flags,
++ compat |= ethtool_set_flags_compat(dev, dev->ethtool_ops->set_flags,
+ features, flags_dup_features);
+
+ return compat;
+@@ -330,7 +353,7 @@ static const char netdev_features_strings[ETHTOOL_DEV_FEATURE_WORDS * 32][ETH_GS
+ /* NETIF_F_IP_CSUM */ "tx-checksum-ipv4",
+ /* NETIF_F_NO_CSUM */ "tx-checksum-unneeded",
+ /* NETIF_F_HW_CSUM */ "tx-checksum-ip-generic",
+- /* NETIF_F_IPV6_CSUM */ "tx_checksum-ipv6",
++ /* NETIF_F_IPV6_CSUM */ "tx-checksum-ipv6",
+ /* NETIF_F_HIGHDMA */ "highdma",
+ /* NETIF_F_FRAGLIST */ "tx-scatter-gather-fraglist",
+ /* NETIF_F_HW_VLAN_TX */ "tx-vlan-hw-insert",
+diff --git a/net/core/filter.c b/net/core/filter.c
+index afb8afb..1238cbd 100644
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -38,6 +38,7 @@
+ #include <asm/unaligned.h>
+ #include <linux/filter.h>
+ #include <linux/reciprocal_div.h>
++#include <linux/ratelimit.h>
+
+ enum {
+ BPF_S_RET_K = 1,
+@@ -409,7 +410,9 @@ load_b:
+ continue;
+ }
+ default:
+- WARN_ON(1);
++ WARN_RATELIMIT(1, "Unknown code:%u jt:%u tf:%u k:%u\n",
++ fentry->code, fentry->jt,
++ fentry->jf, fentry->k);
+ return 0;
+ }
+ }
+diff --git a/net/core/skbuff.c b/net/core/skbuff.c
+index 7ebeed0..3e934fe 100644
+--- a/net/core/skbuff.c
++++ b/net/core/skbuff.c
+@@ -2993,6 +2993,9 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb)
+ skb->destructor = sock_rmem_free;
+ atomic_add(skb->truesize, &sk->sk_rmem_alloc);
+
++ /* before exiting rcu section, make sure dst is refcounted */
++ skb_dst_force(skb);
++
+ skb_queue_tail(&sk->sk_error_queue, skb);
+ if (!sock_flag(sk, SOCK_DEAD))
+ sk->sk_data_ready(sk, skb->len);
+diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
+index 807d83c..6bab50e 100644
+--- a/net/ipv4/af_inet.c
++++ b/net/ipv4/af_inet.c
+@@ -464,6 +464,9 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+ if (addr_len < sizeof(struct sockaddr_in))
+ goto out;
+
++ if (addr->sin_family != AF_INET)
++ goto out;
++
+ chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr);
+
+ /* Not specified by any standard per-se, however it breaks too
+diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
+index 1fd3d9c..57ca93a 100644
+--- a/net/ipv4/igmp.c
++++ b/net/ipv4/igmp.c
+@@ -1169,20 +1169,18 @@ static void igmp_group_dropped(struct ip_mc_list *im)
+
+ if (!in_dev->dead) {
+ if (IGMP_V1_SEEN(in_dev))
+- goto done;
++ return;
+ if (IGMP_V2_SEEN(in_dev)) {
+ if (reporter)
+ igmp_send_report(in_dev, im, IGMP_HOST_LEAVE_MESSAGE);
+- goto done;
++ return;
+ }
+ /* IGMPv3 */
+ igmpv3_add_delrec(in_dev, im);
+
+ igmp_ifc_event(in_dev);
+ }
+-done:
+ #endif
+- ip_mc_clear_src(im);
+ }
+
+ static void igmp_group_added(struct ip_mc_list *im)
+@@ -1319,6 +1317,7 @@ void ip_mc_dec_group(struct in_device *in_dev, __be32 addr)
+ *ip = i->next_rcu;
+ in_dev->mc_count--;
+ igmp_group_dropped(i);
++ ip_mc_clear_src(i);
+
+ if (!in_dev->dead)
+ ip_rt_multicast_event(in_dev);
+@@ -1428,7 +1427,8 @@ void ip_mc_destroy_dev(struct in_device *in_dev)
+ in_dev->mc_list = i->next_rcu;
+ in_dev->mc_count--;
+
+- igmp_group_dropped(i);
++ /* We've dropped the groups in ip_mc_down already */
++ ip_mc_clear_src(i);
+ ip_ma_put(i);
+ }
+ }
+diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
+index 2ada171..65c23d9 100644
+--- a/net/ipv4/inet_diag.c
++++ b/net/ipv4/inet_diag.c
+@@ -437,7 +437,7 @@ static int valid_cc(const void *bc, int len, int cc)
+ return 0;
+ if (cc == len)
+ return 1;
+- if (op->yes < 4)
++ if (op->yes < 4 || op->yes & 3)
+ return 0;
+ len -= op->yes;
+ bc += op->yes;
+@@ -447,11 +447,11 @@ static int valid_cc(const void *bc, int len, int cc)
+
+ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
+ {
+- const unsigned char *bc = bytecode;
++ const void *bc = bytecode;
+ int len = bytecode_len;
+
+ while (len > 0) {
+- struct inet_diag_bc_op *op = (struct inet_diag_bc_op *)bc;
++ const struct inet_diag_bc_op *op = bc;
+
+ //printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len);
+ switch (op->code) {
+@@ -462,22 +462,20 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
+ case INET_DIAG_BC_S_LE:
+ case INET_DIAG_BC_D_GE:
+ case INET_DIAG_BC_D_LE:
+- if (op->yes < 4 || op->yes > len + 4)
+- return -EINVAL;
+ case INET_DIAG_BC_JMP:
+- if (op->no < 4 || op->no > len + 4)
++ if (op->no < 4 || op->no > len + 4 || op->no & 3)
+ return -EINVAL;
+ if (op->no < len &&
+ !valid_cc(bytecode, bytecode_len, len - op->no))
+ return -EINVAL;
+ break;
+ case INET_DIAG_BC_NOP:
+- if (op->yes < 4 || op->yes > len + 4)
+- return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
++ if (op->yes < 4 || op->yes > len + 4 || op->yes & 3)
++ return -EINVAL;
+ bc += op->yes;
+ len -= op->yes;
+ }
+diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
+index 9df4e63..ce616d9 100644
+--- a/net/ipv4/inetpeer.c
++++ b/net/ipv4/inetpeer.c
+@@ -154,11 +154,9 @@ void __init inet_initpeers(void)
+ /* Called with or without local BH being disabled. */
+ static void unlink_from_unused(struct inet_peer *p)
+ {
+- if (!list_empty(&p->unused)) {
+- spin_lock_bh(&unused_peers.lock);
+- list_del_init(&p->unused);
+- spin_unlock_bh(&unused_peers.lock);
+- }
++ spin_lock_bh(&unused_peers.lock);
++ list_del_init(&p->unused);
++ spin_unlock_bh(&unused_peers.lock);
+ }
+
+ static int addr_compare(const struct inetpeer_addr *a,
+@@ -205,6 +203,20 @@ static int addr_compare(const struct inetpeer_addr *a,
+ u; \
+ })
+
++static bool atomic_add_unless_return(atomic_t *ptr, int a, int u, int *newv)
++{
++ int cur, old = atomic_read(ptr);
++
++ while (old != u) {
++ *newv = old + a;
++ cur = atomic_cmpxchg(ptr, old, *newv);
++ if (cur == old)
++ return true;
++ old = cur;
++ }
++ return false;
++}
++
+ /*
+ * Called with rcu_read_lock()
+ * Because we hold no lock against a writer, its quite possible we fall
+@@ -213,7 +225,8 @@ static int addr_compare(const struct inetpeer_addr *a,
+ * We exit from this function if number of links exceeds PEER_MAXDEPTH
+ */
+ static struct inet_peer *lookup_rcu(const struct inetpeer_addr *daddr,
+- struct inet_peer_base *base)
++ struct inet_peer_base *base,
++ int *newrefcnt)
+ {
+ struct inet_peer *u = rcu_dereference(base->root);
+ int count = 0;
+@@ -226,7 +239,7 @@ static struct inet_peer *lookup_rcu(const struct inetpeer_addr *daddr,
+ * distinction between an unused entry (refcnt=0) and
+ * a freed one.
+ */
+- if (unlikely(!atomic_add_unless(&u->refcnt, 1, -1)))
++ if (!atomic_add_unless_return(&u->refcnt, 1, -1, newrefcnt))
+ u = NULL;
+ return u;
+ }
+@@ -465,22 +478,23 @@ struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create)
+ struct inet_peer_base *base = family_to_base(daddr->family);
+ struct inet_peer *p;
+ unsigned int sequence;
+- int invalidated;
++ int invalidated, newrefcnt = 0;
+
+ /* Look up for the address quickly, lockless.
+ * Because of a concurrent writer, we might not find an existing entry.
+ */
+ rcu_read_lock();
+ sequence = read_seqbegin(&base->lock);
+- p = lookup_rcu(daddr, base);
++ p = lookup_rcu(daddr, base, &newrefcnt);
+ invalidated = read_seqretry(&base->lock, sequence);
+ rcu_read_unlock();
+
+ if (p) {
+- /* The existing node has been found.
++found: /* The existing node has been found.
+ * Remove the entry from unused list if it was there.
+ */
+- unlink_from_unused(p);
++ if (newrefcnt == 1)
++ unlink_from_unused(p);
+ return p;
+ }
+
+@@ -494,11 +508,9 @@ struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create)
+ write_seqlock_bh(&base->lock);
+ p = lookup(daddr, stack, base);
+ if (p != peer_avl_empty) {
+- atomic_inc(&p->refcnt);
++ newrefcnt = atomic_inc_return(&p->refcnt);
+ write_sequnlock_bh(&base->lock);
+- /* Remove the entry from unused list if it was there. */
+- unlink_from_unused(p);
+- return p;
++ goto found;
+ }
+ p = create ? kmem_cache_alloc(peer_cachep, GFP_ATOMIC) : NULL;
+ if (p) {
+diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
+index 4614bab..2e97e3e 100644
+--- a/net/ipv4/netfilter.c
++++ b/net/ipv4/netfilter.c
+@@ -17,51 +17,35 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
+ const struct iphdr *iph = ip_hdr(skb);
+ struct rtable *rt;
+ struct flowi4 fl4 = {};
+- unsigned long orefdst;
++ __be32 saddr = iph->saddr;
++ __u8 flags = 0;
+ unsigned int hh_len;
+- unsigned int type;
+
+- type = inet_addr_type(net, iph->saddr);
+- if (skb->sk && inet_sk(skb->sk)->transparent)
+- type = RTN_LOCAL;
+- if (addr_type == RTN_UNSPEC)
+- addr_type = type;
++ if (!skb->sk && addr_type != RTN_LOCAL) {
++ if (addr_type == RTN_UNSPEC)
++ addr_type = inet_addr_type(net, saddr);
++ if (addr_type == RTN_LOCAL || addr_type == RTN_UNICAST)
++ flags |= FLOWI_FLAG_ANYSRC;
++ else
++ saddr = 0;
++ }
+
+ /* some non-standard hacks like ipt_REJECT.c:send_reset() can cause
+ * packets with foreign saddr to appear on the NF_INET_LOCAL_OUT hook.
+ */
+- if (addr_type == RTN_LOCAL) {
+- fl4.daddr = iph->daddr;
+- if (type == RTN_LOCAL)
+- fl4.saddr = iph->saddr;
+- fl4.flowi4_tos = RT_TOS(iph->tos);
+- fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
+- fl4.flowi4_mark = skb->mark;
+- fl4.flowi4_flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0;
+- rt = ip_route_output_key(net, &fl4);
+- if (IS_ERR(rt))
+- return -1;
+-
+- /* Drop old route. */
+- skb_dst_drop(skb);
+- skb_dst_set(skb, &rt->dst);
+- } else {
+- /* non-local src, find valid iif to satisfy
+- * rp-filter when calling ip_route_input. */
+- fl4.daddr = iph->saddr;
+- rt = ip_route_output_key(net, &fl4);
+- if (IS_ERR(rt))
+- return -1;
++ fl4.daddr = iph->daddr;
++ fl4.saddr = saddr;
++ fl4.flowi4_tos = RT_TOS(iph->tos);
++ fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
++ fl4.flowi4_mark = skb->mark;
++ fl4.flowi4_flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : flags;
++ rt = ip_route_output_key(net, &fl4);
++ if (IS_ERR(rt))
++ return -1;
+
+- orefdst = skb->_skb_refdst;
+- if (ip_route_input(skb, iph->daddr, iph->saddr,
+- RT_TOS(iph->tos), rt->dst.dev) != 0) {
+- dst_release(&rt->dst);
+- return -1;
+- }
+- dst_release(&rt->dst);
+- refdst_drop(orefdst);
+- }
++ /* Drop old route. */
++ skb_dst_drop(skb);
++ skb_dst_set(skb, &rt->dst);
+
+ if (skb_dst(skb)->error)
+ return -1;
+diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c
+index 1ff79e5..51f13f8 100644
+--- a/net/ipv4/netfilter/ipt_REJECT.c
++++ b/net/ipv4/netfilter/ipt_REJECT.c
+@@ -40,7 +40,6 @@ static void send_reset(struct sk_buff *oldskb, int hook)
+ struct iphdr *niph;
+ const struct tcphdr *oth;
+ struct tcphdr _otcph, *tcph;
+- unsigned int addr_type;
+
+ /* IP header checks: fragment. */
+ if (ip_hdr(oldskb)->frag_off & htons(IP_OFFSET))
+@@ -55,6 +54,9 @@ static void send_reset(struct sk_buff *oldskb, int hook)
+ if (oth->rst)
+ return;
+
++ if (skb_rtable(oldskb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
++ return;
++
+ /* Check checksum */
+ if (nf_ip_checksum(oldskb, hook, ip_hdrlen(oldskb), IPPROTO_TCP))
+ return;
+@@ -101,19 +103,11 @@ static void send_reset(struct sk_buff *oldskb, int hook)
+ nskb->csum_start = (unsigned char *)tcph - nskb->head;
+ nskb->csum_offset = offsetof(struct tcphdr, check);
+
+- addr_type = RTN_UNSPEC;
+- if (hook != NF_INET_FORWARD
+-#ifdef CONFIG_BRIDGE_NETFILTER
+- || (nskb->nf_bridge && nskb->nf_bridge->mask & BRNF_BRIDGED)
+-#endif
+- )
+- addr_type = RTN_LOCAL;
+-
+ /* ip_route_me_harder expects skb->dst to be set */
+ skb_dst_set_noref(nskb, skb_dst(oldskb));
+
+ nskb->protocol = htons(ETH_P_IP);
+- if (ip_route_me_harder(nskb, addr_type))
++ if (ip_route_me_harder(nskb, RTN_UNSPEC))
+ goto free_nskb;
+
+ niph->ttl = ip4_dst_hoplimit(skb_dst(nskb));
+diff --git a/net/ipv4/route.c b/net/ipv4/route.c
+index 99e6e4b..b8b5c3f 100644
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -1914,9 +1914,7 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr,
+
+ hash = rt_hash(daddr, saddr, dev->ifindex, rt_genid(dev_net(dev)));
+ rth = rt_intern_hash(hash, rth, skb, dev->ifindex);
+- err = 0;
+- if (IS_ERR(rth))
+- err = PTR_ERR(rth);
++ return IS_ERR(rth) ? PTR_ERR(rth) : 0;
+
+ e_nobufs:
+ return -ENOBUFS;
+diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
+index f87a8eb..0e33e34 100644
+--- a/net/ipv4/udp.c
++++ b/net/ipv4/udp.c
+@@ -1241,6 +1241,9 @@ csum_copy_err:
+
+ if (noblock)
+ return -EAGAIN;
++
++ /* starting over for a new packet */
++ msg->msg_flags &= ~MSG_TRUNC;
+ goto try_again;
+ }
+
+diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
+index 9e305d74..b31a2f3 100644
+--- a/net/ipv6/udp.c
++++ b/net/ipv6/udp.c
+@@ -453,8 +453,11 @@ csum_copy_err:
+ }
+ unlock_sock_fast(sk, slow);
+
+- if (flags & MSG_DONTWAIT)
++ if (noblock)
+ return -EAGAIN;
++
++ /* starting over for a new packet */
++ msg->msg_flags &= ~MSG_TRUNC;
+ goto try_again;
+ }
+
+diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
+index 4404973..3740403 100644
+--- a/net/mac80211/cfg.c
++++ b/net/mac80211/cfg.c
+@@ -228,11 +228,11 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
+ goto out;
+
+ if (pairwise)
+- key = sta->ptk;
++ key = rcu_dereference(sta->ptk);
+ else if (key_idx < NUM_DEFAULT_KEYS)
+- key = sta->gtk[key_idx];
++ key = rcu_dereference(sta->gtk[key_idx]);
+ } else
+- key = sdata->keys[key_idx];
++ key = rcu_dereference(sdata->keys[key_idx]);
+
+ if (!key)
+ goto out;
+@@ -921,8 +921,10 @@ static int ieee80211_change_mpath(struct wiphy *wiphy,
+ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
+ struct mpath_info *pinfo)
+ {
+- if (mpath->next_hop)
+- memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN);
++ struct sta_info *next_hop_sta = rcu_dereference(mpath->next_hop);
++
++ if (next_hop_sta)
++ memcpy(next_hop, next_hop_sta->sta.addr, ETH_ALEN);
+ else
+ memset(next_hop, 0, ETH_ALEN);
+
+diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
+index 3e81af1..821590d 100644
+--- a/net/mac80211/ibss.c
++++ b/net/mac80211/ibss.c
+@@ -967,6 +967,10 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
+
+ mutex_lock(&sdata->u.ibss.mtx);
+
++ sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
++ memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
++ sdata->u.ibss.ssid_len = 0;
++
+ active_ibss = ieee80211_sta_active_ibss(sdata);
+
+ if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) {
+@@ -1000,8 +1004,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
+ kfree_skb(skb);
+
+ skb_queue_purge(&sdata->skb_queue);
+- memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
+- sdata->u.ibss.ssid_len = 0;
+
+ del_timer_sync(&sdata->u.ibss.timer);
+
+diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
+index 64d92d5..7ffcb55 100644
+--- a/net/mac80211/mlme.c
++++ b/net/mac80211/mlme.c
+@@ -789,7 +789,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work)
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+ }
+
+- netif_tx_start_all_queues(sdata->dev);
++ netif_tx_wake_all_queues(sdata->dev);
+ }
+
+ void ieee80211_dynamic_ps_timer(unsigned long data)
+diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
+index f1765de..3814b81 100644
+--- a/net/mac80211/wpa.c
++++ b/net/mac80211/wpa.c
+@@ -86,6 +86,11 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
+ struct sk_buff *skb = rx->skb;
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
++ int queue = rx->queue;
++
++ /* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */
++ if (rx->queue == NUM_RX_DATA_QUEUES - 1)
++ queue = 0;
+
+ /* No way to verify the MIC if the hardware stripped it */
+ if (status->flag & RX_FLAG_MMIC_STRIPPED)
+@@ -119,8 +124,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
+ skb_trim(skb, skb->len - MICHAEL_MIC_LEN);
+
+ /* update IV in key information to be able to detect replays */
+- rx->key->u.tkip.rx[rx->queue].iv32 = rx->tkip_iv32;
+- rx->key->u.tkip.rx[rx->queue].iv16 = rx->tkip_iv16;
++ rx->key->u.tkip.rx[queue].iv32 = rx->tkip_iv32;
++ rx->key->u.tkip.rx[queue].iv16 = rx->tkip_iv16;
+
+ return RX_CONTINUE;
+ }
+@@ -201,6 +206,11 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
+ struct ieee80211_key *key = rx->key;
+ struct sk_buff *skb = rx->skb;
+ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
++ int queue = rx->queue;
++
++ /* otherwise, TKIP is vulnerable to TID 0 vs. non-QoS replays */
++ if (rx->queue == NUM_RX_DATA_QUEUES - 1)
++ queue = 0;
+
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
+
+@@ -221,7 +231,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
+ res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm,
+ key, skb->data + hdrlen,
+ skb->len - hdrlen, rx->sta->sta.addr,
+- hdr->addr1, hwaccel, rx->queue,
++ hdr->addr1, hwaccel, queue,
+ &rx->tkip_iv32,
+ &rx->tkip_iv16);
+ if (res != TKIP_DECRYPT_OK)
+diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
+index 72d1ac6..8041bef 100644
+--- a/net/netfilter/ipset/ip_set_core.c
++++ b/net/netfilter/ipset/ip_set_core.c
+@@ -815,7 +815,7 @@ ip_set_flush(struct sock *ctnl, struct sk_buff *skb,
+ ip_set_id_t i;
+
+ if (unlikely(protocol_failed(attr)))
+- return -EPROTO;
++ return -IPSET_ERR_PROTOCOL;
+
+ if (!attr[IPSET_ATTR_SETNAME]) {
+ for (i = 0; i < ip_set_max; i++)
+diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
+index bf28ac2..782db27 100644
+--- a/net/netfilter/ipvs/ip_vs_conn.c
++++ b/net/netfilter/ipvs/ip_vs_conn.c
+@@ -776,8 +776,16 @@ static void ip_vs_conn_expire(unsigned long data)
+ if (cp->control)
+ ip_vs_control_del(cp);
+
+- if (cp->flags & IP_VS_CONN_F_NFCT)
++ if (cp->flags & IP_VS_CONN_F_NFCT) {
+ ip_vs_conn_drop_conntrack(cp);
++ /* Do not access conntracks during subsys cleanup
++ * because nf_conntrack_find_get can not be used after
++ * conntrack cleanup for the net.
++ */
++ smp_rmb();
++ if (ipvs->enable)
++ ip_vs_conn_drop_conntrack(cp);
++ }
+
+ ip_vs_pe_put(cp->pe);
+ kfree(cp->pe_data);
+diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
+index a74dae6..7729eae 100644
+--- a/net/netfilter/ipvs/ip_vs_core.c
++++ b/net/netfilter/ipvs/ip_vs_core.c
+@@ -1965,6 +1965,7 @@ static void __net_exit __ip_vs_dev_cleanup(struct net *net)
+ {
+ EnterFunction(2);
+ net_ipvs(net)->enable = 0; /* Disable packet reception */
++ smp_wmb();
+ __ip_vs_sync_cleanup(net);
+ LeaveFunction(2);
+ }
+diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
+index 6b5dd6d..af63553 100644
+--- a/net/netfilter/ipvs/ip_vs_ftp.c
++++ b/net/netfilter/ipvs/ip_vs_ftp.c
+@@ -411,25 +411,35 @@ static struct ip_vs_app ip_vs_ftp = {
+ static int __net_init __ip_vs_ftp_init(struct net *net)
+ {
+ int i, ret;
+- struct ip_vs_app *app = &ip_vs_ftp;
++ struct ip_vs_app *app;
++ struct netns_ipvs *ipvs = net_ipvs(net);
++
++ app = kmemdup(&ip_vs_ftp, sizeof(struct ip_vs_app), GFP_KERNEL);
++ if (!app)
++ return -ENOMEM;
++ INIT_LIST_HEAD(&app->a_list);
++ INIT_LIST_HEAD(&app->incs_list);
++ ipvs->ftp_app = app;
+
+ ret = register_ip_vs_app(net, app);
+ if (ret)
+- return ret;
++ goto err_exit;
+
+ for (i=0; i<IP_VS_APP_MAX_PORTS; i++) {
+ if (!ports[i])
+ continue;
+ ret = register_ip_vs_app_inc(net, app, app->protocol, ports[i]);
+ if (ret)
+- break;
++ goto err_unreg;
+ pr_info("%s: loaded support on port[%d] = %d\n",
+ app->name, i, ports[i]);
+ }
++ return 0;
+
+- if (ret)
+- unregister_ip_vs_app(net, app);
+-
++err_unreg:
++ unregister_ip_vs_app(net, app);
++err_exit:
++ kfree(ipvs->ftp_app);
+ return ret;
+ }
+ /*
+@@ -437,9 +447,10 @@ static int __net_init __ip_vs_ftp_init(struct net *net)
+ */
+ static void __ip_vs_ftp_exit(struct net *net)
+ {
+- struct ip_vs_app *app = &ip_vs_ftp;
++ struct netns_ipvs *ipvs = net_ipvs(net);
+
+- unregister_ip_vs_app(net, app);
++ unregister_ip_vs_app(net, ipvs->ftp_app);
++ kfree(ipvs->ftp_app);
+ }
+
+ static struct pernet_operations ip_vs_ftp_ops = {
+diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
+index 237cc19..cb5a285 100644
+--- a/net/netfilter/nf_conntrack_sip.c
++++ b/net/netfilter/nf_conntrack_sip.c
+@@ -1419,6 +1419,7 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,
+ const char *dptr, *end;
+ s16 diff, tdiff = 0;
+ int ret = NF_ACCEPT;
++ bool term;
+ typeof(nf_nat_sip_seq_adjust_hook) nf_nat_sip_seq_adjust;
+
+ if (ctinfo != IP_CT_ESTABLISHED &&
+@@ -1453,14 +1454,21 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,
+ if (dptr + matchoff == end)
+ break;
+
+- if (end + strlen("\r\n\r\n") > dptr + datalen)
+- break;
+- if (end[0] != '\r' || end[1] != '\n' ||
+- end[2] != '\r' || end[3] != '\n')
++ term = false;
++ for (; end + strlen("\r\n\r\n") <= dptr + datalen; end++) {
++ if (end[0] == '\r' && end[1] == '\n' &&
++ end[2] == '\r' && end[3] == '\n') {
++ term = true;
++ break;
++ }
++ }
++ if (!term)
+ break;
+ end += strlen("\r\n\r\n") + clen;
+
+ msglen = origlen = end - dptr;
++ if (msglen > datalen)
++ return NF_DROP;
+
+ ret = process_sip_msg(skb, ct, dataoff, &dptr, &msglen);
+ if (ret != NF_ACCEPT)
+diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
+index b5362e9..04098c2 100644
+--- a/net/packet/af_packet.c
++++ b/net/packet/af_packet.c
+@@ -799,6 +799,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
+ h.h2->tp_sec = ts.tv_sec;
+ h.h2->tp_nsec = ts.tv_nsec;
+ h.h2->tp_vlan_tci = vlan_tx_tag_get(skb);
++ h.h2->tp_padding = 0;
+ hdrlen = sizeof(*h.h2);
+ break;
+ default:
+@@ -1727,6 +1728,7 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock,
+ aux.tp_net = skb_network_offset(skb);
+ aux.tp_vlan_tci = vlan_tx_tag_get(skb);
+
++ aux.tp_padding = 0;
+ put_cmsg(msg, SOL_PACKET, PACKET_AUXDATA, sizeof(aux), &aux);
+ }
+
+diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
+index c2e628d..6d96275 100644
+--- a/net/sched/sch_sfq.c
++++ b/net/sched/sch_sfq.c
+@@ -361,7 +361,7 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+ {
+ struct sfq_sched_data *q = qdisc_priv(sch);
+ unsigned int hash;
+- sfq_index x;
++ sfq_index x, qlen;
+ struct sfq_slot *slot;
+ int uninitialized_var(ret);
+
+@@ -405,20 +405,12 @@ sfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
+ if (++sch->q.qlen <= q->limit)
+ return NET_XMIT_SUCCESS;
+
++ qlen = slot->qlen;
+ sfq_drop(sch);
+- return NET_XMIT_CN;
+-}
+-
+-static struct sk_buff *
+-sfq_peek(struct Qdisc *sch)
+-{
+- struct sfq_sched_data *q = qdisc_priv(sch);
+-
+- /* No active slots */
+- if (q->tail == NULL)
+- return NULL;
+-
+- return q->slots[q->tail->next].skblist_next;
++ /* Return Congestion Notification only if we dropped a packet
++ * from this flow.
++ */
++ return (qlen != slot->qlen) ? NET_XMIT_CN : NET_XMIT_SUCCESS;
+ }
+
+ static struct sk_buff *
+@@ -702,7 +694,7 @@ static struct Qdisc_ops sfq_qdisc_ops __read_mostly = {
+ .priv_size = sizeof(struct sfq_sched_data),
+ .enqueue = sfq_enqueue,
+ .dequeue = sfq_dequeue,
+- .peek = sfq_peek,
++ .peek = qdisc_peek_dequeued,
+ .drop = sfq_drop,
+ .init = sfq_init,
+ .reset = sfq_reset,
+diff --git a/net/sctp/associola.c b/net/sctp/associola.c
+index 1a21c57..525f97c 100644
+--- a/net/sctp/associola.c
++++ b/net/sctp/associola.c
+@@ -64,6 +64,7 @@
+ /* Forward declarations for internal functions. */
+ static void sctp_assoc_bh_rcv(struct work_struct *work);
+ static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc);
++static void sctp_assoc_free_asconf_queue(struct sctp_association *asoc);
+
+ /* Keep track of the new idr low so that we don't re-use association id
+ * numbers too fast. It is protected by they idr spin lock is in the
+@@ -446,6 +447,9 @@ void sctp_association_free(struct sctp_association *asoc)
+ /* Free any cached ASCONF_ACK chunk. */
+ sctp_assoc_free_asconf_acks(asoc);
+
++ /* Free the ASCONF queue. */
++ sctp_assoc_free_asconf_queue(asoc);
++
+ /* Free any cached ASCONF chunk. */
+ if (asoc->addip_last_asconf)
+ sctp_chunk_free(asoc->addip_last_asconf);
+@@ -1578,6 +1582,18 @@ retry:
+ return error;
+ }
+
++/* Free the ASCONF queue */
++static void sctp_assoc_free_asconf_queue(struct sctp_association *asoc)
++{
++ struct sctp_chunk *asconf;
++ struct sctp_chunk *tmp;
++
++ list_for_each_entry_safe(asconf, tmp, &asoc->addip_chunk_list, list) {
++ list_del_init(&asconf->list);
++ sctp_chunk_free(asconf);
++ }
++}
++
+ /* Free asconf_ack cache */
+ static void sctp_assoc_free_asconf_acks(struct sctp_association *asoc)
+ {
+diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
+index faf71d1..6150ac5 100644
+--- a/net/sctp/bind_addr.c
++++ b/net/sctp/bind_addr.c
+@@ -140,14 +140,12 @@ void sctp_bind_addr_init(struct sctp_bind_addr *bp, __u16 port)
+ /* Dispose of the address list. */
+ static void sctp_bind_addr_clean(struct sctp_bind_addr *bp)
+ {
+- struct sctp_sockaddr_entry *addr;
+- struct list_head *pos, *temp;
++ struct sctp_sockaddr_entry *addr, *temp;
+
+ /* Empty the bind address list. */
+- list_for_each_safe(pos, temp, &bp->address_list) {
+- addr = list_entry(pos, struct sctp_sockaddr_entry, list);
+- list_del(pos);
+- kfree(addr);
++ list_for_each_entry_safe(addr, temp, &bp->address_list, list) {
++ list_del_rcu(&addr->list);
++ call_rcu(&addr->rcu, sctp_local_addr_free);
+ SCTP_DBG_OBJCNT_DEC(addr);
+ }
+ }
+diff --git a/net/socket.c b/net/socket.c
+index 310d16b..65b2310 100644
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -2122,14 +2122,16 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
+ */
+ if (MSG_CMSG_COMPAT & flags) {
+ err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
+- &msg_sys, flags, datagrams);
++ &msg_sys, flags & ~MSG_WAITFORONE,
++ datagrams);
+ if (err < 0)
+ break;
+ err = __put_user(err, &compat_entry->msg_len);
+ ++compat_entry;
+ } else {
+ err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
+- &msg_sys, flags, datagrams);
++ &msg_sys, flags & ~MSG_WAITFORONE,
++ datagrams);
+ if (err < 0)
+ break;
+ err = put_user(err, &entry->msg_len);
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index 339ba64..5daf6cc 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -577,13 +577,13 @@ retry:
+ }
+ inode = &gss_msg->inode->vfs_inode;
+ for (;;) {
+- prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_INTERRUPTIBLE);
++ prepare_to_wait(&gss_msg->waitqueue, &wait, TASK_KILLABLE);
+ spin_lock(&inode->i_lock);
+ if (gss_msg->ctx != NULL || gss_msg->msg.errno < 0) {
+ break;
+ }
+ spin_unlock(&inode->i_lock);
+- if (signalled()) {
++ if (fatal_signal_pending(current)) {
+ err = -ERESTARTSYS;
+ goto out_intr;
+ }
+diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
+index 0a9a2ec..c3b7533 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
++++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
+@@ -43,6 +43,7 @@
+ #include <linux/sunrpc/gss_krb5.h>
+ #include <linux/sunrpc/xdr.h>
+ #include <linux/crypto.h>
++#include <linux/sunrpc/gss_krb5_enctypes.h>
+
+ #ifdef RPC_DEBUG
+ # define RPCDBG_FACILITY RPCDBG_AUTH
+@@ -750,7 +751,7 @@ static struct gss_api_mech gss_kerberos_mech = {
+ .gm_ops = &gss_kerberos_ops,
+ .gm_pf_num = ARRAY_SIZE(gss_kerberos_pfs),
+ .gm_pfs = gss_kerberos_pfs,
+- .gm_upcall_enctypes = "18,17,16,23,3,1,2",
++ .gm_upcall_enctypes = KRB5_SUPPORTED_ENCTYPES,
+ };
+
+ static int __init init_kerberos_module(void)
+diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
+index 8d83f9d..00df09b 100644
+--- a/net/sunrpc/clnt.c
++++ b/net/sunrpc/clnt.c
+@@ -1058,7 +1058,7 @@ call_allocate(struct rpc_task *task)
+
+ dprintk("RPC: %5u rpc_buffer allocation failed\n", task->tk_pid);
+
+- if (RPC_IS_ASYNC(task) || !signalled()) {
++ if (RPC_IS_ASYNC(task) || !fatal_signal_pending(current)) {
+ task->tk_action = call_allocate;
+ rpc_delay(task, HZ>>4);
+ return;
+@@ -1172,6 +1172,9 @@ call_bind_status(struct rpc_task *task)
+ status = -EOPNOTSUPP;
+ break;
+ }
++ if (task->tk_rebind_retry == 0)
++ break;
++ task->tk_rebind_retry--;
+ rpc_delay(task, 3*HZ);
+ goto retry_timeout;
+ case -ETIMEDOUT:
+diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
+index c652e4c..9574bc4 100644
+--- a/net/sunrpc/rpcb_clnt.c
++++ b/net/sunrpc/rpcb_clnt.c
+@@ -528,7 +528,7 @@ void rpcb_getport_async(struct rpc_task *task)
+ u32 bind_version;
+ struct rpc_xprt *xprt;
+ struct rpc_clnt *rpcb_clnt;
+- static struct rpcbind_args *map;
++ struct rpcbind_args *map;
+ struct rpc_task *child;
+ struct sockaddr_storage addr;
+ struct sockaddr *sap = (struct sockaddr *)&addr;
+diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
+index 6b43ee7..4814e24 100644
+--- a/net/sunrpc/sched.c
++++ b/net/sunrpc/sched.c
+@@ -616,30 +616,25 @@ static void __rpc_execute(struct rpc_task *task)
+ BUG_ON(RPC_IS_QUEUED(task));
+
+ for (;;) {
++ void (*do_action)(struct rpc_task *);
+
+ /*
+- * Execute any pending callback.
++ * Execute any pending callback first.
+ */
+- if (task->tk_callback) {
+- void (*save_callback)(struct rpc_task *);
+-
+- /*
+- * We set tk_callback to NULL before calling it,
+- * in case it sets the tk_callback field itself:
+- */
+- save_callback = task->tk_callback;
+- task->tk_callback = NULL;
+- save_callback(task);
+- } else {
++ do_action = task->tk_callback;
++ task->tk_callback = NULL;
++ if (do_action == NULL) {
+ /*
+ * Perform the next FSM step.
+- * tk_action may be NULL when the task has been killed
+- * by someone else.
++ * tk_action may be NULL if the task has been killed.
++ * In particular, note that rpc_killall_tasks may
++ * do this at any time, so beware when dereferencing.
+ */
+- if (task->tk_action == NULL)
++ do_action = task->tk_action;
++ if (do_action == NULL)
+ break;
+- task->tk_action(task);
+ }
++ do_action(task);
+
+ /*
+ * Lockless check for whether task is sleeping or not.
+@@ -792,6 +787,7 @@ static void rpc_init_task(struct rpc_task *task, const struct rpc_task_setup *ta
+ /* Initialize retry counters */
+ task->tk_garb_retry = 2;
+ task->tk_cred_retry = 2;
++ task->tk_rebind_retry = 2;
+
+ task->tk_priority = task_setup_data->priority - RPC_PRIORITY_LOW;
+ task->tk_owner = current->tgid;
+diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
+index bf005d3..f34f5ab 100644
+--- a/net/sunrpc/xprtsock.c
++++ b/net/sunrpc/xprtsock.c
+@@ -1344,7 +1344,6 @@ static void xs_tcp_state_change(struct sock *sk)
+ case TCP_CLOSE_WAIT:
+ /* The server initiated a shutdown of the socket */
+ xprt_force_disconnect(xprt);
+- case TCP_SYN_SENT:
+ xprt->connect_cookie++;
+ case TCP_CLOSING:
+ /*
+@@ -1758,6 +1757,7 @@ static void xs_tcp_reuse_connection(struct sock_xprt *transport)
+ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
+ {
+ struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt);
++ int ret = -ENOTCONN;
+
+ if (!transport->inet) {
+ struct sock *sk = sock->sk;
+@@ -1789,12 +1789,22 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
+ }
+
+ if (!xprt_bound(xprt))
+- return -ENOTCONN;
++ goto out;
+
+ /* Tell the socket layer to start connecting... */
+ xprt->stat.connect_count++;
+ xprt->stat.connect_start = jiffies;
+- return kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK);
++ ret = kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK);
++ switch (ret) {
++ case 0:
++ case -EINPROGRESS:
++ /* SYN_SENT! */
++ xprt->connect_cookie++;
++ if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
++ xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
++ }
++out:
++ return ret;
+ }
+
+ /**
+diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
+index 4ebce42..29a1ce1 100644
+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -1679,14 +1679,6 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
+ if (err)
+ goto out;
+
+- if (!(rdev->wiphy.flags &
+- WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS)) {
+- if (!key.def_uni || !key.def_multi) {
+- err = -EOPNOTSUPP;
+- goto out;
+- }
+- }
+-
+ err = rdev->ops->set_default_key(&rdev->wiphy, dev, key.idx,
+ key.def_uni, key.def_multi);
+
+@@ -3247,12 +3239,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
+ i = 0;
+ if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) {
+ nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
++ request->ssids[i].ssid_len = nla_len(attr);
+ if (request->ssids[i].ssid_len > IEEE80211_MAX_SSID_LEN) {
+ err = -EINVAL;
+ goto out_free;
+ }
+ memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr));
+- request->ssids[i].ssid_len = nla_len(attr);
+ i++;
+ }
+ }
+diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
+index 47f1b86..b11ea69 100644
+--- a/net/xfrm/xfrm_replay.c
++++ b/net/xfrm/xfrm_replay.c
+@@ -265,7 +265,7 @@ static void xfrm_replay_advance_bmp(struct xfrm_state *x, __be32 net_seq)
+ bitnr = bitnr & 0x1F;
+ replay_esn->bmp[nr] |= (1U << bitnr);
+ } else {
+- nr = replay_esn->replay_window >> 5;
++ nr = (replay_esn->replay_window - 1) >> 5;
+ for (i = 0; i <= nr; i++)
+ replay_esn->bmp[i] = 0;
+
+@@ -471,7 +471,7 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
+ bitnr = bitnr & 0x1F;
+ replay_esn->bmp[nr] |= (1U << bitnr);
+ } else {
+- nr = replay_esn->replay_window >> 5;
++ nr = (replay_esn->replay_window - 1) >> 5;
+ for (i = 0; i <= nr; i++)
+ replay_esn->bmp[i] = 0;
+
+diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
+index ae3a698..3d2fd14 100644
+--- a/security/apparmor/lsm.c
++++ b/security/apparmor/lsm.c
+@@ -593,7 +593,8 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
+ sa.aad.op = OP_SETPROCATTR;
+ sa.aad.info = name;
+ sa.aad.error = -EINVAL;
+- return aa_audit(AUDIT_APPARMOR_DENIED, NULL, GFP_KERNEL,
++ return aa_audit(AUDIT_APPARMOR_DENIED,
++ __aa_current_profile(), GFP_KERNEL,
+ &sa, NULL);
+ }
+ } else if (strcmp(name, "exec") == 0) {
+@@ -611,7 +612,7 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
+ static int apparmor_task_setrlimit(struct task_struct *task,
+ unsigned int resource, struct rlimit *new_rlim)
+ {
+- struct aa_profile *profile = aa_current_profile();
++ struct aa_profile *profile = __aa_current_profile();
+ int error = 0;
+
+ if (!unconfined(profile))
+diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
+index 930634e..7a0c586 100644
+--- a/security/keys/process_keys.c
++++ b/security/keys/process_keys.c
+@@ -845,6 +845,7 @@ void key_replace_session_keyring(void)
+ new-> sgid = old-> sgid;
+ new->fsgid = old->fsgid;
+ new->user = get_uid(old->user);
++ new->user_ns = new->user->user_ns;
+ new->group_info = get_group_info(old->group_info);
+
+ new->securebits = old->securebits;
+diff --git a/security/keys/request_key.c b/security/keys/request_key.c
+index df3c041..6197a26 100644
+--- a/security/keys/request_key.c
++++ b/security/keys/request_key.c
+@@ -470,7 +470,7 @@ static struct key *construct_key_and_link(struct key_type *type,
+ } else if (ret == -EINPROGRESS) {
+ ret = 0;
+ } else {
+- key = ERR_PTR(ret);
++ goto couldnt_alloc_key;
+ }
+
+ key_put(dest_keyring);
+@@ -480,6 +480,7 @@ static struct key *construct_key_and_link(struct key_type *type,
+ construction_failed:
+ key_negate_and_link(key, key_negative_timeout, NULL, NULL);
+ key_put(key);
++couldnt_alloc_key:
+ key_put(dest_keyring);
+ kleave(" = %d", ret);
+ return ERR_PTR(ret);
+diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c
+index 82bf8c2..afa07cf 100644
+--- a/security/tomoyo/mount.c
++++ b/security/tomoyo/mount.c
+@@ -138,7 +138,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name,
+ }
+ if (need_dev) {
+ /* Get mount point or device file. */
+- if (kern_path(dev_name, LOOKUP_FOLLOW, &path)) {
++ if (!dev_name || kern_path(dev_name, LOOKUP_FOLLOW, &path)) {
+ error = -ENOENT;
+ goto out;
+ }
+diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
+index 70a9d32..f5cad7c 100644
+--- a/sound/pci/hda/hda_intel.c
++++ b/sound/pci/hda/hda_intel.c
+@@ -2349,9 +2349,16 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
+ /* Check VIA/ATI HD Audio Controller exist */
+ switch (chip->driver_type) {
+ case AZX_DRIVER_VIA:
+- case AZX_DRIVER_ATI:
+ /* Use link position directly, avoid any transfer problem. */
+ return POS_FIX_VIACOMBO;
++ case AZX_DRIVER_ATI:
++ /* ATI chipsets don't work well with position-buffer */
++ return POS_FIX_LPIB;
++ case AZX_DRIVER_GENERIC:
++ /* AMD chipsets also don't work with position-buffer */
++ if (chip->pci->vendor == PCI_VENDOR_ID_AMD)
++ return POS_FIX_LPIB;
++ break;
+ }
+
+ return POS_FIX_AUTO;
+diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
+index 2942d2a..9f886bf 100644
+--- a/sound/pci/hda/patch_analog.c
++++ b/sound/pci/hda/patch_analog.c
+@@ -3070,6 +3070,7 @@ static void ad1988_auto_init_analog_input(struct hda_codec *codec)
+
+ for (i = 0; i < cfg->num_inputs; i++) {
+ hda_nid_t nid = cfg->inputs[i].pin;
++ int type = cfg->inputs[i].type;
+ switch (nid) {
+ case 0x15: /* port-C */
+ snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0);
+@@ -3079,7 +3080,7 @@ static void ad1988_auto_init_analog_input(struct hda_codec *codec)
+ break;
+ }
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+- i == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
++ type == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN);
+ if (nid != AD1988_PIN_CD_NID)
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_OUT_MUTE);
+diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
+index ad97d93..e47f22c 100644
+--- a/sound/pci/hda/patch_conexant.c
++++ b/sound/pci/hda/patch_conexant.c
+@@ -3036,6 +3036,7 @@ static struct snd_pci_quirk cxt5066_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
+ SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD),
+ SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD),
++ SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS),
+ SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
+ SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */
+ {}
+@@ -3845,6 +3846,8 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = {
+ .patch = patch_cxt5066 },
+ { .id = 0x14f15069, .name = "CX20585",
+ .patch = patch_cxt5066 },
++ { .id = 0x14f1506c, .name = "CX20588",
++ .patch = patch_cxt5066 },
+ { .id = 0x14f1506e, .name = "CX20590",
+ .patch = patch_cxt5066 },
+ { .id = 0x14f15097, .name = "CX20631",
+@@ -3873,6 +3876,7 @@ MODULE_ALIAS("snd-hda-codec-id:14f15066");
+ MODULE_ALIAS("snd-hda-codec-id:14f15067");
+ MODULE_ALIAS("snd-hda-codec-id:14f15068");
+ MODULE_ALIAS("snd-hda-codec-id:14f15069");
++MODULE_ALIAS("snd-hda-codec-id:14f1506c");
+ MODULE_ALIAS("snd-hda-codec-id:14f1506e");
+ MODULE_ALIAS("snd-hda-codec-id:14f15097");
+ MODULE_ALIAS("snd-hda-codec-id:14f15098");
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index c82979a..4145c3c 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -4607,7 +4607,6 @@ static struct snd_pci_quirk alc880_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
+ SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
+ SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
+- SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST),
+ SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
+ SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
+ SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
+@@ -13804,6 +13803,7 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One",
+ ALC268_ACER_ASPIRE_ONE),
+ SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL),
++ SND_PCI_QUIRK(0x1028, 0x02b0, "Dell Inspiron 910", ALC268_AUTO),
+ SND_PCI_QUIRK_MASK(0x1028, 0xfff0, 0x02b0,
+ "Dell Inspiron Mini9/Vostro A90", ALC268_DELL),
+ /* almost compatible with toshiba but with optional digital outs;
+diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
+index 94d19c0..1e32235 100644
+--- a/sound/pci/hda/patch_sigmatel.c
++++ b/sound/pci/hda/patch_sigmatel.c
+@@ -1600,7 +1600,7 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02fe,
+ "Dell Studio XPS 1645", STAC_DELL_M6_BOTH),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0413,
+- "Dell Studio 1558", STAC_DELL_M6_BOTH),
++ "Dell Studio 1558", STAC_DELL_M6_DMIC),
+ {} /* terminator */
+ };
+
+diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
+index 890a0dc..bd11e33 100644
+--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
++++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
+@@ -138,11 +138,20 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
+ pr_debug("%s enter\n", __func__);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ diff = sport_curr_offset_tx(sport);
+- frames = bytes_to_frames(substream->runtime, diff);
+ } else {
+ diff = sport_curr_offset_rx(sport);
+- frames = bytes_to_frames(substream->runtime, diff);
+ }
++
++ /*
++ * TX at least can report one frame beyond the end of the
++ * buffer if we hit the wraparound case - clamp to within the
++ * buffer as the ALSA APIs require.
++ */
++ if (diff == snd_pcm_lib_buffer_bytes(substream))
++ diff = 0;
++
++ frames = bytes_to_frames(substream->runtime, diff);
++
+ return frames;
+ }
+
+diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
+index ab63d52..754c496 100644
+--- a/sound/soc/codecs/ad1836.c
++++ b/sound/soc/codecs/ad1836.c
+@@ -145,22 +145,22 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
+ /* bit size */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+- word_len = 3;
++ word_len = AD1836_WORD_LEN_16;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+- word_len = 1;
++ word_len = AD1836_WORD_LEN_20;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ case SNDRV_PCM_FORMAT_S32_LE:
+- word_len = 0;
++ word_len = AD1836_WORD_LEN_24;
+ break;
+ }
+
+- snd_soc_update_bits(codec, AD1836_DAC_CTRL1,
+- AD1836_DAC_WORD_LEN_MASK, word_len);
++ snd_soc_update_bits(codec, AD1836_DAC_CTRL1, AD1836_DAC_WORD_LEN_MASK,
++ word_len << AD1836_DAC_WORD_LEN_OFFSET);
+
+- snd_soc_update_bits(codec, AD1836_ADC_CTRL2,
+- AD1836_ADC_WORD_LEN_MASK, word_len);
++ snd_soc_update_bits(codec, AD1836_ADC_CTRL2, AD1836_ADC_WORD_LEN_MASK,
++ word_len << AD1836_ADC_WORD_OFFSET);
+
+ return 0;
+ }
+diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h
+index 8455967..9d6a3f8 100644
+--- a/sound/soc/codecs/ad1836.h
++++ b/sound/soc/codecs/ad1836.h
+@@ -25,6 +25,7 @@
+ #define AD1836_DAC_SERFMT_PCK256 (0x4 << 5)
+ #define AD1836_DAC_SERFMT_PCK128 (0x5 << 5)
+ #define AD1836_DAC_WORD_LEN_MASK 0x18
++#define AD1836_DAC_WORD_LEN_OFFSET 3
+
+ #define AD1836_DAC_CTRL2 1
+ #define AD1836_DACL1_MUTE 0
+@@ -51,6 +52,7 @@
+ #define AD1836_ADCL2_MUTE 2
+ #define AD1836_ADCR2_MUTE 3
+ #define AD1836_ADC_WORD_LEN_MASK 0x30
++#define AD1836_ADC_WORD_OFFSET 5
+ #define AD1836_ADC_SERFMT_MASK (7 << 6)
+ #define AD1836_ADC_SERFMT_PCK256 (0x4 << 6)
+ #define AD1836_ADC_SERFMT_PCK128 (0x5 << 6)
+@@ -60,4 +62,8 @@
+
+ #define AD1836_NUM_REGS 16
+
++#define AD1836_WORD_LEN_24 0x0
++#define AD1836_WORD_LEN_20 0x1
++#define AD1836_WORD_LEN_16 0x2
++
+ #endif
+diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
+index 4be0570..65f4604 100644
+--- a/sound/soc/codecs/ak4642.c
++++ b/sound/soc/codecs/ak4642.c
+@@ -357,7 +357,7 @@ static int ak4642_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+ default:
+ return -EINVAL;
+ }
+- snd_soc_update_bits(codec, PW_MGMT2, MS, data);
++ snd_soc_update_bits(codec, PW_MGMT2, MS | MCKO | PMPLL, data);
+ snd_soc_update_bits(codec, MD_CTL1, BCKO_MASK, bcko);
+
+ /* format type */
+diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
+index 6785688..9a5e67c 100644
+--- a/sound/soc/codecs/wm8804.c
++++ b/sound/soc/codecs/wm8804.c
+@@ -680,20 +680,25 @@ static struct snd_soc_dai_ops wm8804_dai_ops = {
+ #define WM8804_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE)
+
++#define WM8804_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
++ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \
++ SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \
++ SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
++
+ static struct snd_soc_dai_driver wm8804_dai = {
+ .name = "wm8804-spdif",
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+- .rates = SNDRV_PCM_RATE_8000_192000,
++ .rates = WM8804_RATES,
+ .formats = WM8804_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+- .rates = SNDRV_PCM_RATE_8000_192000,
++ .rates = WM8804_RATES,
+ .formats = WM8804_FORMATS,
+ },
+ .ops = &wm8804_dai_ops,
+diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
+index 500011e..c22659e 100644
+--- a/sound/soc/codecs/wm8962.c
++++ b/sound/soc/codecs/wm8962.c
+@@ -1998,12 +1998,12 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol,
+ return 0;
+
+ /* If the left PGA is enabled hit that VU bit... */
+- if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTL_PGA_ENA)
++ if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTL_PGA_ENA)
+ return snd_soc_write(codec, WM8962_HPOUTL_VOLUME,
+ reg_cache[WM8962_HPOUTL_VOLUME]);
+
+ /* ...otherwise the right. The VU is stereo. */
+- if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_HPOUTR_PGA_ENA)
++ if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTR_PGA_ENA)
+ return snd_soc_write(codec, WM8962_HPOUTR_VOLUME,
+ reg_cache[WM8962_HPOUTR_VOLUME]);
+
+diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
+index 84e1bd1..89acb0f 100644
+--- a/sound/soc/codecs/wm8994.c
++++ b/sound/soc/codecs/wm8994.c
+@@ -1446,7 +1446,6 @@ SND_SOC_DAPM_INPUT("DMIC1DAT"),
+ SND_SOC_DAPM_INPUT("DMIC2DAT"),
+ SND_SOC_DAPM_INPUT("Clock"),
+
+-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8994_MICBIAS, 2, 0),
+ SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev,
+ SND_SOC_DAPM_PRE_PMU),
+
+@@ -1765,8 +1764,10 @@ static const struct snd_soc_dapm_route wm8994_revd_intercon[] = {
+ { "AIF2DACDAT", NULL, "AIF1DACDAT" },
+ { "AIF1ADCDAT", NULL, "AIF2ADCDAT" },
+ { "AIF2ADCDAT", NULL, "AIF1ADCDAT" },
+- { "MICBIAS", NULL, "CLK_SYS" },
+- { "MICBIAS", NULL, "MICBIAS Supply" },
++ { "MICBIAS1", NULL, "CLK_SYS" },
++ { "MICBIAS1", NULL, "MICBIAS Supply" },
++ { "MICBIAS2", NULL, "CLK_SYS" },
++ { "MICBIAS2", NULL, "MICBIAS Supply" },
+ };
+
+ static const struct snd_soc_dapm_route wm8994_intercon[] = {
+@@ -1969,6 +1970,8 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
+ snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset,
+ WM8994_FLL1_ENA | WM8994_FLL1_FRAC,
+ reg);
++
++ msleep(5);
+ }
+
+ wm8994->fll[id].in = freq_in;
+@@ -3018,7 +3021,7 @@ static void wm8958_default_micdet(u16 status, void *data)
+ report = SND_JACK_MICROPHONE;
+
+ /* Everything else is buttons; just assign slots */
+- if (status & 0x1c0)
++ if (status & 0x1c)
+ report |= SND_JACK_BTN_0;
+
+ done:
+diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
+index 4005e9a..e55b298 100644
+--- a/sound/soc/codecs/wm_hubs.c
++++ b/sound/soc/codecs/wm_hubs.c
+@@ -787,17 +787,17 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
+ static const struct snd_soc_dapm_route lineout1_diff_routes[] = {
+ { "LINEOUT1 Mixer", "IN1L Switch", "IN1L PGA" },
+ { "LINEOUT1 Mixer", "IN1R Switch", "IN1R PGA" },
+- { "LINEOUT1 Mixer", "Output Switch", "Left Output Mixer" },
++ { "LINEOUT1 Mixer", "Output Switch", "Left Output PGA" },
+
+ { "LINEOUT1N Driver", NULL, "LINEOUT1 Mixer" },
+ { "LINEOUT1P Driver", NULL, "LINEOUT1 Mixer" },
+ };
+
+ static const struct snd_soc_dapm_route lineout1_se_routes[] = {
+- { "LINEOUT1N Mixer", "Left Output Switch", "Left Output Mixer" },
+- { "LINEOUT1N Mixer", "Right Output Switch", "Left Output Mixer" },
++ { "LINEOUT1N Mixer", "Left Output Switch", "Left Output PGA" },
++ { "LINEOUT1N Mixer", "Right Output Switch", "Right Output PGA" },
+
+- { "LINEOUT1P Mixer", "Left Output Switch", "Left Output Mixer" },
++ { "LINEOUT1P Mixer", "Left Output Switch", "Left Output PGA" },
+
+ { "LINEOUT1N Driver", NULL, "LINEOUT1N Mixer" },
+ { "LINEOUT1P Driver", NULL, "LINEOUT1P Mixer" },
+@@ -806,17 +806,17 @@ static const struct snd_soc_dapm_route lineout1_se_routes[] = {
+ static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
+ { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" },
+ { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" },
+- { "LINEOUT2 Mixer", "Output Switch", "Right Output Mixer" },
++ { "LINEOUT2 Mixer", "Output Switch", "Right Output PGA" },
+
+ { "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" },
+ { "LINEOUT2P Driver", NULL, "LINEOUT2 Mixer" },
+ };
+
+ static const struct snd_soc_dapm_route lineout2_se_routes[] = {
+- { "LINEOUT2N Mixer", "Left Output Switch", "Left Output Mixer" },
+- { "LINEOUT2N Mixer", "Right Output Switch", "Left Output Mixer" },
++ { "LINEOUT2N Mixer", "Left Output Switch", "Left Output PGA" },
++ { "LINEOUT2N Mixer", "Right Output Switch", "Right Output PGA" },
+
+- { "LINEOUT2P Mixer", "Right Output Switch", "Right Output Mixer" },
++ { "LINEOUT2P Mixer", "Right Output Switch", "Right Output PGA" },
+
+ { "LINEOUT2N Driver", NULL, "LINEOUT2N Mixer" },
+ { "LINEOUT2P Driver", NULL, "LINEOUT2P Mixer" },
+@@ -836,17 +836,21 @@ int wm_hubs_add_analogue_controls(struct snd_soc_codec *codec)
+ snd_soc_update_bits(codec, WM8993_RIGHT_LINE_INPUT_3_4_VOLUME,
+ WM8993_IN2_VU, WM8993_IN2_VU);
+
++ snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_LEFT,
++ WM8993_SPKOUT_VU, WM8993_SPKOUT_VU);
+ snd_soc_update_bits(codec, WM8993_SPEAKER_VOLUME_RIGHT,
+ WM8993_SPKOUT_VU, WM8993_SPKOUT_VU);
+
+ snd_soc_update_bits(codec, WM8993_LEFT_OUTPUT_VOLUME,
+- WM8993_HPOUT1L_ZC, WM8993_HPOUT1L_ZC);
++ WM8993_HPOUT1_VU | WM8993_HPOUT1L_ZC,
++ WM8993_HPOUT1_VU | WM8993_HPOUT1L_ZC);
+ snd_soc_update_bits(codec, WM8993_RIGHT_OUTPUT_VOLUME,
+ WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC,
+ WM8993_HPOUT1_VU | WM8993_HPOUT1R_ZC);
+
+ snd_soc_update_bits(codec, WM8993_LEFT_OPGA_VOLUME,
+- WM8993_MIXOUTL_ZC, WM8993_MIXOUTL_ZC);
++ WM8993_MIXOUTL_ZC | WM8993_MIXOUT_VU,
++ WM8993_MIXOUTL_ZC | WM8993_MIXOUT_VU);
+ snd_soc_update_bits(codec, WM8993_RIGHT_OPGA_VOLUME,
+ WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU,
+ WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU);
+diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
+index 2ce0b2d..fab20a5 100644
+--- a/sound/soc/pxa/pxa2xx-pcm.c
++++ b/sound/soc/pxa/pxa2xx-pcm.c
+@@ -95,14 +95,14 @@ static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+- if (dai->driver->playback.channels_min) {
++ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+ ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ if (ret)
+ goto out;
+ }
+
+- if (dai->driver->capture.channels_min) {
++ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+ ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_CAPTURE);
+ if (ret)
+diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c
+index 2afabaf..1a591f1 100644
+--- a/sound/soc/pxa/raumfeld.c
++++ b/sound/soc/pxa/raumfeld.c
+@@ -151,13 +151,13 @@ static struct snd_soc_ops raumfeld_cs4270_ops = {
+ .hw_params = raumfeld_cs4270_hw_params,
+ };
+
+-static int raumfeld_line_suspend(struct snd_soc_card *card)
++static int raumfeld_analog_suspend(struct snd_soc_card *card)
+ {
+ raumfeld_enable_audio(false);
+ return 0;
+ }
+
+-static int raumfeld_line_resume(struct snd_soc_card *card)
++static int raumfeld_analog_resume(struct snd_soc_card *card)
+ {
+ raumfeld_enable_audio(true);
+ return 0;
+@@ -225,32 +225,53 @@ static struct snd_soc_ops raumfeld_ak4104_ops = {
+ .hw_params = raumfeld_ak4104_hw_params,
+ };
+
+-static struct snd_soc_dai_link raumfeld_dai[] = {
++#define DAI_LINK_CS4270 \
++{ \
++ .name = "CS4270", \
++ .stream_name = "CS4270", \
++ .cpu_dai_name = "pxa-ssp-dai.0", \
++ .platform_name = "pxa-pcm-audio", \
++ .codec_dai_name = "cs4270-hifi", \
++ .codec_name = "cs4270-codec.0-0048", \
++ .ops = &raumfeld_cs4270_ops, \
++}
++
++#define DAI_LINK_AK4104 \
++{ \
++ .name = "ak4104", \
++ .stream_name = "Playback", \
++ .cpu_dai_name = "pxa-ssp-dai.1", \
++ .codec_dai_name = "ak4104-hifi", \
++ .platform_name = "pxa-pcm-audio", \
++ .ops = &raumfeld_ak4104_ops, \
++ .codec_name = "spi0.0", \
++}
++
++static struct snd_soc_dai_link snd_soc_raumfeld_connector_dai[] =
+ {
+- .name = "ak4104",
+- .stream_name = "Playback",
+- .cpu_dai_name = "pxa-ssp-dai.1",
+- .codec_dai_name = "ak4104-hifi",
+- .platform_name = "pxa-pcm-audio",
+- .ops = &raumfeld_ak4104_ops,
+- .codec_name = "ak4104-codec.0",
+-},
++ DAI_LINK_CS4270,
++ DAI_LINK_AK4104,
++};
++
++static struct snd_soc_dai_link snd_soc_raumfeld_speaker_dai[] =
+ {
+- .name = "CS4270",
+- .stream_name = "CS4270",
+- .cpu_dai_name = "pxa-ssp-dai.0",
+- .platform_name = "pxa-pcm-audio",
+- .codec_dai_name = "cs4270-hifi",
+- .codec_name = "cs4270-codec.0-0048",
+- .ops = &raumfeld_cs4270_ops,
+-},};
+-
+-static struct snd_soc_card snd_soc_raumfeld = {
+- .name = "Raumfeld",
+- .dai_link = raumfeld_dai,
+- .suspend_post = raumfeld_line_suspend,
+- .resume_pre = raumfeld_line_resume,
+- .num_links = ARRAY_SIZE(raumfeld_dai),
++ DAI_LINK_CS4270,
++};
++
++static struct snd_soc_card snd_soc_raumfeld_connector = {
++ .name = "Raumfeld Connector",
++ .dai_link = snd_soc_raumfeld_connector_dai,
++ .num_links = ARRAY_SIZE(snd_soc_raumfeld_connector_dai),
++ .suspend_post = raumfeld_analog_suspend,
++ .resume_pre = raumfeld_analog_resume,
++};
++
++static struct snd_soc_card snd_soc_raumfeld_speaker = {
++ .name = "Raumfeld Speaker",
++ .dai_link = snd_soc_raumfeld_speaker_dai,
++ .num_links = ARRAY_SIZE(snd_soc_raumfeld_speaker_dai),
++ .suspend_post = raumfeld_analog_suspend,
++ .resume_pre = raumfeld_analog_resume,
+ };
+
+ static struct platform_device *raumfeld_audio_device;
+@@ -271,22 +292,25 @@ static int __init raumfeld_audio_init(void)
+
+ set_max9485_clk(MAX9485_MCLK_FREQ_122880);
+
+- /* Register LINE and SPDIF */
++ /* Register analog device */
+ raumfeld_audio_device = platform_device_alloc("soc-audio", 0);
+ if (!raumfeld_audio_device)
+ return -ENOMEM;
+
+- platform_set_drvdata(raumfeld_audio_device,
+- &snd_soc_raumfeld);
+- ret = platform_device_add(raumfeld_audio_device);
+-
+- /* no S/PDIF on Speakers */
+ if (machine_is_raumfeld_speaker())
++ platform_set_drvdata(raumfeld_audio_device,
++ &snd_soc_raumfeld_speaker);
++
++ if (machine_is_raumfeld_connector())
++ platform_set_drvdata(raumfeld_audio_device,
++ &snd_soc_raumfeld_connector);
++
++ ret = platform_device_add(raumfeld_audio_device);
++ if (ret < 0)
+ return ret;
+
+ raumfeld_enable_audio(true);
+-
+- return ret;
++ return 0;
+ }
+
+ static void __exit raumfeld_audio_exit(void)
+diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
+index ffa09b3..992a732 100644
+--- a/sound/soc/samsung/i2s.c
++++ b/sound/soc/samsung/i2s.c
+@@ -191,7 +191,7 @@ static inline bool tx_active(struct i2s_dai *i2s)
+ if (!i2s)
+ return false;
+
+- active = readl(i2s->addr + I2SMOD);
++ active = readl(i2s->addr + I2SCON);
+
+ if (is_secondary(i2s))
+ active &= CON_TXSDMA_ACTIVE;
+@@ -223,7 +223,7 @@ static inline bool rx_active(struct i2s_dai *i2s)
+ if (!i2s)
+ return false;
+
+- active = readl(i2s->addr + I2SMOD) & CON_RXDMA_ACTIVE;
++ active = readl(i2s->addr + I2SCON) & CON_RXDMA_ACTIVE;
+
+ return active ? true : false;
+ }
+diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
+index 81c4052..586d10b 100644
+--- a/sound/soc/soc-dapm.c
++++ b/sound/soc/soc-dapm.c
+@@ -362,9 +362,9 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
+ }
+
+ /* create new dapm mixer control */
+-static int dapm_new_mixer(struct snd_soc_dapm_context *dapm,
+- struct snd_soc_dapm_widget *w)
++static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
+ {
++ struct snd_soc_dapm_context *dapm = w->dapm;
+ int i, ret = 0;
+ size_t name_len, prefix_len;
+ struct snd_soc_dapm_path *path;
+@@ -443,9 +443,9 @@ static int dapm_new_mixer(struct snd_soc_dapm_context *dapm,
+ }
+
+ /* create new dapm mux control */
+-static int dapm_new_mux(struct snd_soc_dapm_context *dapm,
+- struct snd_soc_dapm_widget *w)
++static int dapm_new_mux(struct snd_soc_dapm_widget *w)
+ {
++ struct snd_soc_dapm_context *dapm = w->dapm;
+ struct snd_soc_dapm_path *path = NULL;
+ struct snd_kcontrol *kcontrol;
+ struct snd_card *card = dapm->card->snd_card;
+@@ -490,8 +490,7 @@ err:
+ }
+
+ /* create new dapm volume control */
+-static int dapm_new_pga(struct snd_soc_dapm_context *dapm,
+- struct snd_soc_dapm_widget *w)
++static int dapm_new_pga(struct snd_soc_dapm_widget *w)
+ {
+ if (w->num_kcontrols)
+ dev_err(w->dapm->dev,
+@@ -1735,13 +1734,13 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
+ case snd_soc_dapm_mixer:
+ case snd_soc_dapm_mixer_named_ctl:
+ w->power_check = dapm_generic_check_power;
+- dapm_new_mixer(dapm, w);
++ dapm_new_mixer(w);
+ break;
+ case snd_soc_dapm_mux:
+ case snd_soc_dapm_virt_mux:
+ case snd_soc_dapm_value_mux:
+ w->power_check = dapm_generic_check_power;
+- dapm_new_mux(dapm, w);
++ dapm_new_mux(w);
+ break;
+ case snd_soc_dapm_adc:
+ case snd_soc_dapm_aif_out:
+@@ -1754,7 +1753,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
+ case snd_soc_dapm_pga:
+ case snd_soc_dapm_out_drv:
+ w->power_check = dapm_generic_check_power;
+- dapm_new_pga(dapm, w);
++ dapm_new_pga(w);
+ break;
+ case snd_soc_dapm_input:
+ case snd_soc_dapm_output:
+diff --git a/virt/kvm/assigned-dev.c b/virt/kvm/assigned-dev.c
+index ae72ae60..e3f1235 100644
+--- a/virt/kvm/assigned-dev.c
++++ b/virt/kvm/assigned-dev.c
+@@ -197,8 +197,7 @@ static void kvm_free_assigned_device(struct kvm *kvm,
+ {
+ kvm_free_assigned_irq(kvm, assigned_dev);
+
+- __pci_reset_function(assigned_dev->dev);
+- pci_restore_state(assigned_dev->dev);
++ pci_reset_function(assigned_dev->dev);
+
+ pci_release_regions(assigned_dev->dev);
+ pci_disable_device(assigned_dev->dev);
+@@ -515,7 +514,6 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
+ }
+
+ pci_reset_function(dev);
+- pci_save_state(dev);
+
+ match->assigned_dev_id = assigned_dev->assigned_dev_id;
+ match->host_segnr = assigned_dev->segnr;
+@@ -546,7 +544,6 @@ out:
+ mutex_unlock(&kvm->lock);
+ return r;
+ out_list_del:
+- pci_restore_state(dev);
+ list_del(&match->list);
+ pci_release_regions(dev);
+ out_disable:
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-at91sam9260-reset.patch b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-at91sam9260-reset.patch
new file mode 100644
index 0000000..af63d5c
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-at91sam9260-reset.patch
@@ -0,0 +1,26 @@
+Index: linux-2.6.39.4/arch/arm/mach-at91/at91sam9260.c
+===================================================================
+--- linux-2.6.39.4.orig/arch/arm/mach-at91/at91sam9260.c 2012-09-17 16:25:08.248303296 -0500
++++ linux-2.6.39.4/arch/arm/mach-at91/at91sam9260.c 2012-09-17 16:25:45.316033835 -0500
+@@ -310,6 +310,11 @@
+ iotable_init(at91sam9xe_sram_desc, ARRAY_SIZE(at91sam9xe_sram_desc));
+ }
+
++static void at91sam9260_reset(void)
++{
++ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
++}
++
+ void __init at91sam9260_initialize(unsigned long main_clock)
+ {
+ /* Map peripherals */
+@@ -322,7 +327,8 @@
+ else
+ iotable_init(at91sam9260_sram_desc, ARRAY_SIZE(at91sam9260_sram_desc));
+
+- at91_arch_reset = at91sam9_alt_reset;
++ // jjg: use old reset routine, alt reset is not reliable
++ at91_arch_reset = at91sam9260_reset;
+ pm_power_off = at91sam9260_poweroff;
+ at91_extern_irq = (1 << AT91SAM9260_ID_IRQ0) | (1 << AT91SAM9260_ID_IRQ1)
+ | (1 << AT91SAM9260_ID_IRQ2);
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-atmel_serial_disable_hwhs.patch b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-atmel_serial_disable_hwhs.patch
new file mode 100644
index 0000000..88fd8d5
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-atmel_serial_disable_hwhs.patch
@@ -0,0 +1,32 @@
+Revert commit 8e706c4d0dab214c625a2df84a0ca69a76bae65d in linux-2.6:
+ avr32: add hardware handshake support to atmel_serial
+
+Reverting commit since it breaks hardware flow control for at91sam9g20
+
+diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
+index 9d948bc..b659f2c 100644
+--- a/drivers/tty/serial/atmel_serial.c
++++ b/drivers/tty/serial/atmel_serial.c
+@@ -1020,8 +1020,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
+
+ /* Get current mode register */
+ mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL
+- | ATMEL_US_NBSTOP | ATMEL_US_PAR
+- | ATMEL_US_USMODE);
++ | ATMEL_US_NBSTOP | ATMEL_US_PAR);
+
+ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
+ quot = uart_get_divisor(port, baud);
+@@ -1066,12 +1065,6 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
+ } else
+ mode |= ATMEL_US_PAR_NONE;
+
+- /* hardware handshake (RTS/CTS) */
+- if (termios->c_cflag & CRTSCTS)
+- mode |= ATMEL_US_USMODE_HWHS;
+- else
+- mode |= ATMEL_US_USMODE_NORMAL;
+-
+ spin_lock_irqsave(&port->lock, flags);
+
+ port->read_status_mask = ATMEL_US_OVRE;
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-ledtrig-netdev.patch b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-ledtrig-netdev.patch
new file mode 100644
index 0000000..ab4c91b
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-ledtrig-netdev.patch
@@ -0,0 +1,488 @@
+Index: linux-2.6.39.4/drivers/leds/Kconfig
+===================================================================
+--- linux-2.6.39.4.orig/drivers/leds/Kconfig 2011-08-03 14:43:28.000000000 -0500
++++ linux-2.6.39.4/drivers/leds/Kconfig 2012-12-18 13:27:23.579027264 -0600
+@@ -417,6 +417,13 @@
+ load average.
+ If unsure, say Y.
+
++config LEDS_TRIGGER_NETDEV
++ tristate "LED Network Device Trigger"
++ depends on LEDS_TRIGGERS
++ help
++ This allows LEDs to be controlled by Network Device activity.
++ If unsure, say Y.
++
+ config LEDS_TRIGGER_BACKLIGHT
+ tristate "LED backlight Trigger"
+ depends on LEDS_TRIGGERS
+Index: linux-2.6.39.4/drivers/leds/Makefile
+===================================================================
+--- linux-2.6.39.4.orig/drivers/leds/Makefile 2011-08-03 14:43:28.000000000 -0500
++++ linux-2.6.39.4/drivers/leds/Makefile 2012-12-18 13:27:23.579027264 -0600
+@@ -50,6 +50,7 @@
+ obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
+ obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o
+ obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o
++obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o
+ obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o
+ obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o
+ obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
+Index: linux-2.6.39.4/drivers/leds/ledtrig-netdev.c
+===================================================================
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-2.6.39.4/drivers/leds/ledtrig-netdev.c 2012-12-18 14:40:30.078735442 -0600
+@@ -0,0 +1,453 @@
++/*
++ * LED Kernel Netdev Trigger
++ *
++ * Toggles the LED to reflect the link and traffic state of a named net device
++ *
++ * Copyright 2007 Oliver Jowett <oliver@opencloud.com>
++ *
++ * Derived from ledtrig-timer.c which is:
++ * Copyright 2005-2006 Openedhand Ltd.
++ * Author: Richard Purdie <rpurdie@openedhand.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/jiffies.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/spinlock.h>
++#include <linux/device.h>
++#include <linux/sysdev.h>
++#include <linux/netdevice.h>
++#include <linux/timer.h>
++#include <linux/ctype.h>
++#include <linux/leds.h>
++#include <linux/version.h>
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
++#include <net/net_namespace.h>
++#endif
++
++#include "leds.h"
++
++/*
++ * Configurable sysfs attributes:
++ *
++ * device_name - network device name to monitor
++ *
++ * interval - duration of LED blink, in milliseconds
++ *
++ * mode - either "none" (LED is off) or a space separated list of one or more of:
++ * link: LED's normal state reflects whether the link is up (has carrier) or not
++ * tx: LED blinks on transmitted data
++ * rx: LED blinks on receive data
++ *
++ * Some suggestions:
++ *
++ * Simple link status LED:
++ * $ echo netdev >someled/trigger
++ * $ echo eth0 >someled/device_name
++ * $ echo link >someled/mode
++ *
++ * Ethernet-style link/activity LED:
++ * $ echo netdev >someled/trigger
++ * $ echo eth0 >someled/device_name
++ * $ echo "link tx rx" >someled/mode
++ *
++ * Modem-style tx/rx LEDs:
++ * $ echo netdev >led1/trigger
++ * $ echo ppp0 >led1/device_name
++ * $ echo tx >led1/mode
++ * $ echo netdev >led2/trigger
++ * $ echo ppp0 >led2/device_name
++ * $ echo rx >led2/mode
++ *
++ */
++
++#define MODE_LINK 1
++#define MODE_TX 2
++#define MODE_RX 4
++
++struct led_netdev_data {
++ rwlock_t lock;
++
++ struct timer_list timer;
++ struct notifier_block notifier;
++
++ struct led_classdev *led_cdev;
++ struct net_device *net_dev;
++
++ char device_name[IFNAMSIZ];
++ unsigned interval;
++ unsigned mode;
++ unsigned link_up;
++ unsigned last_activity;
++};
++
++static void set_baseline_state(struct led_netdev_data *trigger_data)
++{
++ if ((trigger_data->mode & MODE_LINK) != 0 && trigger_data->link_up)
++ led_set_brightness(trigger_data->led_cdev, LED_FULL);
++ else
++ led_set_brightness(trigger_data->led_cdev, LED_OFF);
++
++ if ((trigger_data->mode & (MODE_TX | MODE_RX)) != 0 && trigger_data->link_up)
++ mod_timer(&trigger_data->timer, jiffies + trigger_data->interval);
++ else
++ del_timer(&trigger_data->timer);
++}
++
++static ssize_t led_device_name_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct led_classdev *led_cdev = dev_get_drvdata(dev);
++ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
++
++ read_lock(&trigger_data->lock);
++ sprintf(buf, "%s\n", trigger_data->device_name);
++ read_unlock(&trigger_data->lock);
++
++ return strlen(buf) + 1;
++}
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,21)
++extern struct net init_net;
++#endif
++
++static ssize_t led_device_name_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ struct led_classdev *led_cdev = dev_get_drvdata(dev);
++ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
++
++ if (size < 0 || size >= IFNAMSIZ)
++ return -EINVAL;
++
++ write_lock(&trigger_data->lock);
++
++ strcpy(trigger_data->device_name, buf);
++ if (size > 0 && trigger_data->device_name[size-1] == '\n')
++ trigger_data->device_name[size-1] = 0;
++
++ if (trigger_data->device_name[0] != 0) {
++ /* check for existing device to update from */
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
++ trigger_data->net_dev = dev_get_by_name(&init_net, trigger_data->device_name);
++#else
++ trigger_data->net_dev = dev_get_by_name(trigger_data->device_name);
++#endif
++ if (trigger_data->net_dev != NULL)
++ trigger_data->link_up = (dev_get_flags(trigger_data->net_dev) & IFF_LOWER_UP) != 0;
++ set_baseline_state(trigger_data); /* updates LEDs, may start timers */
++ }
++
++ write_unlock(&trigger_data->lock);
++ return size;
++}
++
++static DEVICE_ATTR(device_name, 0644, led_device_name_show, led_device_name_store);
++
++static ssize_t led_mode_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct led_classdev *led_cdev = dev_get_drvdata(dev);
++ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
++
++ read_lock(&trigger_data->lock);
++
++ if (trigger_data->mode == 0) {
++ strcpy(buf, "none\n");
++ } else {
++ if (trigger_data->mode & MODE_LINK)
++ strcat(buf, "link ");
++ if (trigger_data->mode & MODE_TX)
++ strcat(buf, "tx ");
++ if (trigger_data->mode & MODE_RX)
++ strcat(buf, "rx ");
++ strcat(buf, "\n");
++ }
++
++ read_unlock(&trigger_data->lock);
++
++ return strlen(buf)+1;
++}
++
++static ssize_t led_mode_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ struct led_classdev *led_cdev = dev_get_drvdata(dev);
++ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
++ char copybuf[1024];
++ int new_mode = -1;
++ char *p, *token;
++
++ /* take a copy since we don't want to trash the inbound buffer when using strsep */
++ strncpy(copybuf, buf, sizeof(copybuf));
++ copybuf[1023] = 0;
++ p = copybuf;
++
++ while ((token = strsep(&p, " \t\n")) != NULL) {
++ if (!*token)
++ continue;
++
++ if (new_mode == -1)
++ new_mode = 0;
++
++ if (!strcmp(token, "none"))
++ new_mode = 0;
++ else if (!strcmp(token, "tx"))
++ new_mode |= MODE_TX;
++ else if (!strcmp(token, "rx"))
++ new_mode |= MODE_RX;
++ else if (!strcmp(token, "link"))
++ new_mode |= MODE_LINK;
++ else
++ return -EINVAL;
++ }
++
++ if (new_mode == -1)
++ return -EINVAL;
++
++ write_lock(&trigger_data->lock);
++ trigger_data->mode = new_mode;
++ set_baseline_state(trigger_data);
++ write_unlock(&trigger_data->lock);
++
++ return size;
++}
++
++static DEVICE_ATTR(mode, 0644, led_mode_show, led_mode_store);
++
++static ssize_t led_interval_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct led_classdev *led_cdev = dev_get_drvdata(dev);
++ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
++
++ read_lock(&trigger_data->lock);
++ sprintf(buf, "%u\n", jiffies_to_msecs(trigger_data->interval));
++ read_unlock(&trigger_data->lock);
++
++ return strlen(buf) + 1;
++}
++
++static ssize_t led_interval_store(struct device *dev,
++ struct device_attribute *attr, const char *buf, size_t size)
++{
++ struct led_classdev *led_cdev = dev_get_drvdata(dev);
++ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
++ int ret = -EINVAL;
++ char *after;
++ unsigned long value = simple_strtoul(buf, &after, 10);
++ size_t count = after - buf;
++
++ if (*after && isspace(*after))
++ count++;
++
++ /* impose some basic bounds on the timer interval */
++ if (count == size && value >= 5 && value <= 10000) {
++ write_lock(&trigger_data->lock);
++ trigger_data->interval = msecs_to_jiffies(value);
++ set_baseline_state(trigger_data); // resets timer
++ write_unlock(&trigger_data->lock);
++ ret = count;
++ }
++
++ return ret;
++}
++
++static DEVICE_ATTR(interval, 0644, led_interval_show, led_interval_store);
++
++static int netdev_trig_notify(struct notifier_block *nb,
++ unsigned long evt,
++ void *dv)
++{
++ struct net_device *dev = dv;
++ struct led_netdev_data *trigger_data = container_of(nb, struct led_netdev_data, notifier);
++
++ if (evt != NETDEV_UP && evt != NETDEV_DOWN && evt != NETDEV_CHANGE && evt != NETDEV_REGISTER && evt != NETDEV_UNREGISTER)
++ return NOTIFY_DONE;
++
++ write_lock(&trigger_data->lock);
++
++ if (strcmp(dev->name, trigger_data->device_name))
++ goto done;
++
++ if (evt == NETDEV_REGISTER) {
++ if (trigger_data->net_dev != NULL)
++ dev_put(trigger_data->net_dev);
++ dev_hold(dev);
++ trigger_data->net_dev = dev;
++ trigger_data->link_up = 0;
++ goto done;
++ }
++
++ if (evt == NETDEV_UNREGISTER && trigger_data->net_dev != NULL) {
++ dev_put(trigger_data->net_dev);
++ trigger_data->net_dev = NULL;
++ goto done;
++ }
++
++ /* UP / DOWN / CHANGE */
++
++ trigger_data->link_up = (evt != NETDEV_DOWN && netif_carrier_ok(dev));
++ set_baseline_state(trigger_data);
++
++done:
++ write_unlock(&trigger_data->lock);
++ return NOTIFY_DONE;
++}
++
++/* here's the real work! */
++static void netdev_trig_timer(unsigned long arg)
++{
++ struct led_netdev_data *trigger_data = (struct led_netdev_data *)arg;
++ unsigned new_activity;
++
++ struct rtnl_link_stats64 *dev_stats;
++ struct rtnl_link_stats64 temp;
++
++ write_lock(&trigger_data->lock);
++
++ if (!trigger_data->link_up || !trigger_data->net_dev || (trigger_data->mode & (MODE_TX | MODE_RX)) == 0) {
++ /* we don't need to do timer work, just reflect link state. */
++ led_set_brightness(trigger_data->led_cdev, ((trigger_data->mode & MODE_LINK) != 0 && trigger_data->link_up) ? LED_FULL : LED_OFF);
++ goto no_restart;
++ }
++
++ dev_stats = dev_get_stats(trigger_data->net_dev, &temp);
++ new_activity =
++ ((trigger_data->mode & MODE_TX) ? dev_stats->tx_packets : 0) +
++ ((trigger_data->mode & MODE_RX) ? dev_stats->rx_packets : 0);
++
++ if (trigger_data->mode & MODE_LINK) {
++ /* base state is ON (link present) */
++ /* if there's no link, we don't get this far and the LED is off */
++
++ /* OFF -> ON always */
++ /* ON -> OFF on activity */
++ if (trigger_data->led_cdev->brightness == LED_OFF) {
++ led_set_brightness(trigger_data->led_cdev, LED_FULL);
++ } else if (trigger_data->last_activity != new_activity) {
++ led_set_brightness(trigger_data->led_cdev, LED_OFF);
++ }
++ } else {
++ /* base state is OFF */
++ /* ON -> OFF always */
++ /* OFF -> ON on activity */
++ if (trigger_data->led_cdev->brightness == LED_FULL) {
++ led_set_brightness(trigger_data->led_cdev, LED_OFF);
++ } else if (trigger_data->last_activity != new_activity) {
++ led_set_brightness(trigger_data->led_cdev, LED_FULL);
++ }
++ }
++
++ trigger_data->last_activity = new_activity;
++ mod_timer(&trigger_data->timer, jiffies + trigger_data->interval);
++
++no_restart:
++ write_unlock(&trigger_data->lock);
++}
++
++static void netdev_trig_activate(struct led_classdev *led_cdev)
++{
++ struct led_netdev_data *trigger_data;
++ int rc;
++
++ trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL);
++ if (!trigger_data)
++ return;
++
++ rwlock_init(&trigger_data->lock);
++
++ trigger_data->notifier.notifier_call = netdev_trig_notify;
++ trigger_data->notifier.priority = 10;
++
++ setup_timer(&trigger_data->timer, netdev_trig_timer, (unsigned long) trigger_data);
++
++ trigger_data->led_cdev = led_cdev;
++ trigger_data->net_dev = NULL;
++ trigger_data->device_name[0] = 0;
++
++ trigger_data->mode = 0;
++ trigger_data->interval = msecs_to_jiffies(50);
++ trigger_data->link_up = 0;
++ trigger_data->last_activity = 0;
++
++ led_cdev->trigger_data = trigger_data;
++
++ rc = device_create_file(led_cdev->dev, &dev_attr_device_name);
++ if (rc)
++ goto err_out;
++ rc = device_create_file(led_cdev->dev, &dev_attr_mode);
++ if (rc)
++ goto err_out_device_name;
++ rc = device_create_file(led_cdev->dev, &dev_attr_interval);
++ if (rc)
++ goto err_out_mode;
++
++ register_netdevice_notifier(&trigger_data->notifier);
++ return;
++
++err_out_mode:
++ device_remove_file(led_cdev->dev, &dev_attr_mode);
++err_out_device_name:
++ device_remove_file(led_cdev->dev, &dev_attr_device_name);
++err_out:
++ led_cdev->trigger_data = NULL;
++ kfree(trigger_data);
++}
++
++static void netdev_trig_deactivate(struct led_classdev *led_cdev)
++{
++ struct led_netdev_data *trigger_data = led_cdev->trigger_data;
++
++ if (trigger_data) {
++ unregister_netdevice_notifier(&trigger_data->notifier);
++
++ device_remove_file(led_cdev->dev, &dev_attr_device_name);
++ device_remove_file(led_cdev->dev, &dev_attr_mode);
++ device_remove_file(led_cdev->dev, &dev_attr_interval);
++
++ write_lock(&trigger_data->lock);
++
++ if (trigger_data->net_dev) {
++ dev_put(trigger_data->net_dev);
++ trigger_data->net_dev = NULL;
++ }
++
++ write_unlock(&trigger_data->lock);
++
++ del_timer_sync(&trigger_data->timer);
++
++ kfree(trigger_data);
++ }
++}
++
++static struct led_trigger netdev_led_trigger = {
++ .name = "netdev",
++ .activate = netdev_trig_activate,
++ .deactivate = netdev_trig_deactivate,
++};
++
++static int __init netdev_trig_init(void)
++{
++ return led_trigger_register(&netdev_led_trigger);
++}
++
++static void __exit netdev_trig_exit(void)
++{
++ led_trigger_unregister(&netdev_led_trigger);
++}
++
++module_init(netdev_trig_init);
++module_exit(netdev_trig_exit);
++
++MODULE_AUTHOR("Oliver Jowett <oliver@opencloud.com>");
++MODULE_DESCRIPTION("Netdev LED trigger");
++MODULE_LICENSE("GPL");
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-option-telit.patch b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-option-telit.patch
new file mode 100644
index 0000000..0a4baa1
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/linux-2.6.39.4-option-telit.patch
@@ -0,0 +1,43 @@
+From 7204cf584836c24b4b06e4ad4a8e6bb8ea84908e Mon Sep 17 00:00:00 2001
+From: Daniele Palmas <dnlplm@gmail.com>
+Date: Wed, 29 Feb 2012 15:32:05 +0100
+Subject: [PATCH] USB: option driver: adding support for Telit CC864-SINGLE,
+ CC864-DUAL and DE910-DUAL modems
+
+Adding PID for Telit CC864-SINGLE, CC864-DUAL and DE910-DUAL
+modems
+
+Signed-off-by: Daniele Palmas <dnlplm@gmail.com>
+Cc: stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/serial/option.c | 6 ++++++
+ 1 files changed, 6 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
+index 005511b..f9b11fb 100644
+--- a/drivers/usb/serial/option.c
++++ b/drivers/usb/serial/option.c
+@@ -307,6 +307,9 @@ static void option_instat_callback(struct urb *urb);
+ #define TELIT_VENDOR_ID 0x1bc7
+ #define TELIT_PRODUCT_UC864E 0x1003
+ #define TELIT_PRODUCT_UC864G 0x1004
++#define TELIT_PRODUCT_CC864_DUAL 0x1005
++#define TELIT_PRODUCT_CC864_SINGLE 0x1006
++#define TELIT_PRODUCT_DE910_DUAL 0x1010
+
+ /* ZTE PRODUCTS */
+ #define ZTE_VENDOR_ID 0x19d2
+@@ -771,6 +774,9 @@ static const struct usb_device_id option_ids[] = {
+ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) },
++ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) },
++ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
++ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
+ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&net_intf1_blacklist },
+--
+1.7.7.6
+
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/defconfig b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/defconfig
new file mode 100644
index 0000000..0afdbee
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/defconfig
@@ -0,0 +1,2328 @@
+#
+# Automatically generated make config: don't edit
+# Linux/arm 2.6.39.4 Kernel Configuration
+# Tue Feb 12 17:21:58 2013
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_KTIME_SCALAR=y
+CONFIG_HAVE_PROC_CPU=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_VECTORS_BASE=0xffff0000
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+CONFIG_HAVE_IRQ_WORK=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_HAVE_SPARSE_IRQ=y
+CONFIG_GENERIC_IRQ_SHOW=y
+# CONFIG_SPARSE_IRQ is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+# CONFIG_CGROUP_NS is not set
+# CONFIG_CGROUP_FREEZER is not set
+# CONFIG_CGROUP_DEVICE is not set
+# CONFIG_CPUSETS is not set
+# CONFIG_CGROUP_CPUACCT is not set
+# CONFIG_RESOURCE_COUNTERS is not set
+# CONFIG_CGROUP_SCHED is not set
+CONFIG_BLK_CGROUP=y
+# CONFIG_DEBUG_BLK_CGROUP is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_XZ=y
+CONFIG_RD_LZO=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EXPERT=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_EMBEDDED=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+# CONFIG_MODVERSIONS is not set
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBDAF=y
+CONFIG_BLK_DEV_BSG=y
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_DEV_THROTTLING is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CFQ_GROUP_IOSCHED is not set
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+CONFIG_DEFAULT_NOOP=y
+CONFIG_DEFAULT_IOSCHED="noop"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+CONFIG_INLINE_SPIN_UNLOCK=y
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+CONFIG_INLINE_READ_UNLOCK=y
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+CONFIG_INLINE_WRITE_UNLOCK=y
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_VEXPRESS is not set
+CONFIG_ARCH_AT91=y
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CNS3XXX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_MXS is not set
+# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_LPC32XX is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_NUC93X is not set
+# CONFIG_ARCH_TEGRA is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_S5P64X0 is not set
+# CONFIG_ARCH_S5P6442 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS4 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_TCC_926 is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_VT8500 is not set
+
+#
+# Atmel AT91 System-on-Chip
+#
+# CONFIG_ARCH_AT91RM9200 is not set
+# CONFIG_ARCH_AT91SAM9260 is not set
+# CONFIG_ARCH_AT91SAM9261 is not set
+# CONFIG_ARCH_AT91SAM9G10 is not set
+# CONFIG_ARCH_AT91SAM9263 is not set
+# CONFIG_ARCH_AT91SAM9RL is not set
+# CONFIG_ARCH_AT91SAM9G20 is not set
+# CONFIG_ARCH_AT91SAM9G45 is not set
+CONFIG_ARCH_AT91SAM9X5=y
+# CONFIG_ARCH_AT91CAP9 is not set
+# CONFIG_ARCH_AT572D940HF is not set
+# CONFIG_ARCH_AT91X40 is not set
+CONFIG_AT91_PMC_UNIT=y
+
+#
+# AT91SAM9x5 Series Board Type
+#
+CONFIG_MACH_AT91SAM9X5EK=y
+
+#
+# AT91 Board Options
+#
+
+#
+# AT91 Feature Selections
+#
+CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
+CONFIG_AT91_SLOW_CLOCK=y
+CONFIG_AT91_TIMER_HZ=100
+CONFIG_AT91_EARLY_DBGU=y
+# CONFIG_AT91_EARLY_USART0 is not set
+# CONFIG_AT91_EARLY_USART1 is not set
+# CONFIG_AT91_EARLY_USART2 is not set
+# CONFIG_GPIO_PCA953X is not set
+
+#
+# System MMU
+#
+
+#
+# Processor Type
+#
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_LEGACY=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+CONFIG_CPU_USE_DOMAINS=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+CONFIG_ARM_L1_CACHE_SHIFT=5
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=999999
+# CONFIG_COMPACTION is not set
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_NEED_PER_CPU_KM=y
+CONFIG_FORCE_MAX_ZONEORDER=11
+CONFIG_LEDS=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+CONFIG_UACCESS_WITH_MEMCPY=y
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=" quiet "
+# CONFIG_CMDLINE_FORCE is not set
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_AUTO_ZRELADDR=y
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_RUNTIME is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM_EMULATION is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_XFRM_IPCOMP=y
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_NET_IPIP=y
+CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_NET_IPGRE=y
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+CONFIG_INET_AH=m
+CONFIG_INET_ESP=m
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+CONFIG_BRIDGE_NETFILTER=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=y
+CONFIG_NETFILTER_NETLINK_QUEUE=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CONNTRACK_TIMESTAMP is not set
+# CONFIG_NF_CT_PROTO_DCCP is not set
+CONFIG_NF_CT_PROTO_GRE=y
+# CONFIG_NF_CT_PROTO_SCTP is not set
+# CONFIG_NF_CT_PROTO_UDPLITE is not set
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+# CONFIG_NF_CONNTRACK_IRC is not set
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_SNMP is not set
+CONFIG_NF_CONNTRACK_PPTP=y
+# CONFIG_NF_CONNTRACK_SANE is not set
+# CONFIG_NF_CONNTRACK_SIP is not set
+# CONFIG_NF_CONNTRACK_TFTP is not set
+# CONFIG_NF_CT_NETLINK is not set
+# CONFIG_NETFILTER_TPROXY is not set
+CONFIG_NETFILTER_XTABLES=y
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=y
+CONFIG_NETFILTER_XT_CONNMARK=y
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+# CONFIG_NETFILTER_XT_TARGET_CONNMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_DSCP is not set
+# CONFIG_NETFILTER_XT_TARGET_HL is not set
+# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
+# CONFIG_NETFILTER_XT_TARGET_LED is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set
+# CONFIG_NETFILTER_XT_MATCH_CONNLIMIT is not set
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set
+# CONFIG_NETFILTER_XT_MATCH_HELPER is not set
+CONFIG_NETFILTER_XT_MATCH_HL=y
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+# CONFIG_NETFILTER_XT_MATCH_MARK is not set
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+# CONFIG_NETFILTER_XT_MATCH_POLICY is not set
+# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set
+# CONFIG_NETFILTER_XT_MATCH_PKTTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+# CONFIG_NETFILTER_XT_MATCH_REALM is not set
+CONFIG_NETFILTER_XT_MATCH_RECENT=y
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set
+# CONFIG_NETFILTER_XT_MATCH_STRING is not set
+# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+# CONFIG_NETFILTER_XT_MATCH_U32 is not set
+# CONFIG_IP_SET is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+# CONFIG_IP_NF_QUEUE is not set
+CONFIG_IP_NF_IPTABLES=y
+# CONFIG_IP_NF_MATCH_AH is not set
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_TARGET_LOG=y
+# CONFIG_IP_NF_TARGET_ULOG is not set
+CONFIG_NF_NAT=y
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_NF_NAT_PROTO_GRE=y
+CONFIG_NF_NAT_FTP=y
+# CONFIG_NF_NAT_IRC is not set
+# CONFIG_NF_NAT_TFTP is not set
+# CONFIG_NF_NAT_AMANDA is not set
+CONFIG_NF_NAT_PPTP=y
+CONFIG_NF_NAT_H323=y
+# CONFIG_NF_NAT_SIP is not set
+CONFIG_IP_NF_MANGLE=y
+# CONFIG_IP_NF_TARGET_CLUSTERIP is not set
+# CONFIG_IP_NF_TARGET_ECN is not set
+# CONFIG_IP_NF_TARGET_TTL is not set
+# CONFIG_IP_NF_RAW is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+# CONFIG_BRIDGE_NF_EBTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_L2TP=y
+# CONFIG_L2TP_V3 is not set
+CONFIG_STP=m
+CONFIG_BRIDGE=m
+CONFIG_BRIDGE_IGMP_SNOOPING=y
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+CONFIG_LLC=m
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_IEEE802154 is not set
+CONFIG_NET_SCHED=y
+
+#
+# Queueing/Scheduling
+#
+# CONFIG_NET_SCH_CBQ is not set
+# CONFIG_NET_SCH_HTB is not set
+# CONFIG_NET_SCH_HFSC is not set
+# CONFIG_NET_SCH_PRIO is not set
+# CONFIG_NET_SCH_MULTIQ is not set
+# CONFIG_NET_SCH_RED is not set
+# CONFIG_NET_SCH_SFB is not set
+# CONFIG_NET_SCH_SFQ is not set
+# CONFIG_NET_SCH_TEQL is not set
+# CONFIG_NET_SCH_TBF is not set
+# CONFIG_NET_SCH_GRED is not set
+# CONFIG_NET_SCH_DSMARK is not set
+# CONFIG_NET_SCH_NETEM is not set
+# CONFIG_NET_SCH_DRR is not set
+# CONFIG_NET_SCH_MQPRIO is not set
+# CONFIG_NET_SCH_CHOKE is not set
+
+#
+# Classification
+#
+# CONFIG_NET_CLS_BASIC is not set
+# CONFIG_NET_CLS_TCINDEX is not set
+# CONFIG_NET_CLS_ROUTE4 is not set
+# CONFIG_NET_CLS_FW is not set
+# CONFIG_NET_CLS_U32 is not set
+# CONFIG_NET_CLS_RSVP is not set
+# CONFIG_NET_CLS_RSVP6 is not set
+# CONFIG_NET_CLS_FLOW is not set
+# CONFIG_NET_CLS_CGROUP is not set
+# CONFIG_NET_EMATCH is not set
+# CONFIG_NET_CLS_ACT is not set
+CONFIG_NET_SCH_FIFO=y
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=y
+# CONFIG_BATMAN_ADV is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+CONFIG_BT=m
+CONFIG_BT_L2CAP=y
+CONFIG_BT_SCO=y
+CONFIG_BT_RFCOMM=m
+CONFIG_BT_RFCOMM_TTY=y
+CONFIG_BT_BNEP=m
+CONFIG_BT_BNEP_MC_FILTER=y
+CONFIG_BT_BNEP_PROTO_FILTER=y
+CONFIG_BT_HIDP=m
+
+#
+# Bluetooth device drivers
+#
+CONFIG_BT_HCIBTUSB=m
+# CONFIG_BT_HCIBTSDIO is not set
+CONFIG_BT_HCIUART=m
+# CONFIG_BT_HCIUART_H4 is not set
+# CONFIG_BT_HCIUART_BCSP is not set
+# CONFIG_BT_HCIUART_ATH3K is not set
+CONFIG_BT_HCIUART_LL=y
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_BT_MRVL is not set
+# CONFIG_BT_ATH3K is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=m
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_WEXT=y
+CONFIG_WIRELESS_EXT_SYSFS=y
+CONFIG_LIB80211=m
+# CONFIG_LIB80211_DEBUG is not set
+CONFIG_MAC80211=m
+CONFIG_MAC80211_HAS_RC=y
+# CONFIG_MAC80211_RC_PID is not set
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH=""
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_TESTS is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_DATAFLASH is not set
+# CONFIG_MTD_M25P80 is not set
+# CONFIG_MTD_SST25L is not set
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_BCH is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+CONFIG_MTD_NAND_ATMEL=y
+CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y
+# CONFIG_MTD_NAND_ATMEL_ECC_NONE is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+# CONFIG_MTD_UBI_GLUEBI is not set
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=32768
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_AD525X_DPOT is not set
+CONFIG_ATMEL_TCLIB=y
+CONFIG_ATMEL_TCB_CLKSRC=y
+CONFIG_ATMEL_TCB_CLKSRC_BLOCK=0
+CONFIG_ATMEL_TCB_CLKSRC_32BIT=y
+# CONFIG_ICS932S401 is not set
+CONFIG_ATMEL_SSC=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_APDS9802ALS is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1780 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_BMP085 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+CONFIG_EEPROM_93CX6=m
+# CONFIG_IWMC3200TOP is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_TARGET_CORE is not set
+CONFIG_HAVE_NET_MACB=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=m
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+CONFIG_MII=y
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_BCM63XX_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MICREL_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MACB=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_KS8842 is not set
+# CONFIG_KS8851 is not set
+# CONFIG_KS8851_MLL is not set
+# CONFIG_FTMAC100 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_WLAN=y
+# CONFIG_LIBERTAS_THINFIRM is not set
+CONFIG_AT76C50X_USB=m
+CONFIG_USB_ZD1201=m
+CONFIG_USB_NET_RNDIS_WLAN=m
+CONFIG_RTL8187=m
+CONFIG_RTL8187_LEDS=y
+# CONFIG_MAC80211_HWSIM is not set
+CONFIG_ATH_COMMON=m
+# CONFIG_ATH_DEBUG is not set
+CONFIG_ATH9K_HW=m
+CONFIG_ATH9K_COMMON=m
+CONFIG_ATH9K_HTC=m
+# CONFIG_AR9170_USB is not set
+CONFIG_CARL9170=m
+CONFIG_CARL9170_LEDS=y
+CONFIG_CARL9170_WPC=y
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_IWM is not set
+# CONFIG_LIBERTAS is not set
+# CONFIG_P54_COMMON is not set
+CONFIG_RT2X00=m
+CONFIG_RT2500USB=m
+CONFIG_RT73USB=m
+CONFIG_RT2800USB=m
+CONFIG_RT2800USB_RT33XX=y
+CONFIG_RT2800USB_RT35XX=y
+# CONFIG_RT2800USB_UNKNOWN is not set
+CONFIG_RT2800_LIB=m
+CONFIG_RT2X00_LIB_USB=m
+CONFIG_RT2X00_LIB=m
+CONFIG_RT2X00_LIB_HT=y
+CONFIG_RT2X00_LIB_FIRMWARE=y
+CONFIG_RT2X00_LIB_CRYPTO=y
+CONFIG_RT2X00_LIB_LEDS=y
+# CONFIG_RT2X00_DEBUG is not set
+CONFIG_RTL8192CU=m
+CONFIG_RTLWIFI=m
+CONFIG_RTL8192C_COMMON=m
+# CONFIG_WL1251 is not set
+CONFIG_WL12XX_MENU=m
+CONFIG_WL12XX=m
+# CONFIG_WL12XX_HT is not set
+# CONFIG_WL12XX_SPI is not set
+CONFIG_WL12XX_SDIO=m
+CONFIG_WL12XX_SDIO_TEST=m
+CONFIG_WL12XX_PLATFORM_DATA=y
+# CONFIG_ZD1211RW is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+CONFIG_USB_CATC=m
+CONFIG_USB_KAWETH=m
+CONFIG_USB_PEGASUS=m
+CONFIG_USB_RTL8150=m
+CONFIG_USB_USBNET=m
+CONFIG_USB_NET_AX8817X=m
+CONFIG_USB_NET_CDCETHER=m
+CONFIG_USB_NET_CDC_EEM=m
+CONFIG_USB_NET_CDC_NCM=m
+CONFIG_USB_NET_DM9601=m
+CONFIG_USB_NET_SMSC75XX=m
+CONFIG_USB_NET_SMSC95XX=m
+CONFIG_USB_NET_GL620A=m
+CONFIG_USB_NET_NET1080=m
+CONFIG_USB_NET_PLUSB=m
+CONFIG_USB_NET_MCS7830=m
+CONFIG_USB_NET_RNDIS_HOST=m
+CONFIG_USB_NET_CDC_SUBSET=m
+CONFIG_USB_ALI_M5632=y
+CONFIG_USB_AN2720=y
+CONFIG_USB_BELKIN=y
+CONFIG_USB_ARMLINUX=y
+# CONFIG_USB_EPSON2888 is not set
+CONFIG_USB_KC2190=y
+CONFIG_USB_NET_ZAURUS=m
+CONFIG_USB_NET_CX82310_ETH=m
+CONFIG_USB_NET_INT51X1=m
+CONFIG_USB_IPHETH=m
+CONFIG_USB_SIERRA_NET=m
+CONFIG_USB_VL600=m
+# CONFIG_WAN is not set
+
+#
+# CAIF transport drivers
+#
+CONFIG_PPP=y
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_ASYNC=y
+# CONFIG_PPP_SYNC_TTY is not set
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_BSDCOMP=y
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPTP is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=y
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+CONFIG_DEVKMEM=y
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_ATMEL=y
+CONFIG_SERIAL_ATMEL_CONSOLE=y
+CONFIG_SERIAL_ATMEL_DMA=y
+# CONFIG_SERIAL_ATMEL_TTYAT is not set
+# CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX3107 is not set
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_RAMOOPS is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_COMPAT=y
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_MUX is not set
+CONFIG_I2C_HELPER_AUTO=y
+CONFIG_I2C_ALGOBIT=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+CONFIG_I2C_GPIO=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+# CONFIG_SPI_DEBUG is not set
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+# CONFIG_SPI_ALTERA is not set
+CONFIG_SPI_ATMEL=y
+CONFIG_SPI_ATMEL_DMA=y
+# CONFIG_SPI_BITBANG is not set
+# CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+# CONFIG_SPI_SPIDEV is not set
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_BASIC_MMIO is not set
+# CONFIG_GPIO_IT8761E is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
+# CONFIG_GPIO_ADP5588 is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_74X164 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_AT91SAM9X_WATCHDOG=y
+# CONFIG_MAX63XX_WATCHDOG is not set
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_MFD_SUPPORT=y
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_88PM860X is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_TPS6105X is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_TC3589X is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM831X_I2C is not set
+# CONFIG_MFD_WM831X_SPI is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_WM8994 is not set
+# CONFIG_MFD_PCF50633 is not set
+# CONFIG_MFD_MC13XXX is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_TPS6586X is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_REGULATOR is not set
+CONFIG_MEDIA_SUPPORT=m
+
+#
+# Multimedia core support
+#
+# CONFIG_MEDIA_CONTROLLER is not set
+CONFIG_VIDEO_DEV=m
+CONFIG_VIDEO_V4L2_COMMON=m
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=m
+
+#
+# Multimedia drivers
+#
+# CONFIG_RC_CORE is not set
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=m
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=m
+CONFIG_MEDIA_TUNER_TDA8290=m
+CONFIG_MEDIA_TUNER_TDA827X=m
+CONFIG_MEDIA_TUNER_TDA18271=m
+CONFIG_MEDIA_TUNER_TDA9887=m
+CONFIG_MEDIA_TUNER_TEA5761=m
+CONFIG_MEDIA_TUNER_TEA5767=m
+CONFIG_MEDIA_TUNER_MT20XX=m
+CONFIG_MEDIA_TUNER_XC2028=m
+CONFIG_MEDIA_TUNER_XC5000=m
+CONFIG_MEDIA_TUNER_MC44S803=m
+CONFIG_VIDEO_V4L2=m
+CONFIG_VIDEOBUF_GEN=m
+CONFIG_VIDEOBUF_VMALLOC=m
+CONFIG_VIDEO_TVEEPROM=m
+CONFIG_VIDEO_TUNER=m
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_AT91SAM9X5 is not set
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+
+#
+# Audio decoders
+#
+CONFIG_VIDEO_MSP3400=m
+CONFIG_VIDEO_CS53L32A=m
+CONFIG_VIDEO_WM8775=m
+
+#
+# RDS decoders
+#
+
+#
+# Video decoders
+#
+CONFIG_VIDEO_SAA711X=m
+
+#
+# Video and audio decoders
+#
+CONFIG_VIDEO_CX25840=m
+
+#
+# MPEG video encoders
+#
+CONFIG_VIDEO_CX2341X=m
+
+#
+# Video encoders
+#
+
+#
+# Video improvement chips
+#
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_TIMBERDALE is not set
+# CONFIG_VIDEO_SR030PC30 is not set
+# CONFIG_VIDEO_NOON010PC30 is not set
+# CONFIG_SOC_CAMERA is not set
+CONFIG_V4L_USB_DRIVERS=y
+CONFIG_USB_VIDEO_CLASS=m
+CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
+CONFIG_USB_GSPCA=m
+CONFIG_USB_M5602=m
+CONFIG_USB_STV06XX=m
+CONFIG_USB_GL860=m
+CONFIG_USB_GSPCA_BENQ=m
+CONFIG_USB_GSPCA_CONEX=m
+CONFIG_USB_GSPCA_CPIA1=m
+CONFIG_USB_GSPCA_ETOMS=m
+CONFIG_USB_GSPCA_FINEPIX=m
+CONFIG_USB_GSPCA_JEILINJ=m
+# CONFIG_USB_GSPCA_KONICA is not set
+CONFIG_USB_GSPCA_MARS=m
+CONFIG_USB_GSPCA_MR97310A=m
+# CONFIG_USB_GSPCA_NW80X is not set
+CONFIG_USB_GSPCA_OV519=m
+CONFIG_USB_GSPCA_OV534=m
+CONFIG_USB_GSPCA_OV534_9=m
+CONFIG_USB_GSPCA_PAC207=m
+CONFIG_USB_GSPCA_PAC7302=m
+CONFIG_USB_GSPCA_PAC7311=m
+CONFIG_USB_GSPCA_SN9C2028=m
+CONFIG_USB_GSPCA_SN9C20X=m
+CONFIG_USB_GSPCA_SONIXB=m
+CONFIG_USB_GSPCA_SONIXJ=m
+CONFIG_USB_GSPCA_SPCA500=m
+CONFIG_USB_GSPCA_SPCA501=m
+CONFIG_USB_GSPCA_SPCA505=m
+CONFIG_USB_GSPCA_SPCA506=m
+CONFIG_USB_GSPCA_SPCA508=m
+CONFIG_USB_GSPCA_SPCA561=m
+# CONFIG_USB_GSPCA_SPCA1528 is not set
+CONFIG_USB_GSPCA_SQ905=m
+CONFIG_USB_GSPCA_SQ905C=m
+# CONFIG_USB_GSPCA_SQ930X is not set
+CONFIG_USB_GSPCA_STK014=m
+CONFIG_USB_GSPCA_STV0680=m
+CONFIG_USB_GSPCA_SUNPLUS=m
+CONFIG_USB_GSPCA_T613=m
+CONFIG_USB_GSPCA_TV8532=m
+CONFIG_USB_GSPCA_VC032X=m
+# CONFIG_USB_GSPCA_VICAM is not set
+# CONFIG_USB_GSPCA_XIRLINK_CIT is not set
+CONFIG_USB_GSPCA_ZC3XX=m
+CONFIG_VIDEO_PVRUSB2=m
+CONFIG_VIDEO_PVRUSB2_SYSFS=y
+# CONFIG_VIDEO_PVRUSB2_DEBUGIFC is not set
+CONFIG_VIDEO_HDPVR=m
+CONFIG_VIDEO_USBVISION=m
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_USB_SN9C102 is not set
+CONFIG_USB_PWC=m
+# CONFIG_USB_PWC_DEBUG is not set
+CONFIG_USB_PWC_INPUT_EVDEV=y
+CONFIG_USB_ZR364XX=m
+CONFIG_USB_STKWEBCAM=m
+CONFIG_USB_S2255=m
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
+# CONFIG_RADIO_ADAPTERS is not set
+
+#
+# Graphics support
+#
+CONFIG_HAVE_FB_ATMEL=y
+# CONFIG_DRM is not set
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_SOUND is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+# CONFIG_USB_HID is not set
+# CONFIG_HID_PID is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_MAGICMOUSE is not set
+# CONFIG_HID_WACOM is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=y
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set
+# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+# CONFIG_USB_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_UAS is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_EZUSB=y
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_FUNSOFT=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+# CONFIG_USB_SERIAL_KEYSPAN_MPR is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XA is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA28XB is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19 is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA18X is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QW is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA19QI is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49W is not set
+# CONFIG_USB_SERIAL_KEYSPAN_USA49WLC is not set
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+CONFIG_USB_SERIAL_MOTOROLA=m
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_HP4X=m
+# CONFIG_USB_SERIAL_SAFE is not set
+CONFIG_USB_SERIAL_SAMBA=m
+CONFIG_USB_SERIAL_SIEMENS_MPI=m
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_WWAN=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+CONFIG_USB_SERIAL_VIVOPAY_SERIAL=m
+CONFIG_USB_SERIAL_ZIO=m
+CONFIG_USB_SERIAL_SSU100=m
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+CONFIG_USB_SEVSEG=m
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+CONFIG_USB_LCD=m
+CONFIG_USB_LED=m
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+CONFIG_USB_CYTHERM=m
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG is not set
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+CONFIG_USB_GADGET_ATMEL_USBA=y
+CONFIG_USB_ATMEL_USBA=m
+# CONFIG_USB_GADGET_FUSB300 is not set
+# CONFIG_USB_GADGET_R8A66597 is not set
+# CONFIG_USB_GADGET_PXA_U2O is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_ETH_EEM is not set
+# CONFIG_USB_G_NCM is not set
+CONFIG_USB_GADGETFS=m
+# CONFIG_USB_FUNCTIONFS is not set
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_MASS_STORAGE=m
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_MULTI is not set
+# CONFIG_USB_G_HID is not set
+# CONFIG_USB_G_DBGP is not set
+# CONFIG_USB_G_WEBCAM is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ULPI is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+# CONFIG_MMC_CLKGATE is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MMC_AT91 is not set
+CONFIG_MMC_ATMELMCI=m
+# CONFIG_MMC_ATMELMCI_DMA is not set
+# CONFIG_MMC_SPI is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_USHC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_LM3530 is not set
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_LP5523 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
+CONFIG_LEDS_TRIGGERS=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_NETDEV=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_NFC_DEVICES is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS3232 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+CONFIG_RTC_DRV_AT91RM9200=y
+CONFIG_DMADEVICES=y
+# CONFIG_DMADEVICES_DEBUG is not set
+
+#
+# DMA Devices
+#
+# CONFIG_DW_DMAC is not set
+CONFIG_AT_HDMAC=y
+# CONFIG_TIMB_DMA is not set
+CONFIG_DMA_ENGINE=y
+
+#
+# DMA Clients
+#
+# CONFIG_NET_DMA is not set
+# CONFIG_ASYNC_TX_DMA is not set
+# CONFIG_DMATEST is not set
+# CONFIG_AUXDISPLAY is not set
+CONFIG_UIO=m
+CONFIG_UIO_PDRV=m
+CONFIG_UIO_PDRV_GENIRQ=m
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD=y
+CONFIG_JBD2=y
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+CONFIG_GENERIC_ACL=y
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_ECRYPT_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+CONFIG_JFFS2_FS_WBUF_VERIFY=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_FS_POSIX_ACL=y
+CONFIG_JFFS2_FS_SECURITY=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_LZO=y
+CONFIG_JFFS2_RTIME=y
+CONFIG_JFFS2_RUBIN=y
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_JFFS2_CMODE_FAVOURLZO is not set
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_XATTR=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+# CONFIG_LOGFS is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_BLOCK=y
+# CONFIG_ROMFS_BACKED_BY_MTD is not set
+# CONFIG_ROMFS_BACKED_BY_BOTH is not set
+CONFIG_ROMFS_ON_BLOCK=y
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+# CONFIG_NFS_V4_1 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFS_USE_NEW_IDMAPPER is not set
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+CONFIG_SUNRPC_GSS=y
+# CONFIG_CEPH_FS is not set
+CONFIG_CIFS=y
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+# CONFIG_CIFS_XATTR is not set
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_DFS_UPCALL is not set
+# CONFIG_CIFS_EXPERIMENTAL is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+CONFIG_NLS_CODEPAGE_850=y
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_HARDLOCKUP_DETECTOR is not set
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+CONFIG_DEBUG_LL=y
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_DEBUG_ICEDCC is not set
+# CONFIG_OC_ETM is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_KEYS_DEBUG_PROC_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=m
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=y
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=y
+# CONFIG_CRYPTO_CAMELLIA is not set
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_DES=y
+CONFIG_CRYPTO_FCRYPT=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_SALSA20=y
+CONFIG_CRYPTO_SEED=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+CONFIG_CRC7=m
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_AVERAGE=y
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-at91sam9_wdt-10second-timeout.patch b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-at91sam9_wdt-10second-timeout.patch
new file mode 100644
index 0000000..90c906c
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-at91sam9_wdt-10second-timeout.patch
@@ -0,0 +1,14 @@
+Index: linux-2.6.39.4/drivers/watchdog/at91sam9_wdt.c
+===================================================================
+--- linux-2.6.39.4.orig/drivers/watchdog/at91sam9_wdt.c 2013-01-16 14:33:37.565560189 -0600
++++ linux-2.6.39.4/drivers/watchdog/at91sam9_wdt.c 2013-01-16 14:34:26.531727425 -0600
+@@ -43,7 +43,8 @@
+ #define ticks_to_ms(t) (((t + 1) * 1000) >> 8)
+
+ /* Hardware timeout in seconds */
+-#define WDT_HW_TIMEOUT 2
++/* MTR: use longer timeout */
++#define WDT_HW_TIMEOUT 10
+
+ /* Timer heartbeat (500ms) */
+ #define WDT_TIMEOUT (HZ/2)
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-at91sam9x5-extreset.patch b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-at91sam9x5-extreset.patch
new file mode 100644
index 0000000..31b7441
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-at91sam9x5-extreset.patch
@@ -0,0 +1,16 @@
+Index: linux-2.6.39.4/arch/arm/mach-at91/at91sam9x5.c
+===================================================================
+--- linux-2.6.39.4.orig/arch/arm/mach-at91/at91sam9x5.c 2012-06-25 17:00:27.060489533 -0500
++++ linux-2.6.39.4/arch/arm/mach-at91/at91sam9x5.c 2012-06-25 17:00:33.051404086 -0500
+@@ -330,7 +330,10 @@
+
+ static void at91sam9x5_reset(void)
+ {
+- at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST);
++ // MTR: generate an external reset (assert the NRST pin) on soft reset
++ // set reset duration to 125 ms --> set ERSTL to 0xb (0xb = 11 = 2^12 slow clock cycles = 4096 clocks = 125 ms)
++ at91_sys_write(AT91_RSTC_MR, AT91_RSTC_KEY | (0xb << 8));
++ at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_PROCRST | AT91_RSTC_PERRST | AT91_RSTC_EXTRST);
+ }
+
+ static void at91sam9x5_poweroff(void)
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-atmel-mci-force-detect.patch b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-atmel-mci-force-detect.patch
new file mode 100644
index 0000000..d59a7cc
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-atmel-mci-force-detect.patch
@@ -0,0 +1,30 @@
+Index: linux-2.6.39.4/drivers/mmc/host/atmel-mci.c
+===================================================================
+--- linux-2.6.39.4.orig/drivers/mmc/host/atmel-mci.c 2012-05-10 11:44:02.069173755 -0500
++++ linux-2.6.39.4/drivers/mmc/host/atmel-mci.c 2012-05-11 11:21:42.119198300 -0500
+@@ -1059,6 +1059,10 @@
+ dev_dbg(&mmc->class_dev, "card is %spresent\n",
+ present ? "" : "not ");
+ }
++ else {
++ // jjg - assume card is present if detect pin is unset
++ present = 1;
++ }
+
+ return present;
+ }
+@@ -1655,8 +1659,12 @@
+ }
+ }
+
+- if (!gpio_is_valid(slot->detect_pin))
+- mmc->caps |= MMC_CAP_NEEDS_POLL;
++ // jjg - if detect pin isn't set, don't poll -- just assume device
++ // is there and mark it non-removable
++ if (!gpio_is_valid(slot->detect_pin)) {
++ dev_info(&host->pdev->dev,"No detect pin, marking non-removable and assuming device is present\n");
++ mmc->caps |= MMC_CAP_NONREMOVABLE;
++ }
+
+ if (gpio_is_valid(slot->wp_pin)) {
+ if (gpio_request(slot->wp_pin, "mmc_wp")) {
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-atmel-mci-module-alias.patch b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-atmel-mci-module-alias.patch
new file mode 100644
index 0000000..8081bb9
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-atmel-mci-module-alias.patch
@@ -0,0 +1,9 @@
+Index: linux-2.6.39.4/drivers/mmc/host/atmel-mci.c
+===================================================================
+--- linux-2.6.39.4.orig/drivers/mmc/host/atmel-mci.c 2013-03-08 10:25:21.024073265 -0600
++++ linux-2.6.39.4/drivers/mmc/host/atmel-mci.c 2013-03-08 10:25:25.523819243 -0600
+@@ -1973,3 +1973,4 @@
+ MODULE_DESCRIPTION("Atmel Multimedia Card Interface driver");
+ MODULE_AUTHOR("Haavard Skinnemoen <haavard.skinnemoen@atmel.com>");
+ MODULE_LICENSE("GPL v2");
++MODULE_ALIAS("platform:atmel_mci");
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-cdc-acm-ignore-exar-devices.patch b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-cdc-acm-ignore-exar-devices.patch
new file mode 100644
index 0000000..5f9d8f7
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-cdc-acm-ignore-exar-devices.patch
@@ -0,0 +1,45 @@
+Index: linux-2.6.39.4/drivers/usb/class/cdc-acm.c
+===================================================================
+--- linux-2.6.39.4.orig/drivers/usb/class/cdc-acm.c 2013-02-19 09:22:57.860051682 -0600
++++ linux-2.6.39.4/drivers/usb/class/cdc-acm.c 2013-02-19 09:30:35.274209660 -0600
+@@ -963,6 +963,12 @@
+ goto skip_normal_probe;
+ }
+
++ /* ignore devices we don't want to support */
++ if (quirks == IGNORE_DEVICE) {
++ dev_dbg(&intf->dev, "Ignoring device\n");
++ return -ENODEV;
++ }
++
+ /* normal probing*/
+ if (!buffer) {
+ dev_err(&intf->dev, "Weird descriptor references\n");
+@@ -1633,6 +1639,18 @@
+ .driver_info = NO_DATA_INTERFACE,
+ },
+
++ /* Ignore Exar XR21V141X usb serial chips
++ * This elminates conflicting with the Exar vizzini driver */
++ { USB_DEVICE(0x04e2, 0x1410),
++ .driver_info = IGNORE_DEVICE,
++ },
++ { USB_DEVICE(0x04e2, 0x1412),
++ .driver_info = IGNORE_DEVICE,
++ },
++ { USB_DEVICE(0x04e2, 0x1414),
++ .driver_info = IGNORE_DEVICE,
++ },
++
+ /* control interfaces without any protocol set */
+ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
+ USB_CDC_PROTO_NONE) },
+Index: linux-2.6.39.4/drivers/usb/class/cdc-acm.h
+===================================================================
+--- linux-2.6.39.4.orig/drivers/usb/class/cdc-acm.h 2013-02-19 09:22:54.860050647 -0600
++++ linux-2.6.39.4/drivers/usb/class/cdc-acm.h 2013-02-19 09:24:00.856126438 -0600
+@@ -138,3 +138,4 @@
+ #define NO_CAP_LINE 4
+ #define NOT_A_MODEM 8
+ #define NO_DATA_INTERFACE 16
++#define IGNORE_DEVICE 32
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-macb-force-link.patch b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-macb-force-link.patch
new file mode 100644
index 0000000..2ef39a9
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-macb-force-link.patch
@@ -0,0 +1,87 @@
+Index: linux-2.6.39.4/drivers/net/macb.c
+===================================================================
+--- linux-2.6.39.4.orig/drivers/net/macb.c 2011-08-03 14:43:28.000000000 -0500
++++ linux-2.6.39.4/drivers/net/macb.c 2013-03-12 15:31:34.710687318 -0500
+@@ -193,7 +193,9 @@
+ struct eth_platform_data *pdata;
+ int ret;
+
+- phydev = phy_find_first(bp->mii_bus);
++ // MTR2: use phy 5
++ //phydev = phy_find_first(bp->mii_bus);
++ phydev = bp->mii_bus->phy_map[5];
+ if (!phydev) {
+ printk (KERN_ERR "%s: no PHY found\n", dev->name);
+ return -1;
+@@ -203,14 +205,19 @@
+ /* TODO : add pin_irq */
+
+ /* attach the mac to the phy */
+- ret = phy_connect_direct(dev, phydev, &macb_handle_link_change, 0,
++ // MTR2: attach directly to phy and set link state ourselves
++ //ret = phy_connect_direct(dev, phydev, &macb_handle_link_change, 0,
++ phy_attach(dev, dev_name(&phydev->dev), 0,
+ pdata && pdata->is_rmii ?
+ PHY_INTERFACE_MODE_RMII :
+ PHY_INTERFACE_MODE_MII);
++
++ /*
+ if (ret) {
+ printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+ return ret;
+ }
++ */
+
+ /* mask with MAC supported features */
+ phydev->supported &= PHY_BASIC_FEATURES;
+@@ -942,6 +949,7 @@
+ {
+ struct macb *bp = netdev_priv(dev);
+ int err;
++ unsigned long flags;
+
+ dev_dbg(&bp->pdev->dev, "open\n");
+
+@@ -966,8 +974,19 @@
+ macb_init_hw(bp);
+
+ /* schedule a link state check */
+- phy_start(bp->phy_dev);
++ // MTR2: disable link updates
++ //phy_start(bp->phy_dev);
++
++ // MTR2: force link up, 100MB, full duplex
++ printk(KERN_INFO "macb: forcing link to 100, full\n");
++ bp->phy_dev->link = 1;
++ bp->phy_dev->speed = SPEED_100;
++ bp->phy_dev->duplex = 1;
++ macb_handle_link_change(bp->dev);
+
++ spin_lock_irqsave(&bp->lock, flags);
++ netif_carrier_on(dev);
++ spin_unlock_irqrestore(&bp->lock, flags);
+ netif_start_queue(dev);
+
+ return 0;
+@@ -981,8 +1000,19 @@
+ netif_stop_queue(dev);
+ napi_disable(&bp->napi);
+
+- if (bp->phy_dev)
+- phy_stop(bp->phy_dev);
++ // MTR2: disabled since we didn't call phy_start
++ //if (bp->phy_dev)
++ // phy_stop(bp->phy_dev);
++
++ // MTR2: set link down manually
++ if (bp->phy_dev) {
++ printk(KERN_INFO "macb: forcing link down\n");
++ bp->phy_dev->link = 0;
++ bp->phy_dev->speed = 0;
++ bp->phy_dev->duplex = -1;
++ }
++
++ macb_handle_link_change(bp->dev);
+
+ spin_lock_irqsave(&bp->lock, flags);
+ macb_reset_hw(bp);
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-mach-at91-mtocgd3.patch b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-mach-at91-mtocgd3.patch
new file mode 100644
index 0000000..6fd737b
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-mach-at91-mtocgd3.patch
@@ -0,0 +1,425 @@
+Index: linux-2.6.39.4/arch/arm/mach-at91/board-sam9x5cm.c
+===================================================================
+--- linux-2.6.39.4.orig/arch/arm/mach-at91/board-sam9x5cm.c 2013-03-07 17:07:04.793136604 -0600
++++ linux-2.6.39.4/arch/arm/mach-at91/board-sam9x5cm.c 2013-03-07 17:07:04.793136604 -0600
+@@ -18,6 +18,9 @@
+ #include <linux/platform_device.h>
+ #include <linux/spi/flash.h>
+ #include <linux/spi/spi.h>
++#include <linux/spi/eeprom.h>
++#include <linux/i2c/at24.h>
++#include <linux/delay.h>
+ #include <linux/fb.h>
+ #include <linux/gpio_keys.h>
+ #include <linux/input.h>
+@@ -103,6 +106,11 @@
+ .irq = -1,
+ },
+ #endif
++ {
++ .modalias = "mts-io-board-temp",
++ .chip_select = 1,
++ .bus_num = 1,
++ },
+ #endif
+ };
+
+@@ -111,13 +119,48 @@
+ */
+ static struct mtd_partition __initdata cm_nand_partition[] = {
+ {
+- .name = "Partition 1",
++ .name = "NANDFlash",
++ .offset = 0,
++ .size = 256*1024*1024,
++ },
++ {
++ .name = "AT91Bootstrap",
+ .offset = 0,
+- .size = SZ_64M,
++ .size = 256*1024,
++ },
++ {
++ .name = "UBoot",
++ .offset = 256*1024,
++ .size = 512*1024,
++ },
++ {
++ .name = "UBoot Config",
++ .offset = 768*1024,
++ .size = 640*1024,
++ },
++ {
++ .name = "UBoot Redundant Config",
++ .offset = 1408*1024,
++ .size = 640*1024,
+ },
+ {
+- .name = "Partition 2",
+- .offset = MTDPART_OFS_NXTBLK,
++ .name = "uImage",
++ .offset = 2*1024*1024,
++ .size = 6*1024*1024,
++ },
++ {
++ .name = "Config",
++ .offset = 8*1024*1024,
++ .size = 8*1024*1024,
++ },
++ {
++ .name = "Oem Config",
++ .offset = 16*1024*1024,
++ .size = 8*1024*1024,
++ },
++ {
++ .name = "Rootfs",
++ .offset = 24*1024*1024,
+ .size = MTDPART_SIZ_FULL,
+ },
+ };
+@@ -135,7 +178,8 @@
+ .enable_pin = AT91_PIN_PD4,
+ .ecc_mode = NAND_ECC_HW,
+ .has_pmecc = 1,
+- .pmecc_corr_cap = 2,
++// MTOCGD3: 4-bit PMECC
++ .pmecc_corr_cap = 4,
+ .pmecc_sector_size = 512,
+ .pmecc_lookup_table_offset = 0x8000,
+ .partition_info = nand_partitions,
+@@ -170,7 +214,13 @@
+ else
+ cm_nand_smc_config.mode |= AT91_SMC_DBW_8;
+
++ // MTOCGD3 Rev A
++ cm_nand_data.bus_on_d0 = 1;
++ cm_nand_data.rdy_pin = AT91_PIN_PC31;
++
++ // MTOCGD3: disable
+ /* revision of board modify NAND wiring */
++ /*
+ if (cm_is_revA()) {
+ cm_nand_data.bus_on_d0 = 1;
+ cm_nand_data.rdy_pin = AT91_PIN_PD6;
+@@ -178,6 +228,7 @@
+ cm_nand_data.bus_on_d0 = 0;
+ cm_nand_data.rdy_pin = AT91_PIN_PD5;
+ }
++ */
+
+ /* configure chip-select 3 (NAND) */
+ sam9_smc_configure(3, &cm_nand_smc_config);
+@@ -189,25 +240,71 @@
+ * LEDs
+ */
+ static struct gpio_led cm_leds[] = {
+- { /* "left" led, blue, userled1 */
+- .name = "d1",
+- .gpio = AT91_PIN_PB18,
++ { /* default status LED */
++ .name = "led-a",
++ .gpio = AT91_PIN_PA24,
++ .active_low = 1,
+ .default_trigger = "heartbeat",
+ },
+- { /* "right" led, red, userled2 */
+- .name = "d2",
+- .gpio = AT91_PIN_PD21,
+- .active_low = 1,
+- .default_trigger = "mmc0",
++ {
++ .name = "led-b",
++ .gpio = AT91_PIN_PA29,
++ .active_low = 1
++ },
++ {
++ .name = "led-c",
++ .gpio = AT91_PIN_PA25,
++ .active_low = 1
++ },
++ {
++ .name = "led-d",
++ .gpio = AT91_PIN_PA26,
++ .active_low = 1
++ },
++ {
++ .name = "led-e",
++ .gpio = AT91_PIN_PA27,
++ .active_low = 1
++ },
++ {
++ .name = "led-f",
++ .gpio = AT91_PIN_PA28,
++ .active_low = 1
+ },
+ };
+
++
++uint8_t mts_id_eeprom[512];
++
++EXPORT_SYMBOL(mts_id_eeprom);
++
++static void mts_id_eeprom_load(struct memory_accessor *macc, void *context)
++{
++ int tmp;
++
++ memset(mts_id_eeprom, 0, sizeof(mts_id_eeprom));
++
++ tmp = macc->read(macc, mts_id_eeprom, 0, sizeof(mts_id_eeprom));
++ if (tmp != sizeof(mts_id_eeprom)) {
++ printk(KERN_ERR "sam9x5: id eeprom read failed: %d\n", tmp);
++ } else {
++ printk(KERN_INFO "sam9x5: read %d bytes from id eeprom\n", tmp);
++ }
++}
++
++static struct at24_platform_data at24c04_data = {
++ .byte_len = SZ_4K / 8,
++ .page_size = 16,
++ .setup = mts_id_eeprom_load,
++};
++
+ /*
+ * I2C Devices
+ */
+ static struct i2c_board_info __initdata cm_i2c_devices[] = {
+ {
+- I2C_BOARD_INFO("24c512", 0x50)
++ I2C_BOARD_INFO("24c04", 0x56),
++ .platform_data = &at24c04_data,
+ },
+ };
+
+@@ -234,8 +331,12 @@
+ /* LEDs */
+ at91_gpio_leds(cm_leds, ARRAY_SIZE(cm_leds));
+
++ printk(KERN_CRIT "AT91: MTOCGD3 board\n");
++
++ /* MTOCGD3: disable
+ if (cm_is_revA())
+ printk(KERN_CRIT "AT91: CM rev A\n");
+ else
+ printk(KERN_CRIT "AT91: CM rev B and higher\n");
++ */
+ }
+Index: linux-2.6.39.4/arch/arm/mach-at91/board-sam9x5ek.c
+===================================================================
+--- linux-2.6.39.4.orig/arch/arm/mach-at91/board-sam9x5ek.c 2013-03-07 17:07:03.293174822 -0600
++++ linux-2.6.39.4/arch/arm/mach-at91/board-sam9x5ek.c 2013-03-08 10:11:42.653155621 -0600
+@@ -23,6 +23,7 @@
+ #include <linux/leds.h>
+ #include <linux/clk.h>
+ #include <linux/delay.h>
++#include <linux/wl12xx.h>
+ #include <mach/cpu.h>
+
+ #include <video/atmel_lcdfb.h>
+@@ -53,12 +54,10 @@
+ /* Initialize processor and DBGU */
+ cm_map_io();
+
+- /* USART0 on ttyS1. (Rx, Tx) */
+- at91_register_uart(AT91SAM9X5_ID_USART0, 1, 0);
+- /* USART1 on ttyS2. (Rx, Tx) */
+- at91_register_uart(AT91SAM9X5_ID_USART1, 2, 0);
+- /* USART2 on ttyS3. (Rx, Tx) */
+- at91_register_uart(AT91SAM9X5_ID_USART2, 3, 0);
++ // MTOCGD3: GPS on UART0 as ttyS1 with Rx/Tx only
++ at91_register_uart(AT91SAM9X5_ID_UART0, 1, 0);
++ // MTOCGD3 Rev A: Daughter card serial on USART1 as ttyS2 with RTS/CTS
++ at91_register_uart(AT91SAM9X5_ID_USART1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS);
+ }
+
+ /*
+@@ -89,34 +88,65 @@
+ * MACB Ethernet devices
+ */
+ static struct at91_eth_data __initdata ek_macb0_data = {
+- .is_rmii = 1,
++ .is_rmii = 0,
++ .phy_irq_pin = 0,
+ };
+
++/* MTOCGD3: no macb1
+ static struct at91_eth_data __initdata ek_macb1_data = {
+ .phy_irq_pin = AT91_PIN_PC26,
+ .is_rmii = 1,
+ };
++*/
+
+
+ /*
+ * MCI (SD/MMC)
+ */
+-/* mci0 detect_pin is revision dependent */
++// MTOCGD3: MCI0 is BT/Wifi
+ static struct mci_platform_data __initdata mci0_data = {
+ .slot[0] = {
+ .bus_width = 4,
++ .detect_pin = -1,
+ .wp_pin = -1,
+ },
+ };
+
++// MTOCGD3: MCI1 is SD card slot
+ static struct mci_platform_data __initdata mci1_data = {
+ .slot[0] = {
+ .bus_width = 4,
+- .detect_pin = AT91_PIN_PD14,
+- .wp_pin = -1,
++ .detect_pin = AT91_PIN_PA1,
++ .wp_pin = AT91_PIN_PA0,
+ },
+ };
+
++// MTR: Wi-fi
++static void wl12xx_enable(int poweron)
++{
++ if (poweron) {
++ at91_set_gpio_output_with_pullup(AT91_PIN_PC1, 0, 0);
++ msleep(10);
++ at91_set_gpio_output_with_pullup(AT91_PIN_PC1, 1, 0);
++ msleep(100);
++ printk(KERN_INFO "sam9x5: WLAN Enabled\n");
++ }
++ else {
++ at91_set_gpio_output_with_pullup(AT91_PIN_PC1, 0, 0);
++ msleep(10);
++ printk(KERN_INFO "sam9x5: WLAN Disabled\n");
++ }
++};
++
++// MTR: Wi-fi
++struct wl12xx_platform_data mtr_wlan_data __initdata = {
++ .irq = AT91_PIN_PC2,
++ /* ref clock is 38.4 MHz */
++ .board_ref_clock = WL12XX_REFCLOCK_38,
++ /* toggles the WLAN_ENABLE pin */
++ .set_power = wl12xx_enable,
++};
++
+ /*
+ * ISI
+ */
+@@ -326,9 +356,11 @@
+ * I2C Devices
+ */
+ static struct i2c_board_info __initdata ek_i2c_devices[] = {
++#if 0
+ {
+ I2C_BOARD_INFO("wm8731", 0x1a)
+ },
++#endif
+ #if defined(CONFIG_KEYBOARD_QT1070)
+ {
+ I2C_BOARD_INFO("qt1070", 0x1b),
+@@ -384,18 +416,24 @@
+ bool config_isi_enabled = false;
+
+ cm_board_init(&cm_config);
+- ek_board_configure_pins();
++ // MTOCGD3: disable
++ //ek_board_configure_pins();
+ /* Serial */
+ at91_add_device_serial();
+ /* USB HS Host */
+ at91_add_device_usbh_ohci(&ek_usbh_fs_data);
+ at91_add_device_usbh_ehci(&ek_usbh_hs_data);
+ /* USB HS Device */
++ // MTOCGD3: set usb device vcc pin
++ ek_usba_udc_data.vbus_pin = AT91_PIN_PC7;
+ at91_add_device_usba(&ek_usba_udc_data);
+ /* Ethernet */
+ at91_add_device_eth(0, &ek_macb0_data);
++ /* MTOCGD3: no macb1
+ at91_add_device_eth(1, &ek_macb1_data);
++ */
+ /* MMC0 */
++ // MTOCGD3: MCI0 for BT/Wifi
+ at91_add_device_mci(0, &mci0_data);
+ /* I2C */
+ if (cm_config & CM_CONFIG_I2C0_ENABLE)
+@@ -405,6 +443,18 @@
+ at91_add_device_i2c(0,
+ ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices));
+
++ // MTOCGD3: Wi-fi
++ at91_set_gpio_input(mtr_wlan_data.irq, 0);
++ at91_set_deglitch(mtr_wlan_data.irq, 1);
++
++ if (wl12xx_set_platform_data(&mtr_wlan_data))
++ pr_err("error setting wl12xx data\n");
++
++ // MTOCGD3: enable wl1271 chip so it is detected by SDIO scan on start up
++ wl12xx_enable(1);
++
++/* MTOCGD3: no LCD */
++#if 0
+ if (cpu_is_at91sam9g25()) {
+ /* ISI */
+ /* NOTE: PCK0 provides ISI_MCK to the ISI module.
+@@ -430,13 +480,10 @@
+ /* Touch Screen */
+ at91_add_device_tsadcc(&ek_tsadcc_data);
+ }
++#endif
+
+- /* MMC1 */
+- /* Conflict between SPI0, MCI1 and ISI pins.
+- * add MCI1 only if SPI0 and ISI are both disabled.
+- */
+- if (!(cm_config & CM_CONFIG_SPI0_ENABLE) && !config_isi_enabled)
+- at91_add_device_mci(1, &mci1_data);
++ // MTOCGD3: MCI1 to SD Card
++ at91_add_device_mci(1, &mci1_data);
+
+ #if 0
+ if (cpu_is_at91sam9x25() || cpu_is_at91sam9x35())
+@@ -448,6 +495,8 @@
+ at91_add_device_can(0, NULL);
+ #endif
+
++/* MTOCGD3: disable things we don't have */
++#if 0
+ if (cpu_is_at91sam9x25() || cpu_is_at91sam9x35())
+ /* this conflicts with usart.1 */
+ at91_add_device_can(1, NULL);
+@@ -474,6 +523,9 @@
+ else if (config_isi_enabled)
+ printk(KERN_CRIT
+ "AT91: ISI conficts with MCI1, disable MCI1\n");
++#endif
++
++ printk(KERN_CRIT "AT91: MTOCGD3 board EK init\n");
+ }
+
+ MACHINE_START(AT91SAM9X5EK, "Atmel AT91SAM9X5-EK")
+Index: linux-2.6.39.4/arch/arm/mach-at91/at91sam9x5_devices.c
+===================================================================
+--- linux-2.6.39.4.orig/arch/arm/mach-at91/at91sam9x5_devices.c 2013-03-07 17:07:03.793204785 -0600
++++ linux-2.6.39.4/arch/arm/mach-at91/at91sam9x5_devices.c 2013-03-07 17:07:04.793136604 -0600
+@@ -543,11 +543,11 @@
+ #endif
+
+ /* input/irq */
+- if (data->slot[0].detect_pin) {
++ if (data->slot[0].detect_pin > 0) {
+ at91_set_gpio_input(data->slot[0].detect_pin, 1);
+ at91_set_deglitch(data->slot[0].detect_pin, 1);
+ }
+- if (data->slot[0].wp_pin)
++ if (data->slot[0].wp_pin > 0)
+ at91_set_gpio_input(data->slot[0].wp_pin, 1);
+
+ if (mmc_id == 0) { /* MCI0 */
+@@ -849,7 +849,8 @@
+ .num_resources = ARRAY_SIZE(spi1_resources),
+ };
+
+-static const unsigned spi1_standard_cs[4] = { AT91_PIN_PA8, AT91_PIN_PA0, AT91_PIN_PA31, AT91_PIN_PA30 };
++// MTOCGD3: SPI1 chip selects on pins SPI1_NCS1 to SPI1_NCS5
++static const unsigned spi1_standard_cs[5] = { AT91_PIN_PC15, AT91_PIN_PC16, AT91_PIN_PC17, AT91_PIN_PC18, AT91_PIN_PC19 };
+
+ void __init at91_add_device_spi(struct spi_board_info *devices, int nr_devices)
+ {
diff --git a/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-wl12xx-sdio-irq.patch b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-wl12xx-sdio-irq.patch
new file mode 100644
index 0000000..6c1abcd
--- /dev/null
+++ b/multitech/recipes/linux/linux-2.6.39-at91/mtocgd3/linux-2.6.39.4-wl12xx-sdio-irq.patch
@@ -0,0 +1,15 @@
+Index: linux-2.6.39.4/drivers/net/wireless/wl12xx/sdio.c
+===================================================================
+--- linux-2.6.39.4.orig/drivers/net/wireless/wl12xx/sdio.c 2012-05-10 11:49:16.349486059 -0500
++++ linux-2.6.39.4/drivers/net/wireless/wl12xx/sdio.c 2012-05-10 16:36:15.009543390 -0500
+@@ -241,7 +242,9 @@
+ wl->ref_clock = wlan_data->board_ref_clock;
+
+ ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq,
+- IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
++// MTR: use rising edge interrupts, level doesn't work
++// IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
++ IRQF_TRIGGER_RISING,
+ DRIVER_NAME, wl);
+ if (ret < 0) {
+ wl1271_error("request_irq() failed: %d", ret);
diff --git a/multitech/recipes/linux/linux_2.6.39-at91.bb b/multitech/recipes/linux/linux_2.6.39-at91.bb
new file mode 100644
index 0000000..dc1e89f
--- /dev/null
+++ b/multitech/recipes/linux/linux_2.6.39-at91.bb
@@ -0,0 +1,39 @@
+require recipes/linux/linux.inc
+
+# PR is set by MACHINE_KERNEL_PR in machine config
+
+# Linux 2.6.39 for AT91
+# commit Mar 17, 2013 - Serial: 9n12: Enable dbgu dma transfer
+SRCREV="0fdbb8dc2ea4f6f4227a855067ed070fe3a9cff1"
+
+# Add 2.6.39.4 patch customized to patch against at91 branch
+SRC_URI = "git://github.com/linux4sam/linux-at91.git;protocol=http;tag=${SRCREV} \
+ file://linux-2.6.39.4-at91.patch"
+
+S = "${WORKDIR}/git"
+
+SRC_URI_append_mtocgd3 = " \
+ file://defconfig \
+ file://linux-2.6.39.4-mach-at91-mtocgd3.patch \
+ file://linux-2.6.39.4-macb-force-link.patch \
+ file://linux-2.6.39.4-ledtrig-netdev.patch \
+ file://linux-2.6.39.4-at91sam9x5-extreset.patch \
+ file://linux-2.6.39.4-atmel-mci-force-detect.patch \
+ file://linux-2.6.39.4-atmel-mci-module-alias.patch \
+ file://linux-2.6.39.4-wl12xx-sdio-irq.patch \
+ file://linux-2.6.35.14-at91-gpio-pullup.patch \
+ file://linux-2.6.32.3-atmel_spi.patch \
+ file://linux-2.6.32.3-at25.patch \
+ file://linux-2.6.39.4-atmel_serial_disable_hwhs.patch \
+ file://linux-2.6.39.4-at91sam9_wdt-10second-timeout.patch \
+ file://linux-2.6.35.14-option-zte.patch \
+ file://linux-2.6.39.4-option-telit.patch \
+ file://linux-2.6.38-sierra-1.7.40.patch \
+ file://linux-2.6.39.4-cdc-acm-ignore-exar-devices.patch \
+ "
+
+# add missing crypto headers
+sysroot_stage_all_append() {
+ kerneldir=${SYSROOT_DESTDIR}${STAGING_KERNEL_DIR}
+ cp -fR include/crypto* $kerneldir/include/
+}