Netdev List
 help / color / mirror / Atom feed
* Re: [RFC PATCH] gianfar: fix undo of reserve()
From: David Miller @ 2010-03-27  3:16 UTC (permalink / raw)
  To: ben; +Cc: netdev
In-Reply-To: <A6A1774AFD79E346AE6D49A33CB294530DC19FC4@EX-BE-017-SFO.shared.themessagecenter.com>

From: "Ben Menchaca (ben@bigfootnetworks.com)" <ben@bigfootnetworks.com>
Date: Wed, 24 Mar 2010 08:05:02 -0700

> From: Ben Menchaca <ben@bigfootnetworks.com>
> 
> Fix undo of reserve() before RX recycle
> 
> gfar_new_skb reserve()s space in the SKB to align it.  If an error occurs,
> and the skb needs to be returned to the RX recycle queue, the current code
> attempts to reset head, but did not reset tail.  This patch remembers the
> alignment amount, and reverses the reserve() when needed.
> 
> Signed-off-by: Ben Menchaca <ben@bigfootnetworks.com>

Applied, thanks.

^ permalink raw reply

* Re: [PATCH] netlink: use the appropriate namespace pid
From: David Miller @ 2010-03-27  3:15 UTC (permalink / raw)
  To: Thomas.Goff; +Cc: adobriyan, netdev, adobriyan
In-Reply-To: <6AFD35BEDB60334C9A31FD694E13EF0D226771E62E@XCH-NW-18V.nw.nos.boeing.com>

From: "Goff, Thomas" <Thomas.Goff@boeing.com>
Date: Wed, 24 Mar 2010 07:18:12 -0700

> On Wed March 24, 2010 12:59 AM, Alexey Dobriyan <adobriyan@gmail.com> wrote:
>> ACK tgid patch, should have sent it myself long ago.
> 
> Thanks for reviewing this.
> 
> David is correct that pid is arbitrary here anyway so it really
> shouldn't matter.  The patch just lets applications that make an
> incorrect assumption that happens to usually be right for the
> initial namespace work similarly in other namespaces.  So
> including the patch seems more of a policy question.

I ended up applying this to net-next-2.6, it's not critical
so it's not net-2.6 material, but it's harmless so we can
still queue it up for the next merge window.

^ permalink raw reply

* Re: [PATCH] netlink: use the appropriate namespace pid
From: David Miller @ 2010-03-27  3:14 UTC (permalink / raw)
  To: adobriyan; +Cc: thomas.goff, netdev, adobriyan
In-Reply-To: <b6fcc0a1003240119h7c26d649taa1f947c2aeb6064@mail.gmail.com>

From: Alexey Dobriyan <adobriyan@gmail.com>
Date: Wed, 24 Mar 2010 10:19:37 +0200

>>> Alexey, can you review Tom's namespace patches in this
>>> set?
> 
> re netns sched patch:
> 
> * in psched_open() PDE(inode)->data isn't needed because
>   it isn't used -- just pass NULL.
> * drop useless trailing return; in psched_net_exit() :^)
> * sch_mirred.c still won't work in netns

Tom, please send a patch to fixup these issues.

Thanks.

^ permalink raw reply

* Re: [PATCH 2/2] ixgbevf: convert to use netdev_for_each_mc_addr
From: David Miller @ 2010-03-27  3:10 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, jpirko
In-Reply-To: <20100324085819.32706.384.stgit@localhost.localdomain>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Wed, 24 Mar 2010 01:58:20 -0700

> From: Jiri Pirko <jpirko@redhat.com>
> 
> Signed-off-by: Jiri Pirko <jpirko@redhat.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.

^ permalink raw reply

* Re: [PATCH 1/2] ixgbe: convert to use netdev_for_each_mc_addr
From: David Miller @ 2010-03-27  3:10 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, jpirko
In-Reply-To: <20100324085733.32706.70587.stgit@localhost.localdomain>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Wed, 24 Mar 2010 01:58:01 -0700

> From: Jiri Pirko <jpirko@redhat.com>
> 
> Signed-off-by: Jiri Pirko <jpirko@redhat.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.

^ permalink raw reply

* [PATCH 6/9] drivers/net: Fix continuation lines
From: Joe Perches @ 2010-03-27  2:27 UTC (permalink / raw)
  To: linux-kernel; +Cc: Jay Cliburn, Chris Snook, Jie Yang, atl1-devel, netdev
In-Reply-To: <cover.1269655208.git.joe@perches.com>

Signed-off-by: Joe Perches <joe@perches.com>
---
 drivers/net/atlx/atl1.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c
index 9ba5470..0ebd820 100644
--- a/drivers/net/atlx/atl1.c
+++ b/drivers/net/atlx/atl1.c
@@ -84,7 +84,7 @@
 
 #define ATLX_DRIVER_VERSION "2.1.3"
 MODULE_AUTHOR("Xiong Huang <xiong.huang@atheros.com>, \
-	Chris Snook <csnook@redhat.com>, Jay Cliburn <jcliburn@gmail.com>");
+Chris Snook <csnook@redhat.com>, Jay Cliburn <jcliburn@gmail.com>");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(ATLX_DRIVER_VERSION);
 
-- 
1.7.0.14.g7e948

^ permalink raw reply related

* [PATCH v2] Add MSG_WAITFORONE flag to recvmmsg
From: Brandon L Black @ 2010-03-27  2:18 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Arnaldo Carvalho de Melo, Ulrich Drepper,
	linux-kernel
In-Reply-To: <a36005b51003261907x7ebe057bt2d541f63f20f632b@mail.gmail.com>


From: Brandon L Black <blblack@gmail.com>

Add new flag MSG_WAITFORONE for the recvmmsg() syscall.
When this flag is specified for a blocking socket, recvmmsg()
will only block until at least 1 packet is available.  The
default behavior is to block until all vlen packets are
available.  This flag has no effect on non-blocking sockets
or when used in combination with MSG_DONTWAIT.

Signed-off-by: Brandon L Black <blblack@gmail.com>

---
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 7b3aae2..354cc56 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -255,6 +255,7 @@ struct ucred {
 #define MSG_ERRQUEUE	0x2000	/* Fetch message from error queue */
 #define MSG_NOSIGNAL	0x4000	/* Do not generate SIGPIPE */
 #define MSG_MORE	0x8000	/* Sender will send more */
+#define MSG_WAITFORONE	0x10000	/* recvmmsg(): block until 1+ packets avail */
 
 #define MSG_EOF         MSG_FIN
 
diff --git a/net/socket.c b/net/socket.c
index 769c386..f55ffe9 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2135,6 +2135,10 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
 			break;
 		++datagrams;
 
+		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
+		if (flags & MSG_WAITFORONE)
+			flags |= MSG_DONTWAIT;
+
 		if (timeout) {
 			ktime_get_ts(timeout);
 			*timeout = timespec_sub(end_time, *timeout);

^ permalink raw reply related

* Re: [PATCH] Add MSG_WAITFORONE flag to recvmmsg
From: Ulrich Drepper @ 2010-03-27  2:07 UTC (permalink / raw)
  To: Brandon Black
  Cc: Eric Dumazet, netdev, David S. Miller, Arnaldo Carvalho de Melo,
	linux-kernel
In-Reply-To: <84621a61003261555q2c78f6a8o5b438113bed6bd2@mail.gmail.com>

On Fri, Mar 26, 2010 at 15:55, Brandon Black <blblack@gmail.com> wrote:
> Ok.  I've never been through this process before.  Do I resubmit a new
> subject/thread with the changed patch and [PATCH v2] at this point?

The patch is small enough for this to be OK.

^ permalink raw reply

* Re: [Regression] r8169: enable 64-bit DMA by default for PCI Express devices (v2)
From: Robert Hancock @ 2010-03-27  1:55 UTC (permalink / raw)
  To: � Engel; +Cc: David Miller, torvalds, linux-kernel, netdev, romieu
In-Reply-To: <20100326091234.GA11959@Dublin.logfs.org>

On 03/26/2010 03:12 AM, � Engel wrote:
> On Thu, 25 March 2010 18:56:03 -0600, Robert Hancock wrote:
>>
>> Francois, ping? Is there anyone else that has access to this kind of
>> information about these chips?
>>
>> It's kind of interesting that there's only been one report of this
>> though. Either the affected chips are rare among people testing
>> 2.6.34-rc or there's something more to this. Maybe something
>> wierd/unusual about Jörn's system?
>>
>> Jörn, are any other devices on your system working with 64-bit
>> addressing? Try doing this:
>>
>> find /sys -name "*dma_mask_bits*" | xargs cat
>>
>> Does anything show more than 32?
>
> I've slightly changed the command:
> # for i in `find /sys -name "*dma_mask_bits*"`; do echo -n "$i: "; cat $i; done
> /sys/devices/pci0000:00/0000:00:00.0/dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:00.0/consistent_dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:02.0/dma_mask_bits: 36
> /sys/devices/pci0000:00/0000:00:02.0/consistent_dma_mask_bits: 36
> /sys/devices/pci0000:00/0000:00:1c.0/dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1c.0/consistent_dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1c.1/dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1c.1/consistent_dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1c.1/0000:01:00.0/dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1c.1/0000:01:00.0/consistent_dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1d.0/dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1d.0/consistent_dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1d.1/dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1d.1/consistent_dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1d.2/dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1d.2/consistent_dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1d.3/dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1d.3/consistent_dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1d.7/dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1d.7/consistent_dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1e.0/dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1e.0/consistent_dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1f.0/dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1f.0/consistent_dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1f.1/dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1f.1/consistent_dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1f.2/dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1f.2/consistent_dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1f.3/dma_mask_bits: 32
> /sys/devices/pci0000:00/0000:00:1f.3/consistent_dma_mask_bits: 32
>
> One device, which should be this one:
> 00:02.0 VGA compatible controller: Intel Corporation 82G33/G31 Express Integrated Graphics Controller (rev 10)

Well, that one's 36 bits, but it's unclear whether that driver would 
actually be likely to access anything over 4GB. It's possible that 
there's just some general problem with 64-bit DMA on that machine.

The fact that even stuff like lspci and MII is breaking seems odd, 
though. It could be that model of card doesn't like the PCIDAC register 
bit being set (maybe it means something different on that model, or 
something).

I suppose a publicly accessible datasheet for these chips is too much to 
hope for?

^ permalink raw reply

* [ANNOUNCEMENT] NET: usb: sierra_net.c driver
From: Elina Pasheva @ 2010-03-27  1:21 UTC (permalink / raw)
  To: David Brownell
  Cc: Rory Filer, epasheva-ywE8TTl5eJHWpu6QEFMNjNBPR1lH4CV8,
	netdev-u79uwXL29TY76Z2rM5mHXA, linux-usb

Subject: [ANNOUNCEMENT] NET: usb: sierra_net.c driver
From: Elina Pasheva <epasheva-ywE8TTl5eJHWpu6QEFMNjNBPR1lH4CV8@public.gmane.org>

The following is a new Linux driver which exposes certain models of Sierra
Wireless modems to the operating system as Network Interface Cards (NICs).

This driver requires a version of the sierra.c driver which supports
blacklisting to work properly. The blacklist in sierra.c rejects the interfaces
claimed by sierra_net.c. Likewise, the sierra_net.c driver only accepts
(i.e. whitelists) the interface(s) used for Direct IP traffic.
The term "Direct IP" is used within Sierra Wireless to refer to these alternate
data interfaces. The version of sierra.c which supports blacklisting is
available from the sierra wireless knowledge base page for older kernels. It is
also available in Linux kernel starting from version 2.6.31.

This driver works with all Sierra Wireless devices configured with PID=68A3
like USB305, USB306 provided the corresponding firmware version is I2.0
(for USB305) or M3.0 (for USB306) and later.
This driver will not work with earlier firmware versions than the ones shown
above. In this case the driver will issue an error message indicating 
incompatibility and will not serve the device's DirectIP interface.

Sierra_net.c sits atop a pre-existing Linux driver called usbnet.c.
A series of hook functions are provided in sierra_net.c which are called by
usbnet.c in response to a particular condition such as receipt or transmission
of a data packet. As such, usbnet.c does most of the work of making
a modem appear to the system as a network device and for properly exchanging
traffic between the USB subsystem and the Network card interface.
Sierra_net.c is concerned with managing the data exchanged between the
so-called Direct-IP interface and the upper layers of the operating system.

The version number of sierra_net.c driver is set to 2.0.
This patch has been tested on the latest stable kernel-2.6.33.1.
Signed-off-by: Elina Pasheva <epasheva-ywE8TTl5eJHWpu6QEFMNjNBPR1lH4CV8@public.gmane.org>
Signed-off-by: Rory Filer <epasheva-ywE8TTl5eJHWpu6QEFMNjNBPR1lH4CV8@public.gmane.org>
---

 drivers/net/usb/Kconfig |   10 ++++++++++
 1 file changed, 10 insertions(+)

--- a/drivers/net/usb/Kconfig	2010-03-25 12:46:33.000000000 -0700
+++ b/drivers/net/usb/Kconfig	2010-03-25 15:56:29.000000000 -0700
@@ -377,4 +377,14 @@ config USB_CDC_PHONET
 	  cellular modem, as found on most Nokia handsets with the
 	  "PC suite" USB profile.
 
+config USB_SIERRA_NET
+	tristate "DirectIP Driver for Sierra Wireless modems"
+	depends on USB_USBNET
+
+	help
+	  Choose this option if you have a Sierra Wireless DirectIP device.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called sierra_net.
+
 endmenu


 drivers/net/usb/Makefile |    2 ++
 1 file changed, 2 insertions(+)

--- a/drivers/net/usb/Makefile	2010-03-25 12:46:56.000000000 -0700
+++ b/drivers/net/usb/Makefile	2010-03-25 12:48:27.000000000 -0700
@@ -22,4 +22,6 @@ obj-$(CONFIG_USB_NET_MCS7830)	+= mcs7830
 obj-$(CONFIG_USB_USBNET)	+= usbnet.o
 obj-$(CONFIG_USB_NET_INT51X1)	+= int51x1.o
 obj-$(CONFIG_USB_CDC_PHONET)	+= cdc-phonet.o
+obj-$(CONFIG_USB_SIERRA_NET)	+= sierra_net.o
+
 

 drivers/net/usb/sierra_net.c |  968 +++++++++++++++++++++++++++++++++
 1 file changed, 968 insertions(+)

--- a/drivers/net/usb/sierra_net.c	2010-03-23 00:33:20.000000000 -0700
+++ b/drivers/net/usb/sierra_net.c	2010-03-25 15:54:47.000000000 -0700
@@ -1 +1,969 @@
+/*
+ * DirectIP Driver for Sierra Wireless modems
+ *
+ * Copyright (C) 2008, 2009, 2010 Paxton Smith, Matthew Safar, Rory Filer
+ *                          <linux-ywE8TTl5eJHWpu6QEFMNjNBPR1lH4CV8@public.gmane.org>
+ *
+ * Portions of this based on the cdc_ether driver by David Brownell (2003-2005)
+ * and Ole Andre Vadla Ravnas (ActiveSync) (2006).
+ *
+ * IMPORTANT DISCLAIMER: This driver is not commercially supported by
+ * Sierra Wireless. Use at your own risk.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define DRIVER_VERSION "v.2.0"
+#define DRIVER_AUTHOR "Paxton Smith, Matthew Safar, Rory Filer"
+#define DRIVER_DESC "DirectIP Driver for Sierra Wireless modems"
+static const char driver_name[] = "sierra_net";
+
+/* if defined debug messages enabled */
+/*#define	DEBUG*/
+/* more debug messages */
+/*#define	VERBOSE*/
+
+#include <linux/module.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/usb.h>
+#include <linux/usb/cdc.h>
+#include <net/ip.h>
+#include <net/udp.h>
+#include <asm/unaligned.h>
+#include <linux/usb/usbnet.h>
+
+#define SWI_USB_REQUEST_GET_FW_ATTR	0x06
+#define SWI_GET_FW_ATTR_MASK		0x08
+
+/* 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
+ */
+static	atomic_t iface_counter = ATOMIC_INIT(0);
+
+/*
+ * SYNC Timer Delay definition used to set the expiry time
+ */
+#define SIERRA_NET_SYNCDELAY (2*HZ)
+
+/* Max. MTU supported. The modem buffers are limited to 1500 */
+#define SIERRA_NET_MAX_SUPPORTED_MTU	1500
+
+/* The SIERRA_NET_USBCTL_BUF_LEN defines a buffer size allocated for control
+ * message reception ... and thus the max. received packet.
+ * (May be the cause for parse_hip returning -3)
+ */
+#define SIERRA_NET_USBCTL_BUF_LEN	1024
+
+/* list of interface numbers - used for constructing interface lists */
+struct sierra_net_iface_info {
+	const u32 infolen;	/* number of interface numbers on list */
+	const u8  *ifaceinfo;	/* pointer to the array holding the numbers */
+};
+
+struct sierra_net_info_data {
+	u16 rx_urb_size;
+	struct sierra_net_iface_info whitelist;
+};
+
+/* Private data structure */
+struct sierra_net_data {
+
+	u8 ethr_hdr_tmpl[ETH_HLEN]; /* ethernet header template for rx'd pkts */
+
+	u16 link_up; 		/* air link up or down */
+	u8 tx_hdr_template[4];	/* part of HIP hdr for tx'd packets */
+
+	u8 sync_msg[4];		/* SYNC message */
+	u8 shdwn_msg[4];	/* Shutdown message */
+
+	/* Backpointer to the container */
+	struct usbnet *usbnet;
+
+	u8 ifnum;	/* interface number */
+
+/* Bit masks, must be a power of 2 */
+#define SIERRA_NET_EVENT_RESP_AVAIL    0x01
+#define SIERRA_NET_TIMER_EXPIRY        0x02
+	unsigned long kevent_flags;
+	struct work_struct sierra_net_kevent;
+	struct timer_list sync_timer; /* For retrying SYNC sequence */
+};
+
+struct param {
+	int is_present;
+	union {
+		void  *ptr;
+		u32    dword;
+		u16    word;
+		u8     byte;
+	};
+};
+
+/* HIP message type */
+#define SIERRA_NET_HIP_EXTENDEDID	0x7F
+#define SIERRA_NET_HIP_HSYNC_ID 	0x60	/* Modem -> host */
+#define SIERRA_NET_HIP_RESTART_ID	0x62	/* Modem -> host */
+#define SIERRA_NET_HIP_MSYNC_ID 	0x20	/* Host -> modem */
+#define SIERRA_NET_HIP_SHUTD_ID 	0x26	/* Host -> modem */
+
+#define SIERRA_NET_HIP_EXT_IP_IN_ID   0x0202
+#define SIERRA_NET_HIP_EXT_IP_OUT_ID  0x0002
+
+/* 3G UMTS Link Sense Indication definitions */
+#define SIERRA_NET_HIP_LSI_UMTSID	0x78
+
+/* Reverse Channel Grant Indication HIP message */
+#define SIERRA_NET_HIP_RCGI		0x64
+
+/* LSI Protocol types */
+#define SIERRA_NET_PROTOCOL_UMTS      0x01
+/* LSI Coverage */
+#define SIERRA_NET_COVERAGE_NONE      0x00
+#define SIERRA_NET_COVERAGE_NOPACKET  0x01
+
+/* LSI Session */
+#define SIERRA_NET_SESSION_IDLE       0x00
+/* LSI Link types */
+#define SIERRA_NET_AS_LINK_TYPE_IPv4  0x00
+
+typedef struct s_lsi_umts {
+	u8 protocol;
+	u8 unused1;
+	__be16 length;
+	/* eventually use a union for the rest - assume umts for now */
+	u8 coverage;
+	u8 unused2[41];
+	u8 session_state;
+	u8 unused3[33];
+	u8 link_type;
+	u8 pdp_addr_len; /* NW-supplied PDP address len */
+	u8 pdp_addr[16]; /* NW-supplied PDP address (bigendian)) */
+	u8 unused4[23];
+	u8 dns1_addr_len; /* NW-supplied 1st DNS address len (bigendian) */
+	u8 dns1_addr[16]; /* NW-supplied 1st DNS address */
+	u8 dns2_addr_len; /* NW-supplied 2nd DNS address len */
+	u8 dns2_addr[16]; /* NW-supplied 2nd DNS address (bigendian)*/
+	u8 wins1_addr_len; /* NW-supplied 1st Wins address len */
+	u8 wins1_addr[16]; /* NW-supplied 1st Wins address (bigendian)*/
+	u8 wins2_addr_len; /* NW-supplied 2nd Wins address len */
+	u8 wins2_addr[16]; /* NW-supplied 2nd Wins address (bigendian) */
+	u8 unused5[4];
+	u8 gw_addr_len; /* NW-supplied GW address len */
+	u8 gw_addr[16]; /* NW-supplied GW address (bigendian) */
+	u8 reserved[8];
+} __attribute__ ((packed)) lsi_umts_t;
+
+#define SIERRA_NET_LSI_COMMON_LEN      4
+#define SIERRA_NET_LSI_UMTS_LEN        (sizeof(lsi_umts_t))
+#define SIERRA_NET_LSI_UMTS_STATUS_LEN \
+	(SIERRA_NET_LSI_UMTS_LEN - SIERRA_NET_LSI_COMMON_LEN)
+
+/* Forward definitions */
+extern void sierra_sync_timer(unsigned long syncdata);
+static int sierra_net_change_mtu(struct net_device *net, int new_mtu);
+
+/* Our own net device operations structure */
+static const struct net_device_ops sierra_net_device_ops = {
+	.ndo_open               = usbnet_open,
+	.ndo_stop               = usbnet_stop,
+	.ndo_start_xmit         = usbnet_start_xmit,
+	.ndo_tx_timeout         = usbnet_tx_timeout,
+	.ndo_change_mtu         = sierra_net_change_mtu,
+	.ndo_set_mac_address    = eth_mac_addr,
+	.ndo_validate_addr      = eth_validate_addr,
+};
+
+/* get private data associated with passed in usbnet device */
+static inline struct sierra_net_data *sierra_net_get_private(struct usbnet *dev)
+{
+	return (struct sierra_net_data *)dev->data[0];
+}
+
+/* set private data associated with passed in usbnet device */
+static inline void sierra_net_set_private(struct usbnet *dev,
+			struct sierra_net_data *priv)
+{
+	dev->data[0] = (unsigned long)priv;
+}
+
+/* is packet IPv4 */
+static inline int is_ip(struct sk_buff *skb)
+{
+	return (skb->protocol == cpu_to_be16(ETH_P_IP));
+}
+
+/*
+ * check passed in packet and make sure that:
+ *  - it is linear (no scatter/gather)
+ *  - it is ethernet (mac_header properly set)
+ */
+static int check_ethip_packet(struct sk_buff *skb, struct usbnet *dev)
+{
+	skb_reset_mac_header(skb); /* ethernet header */
+
+	if (skb_is_nonlinear(skb)) {
+		deverr(dev, "Non linear buffer-dropping");
+		return 0;
+	}
+
+	if (!pskb_may_pull(skb, ETH_HLEN))
+		return 0;
+	skb->protocol = eth_hdr(skb)->h_proto;
+
+	return 1;
+}
+
+static const u8 *save16bit(struct param *p, const u8 *datap)
+{
+	p->is_present = 1;
+	p->word = get_unaligned_be16(datap);
+	return datap + sizeof(p->word);
+}
+
+static const u8 *save8bit(struct param *p, const u8 *datap)
+{
+	p->is_present = 1;
+	p->byte = *datap;
+	return datap + sizeof(p->byte);
+}
+
+/*----------------------------------------------------------------------------*
+ *                              BEGIN HIP                                     *
+ *----------------------------------------------------------------------------*/
+/* HIP header */
+#define SIERRA_NET_HIP_HDR_LEN 4
+/* Extended HIP header */
+#define SIERRA_NET_HIP_EXT_HDR_LEN 6
+
+struct hip_hdr {
+	int    hdrlen;
+	struct param payload_len;
+	struct param msgid;
+	struct param msgspecific;
+	struct param extmsgid;
+};
+
+static int parse_hip(const u8 *buf, const u32 buflen, struct hip_hdr *hh)
+{
+	const u8 *curp = buf;
+	int    padded;
+
+	if (buflen < SIERRA_NET_HIP_HDR_LEN)
+		return -1;
+
+	curp = save16bit(&hh->payload_len, curp);
+	curp = save8bit(&hh->msgid, curp);
+	curp = save8bit(&hh->msgspecific, curp);
+
+	padded = hh->msgid.byte & 0x80;
+	hh->msgid.byte &= 0x7F;			/* 7 bits */
+
+	hh->extmsgid.is_present = (hh->msgid.byte == SIERRA_NET_HIP_EXTENDEDID);
+	if (hh->extmsgid.is_present) {
+		if (buflen < SIERRA_NET_HIP_EXT_HDR_LEN)
+			return -2;
+
+		hh->payload_len.word &= 0x3FFF; /* 14 bits */
+
+		curp = save16bit(&hh->extmsgid, curp);
+		hh->extmsgid.word &= 0x03FF;	/* 10 bits */
+
+		hh->hdrlen = SIERRA_NET_HIP_EXT_HDR_LEN;
+	} else {
+		hh->payload_len.word &= 0x07FF;	/* 11 bits */
+		hh->hdrlen = SIERRA_NET_HIP_HDR_LEN;
+	}
+
+	if (padded) {
+		hh->hdrlen++;
+		hh->payload_len.word--;
+	}
+
+	/* if real packet shorter than the claimed length */
+	if (buflen < (hh->hdrlen + hh->payload_len.word))
+		return -3;
+
+	return 0;
+}
+
+static void build_hip(u8 *buf, const u16 payloadlen,
+		struct sierra_net_data *priv)
+{
+	/* the following doesn't have the full functionality. We
+	 * currently build only one kind of header, so it is faster this way
+	 */
+	put_unaligned_be16(payloadlen, buf);
+	memcpy(buf+2, priv->tx_hdr_template, sizeof(priv->tx_hdr_template));
+}
+/*----------------------------------------------------------------------------*
+ *                              END HIP                                       *
+ *----------------------------------------------------------------------------*/
+
+static void sierra_net_send_cmd(struct usbnet *dev,
+		u8 *cmd, int cmdlen, const char * cmd_name)
+{
+	struct sierra_net_data *priv = sierra_net_get_private(dev);
+	int  status;
+
+	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, 0);
+
+	if (status != cmdlen && status != -ENODEV)
+		deverr(dev, "Submit %s failed %d", cmd_name, status);
+}
+
+static void sierra_net_send_sync(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->sync_msg,
+			sizeof(priv->sync_msg), "SYNC");
+}
+
+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)
+{
+	dev_dbg(&(priv->usbnet->udev->dev), "%s %d", __func__, ctx_ix);
+	priv->tx_hdr_template[0] = 0x3F;
+	priv->tx_hdr_template[1] = ctx_ix;
+	*((u16 *)&priv->tx_hdr_template[2]) =
+		cpu_to_be16(SIERRA_NET_HIP_EXT_IP_OUT_ID);
+}
+
+static inline int sierra_net_is_valid_addrlen(u8 len)
+{
+	return (len == sizeof(struct in_addr));
+}
+
+static int sierra_net_parse_lsi(struct usbnet *dev, char *data, int datalen)
+{
+	lsi_umts_t *lsi = (lsi_umts_t *)data;
+
+	if (lsi->length != cpu_to_be16(SIERRA_NET_LSI_UMTS_STATUS_LEN)) {
+		deverr(dev, "%s: LSI_UMTS_STATUS_LEN %d, expected %u",
+				__func__, be16_to_cpu(lsi->length),
+				(u32)SIERRA_NET_LSI_UMTS_STATUS_LEN);
+		return -1;
+	}
+
+	/* Validate the protocol  - only support UMTS for now */
+	if (lsi->protocol != SIERRA_NET_PROTOCOL_UMTS) {
+		deverr(dev, "Protocol unsupported, 0x%02x", lsi->protocol);
+		return -1;
+	}
+
+	/* Validate the link type */
+	if (lsi->link_type != SIERRA_NET_AS_LINK_TYPE_IPv4) {
+		deverr(dev, "Link type unsupported: 0x%02x", lsi->link_type);
+		return -1;
+	}
+
+	/* Validate the coverage */
+	if (lsi->coverage == SIERRA_NET_COVERAGE_NONE
+	   || lsi->coverage == SIERRA_NET_COVERAGE_NOPACKET) {
+		deverr(dev, "No coverage, 0x%02x", lsi->coverage);
+		return 0;
+	}
+
+	/* Validate the session state */
+	if (lsi->session_state == SIERRA_NET_SESSION_IDLE) {
+		deverr(dev, "Session idle, 0x%02x", lsi->session_state);
+		return 0;
+	}
+
+	/* Set link_sense true */
+	return 1;
+}
+
+static void sierra_net_handle_lsi(struct usbnet *dev, char *data,
+		struct hip_hdr	*hh)
+{
+	struct sierra_net_data *priv = sierra_net_get_private(dev);
+	int link_up;
+
+	link_up = sierra_net_parse_lsi(dev, data + hh->hdrlen,
+					hh->payload_len.word);
+	if (link_up < 0) {
+		deverr(dev, "Invalid LSI");
+		return;
+	}
+	if (link_up) {
+		sierra_net_set_ctx_index(priv, hh->msgspecific.byte);
+		priv->link_up = 1;
+		netif_carrier_on(dev->net);
+	} else {
+		priv->link_up = 0;
+		netif_carrier_off(dev->net);
+	}
+}
+
+static void sierra_net_dosync(struct usbnet *dev)
+{
+	struct sierra_net_data *priv = sierra_net_get_private(dev);
+
+	dev_dbg(&dev->udev->dev, "%s", __func__);
+
+	/* tell modem we are ready */
+	sierra_net_send_sync(dev);
+	sierra_net_send_sync(dev);
+
+	/* Now, start a timer and make sure we get the Restart Indication */
+	priv->sync_timer.function = sierra_sync_timer;
+	priv->sync_timer.data = (unsigned long) dev;
+	priv->sync_timer.expires = jiffies + SIERRA_NET_SYNCDELAY;
+	add_timer(&priv->sync_timer);
+}
+
+static void sierra_net_kevent(struct work_struct *work)
+{
+	struct sierra_net_data *priv =
+		container_of(work, struct sierra_net_data, sierra_net_kevent);
+	struct usbnet *dev = priv->usbnet;
+	int  len;
+	int  err;
+	u8  *buf;
+	u8   ifnum;
+
+	if (test_bit(SIERRA_NET_EVENT_RESP_AVAIL, &priv->kevent_flags)) {
+		clear_bit(SIERRA_NET_EVENT_RESP_AVAIL, &priv->kevent_flags);
+
+		/* Query the modem for the LSI message */
+		buf = kzalloc(SIERRA_NET_USBCTL_BUF_LEN, GFP_KERNEL);
+		if (!buf) {
+			deverr(dev, "failed to allocate buf for LS msg");
+			return;
+		}
+		ifnum = priv->ifnum;
+		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, 0);
+
+		if (unlikely(len < 0)) {
+			deverr(dev,
+				"usb_control_msg failed, status %d", len);
+		} else {
+			struct hip_hdr	hh;
+
+			dev_dbg(&dev->udev->dev, "%s: Received status message,"
+				" %04x bytes", __func__, len);
+
+			err = parse_hip(buf, len, &hh);
+			if (err) {
+				deverr(dev, "%s: Bad packet, parse result %d",
+					__func__, err);
+				kfree(buf);
+				return;
+			}
+
+			/* Validate packet length */
+			if (len != hh.hdrlen + hh.payload_len.word) {
+				deverr(dev, "%s: Bad packet, received %d,"
+					" expected %d",	__func__, len,
+					hh.hdrlen + hh.payload_len.word);
+				kfree(buf);
+				return;
+			}
+
+			/* Switch on received message types */
+			switch (hh.msgid.byte) {
+			case SIERRA_NET_HIP_LSI_UMTSID:
+				dev_dbg(&dev->udev->dev, "LSI for ctx:%d",
+					hh.msgspecific.byte);
+				sierra_net_handle_lsi(dev, buf, &hh);
+				break;
+			case SIERRA_NET_HIP_RESTART_ID:
+				dev_dbg(&dev->udev->dev, "Restart reported: %d,"
+						" stopping sync timer",
+						hh.msgspecific.byte);
+				/* Got sync resp - stop timer & clear mask */
+				del_timer_sync(&priv->sync_timer);
+				clear_bit(SIERRA_NET_TIMER_EXPIRY,
+					  &priv->kevent_flags);
+				break;
+			case SIERRA_NET_HIP_HSYNC_ID:
+				dev_dbg(&dev->udev->dev, "SYNC received");
+				sierra_net_send_sync(dev);
+				break;
+			case SIERRA_NET_HIP_EXTENDEDID:
+				deverr(dev, "Unrecognized HIP msg, "
+					"extmsgid 0x%04x", hh.extmsgid.word);
+				break;
+			case SIERRA_NET_HIP_RCGI:
+				/* Ignored */
+				break;
+			default:
+				deverr(dev, "Unrecognized HIP msg, "
+					"msgid 0x%02x", hh.msgid.byte);
+				break;
+			}
+		}
+		kfree(buf);
+	}
+	/* The sync timer bit might be set */
+	if (test_bit(SIERRA_NET_TIMER_EXPIRY, &priv->kevent_flags)) {
+		clear_bit(SIERRA_NET_TIMER_EXPIRY, &priv->kevent_flags);
+		dev_dbg(&dev->udev->dev, "Deferred sync timer expiry");
+		sierra_net_dosync(priv->usbnet);
+	}
+
+	if (priv->kevent_flags)
+		dev_dbg(&dev->udev->dev, "sierra_net_kevent done, "
+			"kevent_flags = 0x%lx", priv->kevent_flags);
+}
+
+static void sierra_net_defer_kevent(struct usbnet *dev, int work)
+{
+	struct sierra_net_data *priv = sierra_net_get_private(dev);
+
+	set_bit(work, &priv->kevent_flags);
+	schedule_work(&priv->sierra_net_kevent);
+}
+
+/*
+ * Sync Retransmit Timer Handler. On expiry, kick the work queue
+ */
+void sierra_sync_timer(unsigned long syncdata)
+{
+	struct usbnet *dev = (struct usbnet *)syncdata;
+
+	dev_dbg(&dev->udev->dev, "%s", __func__);
+	/* Kick the tasklet */
+	sierra_net_defer_kevent(dev, SIERRA_NET_TIMER_EXPIRY);
+}
+
+static void sierra_net_status(struct usbnet *dev, struct urb *urb)
+{
+	struct usb_cdc_notification *event;
+
+	dev_dbg(&dev->udev->dev, "%s", __func__);
+
+	if (urb->actual_length < sizeof *event)
+		return;
+
+	/* Add cases to handle other standard notifications. */
+	event = urb->transfer_buffer;
+	switch (event->bNotificationType) {
+	case USB_CDC_NOTIFY_NETWORK_CONNECTION:
+	case USB_CDC_NOTIFY_SPEED_CHANGE:
+		/* USB 305 sends those */
+		break;
+	case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
+		sierra_net_defer_kevent(dev, SIERRA_NET_EVENT_RESP_AVAIL);
+		break;
+	default:
+		deverr(dev, ": unexpected notification %02x!",
+				event->bNotificationType);
+		break;
+	}
+}
+
+static void sierra_net_get_drvinfo(struct net_device *net,
+		struct ethtool_drvinfo *info)
+{
+	/* Inherit standard device info */
+	usbnet_get_drvinfo(net, info);
+	strncpy(info->driver, driver_name, sizeof info->driver);
+	strncpy(info->version, DRIVER_VERSION, sizeof info->version);
+}
+
+static u32 sierra_net_get_link(struct net_device *net)
+{
+	struct usbnet *dev = netdev_priv(net);
+	/* Report link is down whenever the interface is down */
+	return sierra_net_get_private(dev)->link_up && netif_running(net);
+}
+
+static struct ethtool_ops sierra_net_ethtool_ops = {
+	.get_drvinfo = sierra_net_get_drvinfo,
+	.get_link = sierra_net_get_link,
+	.get_msglevel = usbnet_get_msglevel,
+	.set_msglevel = usbnet_set_msglevel,
+	.get_settings = usbnet_get_settings,
+	.set_settings = usbnet_set_settings,
+	.nway_reset = usbnet_nway_reset,
+};
+
+/* MTU can not be more than 1500 bytes, enforce it. */
+static int sierra_net_change_mtu(struct net_device *net, int new_mtu)
+{
+	if (new_mtu > SIERRA_NET_MAX_SUPPORTED_MTU)
+		return -EINVAL;
+
+	return usbnet_change_mtu(net, new_mtu);
+}
+
+static int is_whitelisted(const u8 ifnum,
+			const struct sierra_net_iface_info *whitelist)
+{
+	if (whitelist) {
+		const u8 *list = whitelist->ifaceinfo;
+		int i;
+
+		for (i = 0; i < whitelist->infolen; i++) {
+			if (list[i] == ifnum)
+				return 1;
+		}
+	}
+	return 0;
+}
+
+static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap)
+{
+	int result = 0;
+	u16 *attrdata;
+
+	attrdata = kmalloc(sizeof(*attrdata), GFP_KERNEL);
+	if (!attrdata)
+		return -ENOMEM;
+
+	result = usb_control_msg(
+			dev->udev,
+			usb_rcvctrlpipe(dev->udev, 0),
+			/* _u8 vendor specific request */
+			SWI_USB_REQUEST_GET_FW_ATTR,
+			USB_DIR_IN | USB_TYPE_VENDOR,	/* __u8 request type */
+			0x0000,		/* __u16 value not used */
+			0x0000,		/* __u16 index  not used */
+			attrdata,	/* char *data */
+			sizeof(*attrdata),		/* __u16 size */
+			USB_CTRL_SET_TIMEOUT);	/* int timeout */
+
+	if (result < 0) {
+		kfree(attrdata);
+		return -EIO;
+	}
+
+	*datap = *attrdata;
+
+	kfree(attrdata);
+	return result;
+}
+
+/*
+ * collects the bulk endpoints, the status endpoint.
+ */
+static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	u8	ifacenum;
+	u8	numendpoints;
+	u16	fwattr = 0;
+	int	status;
+	struct ethhdr *eth;
+	struct sierra_net_data *priv;
+	static const u8 sync_tmplate[sizeof(priv->sync_msg)] = {
+		0x00, 0x00, SIERRA_NET_HIP_MSYNC_ID, 0x00};
+	static const u8 shdwn_tmplate[sizeof(priv->shdwn_msg)] = {
+		0x00, 0x00, SIERRA_NET_HIP_SHUTD_ID, 0x00};
+
+	struct sierra_net_info_data *data =
+			(struct sierra_net_info_data *)dev->driver_info->data;
+
+	dev_dbg(&dev->udev->dev, "%s", __func__);
+
+	ifacenum = intf->cur_altsetting->desc.bInterfaceNumber;
+	/* We only accept certain interfaces */
+	if (!is_whitelisted(ifacenum, &data->whitelist)) {
+		dev_dbg(&dev->udev->dev, "Ignoring interface: %d", ifacenum);
+		return -ENODEV;
+	}
+
+	numendpoints = intf->cur_altsetting->desc.bNumEndpoints;
+	/* We have three endpoints, bulk in and out, and a status */
+	if (numendpoints != 3) {
+		deverr(dev, "Expected 3 endpoints, found: %d", numendpoints);
+		return -ENODEV;
+	}
+
+	/* Status endpoint set in usbnet_get_endpoints() */
+	dev->status = NULL;
+	status = usbnet_get_endpoints(dev, intf);
+	if (status < 0) {
+		deverr(dev, "Error in usbnet_get_endpoints (%d)",
+			status);
+		return -ENODEV;
+	}
+
+	/* Initialize sierra private data */
+	priv = kzalloc(sizeof *priv, GFP_KERNEL);
+	if (!priv) {
+		deverr(dev, "No memory");
+		return -ENOMEM;
+	}
+
+	priv->usbnet = dev;
+	priv->ifnum = ifacenum;
+	dev->net->netdev_ops = &sierra_net_device_ops;
+
+	/* change MAC addr to include, ifacenum, and to be unique */
+	dev->net->dev_addr[ETH_ALEN-2] = atomic_inc_return(&iface_counter);
+	dev->net->dev_addr[ETH_ALEN-1] = ifacenum;
+
+	/* we will have to manufacture ethernet headers, prepare template */
+	eth = (struct ethhdr *)priv->ethr_hdr_tmpl;
+	memcpy(&eth->h_dest, dev->net->dev_addr, ETH_ALEN);
+	eth->h_proto = cpu_to_be16(ETH_P_IP);
+
+	/* prepare shutdown message template */
+	memcpy(priv->shdwn_msg, shdwn_tmplate, sizeof(priv->shdwn_msg));
+	/* set context index initially to 0 - prepares tx hdr template */
+	sierra_net_set_ctx_index(priv, 0);
+
+	/* decrease the rx_urb_size and max_tx_size to 4k on USB 1.1 */
+	dev->rx_urb_size  = data->rx_urb_size;
+	if (dev->udev->speed != USB_SPEED_HIGH)
+		dev->rx_urb_size  = min_t(size_t, 4096, data->rx_urb_size);
+
+	dev->net->hard_header_len += SIERRA_NET_HIP_EXT_HDR_LEN;
+	dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
+
+	/* Set up the netdev */
+	dev->net->flags |= IFF_NOARP;
+	dev->net->ethtool_ops = &sierra_net_ethtool_ops;
+	netif_carrier_off(dev->net);
+
+	sierra_net_set_private(dev, priv);
+
+	priv->kevent_flags = 0;
+
+	/* Use the shared workqueue */
+	INIT_WORK(&priv->sierra_net_kevent, sierra_net_kevent);
+
+	/* 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);
+
+	/* test whether firmware supports DHCP */
+	if (!(status == sizeof(fwattr) && (fwattr & SWI_GET_FW_ATTR_MASK))) {
+		/* found incompatible firmware version */
+		deverr(dev, "Incompatible driver and firmware"
+			" versions\n");
+		return -ENODEV;
+	}
+	/* prepare sync message from template */
+	memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg));
+
+	/* initiate the sync sequence */
+	sierra_net_dosync(dev);
+
+	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__);
+
+	/* Kill the timer then flush the work queue */
+	del_timer_sync(&priv->sync_timer);
+
+	flush_scheduled_work();
+
+	/* tell modem we are going away */
+	sierra_net_send_shutdown(dev);
+
+	sierra_net_set_private(dev, NULL);
+
+	kfree(priv);
+}
+
+static struct sk_buff *sierra_net_skb_clone(struct usbnet *dev,
+		struct sk_buff *skb, int len)
+{
+	struct sk_buff *new_skb;
+
+	/* clone skb */
+	new_skb = skb_clone(skb, GFP_ATOMIC);
+
+	/* remove len bytes from original */
+	skb_pull(skb, len);
+
+	/* trim next packet to it's length */
+	if (new_skb) {
+		skb_trim(new_skb, len);
+	} else {
+		if (netif_msg_rx_err(dev))
+			deverr(dev, "failed to get skb");
+		dev->net->stats.rx_dropped++;
+	}
+
+	return new_skb;
+}
+
+/* ---------------------------- Receive data path ----------------------*/
+static int sierra_net_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+	int err;
+	struct hip_hdr  hh;
+	struct sk_buff *new_skb;
+
+	dev_dbg(&dev->udev->dev, "%s", __func__);
+
+	/* could contain multiple packets */
+	while (likely(skb->len)) {
+		err = parse_hip(skb->data, skb->len, &hh);
+		if (err) {
+			if (netif_msg_rx_err(dev))
+				deverr(dev, "Invalid HIP header %d", err);
+			/* dev->net->stats.rx_errors incremented by caller */
+			dev->net->stats.rx_length_errors++;
+			return 0;
+		}
+
+		/* Validate Extended HIP header */
+		if (!hh.extmsgid.is_present
+		    || hh.extmsgid.word != SIERRA_NET_HIP_EXT_IP_IN_ID) {
+			if (netif_msg_rx_err(dev))
+				deverr(dev, "HIP/ETH: Invalid packet");
+
+			dev->net->stats.rx_frame_errors++;
+			/* dev->net->stats.rx_errors incremented by caller */;
+			return 0;
+		}
+
+		skb_pull(skb, hh.hdrlen);
+
+		/* We are going to accept this packet, prepare it */
+		memcpy(skb->data, sierra_net_get_private(dev)->ethr_hdr_tmpl,
+			ETH_HLEN);
+
+		/* Last packet in batch handled by usbnet */
+		if (hh.payload_len.word == skb->len)
+			return 1;
+
+		new_skb = sierra_net_skb_clone(dev, skb, hh.payload_len.word);
+		if (new_skb)
+			usbnet_skb_return(dev, new_skb);
+
+	} /* while */
+
+	return 0;
+}
+
+/* ---------------------------- Transmit data path ----------------------*/
+struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+		gfp_t flags)
+{
+	struct sierra_net_data *priv = sierra_net_get_private(dev);
+	u16 len;
+
+	dev_dbg(&dev->udev->dev, "%s", __func__);
+	if (priv->link_up && check_ethip_packet(skb, dev) && is_ip(skb)) {
+		/* enough head room as is? */
+		if (SIERRA_NET_HIP_EXT_HDR_LEN <= skb_headroom(skb)) {
+			/* Save the Eth/IP length and set up HIP hdr */
+			len = skb->len;
+			skb_push(skb, SIERRA_NET_HIP_EXT_HDR_LEN);
+			build_hip(skb->data, len, priv);
+			return skb;
+		} else {
+			/*
+			 * compensate in the future if necessary
+			 */
+			deverr(dev, "tx_fixup: no room for HIP");
+		} /* headroom */
+	}
+
+	if (!priv->link_up)
+		dev->net->stats.tx_carrier_errors++;
+
+	/* tx_dropped incremented by usbnet */
+
+	/* filter the packet out, release it  */
+	dev_kfree_skb_any(skb);
+	return NULL;
+}
+
+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,
+	.whitelist = {
+		.infolen = ARRAY_SIZE(sierra_net_ifnum_list),
+		.ifaceinfo = sierra_net_ifnum_list
+	}
+};
+
+static const struct driver_info sierra_net_info_68A3 = {
+	.description = "Sierra Wireless USB-Ethernet Modem",
+	.flags = FLAG_ETHER | FLAG_SEND_ZLP,
+	.bind = sierra_net_bind,
+	.unbind = sierra_net_unbind,
+	.status = sierra_net_status,
+	.rx_fixup = sierra_net_rx_fixup,
+	.tx_fixup = sierra_net_tx_fixup,
+	.data = (unsigned long)&sierra_net_info_data_68A3,
+};
+
+static const struct usb_device_id products[] = {
+	{USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modem */
+	.driver_info = (unsigned long) &sierra_net_info_68A3},
+
+	{}, /* last item */
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+/* We are based on usbnet, so let it handle the USB driver specifics */
+static struct usb_driver sierra_net_driver = {
+	.name = "sierra_net",
+	.id_table = products,
+	.probe = usbnet_probe,
+	.disconnect = usbnet_disconnect,
+	.suspend = usbnet_suspend,
+	.resume = usbnet_resume,
+	.no_dynamic_id = 1,
+};
+
+static int __init sierra_net_init(void)
+{
+	BUILD_BUG_ON(FIELD_SIZEOF(struct usbnet, data)
+				< sizeof(struct cdc_state));
+
+	return usb_register(&sierra_net_driver);
+}
+
+static void __exit sierra_net_exit(void)
+{
+	usb_deregister(&sierra_net_driver);
+}
+
+module_exit(sierra_net_exit);
+module_init(sierra_net_init);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL");


--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: ICMP echo reply fails
From: Andy Fleming @ 2010-03-27  0:56 UTC (permalink / raw)
  To: netdev
In-Reply-To: <1269643575.2256.19.camel@edumazet-laptop>

On Fri, Mar 26, 2010 at 5:46 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> Le vendredi 26 mars 2010 à 23:06 +0100, Eric Dumazet a écrit :
>> Le vendredi 26 mars 2010 à 16:48 -0500, Andy Fleming a écrit :
>> > For various reasons, we have been running a stress test on one of our
>> > boards.  The test consists of initiating 2-3 flood pings from a
>> > Windows box running Cygwin, plus one additional ping we use as a
>> > "heartbeat".  The ping flood is overwhelming our board (we're dropping
>> > packets at a prodigious rate), but the board continues to respond for
>> > a while.  In addition, we are running a script on the  board which
>> > alternates bringing up and bringing down the interface every ten
>> > seconds.  After a highly variable amount of time, the board stops
>> > replying to the pings.  We suspected a driver issue, however, on
>> > closer inspection, we are still able to send and receive packets (I
>> > can ping *from* the board to the PC, and I can *telnet* from the PC to
>> > the board).  We tried pinging the board from another PC, and it also
>> > failed.  Essentially, ICMP echo requests are being ignored (A glance
>> > at memory indicates that packets are arriving, but no packets are
>> > being enqueued to the ethernet controller).  We still have a lot more
>> > debugging to do, but I was wondering if anyone had ever seen something
>> > like this, or might be quicker to realize the obvious mistake we're
>> > making.
>> >
>> > Thanks,
>> > Andy Fleming
>>
>>
>> kernel version ?
>>
>> NIC driver ?
>>
>> Are ICMP echo request received ? (grep Icmp /proc/net/snmp)
>>
>
> vi +1166 net/ipv4/icmp.c
>
>        /* Enough space for 2 64K ICMP packets, including
>         * sk_buff struct overhead.
>         */
>        sk->sk_sndbuf =
>                (2 * ((64 * 1024) + sizeof(struct sk_buff)));
>
>
> If many ICMP replies are lost/leaked by your driver when doing up/down
> things, ICMP socket can consume all its sndbuf reserve and no more icmp
> replies can be sent (a reboot is needed)
>
> You could try changing sk->sk_sndbuf to 0x7FFFFFFF  to see if the icmp
> replies survive longer to your tests. If this is the case, then find the
> leaks in your driver (tx path, maybe you forgot to free skbs in some
> reset cases ?)
>

Ah, that makes a bunch of sense.  I had a feeling the socket was
involved.  Thank you so much for your help.  I will test this as soon
as I have access to the board again!

^ permalink raw reply

* Re: [PATCH] Add MSG_WAITFORONE flag to recvmmsg
From: Brandon Black @ 2010-03-26 22:55 UTC (permalink / raw)
  To: Eric Dumazet
  Cc: netdev, David S. Miller, Arnaldo Carvalho de Melo, Ulrich Drepper,
	linux-kernel
In-Reply-To: <1269643470.2256.17.camel@edumazet-laptop>

On Fri, Mar 26, 2010 at 5:44 PM, Eric Dumazet <eric.dumazet@gmail.com> wrote:
> Hmmm, no need to test !datagram, just do :
>
>        ++datagrams;
>
>        if (flags & MSG_WAITFORONE)
>                flags |= MSG_DONTWAIT;
>

Ok.  I've never been through this process before.  Do I resubmit a new
subject/thread with the changed patch and [PATCH v2] at this point?
Any other nits about how the patch was sent before I do?

Thanks,
-- Brandon

^ permalink raw reply

* Re: ICMP echo reply fails
From: Eric Dumazet @ 2010-03-26 22:46 UTC (permalink / raw)
  To: Andy Fleming; +Cc: netdev
In-Reply-To: <1269641190.2256.1.camel@edumazet-laptop>

Le vendredi 26 mars 2010 à 23:06 +0100, Eric Dumazet a écrit :
> Le vendredi 26 mars 2010 à 16:48 -0500, Andy Fleming a écrit :
> > For various reasons, we have been running a stress test on one of our
> > boards.  The test consists of initiating 2-3 flood pings from a
> > Windows box running Cygwin, plus one additional ping we use as a
> > "heartbeat".  The ping flood is overwhelming our board (we're dropping
> > packets at a prodigious rate), but the board continues to respond for
> > a while.  In addition, we are running a script on the  board which
> > alternates bringing up and bringing down the interface every ten
> > seconds.  After a highly variable amount of time, the board stops
> > replying to the pings.  We suspected a driver issue, however, on
> > closer inspection, we are still able to send and receive packets (I
> > can ping *from* the board to the PC, and I can *telnet* from the PC to
> > the board).  We tried pinging the board from another PC, and it also
> > failed.  Essentially, ICMP echo requests are being ignored (A glance
> > at memory indicates that packets are arriving, but no packets are
> > being enqueued to the ethernet controller).  We still have a lot more
> > debugging to do, but I was wondering if anyone had ever seen something
> > like this, or might be quicker to realize the obvious mistake we're
> > making.
> > 
> > Thanks,
> > Andy Fleming
> 
> 
> kernel version ?
> 
> NIC driver ?
> 
> Are ICMP echo request received ? (grep Icmp /proc/net/snmp)
> 

vi +1166 net/ipv4/icmp.c

        /* Enough space for 2 64K ICMP packets, including
         * sk_buff struct overhead.
         */
        sk->sk_sndbuf =
                (2 * ((64 * 1024) + sizeof(struct sk_buff)));


If many ICMP replies are lost/leaked by your driver when doing up/down
things, ICMP socket can consume all its sndbuf reserve and no more icmp
replies can be sent (a reboot is needed)

You could try changing sk->sk_sndbuf to 0x7FFFFFFF  to see if the icmp
replies survive longer to your tests. If this is the case, then find the
leaks in your driver (tx path, maybe you forgot to free skbs in some
reset cases ?)



We should add a SNMP counter for failed ip_append() calls in
icmp_push_reply()...



^ permalink raw reply

* Re: [PATCH] Add MSG_WAITFORONE flag to recvmmsg
From: Eric Dumazet @ 2010-03-26 22:44 UTC (permalink / raw)
  To: Brandon L Black
  Cc: netdev, David S. Miller, Arnaldo Carvalho de Melo, Ulrich Drepper,
	linux-kernel
In-Reply-To: <20100326223530.GA11817@xpc.home>

Le vendredi 26 mars 2010 à 17:35 -0500, Brandon L Black a écrit :
> From: Brandon L Black <blblack@gmail.com>
> 
> Add new flag MSG_WAITFORONE for the recvmmsg() syscall.
> When this flag is specified for a blocking socket, recvmmsg()
> will only block until at least 1 packet is available.  The
> default behavior is to block until all vlen packets are
> available.  This flag has no effect on non-blocking sockets
> or when used in combination with MSG_DONTWAIT.
> 
> Signed-off-by: Brandon L Black <blblack@gmail.com>


> 
> ---
> diff --git a/include/linux/socket.h b/include/linux/socket.h
> index 7b3aae2..354cc56 100644
> --- a/include/linux/socket.h
> +++ b/include/linux/socket.h
> @@ -255,6 +255,7 @@ struct ucred {
>  #define MSG_ERRQUEUE	0x2000	/* Fetch message from error queue */
>  #define MSG_NOSIGNAL	0x4000	/* Do not generate SIGPIPE */
>  #define MSG_MORE	0x8000	/* Sender will send more */
> +#define MSG_WAITFORONE	0x10000	/* recvmmsg(): block until 1+ packets avail */
>  
>  #define MSG_EOF         MSG_FIN
>  
> diff --git a/net/socket.c b/net/socket.c
> index 769c386..33304d1 100644
> --- a/net/socket.c
> +++ b/net/socket.c
> @@ -2133,7 +2133,10 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
>  
>  		if (err)
>  			break;
> -		++datagrams;
> +
> +		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
> +		if (!datagrams++ && (flags & MSG_WAITFORONE))
> +			flags |= MSG_DONTWAIT;


Hmmm, no need to test !datagram, just do :

	++datagrams;

	if (flags & MSG_WAITFORONE)
		flags |= MSG_DONTWAIT;




^ permalink raw reply

* [PATCH] Add MSG_WAITFORONE flag to recvmmsg
From: Brandon L Black @ 2010-03-26 22:35 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Arnaldo Carvalho de Melo, Ulrich Drepper,
	linux-kernel


From: Brandon L Black <blblack@gmail.com>

Add new flag MSG_WAITFORONE for the recvmmsg() syscall.
When this flag is specified for a blocking socket, recvmmsg()
will only block until at least 1 packet is available.  The
default behavior is to block until all vlen packets are
available.  This flag has no effect on non-blocking sockets
or when used in combination with MSG_DONTWAIT.

Signed-off-by: Brandon L Black <blblack@gmail.com>

---
diff --git a/include/linux/socket.h b/include/linux/socket.h
index 7b3aae2..354cc56 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -255,6 +255,7 @@ struct ucred {
 #define MSG_ERRQUEUE	0x2000	/* Fetch message from error queue */
 #define MSG_NOSIGNAL	0x4000	/* Do not generate SIGPIPE */
 #define MSG_MORE	0x8000	/* Sender will send more */
+#define MSG_WAITFORONE	0x10000	/* recvmmsg(): block until 1+ packets avail */
 
 #define MSG_EOF         MSG_FIN
 
diff --git a/net/socket.c b/net/socket.c
index 769c386..33304d1 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2133,7 +2133,10 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
 
 		if (err)
 			break;
-		++datagrams;
+
+		/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
+		if (!datagrams++ && (flags & MSG_WAITFORONE))
+			flags |= MSG_DONTWAIT;
 
 		if (timeout) {
 			ktime_get_ts(timeout);

^ permalink raw reply related

* Re: ICMP echo reply fails
From: Eric Dumazet @ 2010-03-26 22:06 UTC (permalink / raw)
  To: Andy Fleming; +Cc: netdev
In-Reply-To: <2acbd3e41003261448q26cb19d4w63487894b24f0254@mail.gmail.com>

Le vendredi 26 mars 2010 à 16:48 -0500, Andy Fleming a écrit :
> For various reasons, we have been running a stress test on one of our
> boards.  The test consists of initiating 2-3 flood pings from a
> Windows box running Cygwin, plus one additional ping we use as a
> "heartbeat".  The ping flood is overwhelming our board (we're dropping
> packets at a prodigious rate), but the board continues to respond for
> a while.  In addition, we are running a script on the  board which
> alternates bringing up and bringing down the interface every ten
> seconds.  After a highly variable amount of time, the board stops
> replying to the pings.  We suspected a driver issue, however, on
> closer inspection, we are still able to send and receive packets (I
> can ping *from* the board to the PC, and I can *telnet* from the PC to
> the board).  We tried pinging the board from another PC, and it also
> failed.  Essentially, ICMP echo requests are being ignored (A glance
> at memory indicates that packets are arriving, but no packets are
> being enqueued to the ethernet controller).  We still have a lot more
> debugging to do, but I was wondering if anyone had ever seen something
> like this, or might be quicker to realize the obvious mistake we're
> making.
> 
> Thanks,
> Andy Fleming


kernel version ?

NIC driver ?

Are ICMP echo request received ? (grep Icmp /proc/net/snmp)



^ permalink raw reply

* ICMP echo reply fails
From: Andy Fleming @ 2010-03-26 21:48 UTC (permalink / raw)
  To: netdev

For various reasons, we have been running a stress test on one of our
boards.  The test consists of initiating 2-3 flood pings from a
Windows box running Cygwin, plus one additional ping we use as a
"heartbeat".  The ping flood is overwhelming our board (we're dropping
packets at a prodigious rate), but the board continues to respond for
a while.  In addition, we are running a script on the  board which
alternates bringing up and bringing down the interface every ten
seconds.  After a highly variable amount of time, the board stops
replying to the pings.  We suspected a driver issue, however, on
closer inspection, we are still able to send and receive packets (I
can ping *from* the board to the PC, and I can *telnet* from the PC to
the board).  We tried pinging the board from another PC, and it also
failed.  Essentially, ICMP echo requests are being ignored (A glance
at memory indicates that packets are arriving, but no packets are
being enqueued to the ethernet controller).  We still have a lot more
debugging to do, but I was wondering if anyone had ever seen something
like this, or might be quicker to realize the obvious mistake we're
making.

Thanks,
Andy Fleming

^ permalink raw reply

* [net-next-2.6 PATCH] igb: add per-packet timestamping
From: Jeff Kirsher @ 2010-03-26 21:36 UTC (permalink / raw)
  To: davem; +Cc: netdev, gospo, Nicholas Nunley, Jeff Kirsher

From: Nick Nunley <nicholasx.d.nunley@intel.com>

This patch adds support for per-packet timestamping for the
82580 adapter. The rx timestamp code is also pulled out of the
inlined rx hotpath and instead moved to a seperate function.

This version adds a comment explaining the per-packet timestamping
code added to igb_hwtstamp_ioctl().

Signed-off-by: Nicholas Nunley <nicholasx.d.nunley@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/igb/e1000_82575.h |    2 ++
 drivers/net/igb/igb.h         |    2 ++
 drivers/net/igb/igb_main.c    |   45 ++++++++++++++++++++++++++++++++++-------
 3 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h
index c1cad8a..cbd1e12 100644
--- a/drivers/net/igb/e1000_82575.h
+++ b/drivers/net/igb/e1000_82575.h
@@ -53,6 +53,7 @@ extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
 #define E1000_SRRCTL_DESCTYPE_ADV_ONEBUF                0x02000000
 #define E1000_SRRCTL_DESCTYPE_HDR_SPLIT_ALWAYS          0x0A000000
 #define E1000_SRRCTL_DROP_EN                            0x80000000
+#define E1000_SRRCTL_TIMESTAMP                          0x40000000
 
 #define E1000_MRQC_ENABLE_RSS_4Q            0x00000002
 #define E1000_MRQC_ENABLE_VMDQ              0x00000003
@@ -109,6 +110,7 @@ union e1000_adv_rx_desc {
 #define E1000_RXDADV_HDRBUFLEN_MASK      0x7FE0
 #define E1000_RXDADV_HDRBUFLEN_SHIFT     5
 #define E1000_RXDADV_STAT_TS             0x10000 /* Pkt was time stamped */
+#define E1000_RXDADV_STAT_TSIP           0x08000 /* timestamp in packet */
 
 /* Transmit Descriptor - Advanced */
 union e1000_adv_tx_desc {
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index a177570..4f69b6d 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -107,6 +107,7 @@ struct vf_data_storage {
 #define MAXIMUM_ETHERNET_VLAN_SIZE 1522
 
 /* Supported Rx Buffer Sizes */
+#define IGB_RXBUFFER_64    64     /* Used for packet split */
 #define IGB_RXBUFFER_128   128    /* Used for packet split */
 #define IGB_RXBUFFER_1024  1024
 #define IGB_RXBUFFER_2048  2048
@@ -324,6 +325,7 @@ struct igb_adapter {
 
 #define IGB_82576_TSYNC_SHIFT 19
 #define IGB_82580_TSYNC_SHIFT 24
+#define IGB_TS_HDR_LEN        16
 enum e1000_state_t {
 	__IGB_TESTING,
 	__IGB_RESETTING,
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index 2501c5d..9f9382b 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -2602,6 +2602,8 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
 		         E1000_SRRCTL_BSIZEPKT_SHIFT;
 		srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
 	}
+	if (hw->mac.type == e1000_82580)
+		srrctl |= E1000_SRRCTL_TIMESTAMP;
 	/* Only set Drop Enable if we are supporting multiple queues */
 	if (adapter->vfs_allocated_count || adapter->num_rx_queues > 1)
 		srrctl |= E1000_SRRCTL_DROP_EN;
@@ -3936,6 +3938,9 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
 	 * i.e. RXBUFFER_2048 --> size-4096 slab
 	 */
 
+	if (adapter->hw.mac.type == e1000_82580)
+		max_frame += IGB_TS_HDR_LEN;
+
 	if (max_frame <= IGB_RXBUFFER_1024)
 		rx_buffer_len = IGB_RXBUFFER_1024;
 	else if (max_frame <= MAXIMUM_ETHERNET_VLAN_SIZE)
@@ -3943,6 +3948,14 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
 	else
 		rx_buffer_len = IGB_RXBUFFER_128;
 
+	if ((max_frame == ETH_FRAME_LEN + ETH_FCS_LEN + IGB_TS_HDR_LEN) ||
+	     (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE + IGB_TS_HDR_LEN))
+		rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE + IGB_TS_HDR_LEN;
+
+	if ((adapter->hw.mac.type == e1000_82580) &&
+	    (rx_buffer_len == IGB_RXBUFFER_128))
+		rx_buffer_len += IGB_RXBUFFER_64;
+
 	if (netif_running(netdev))
 		igb_down(adapter);
 
@@ -5159,7 +5172,7 @@ static inline void igb_rx_checksum_adv(struct igb_ring *ring,
 	dev_dbg(&ring->pdev->dev, "cksum success: bits %08X\n", status_err);
 }
 
-static inline void igb_rx_hwtstamp(struct igb_q_vector *q_vector, u32 staterr,
+static void igb_rx_hwtstamp(struct igb_q_vector *q_vector, u32 staterr,
                                    struct sk_buff *skb)
 {
 	struct igb_adapter *adapter = q_vector->adapter;
@@ -5177,13 +5190,18 @@ static inline void igb_rx_hwtstamp(struct igb_q_vector *q_vector, u32 staterr,
 	 * If nothing went wrong, then it should have a skb_shared_tx that we
 	 * can turn into a skb_shared_hwtstamps.
 	 */
-	if (likely(!(staterr & E1000_RXDADV_STAT_TS)))
-		return;
-	if (!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
-		return;
+	if (staterr & E1000_RXDADV_STAT_TSIP) {
+		u32 *stamp = (u32 *)skb->data;
+		regval = le32_to_cpu(*(stamp + 2));
+		regval |= (u64)le32_to_cpu(*(stamp + 3)) << 32;
+		skb_pull(skb, IGB_TS_HDR_LEN);
+	} else {
+		if(!(rd32(E1000_TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID))
+			return;
 
-	regval = rd32(E1000_RXSTMPL);
-	regval |= (u64)rd32(E1000_RXSTMPH) << 32;
+		regval = rd32(E1000_RXSTMPL);
+		regval |= (u64)rd32(E1000_RXSTMPH) << 32;
+	}
 
 	igb_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
 }
@@ -5291,7 +5309,8 @@ send_up:
 			goto next_desc;
 		}
 
-		igb_rx_hwtstamp(q_vector, staterr, skb);
+		if (staterr & (E1000_RXDADV_STAT_TSIP | E1000_RXDADV_STAT_TS))
+			igb_rx_hwtstamp(q_vector, staterr, skb);
 		total_bytes += skb->len;
 		total_packets++;
 
@@ -5571,6 +5590,16 @@ static int igb_hwtstamp_ioctl(struct net_device *netdev,
 		return 0;
 	}
 
+	/*
+	 * Per-packet timestamping only works if all packets are
+	 * timestamped, so enable timestamping in all packets as
+	 * long as one rx filter was configured.
+	 */
+	if ((hw->mac.type == e1000_82580) && tsync_rx_ctl) {
+		tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED;
+		tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL;
+	}
+
 	/* enable/disable TX */
 	regval = rd32(E1000_TSYNCTXCTL);
 	regval &= ~E1000_TSYNCTXCTL_ENABLED;


^ permalink raw reply related

* [net-2.6 PATCH] e1000: do not modify tx_queue_len on link speed change
From: Jeff Kirsher @ 2010-03-26 21:25 UTC (permalink / raw)
  To: davem
  Cc: netdev, gospo, Franco Fichtner, Emil Tantilov, Jesse Brandeburg,
	Jeff Kirsher

From: Emil Tantilov <emil.s.tantilov@intel.com>

Previously the driver tweaked txqueuelen to avoid false Tx hang reports
seen at half duplex.  This had the effect of overriding user set values
on link change/reset. Testing shows that adjusting only the timeout
factor is sufficient to prevent Tx hang reports at half duplex.

This patch removes all instances of tx_queue_len in the driver.

Based on e1000e patch by Franco Fichtner <franco@lastsummer.de>

CC: Franco Fichtner <franco@lastsummer.de>
Signed-off-by: Emil Tantilov <emil.s.tantilov@intel.com>
Acked-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
---

 drivers/net/e1000/e1000.h      |    1 -
 drivers/net/e1000/e1000_main.c |    9 +--------
 2 files changed, 1 insertions(+), 9 deletions(-)

diff --git a/drivers/net/e1000/e1000.h b/drivers/net/e1000/e1000.h
index 9902b33..2f29c21 100644
--- a/drivers/net/e1000/e1000.h
+++ b/drivers/net/e1000/e1000.h
@@ -261,7 +261,6 @@ struct e1000_adapter {
 	/* TX */
 	struct e1000_tx_ring *tx_ring;      /* One per active queue */
 	unsigned int restart_queue;
-	unsigned long tx_queue_len;
 	u32 txd_cmd;
 	u32 tx_int_delay;
 	u32 tx_abs_int_delay;
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c
index 8be6fae..b15ece2 100644
--- a/drivers/net/e1000/e1000_main.c
+++ b/drivers/net/e1000/e1000_main.c
@@ -383,8 +383,6 @@ static void e1000_configure(struct e1000_adapter *adapter)
 		adapter->alloc_rx_buf(adapter, ring,
 		                      E1000_DESC_UNUSED(ring));
 	}
-
-	adapter->tx_queue_len = netdev->tx_queue_len;
 }
 
 int e1000_up(struct e1000_adapter *adapter)
@@ -503,7 +501,6 @@ void e1000_down(struct e1000_adapter *adapter)
 	del_timer_sync(&adapter->watchdog_timer);
 	del_timer_sync(&adapter->phy_info_timer);
 
-	netdev->tx_queue_len = adapter->tx_queue_len;
 	adapter->link_speed = 0;
 	adapter->link_duplex = 0;
 	netif_carrier_off(netdev);
@@ -2316,19 +2313,15 @@ static void e1000_watchdog(unsigned long data)
 			        E1000_CTRL_RFCE) ? "RX" : ((ctrl &
 			        E1000_CTRL_TFCE) ? "TX" : "None" )));
 
-			/* tweak tx_queue_len according to speed/duplex
-			 * and adjust the timeout factor */
-			netdev->tx_queue_len = adapter->tx_queue_len;
+			/* adjust timeout factor according to speed/duplex */
 			adapter->tx_timeout_factor = 1;
 			switch (adapter->link_speed) {
 			case SPEED_10:
 				txb2b = false;
-				netdev->tx_queue_len = 10;
 				adapter->tx_timeout_factor = 16;
 				break;
 			case SPEED_100:
 				txb2b = false;
-				netdev->tx_queue_len = 100;
 				/* maybe add some timeout factor ? */
 				break;
 			}


^ permalink raw reply related

* Re: [PATCH] r8169: Fix rtl8169_rx_interrupt()
From: François Romieu @ 2010-03-26 20:29 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Sergey Senozhatsky, Oleg Nesterov, David Miller, netdev
In-Reply-To: <1269523180.3626.25.camel@edumazet-laptop>

Eric Dumazet <eric.dumazet@gmail.com> :
[...]
> Thanks for the report. Problem is I am not confident enough on this
> driver.

Your patch is simple and it improves things.

> I believe François Romieu is the one that can possibly push a patch ?

Feel free to push.

-- 
Ueimor

^ permalink raw reply

* RE: [net-2.6 PATCH 2/3] ixgbe: In SR-IOV mode insert delay before bring the adapter up
From: Rose, Gregory V @ 2010-03-26 19:45 UTC (permalink / raw)
  To: David Miller, Kirsher, Jeffrey T; +Cc: netdev@vger.kernel.org, gospo@redhat.com
In-Reply-To: <20100326.115753.160228163.davem@davemloft.net>

>-----Original Message-----
>From: David Miller [mailto:davem@davemloft.net]
>Sent: Friday, March 26, 2010 11:58 AM
>To: Kirsher, Jeffrey T
>Cc: netdev@vger.kernel.org; gospo@redhat.com; Rose, Gregory V
>Subject: Re: [net-2.6 PATCH 2/3] ixgbe: In SR-IOV mode insert delay
>before bring the adapter up
>
>
>
> My point is that this behavior is basically extremely undesirable.

No argument from me there.  We've been discussing design changes to maintain a little more state in the driver so that we wouldn't have to reset the entire device every time someone makes a minor configuration change.  However, I have no target date for that.  I agree that at some point in systems with a large number of interfaces this behavior becomes untenable.

- Greg


^ permalink raw reply

* Re: [net-2.6 PATCH 2/2] ixgbe: filter FIP frames into the FCoE offload queues
From: David Miller @ 2010-03-26 18:58 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, christopher.leech
In-Reply-To: <20100324224521.6653.17418.stgit@localhost.localdomain>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Wed, 24 Mar 2010 15:45:21 -0700

> From: Chris Leech <christopher.leech@intel.com>
> 
> During FCF solicitation, the switch is supposed to pad the
> solicited advertisement out to the endpoints specified
> maximum FCoE frame size.  That means that we need to receive
> FIP frames that are larger than the standard MTU.  To make
> sure the receive queue is configured correctly, we should be
> filtering FIP traffic into the FCoE queues.
> 
> Signed-off-by: Chris Leech <christopher.leech@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.

^ permalink raw reply

* Re: [net-2.6 PATCH 1/2] ixgbe: Priority tag FIP frames
From: David Miller @ 2010-03-26 18:58 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, robert.w.love, christopher.leech
In-Reply-To: <20100324224500.6653.28216.stgit@localhost.localdomain>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Wed, 24 Mar 2010 15:45:00 -0700

> From: Robert Love <robert.w.love@intel.com>
> 
> Currently FIP (FCoE Initialization Protocol) frames
> are going untagged. This causes various problems
> with FCFs (switches) that have negotiated a priority
> over dcbx. This patch tags FIP frames with the same
> priority as the FCoE frames.
> 
> Signed-off-by: Robert Love <robert.w.love@intel.com>
> Signed-off-by: Chris Leech <christopher.leech@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.

^ permalink raw reply

* Re: [net-2.6 PATCH] ixgbe: Don't allow user buffer count to exceed 256
From: David Miller @ 2010-03-26 18:58 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, robert.w.love, yi.zou, frank_1.zhang
In-Reply-To: <20100324200204.6384.63977.stgit@localhost.localdomain>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Wed, 24 Mar 2010 13:02:04 -0700

> From: Robert Love <robert.w.love@intel.com>
> 
> If the user buffer count was 256 the shift would place a 1
> in the offset region leading to errors. It also overwrites
> the uers buffer list. This patch makes sure that at most
> 256 user buffers are allowed for DDP and the buffer count
> is masked properly such that it doesn't overwrite the offset
> when shifting the bits.
> 
> Signed-off-by: Robert Love <robert.w.love@intel.com>
> Signed-off-by: Yi Zou <yi.zou@intel.com>
> Signed-off-by: Frank Zhang <frank_1.zhang@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.

^ permalink raw reply

* Re: [net-2.6 PATCH] ixgbe: cleanup maximum number of tx queues
From: David Miller @ 2010-03-26 18:58 UTC (permalink / raw)
  To: jeffrey.t.kirsher; +Cc: netdev, gospo, john.r.fastabend
In-Reply-To: <20100324200144.6384.17291.stgit@localhost.localdomain>

From: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Date: Wed, 24 Mar 2010 13:01:45 -0700

> From: John Fastabend <john.r.fastabend@intel.com>
> 
> In the last patch I missed an unecessary min_t comparison.
> This patch removes it, the path allocates at most
> 72 tx queues for 82599 and 24 for 82598 there is no need
> for this check.
> 
> Additionally this sets MAX_[TX|RX]_QUEUES to 72.  Which is
> used as the size for the tx/rx_ring arrays. There is no
> reason to have more tx_rings/rx_rings then num_tx_queues.
> 
> Signed-off-by: John Fastabend <john.r.fastabend@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>

Applied.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox