summaryrefslogtreecommitdiff
path: root/multitech/recipes/linux
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 /multitech/recipes/linux
parentf547c4161d0e058326b2341519029fbebc739dce (diff)
linux: add 2.6.39-at91 recipe using Atmel github branch
Diffstat (limited to 'multitech/recipes/linux')
-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 */