--- /dev/null
+From 87943415110077993d4a087999061322692a11a3 Mon Sep 17 00:00:00 2001
+From: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Date: Fri, 15 Mar 2013 11:32:30 +0000
+Subject: inet: limit length of fragment queue hash table bucket lists
+
+
+From: Hannes Frederic Sowa <hannes@stressinduktion.org>
+
+[ Upstream commit 5a3da1fe9561828d0ca7eca664b16ec2b9bf0055 ]
+
+This patch introduces a constant limit of the fragment queue hash
+table bucket list lengths. Currently the limit 128 is choosen somewhat
+arbitrary and just ensures that we can fill up the fragment cache with
+empty packets up to the default ip_frag_high_thresh limits. It should
+just protect from list iteration eating considerable amounts of cpu.
+
+If we reach the maximum length in one hash bucket a warning is printed.
+This is implemented on the caller side of inet_frag_find to distinguish
+between the different users of inet_fragment.c.
+
+I dropped the out of memory warning in the ipv4 fragment lookup path,
+because we already get a warning by the slab allocator.
+
+Cc: Eric Dumazet <eric.dumazet@gmail.com>
+Cc: Jesper Dangaard Brouer <jbrouer@redhat.com>
+Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Acked-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/inet_frag.h | 9 +++++++++
+ net/ipv4/inet_fragment.c | 20 +++++++++++++++++++-
+ net/ipv4/ip_fragment.c | 12 ++++++------
+ net/ipv6/netfilter/nf_conntrack_reasm.c | 12 ++++++------
+ net/ipv6/reassembly.c | 8 ++++++--
+ 5 files changed, 46 insertions(+), 15 deletions(-)
+
+--- a/include/net/inet_frag.h
++++ b/include/net/inet_frag.h
+@@ -33,6 +33,13 @@ struct inet_frag_queue {
+
+ #define INETFRAGS_HASHSZ 64
+
++/* averaged:
++ * max_depth = default ipfrag_high_thresh / INETFRAGS_HASHSZ /
++ * rounded up (SKB_TRUELEN(0) + sizeof(struct ipq or
++ * struct frag_queue))
++ */
++#define INETFRAGS_MAXDEPTH 128
++
+ struct inet_frags {
+ struct hlist_head hash[INETFRAGS_HASHSZ];
+ rwlock_t lock;
+@@ -64,6 +71,8 @@ int inet_frag_evictor(struct netns_frags
+ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
+ struct inet_frags *f, void *key, unsigned int hash)
+ __releases(&f->lock);
++void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
++ const char *prefix);
+
+ static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
+ {
+--- a/net/ipv4/inet_fragment.c
++++ b/net/ipv4/inet_fragment.c
+@@ -21,6 +21,7 @@
+ #include <linux/rtnetlink.h>
+ #include <linux/slab.h>
+
++#include <net/sock.h>
+ #include <net/inet_frag.h>
+
+ static void inet_frag_secret_rebuild(unsigned long dummy)
+@@ -271,6 +272,7 @@ struct inet_frag_queue *inet_frag_find(s
+ {
+ struct inet_frag_queue *q;
+ struct hlist_node *n;
++ int depth = 0;
+
+ hlist_for_each_entry(q, n, &f->hash[hash], list) {
+ if (q->net == nf && f->match(q, key)) {
+@@ -278,9 +280,25 @@ struct inet_frag_queue *inet_frag_find(s
+ read_unlock(&f->lock);
+ return q;
+ }
++ depth++;
+ }
+ read_unlock(&f->lock);
+
+- return inet_frag_create(nf, f, key);
++ if (depth <= INETFRAGS_MAXDEPTH)
++ return inet_frag_create(nf, f, key);
++ else
++ return ERR_PTR(-ENOBUFS);
+ }
+ EXPORT_SYMBOL(inet_frag_find);
++
++void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
++ const char *prefix)
++{
++ static const char msg[] = "inet_frag_find: Fragment hash bucket"
++ " list length grew over limit " __stringify(INETFRAGS_MAXDEPTH)
++ ". Dropping fragment.\n";
++
++ if (PTR_ERR(q) == -ENOBUFS)
++ LIMIT_NETDEBUG(KERN_WARNING "%s%s", prefix, msg);
++}
++EXPORT_SYMBOL(inet_frag_maybe_warn_overflow);
+--- a/net/ipv4/ip_fragment.c
++++ b/net/ipv4/ip_fragment.c
+@@ -20,6 +20,8 @@
+ * Patrick McHardy : LRU queue of frag heads for evictor.
+ */
+
++#define pr_fmt(fmt) "IPv4: " fmt
++
+ #include <linux/compiler.h>
+ #include <linux/module.h>
+ #include <linux/types.h>
+@@ -292,14 +294,12 @@ static inline struct ipq *ip_find(struct
+ hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);
+
+ q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash);
+- if (q == NULL)
+- goto out_nomem;
++ if (IS_ERR_OR_NULL(q)) {
++ inet_frag_maybe_warn_overflow(q, pr_fmt());
++ return NULL;
++ }
+
+ return container_of(q, struct ipq, q);
+-
+-out_nomem:
+- LIMIT_NETDEBUG(KERN_ERR "ip_frag_create: no memory left !\n");
+- return NULL;
+ }
+
+ /* Is the fragment too far ahead to be part of ipq? */
+--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
++++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
+@@ -14,6 +14,8 @@
+ * 2 of the License, or (at your option) any later version.
+ */
+
++#define pr_fmt(fmt) "IPv6-nf: " fmt
++
+ #include <linux/errno.h>
+ #include <linux/types.h>
+ #include <linux/string.h>
+@@ -176,14 +178,12 @@ fq_find(__be32 id, u32 user, struct in6_
+
+ q = inet_frag_find(&nf_init_frags, &nf_frags, &arg, hash);
+ local_bh_enable();
+- if (q == NULL)
+- goto oom;
++ if (IS_ERR_OR_NULL(q)) {
++ inet_frag_maybe_warn_overflow(q, pr_fmt());
++ return NULL;
++ }
+
+ return container_of(q, struct nf_ct_frag6_queue, q);
+-
+-oom:
+- pr_debug("Can't alloc new queue\n");
+- return NULL;
+ }
+
+
+--- a/net/ipv6/reassembly.c
++++ b/net/ipv6/reassembly.c
+@@ -26,6 +26,9 @@
+ * YOSHIFUJI,H. @USAGI Always remove fragment header to
+ * calculate ICV correctly.
+ */
++
++#define pr_fmt(fmt) "IPv6: " fmt
++
+ #include <linux/errno.h>
+ #include <linux/types.h>
+ #include <linux/string.h>
+@@ -239,9 +242,10 @@ fq_find(struct net *net, __be32 id, cons
+ hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd);
+
+ q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash);
+- if (q == NULL)
++ if (IS_ERR_OR_NULL(q)) {
++ inet_frag_maybe_warn_overflow(q, pr_fmt());
+ return NULL;
+-
++ }
+ return container_of(q, struct frag_queue, q);
+ }
+
--- /dev/null
+From 6a3f604d999488847254e8e71202420e92961cdf Mon Sep 17 00:00:00 2001
+From: "Denis V. Lunev" <den@openvz.org>
+Date: Wed, 13 Mar 2013 00:24:15 +0000
+Subject: ipv4: fix definition of FIB_TABLE_HASHSZ
+
+
+From: "Denis V. Lunev" <den@openvz.org>
+
+[ Upstream commit 5b9e12dbf92b441b37136ea71dac59f05f2673a9 ]
+
+a long time ago by the commit
+
+ commit 93456b6d7753def8760b423ac6b986eb9d5a4a95
+ Author: Denis V. Lunev <den@openvz.org>
+ Date: Thu Jan 10 03:23:38 2008 -0800
+
+ [IPV4]: Unify access to the routing tables.
+
+the defenition of FIB_HASH_TABLE size has obtained wrong dependency:
+it should depend upon CONFIG_IP_MULTIPLE_TABLES (as was in the original
+code) but it was depended from CONFIG_IP_ROUTE_MULTIPATH
+
+This patch returns the situation to the original state.
+
+The problem was spotted by Tingwei Liu.
+
+Signed-off-by: Denis V. Lunev <den@openvz.org>
+CC: Tingwei Liu <tingw.liu@gmail.com>
+CC: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/ip_fib.h | 12 +++++-------
+ 1 file changed, 5 insertions(+), 7 deletions(-)
+
+--- a/include/net/ip_fib.h
++++ b/include/net/ip_fib.h
+@@ -129,18 +129,16 @@ struct fib_result_nl {
+ };
+
+ #ifdef CONFIG_IP_ROUTE_MULTIPATH
+-
+ #define FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel])
+-
+-#define FIB_TABLE_HASHSZ 2
+-
+ #else /* CONFIG_IP_ROUTE_MULTIPATH */
+-
+ #define FIB_RES_NH(res) ((res).fi->fib_nh[0])
++#endif /* CONFIG_IP_ROUTE_MULTIPATH */
+
++#ifdef CONFIG_IP_MULTIPLE_TABLES
+ #define FIB_TABLE_HASHSZ 256
+-
+-#endif /* CONFIG_IP_ROUTE_MULTIPATH */
++#else
++#define FIB_TABLE_HASHSZ 2
++#endif
+
+ extern __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
+
--- /dev/null
+From fddadd642d6f754bb2b375af63b1d58dd14a4bb0 Mon Sep 17 00:00:00 2001
+From: David Ward <david.ward@ll.mit.edu>
+Date: Mon, 11 Mar 2013 10:43:39 +0000
+Subject: net/ipv4: Ensure that location of timestamp option is stored
+
+
+From: David Ward <david.ward@ll.mit.edu>
+
+[ Upstream commit 4660c7f498c07c43173142ea95145e9dac5a6d14 ]
+
+This is needed in order to detect if the timestamp option appears
+more than once in a packet, to remove the option if the packet is
+fragmented, etc. My previous change neglected to store the option
+location when the router addresses were prespecified and Pointer >
+Length. But now the option location is also stored when Flag is an
+unrecognized value, to ensure these option handling behaviors are
+still performed.
+
+Signed-off-by: David Ward <david.ward@ll.mit.edu>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/ip_options.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+--- a/net/ipv4/ip_options.c
++++ b/net/ipv4/ip_options.c
+@@ -358,7 +358,6 @@ int ip_options_compile(struct net *net,
+ }
+ switch (optptr[3]&0xF) {
+ case IPOPT_TS_TSONLY:
+- opt->ts = optptr - iph;
+ if (skb)
+ timeptr = &optptr[optptr[2]-1];
+ opt->ts_needtime = 1;
+@@ -369,7 +368,6 @@ int ip_options_compile(struct net *net,
+ pp_ptr = optptr + 2;
+ goto error;
+ }
+- opt->ts = optptr - iph;
+ if (rt) {
+ memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4);
+ timeptr = &optptr[optptr[2]+3];
+@@ -383,7 +381,6 @@ int ip_options_compile(struct net *net,
+ pp_ptr = optptr + 2;
+ goto error;
+ }
+- opt->ts = optptr - iph;
+ {
+ __be32 addr;
+ memcpy(&addr, &optptr[optptr[2]-1], 4);
+@@ -416,12 +413,12 @@ int ip_options_compile(struct net *net,
+ pp_ptr = optptr + 3;
+ goto error;
+ }
+- opt->ts = optptr - iph;
+ if (skb) {
+ optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4);
+ opt->is_changed = 1;
+ }
+ }
++ opt->ts = optptr - iph;
+ break;
+ case IPOPT_RA:
+ if (optlen < 4) {
--- /dev/null
+From 7d189b63179e2260024257f8b3ec9eb664d5773f Mon Sep 17 00:00:00 2001
+From: Veaceslav Falico <vfalico@redhat.com>
+Date: Mon, 11 Mar 2013 00:21:48 +0000
+Subject: netconsole: don't call __netpoll_cleanup() while atomic
+
+
+From: Veaceslav Falico <vfalico@redhat.com>
+
+[ Upstream commit 3f315bef23075ea8a98a6fe4221a83b83456d970 ]
+
+__netpoll_cleanup() is called in netconsole_netdev_event() while holding a
+spinlock. Release/acquire the spinlock before/after it and restart the
+loop. Also, disable the netconsole completely, because we won't have chance
+after the restart of the loop, and might end up in a situation where
+nt->enabled == 1 and nt->np.dev == NULL.
+
+Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
+Acked-by: Neil Horman <nhorman@tuxdriver.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/netconsole.c | 20 +++++++++-----------
+ 1 file changed, 9 insertions(+), 11 deletions(-)
+
+--- a/drivers/net/netconsole.c
++++ b/drivers/net/netconsole.c
+@@ -630,6 +630,7 @@ static int netconsole_netdev_event(struc
+ goto done;
+
+ spin_lock_irqsave(&target_list_lock, flags);
++restart:
+ list_for_each_entry(nt, &target_list, list) {
+ netconsole_target_get(nt);
+ if (nt->np.dev == dev) {
+@@ -642,20 +643,17 @@ static int netconsole_netdev_event(struc
+ case NETDEV_UNREGISTER:
+ /*
+ * rtnl_lock already held
++ * we might sleep in __netpoll_cleanup()
+ */
+- if (nt->np.dev) {
+- spin_unlock_irqrestore(
+- &target_list_lock,
+- flags);
+- __netpoll_cleanup(&nt->np);
+- spin_lock_irqsave(&target_list_lock,
+- flags);
+- dev_put(nt->np.dev);
+- nt->np.dev = NULL;
+- }
++ spin_unlock_irqrestore(&target_list_lock, flags);
++ __netpoll_cleanup(&nt->np);
++ spin_lock_irqsave(&target_list_lock, flags);
++ dev_put(nt->np.dev);
++ nt->np.dev = NULL;
+ nt->enabled = 0;
+ stopped = true;
+- break;
++ netconsole_target_put(nt);
++ goto restart;
+ }
+ }
+ netconsole_target_put(nt);
--- /dev/null
+From 11353872c868b308382cc0bda4e05c29646e23f2 Mon Sep 17 00:00:00 2001
+From: Vlad Yasevich <vyasevic@redhat.com>
+Date: Wed, 13 Mar 2013 04:18:58 +0000
+Subject: rtnetlink: Mask the rta_type when range checking
+
+
+From: Vlad Yasevich <vyasevic@redhat.com>
+
+[ Upstream commit a5b8db91442fce9c9713fcd656c3698f1adde1d6 ]
+
+Range/validity checks on rta_type in rtnetlink_rcv_msg() do
+not account for flags that may be set. This causes the function
+to return -EINVAL when flags are set on the type (for example
+NLA_F_NESTED).
+
+Signed-off-by: Vlad Yasevich <vyasevic@redhat.com>
+Acked-by: Thomas Graf <tgraf@suug.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/rtnetlink.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/core/rtnetlink.c
++++ b/net/core/rtnetlink.c
+@@ -2011,7 +2011,7 @@ static int rtnetlink_rcv_msg(struct sk_b
+ struct rtattr *attr = (void *)nlh + NLMSG_ALIGN(min_len);
+
+ while (RTA_OK(attr, attrlen)) {
+- unsigned flavor = attr->rta_type;
++ unsigned int flavor = attr->rta_type & NLA_TYPE_MASK;
+ if (flavor) {
+ if (flavor > rta_max[sz_idx])
+ return -EINVAL;
--- /dev/null
+From 878d9aac5ab18c9452efc4df53ae69f72ca2502b Mon Sep 17 00:00:00 2001
+From: Xufeng Zhang <xufeng.zhang@windriver.com>
+Date: Thu, 7 Mar 2013 21:39:37 +0000
+Subject: sctp: don't break the loop while meeting the active_path so as to find the matched transport
+
+
+From: Xufeng Zhang <xufeng.zhang@windriver.com>
+
+[ Upstream commit 2317f449af30073cfa6ec8352e4a65a89e357bdd ]
+
+sctp_assoc_lookup_tsn() function searchs which transport a certain TSN
+was sent on, if not found in the active_path transport, then go search
+all the other transports in the peer's transport_addr_list, however, we
+should continue to the next entry rather than break the loop when meet
+the active_path transport.
+
+Signed-off-by: Xufeng Zhang <xufeng.zhang@windriver.com>
+Acked-by: Neil Horman <nhorman@tuxdriver.com>
+Acked-by: Vlad Yasevich <vyasevich@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/associola.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/sctp/associola.c
++++ b/net/sctp/associola.c
+@@ -1043,7 +1043,7 @@ struct sctp_transport *sctp_assoc_lookup
+ transports) {
+
+ if (transport == active)
+- break;
++ continue;
+ list_for_each_entry(chunk, &transport->transmitted,
+ transmitted_list) {
+ if (key == chunk->subh.data_hdr->tsn) {
revert-usb-ehci-don-t-check-dma-values-in-qh-overlays.patch
sunsu-fix-panic-in-case-of-nonexistent-port-at-console-ttysy-cmdline-option.patch
+net-ipv4-ensure-that-location-of-timestamp-option-is-stored.patch
+netconsole-don-t-call-__netpoll_cleanup-while-atomic.patch
+sctp-don-t-break-the-loop-while-meeting-the-active_path-so-as-to-find-the-matched-transport.patch
+ipv4-fix-definition-of-fib_table_hashsz.patch
+rtnetlink-mask-the-rta_type-when-range-checking.patch
+inet-limit-length-of-fragment-queue-hash-table-bucket-lists.patch
+sfc-fix-loop-condition-for-efx_filter_search-when-for_insert.patch
+sfc-fix-siena-mac-statistics-on-big-endian-platforms.patch
+sfc-do-not-attempt-to-flush-queues-if-dma-is-disabled.patch
+sfc-convert-firmware-subtypes-to-native-byte-order-in-efx_mcdi_get_board_cfg.patch
+sfc-fix-two-causes-of-flush-failure.patch
+sfc-lock-tx-queues-when-calling-netif_device_detach.patch
+sfc-fix-timekeeping-in-efx_mcdi_poll.patch
+sfc-properly-sync-rx-dma-buffer-when-it-is-not-the-last-in-the-page.patch
+sfc-fix-efx_rx_buf_offset-in-the-presence-of-swiotlb.patch
+sfc-detach-net-device-when-stopping-queues-for-reconfiguration.patch
+sfc-disable-soft-interrupt-handling-during-efx_device_detach_sync.patch
+sfc-only-use-tx-push-if-a-single-descriptor-is-to-be-written.patch
--- /dev/null
+From 6d7cf8ca06e28ea10f95a3f8af14e69a19df63ff Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <bhutchings@solarflare.com>
+Date: Fri, 7 Sep 2012 00:58:10 +0100
+Subject: sfc: Convert firmware subtypes to native byte order in efx_mcdi_get_board_cfg()
+
+
+From: Ben Hutchings <bhutchings@solarflare.com>
+
+[ Upstream commit bfeed902946a31692e7a24ed355b6d13ac37d014 ]
+
+On big-endian systems the MTD partition names currently have mangled
+subtype numbers and are not recognised by the firmware update tool
+(sfupdate).
+
+Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
+[bwh: Backported to 3.0: use old macros for length of firmware subtype array]
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/sfc/mcdi.c | 17 +++++++++++------
+ 1 file changed, 11 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/sfc/mcdi.c
++++ b/drivers/net/sfc/mcdi.c
+@@ -666,9 +666,8 @@ int efx_mcdi_get_board_cfg(struct efx_ni
+ u16 *fw_subtype_list)
+ {
+ uint8_t outbuf[MC_CMD_GET_BOARD_CFG_OUT_LEN];
+- size_t outlen;
++ size_t outlen, offset, i;
+ int port_num = efx_port_num(efx);
+- int offset;
+ int rc;
+
+ BUILD_BUG_ON(MC_CMD_GET_BOARD_CFG_IN_LEN != 0);
+@@ -688,10 +687,16 @@ int efx_mcdi_get_board_cfg(struct efx_ni
+ : MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_OFST;
+ if (mac_address)
+ memcpy(mac_address, outbuf + offset, ETH_ALEN);
+- if (fw_subtype_list)
+- memcpy(fw_subtype_list,
+- outbuf + MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST,
+- MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN);
++ if (fw_subtype_list) {
++ offset = MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST;
++ for (i = 0;
++ i < MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_LEN / 2;
++ i++) {
++ fw_subtype_list[i] =
++ le16_to_cpup((__le16 *)(outbuf + offset));
++ offset += 2;
++ }
++ }
+
+ return 0;
+
--- /dev/null
+From 0013c4ed507a351c4f5d26afc5bf0fb3e11528aa Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <bhutchings@solarflare.com>
+Date: Mon, 28 Jan 2013 19:01:06 +0000
+Subject: sfc: Detach net device when stopping queues for reconfiguration
+
+
+From: Ben Hutchings <bhutchings@solarflare.com>
+
+[ Upstream commit 29c69a4882641285a854d6d03ca5adbba68c0034 ]
+
+We must only ever stop TX queues when they are full or the net device
+is not 'ready' so far as the net core, and specifically the watchdog,
+is concerned. Otherwise, the watchdog may fire *immediately* if no
+packets have been added to the queue in the last 5 seconds.
+
+The device is ready if all the following are true:
+
+(a) It has a qdisc
+(b) It is marked present
+(c) It is running
+(d) The link is reported up
+
+(a) and (c) are normally true, and must not be changed by a driver.
+(d) is under our control, but fake link changes may disturb userland.
+This leaves (b). We already mark the device absent during reset
+and self-test, but we need to do the same during MTU changes and ring
+reallocation. We don't need to do this when the device is brought
+down because then (c) is already false.
+
+Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
+[bwh: Backported to 3.0: adjust context]
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/sfc/efx.c | 16 ++++++++++++----
+ 1 file changed, 12 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/sfc/efx.c
++++ b/drivers/net/sfc/efx.c
+@@ -720,6 +720,7 @@ efx_realloc_channels(struct efx_nic *efx
+ unsigned i;
+ int rc;
+
++ efx_device_detach_sync(efx);
+ efx_stop_all(efx);
+ efx_fini_channels(efx);
+
+@@ -763,6 +764,7 @@ out:
+
+ efx_init_channels(efx);
+ efx_start_all(efx);
++ netif_device_attach(efx->net_dev);
+ return rc;
+
+ rollback:
+@@ -1530,8 +1532,12 @@ static void efx_stop_all(struct efx_nic
+ /* Flush efx_mac_work(), refill_workqueue, monitor_work */
+ efx_flush_all(efx);
+
+- /* Stop the kernel transmit interface late, so the watchdog
+- * timer isn't ticking over the flush */
++ /* Stop the kernel transmit interface. This is only valid if
++ * the device is stopped or detached; otherwise the watchdog
++ * may fire immediately.
++ */
++ WARN_ON(netif_running(efx->net_dev) &&
++ netif_device_present(efx->net_dev));
+ if (efx_dev_registered(efx)) {
+ netif_tx_stop_all_queues(efx->net_dev);
+ netif_tx_lock_bh(efx->net_dev);
+@@ -1801,10 +1807,11 @@ static int efx_change_mtu(struct net_dev
+ if (new_mtu > EFX_MAX_MTU)
+ return -EINVAL;
+
+- efx_stop_all(efx);
+-
+ netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu);
+
++ efx_device_detach_sync(efx);
++ efx_stop_all(efx);
++
+ efx_fini_channels(efx);
+
+ mutex_lock(&efx->mac_lock);
+@@ -1817,6 +1824,7 @@ static int efx_change_mtu(struct net_dev
+ efx_init_channels(efx);
+
+ efx_start_all(efx);
++ netif_device_attach(efx->net_dev);
+ return rc;
+ }
+
--- /dev/null
+From db0b188983e2d83bea89206e03a30b55ee283d3e Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <bhutchings@solarflare.com>
+Date: Tue, 5 Mar 2013 01:03:47 +0000
+Subject: sfc: Disable soft interrupt handling during efx_device_detach_sync()
+
+
+From: Ben Hutchings <bhutchings@solarflare.com>
+
+[ Upstream commit 35205b211c8d17a8a0b5e8926cb7c73e9a7ef1ad ]
+
+efx_device_detach_sync() locks all TX queues before marking the device
+detached and thus disabling further TX scheduling. But it can still
+be interrupted by TX completions which then result in TX scheduling in
+soft interrupt context. This will deadlock when it tries to acquire
+a TX queue lock that efx_device_detach_sync() already acquired.
+
+To avoid deadlock, we must use netif_tx_{,un}lock_bh().
+
+Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/sfc/efx.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/sfc/efx.h
++++ b/drivers/net/sfc/efx.h
+@@ -158,9 +158,9 @@ static inline void efx_device_detach_syn
+ * TX scheduler is stopped when we're done and before
+ * netif_device_present() becomes false.
+ */
+- netif_tx_lock(dev);
++ netif_tx_lock_bh(dev);
+ netif_device_detach(dev);
+- netif_tx_unlock(dev);
++ netif_tx_unlock_bh(dev);
+ }
+
+ #endif /* EFX_EFX_H */
--- /dev/null
+From fd216215412a7635c4ba7054eac461a8500f7475 Mon Sep 17 00:00:00 2001
+From: Stuart Hodgson <smhodgson@solarflare.com>
+Date: Fri, 30 Mar 2012 13:04:51 +0100
+Subject: sfc: Do not attempt to flush queues if DMA is disabled
+
+
+From: Stuart Hodgson <smhodgson@solarflare.com>
+
+[ Upstream commit 3dca9d2dc285faf1910d405b65df845cab061356 ]
+
+efx_nic_fatal_interrupt() disables DMA before scheduling a reset.
+After this, we need not and *cannot* flush queues.
+
+Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/sfc/efx.c | 33 +++++++++++++++++++--------------
+ 1 file changed, 19 insertions(+), 14 deletions(-)
+
+--- a/drivers/net/sfc/efx.c
++++ b/drivers/net/sfc/efx.c
+@@ -651,25 +651,30 @@ static void efx_fini_channels(struct efx
+ struct efx_channel *channel;
+ struct efx_tx_queue *tx_queue;
+ struct efx_rx_queue *rx_queue;
++ struct pci_dev *dev = efx->pci_dev;
+ int rc;
+
+ EFX_ASSERT_RESET_SERIALISED(efx);
+ BUG_ON(efx->port_enabled);
+
+- rc = efx_nic_flush_queues(efx);
+- if (rc && EFX_WORKAROUND_7803(efx)) {
+- /* Schedule a reset to recover from the flush failure. The
+- * descriptor caches reference memory we're about to free,
+- * but falcon_reconfigure_mac_wrapper() won't reconnect
+- * the MACs because of the pending reset. */
+- netif_err(efx, drv, efx->net_dev,
+- "Resetting to recover from flush failure\n");
+- efx_schedule_reset(efx, RESET_TYPE_ALL);
+- } else if (rc) {
+- netif_err(efx, drv, efx->net_dev, "failed to flush queues\n");
+- } else {
+- netif_dbg(efx, drv, efx->net_dev,
+- "successfully flushed all queues\n");
++ /* Only perform flush if dma is enabled */
++ if (dev->is_busmaster) {
++ rc = efx_nic_flush_queues(efx);
++
++ if (rc && EFX_WORKAROUND_7803(efx)) {
++ /* Schedule a reset to recover from the flush failure. The
++ * descriptor caches reference memory we're about to free,
++ * but falcon_reconfigure_mac_wrapper() won't reconnect
++ * the MACs because of the pending reset. */
++ netif_err(efx, drv, efx->net_dev,
++ "Resetting to recover from flush failure\n");
++ efx_schedule_reset(efx, RESET_TYPE_ALL);
++ } else if (rc) {
++ netif_err(efx, drv, efx->net_dev, "failed to flush queues\n");
++ } else {
++ netif_dbg(efx, drv, efx->net_dev,
++ "successfully flushed all queues\n");
++ }
+ }
+
+ efx_for_each_channel(channel, efx) {
--- /dev/null
+From f421edcd754f77c2f773aaae7b68067c433f3816 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <bhutchings@solarflare.com>
+Date: Thu, 10 Jan 2013 23:51:54 +0000
+Subject: sfc: Fix efx_rx_buf_offset() in the presence of swiotlb
+
+
+From: Ben Hutchings <bhutchings@solarflare.com>
+
+[ Upstream commits 06e63c57acbb1df7c35ebe846ae416a8b88dfafa,
+ b590ace09d51cd39744e0f7662c5e4a0d1b5d952 and
+ c73e787a8db9117d59b5180baf83203a42ecadca ]
+
+We assume that the mapping between DMA and virtual addresses is done
+on whole pages, so we can find the page offset of an RX buffer using
+the lower bits of the DMA address. However, swiotlb maps in units of
+2K, breaking this assumption.
+
+Add an explicit page_offset field to struct efx_rx_buffer.
+
+Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
+[bwh: Backported to 3.0: adjust context]
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/sfc/net_driver.h | 4 +++-
+ drivers/net/sfc/rx.c | 10 +++++-----
+ 2 files changed, 8 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/sfc/net_driver.h
++++ b/drivers/net/sfc/net_driver.h
+@@ -214,6 +214,7 @@ struct efx_tx_queue {
+ * If both this and page are %NULL, the buffer slot is currently free.
+ * @page: The associated page buffer, if any.
+ * If both this and skb are %NULL, the buffer slot is currently free.
++ * @page_offset: Offset within page. Valid iff @flags & %EFX_RX_BUF_PAGE.
+ * @len: Buffer length, in bytes.
+ * @is_page: Indicates if @page is valid. If false, @skb is valid.
+ */
+@@ -223,7 +224,8 @@ struct efx_rx_buffer {
+ struct sk_buff *skb;
+ struct page *page;
+ } u;
+- unsigned int len;
++ u16 page_offset;
++ u16 len;
+ bool is_page;
+ };
+
+--- a/drivers/net/sfc/rx.c
++++ b/drivers/net/sfc/rx.c
+@@ -94,11 +94,7 @@ static unsigned int rx_refill_limit = 95
+ static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx,
+ struct efx_rx_buffer *buf)
+ {
+- /* Offset is always within one page, so we don't need to consider
+- * the page order.
+- */
+- return (((__force unsigned long) buf->dma_addr & (PAGE_SIZE - 1)) +
+- efx->type->rx_buffer_hash_size);
++ return buf->page_offset + efx->type->rx_buffer_hash_size;
+ }
+ static inline unsigned int efx_rx_buf_size(struct efx_nic *efx)
+ {
+@@ -193,6 +189,7 @@ static int efx_init_rx_buffers_page(stru
+ struct efx_rx_buffer *rx_buf;
+ struct page *page;
+ void *page_addr;
++ unsigned int page_offset;
+ struct efx_rx_page_state *state;
+ dma_addr_t dma_addr;
+ unsigned index, count;
+@@ -219,12 +216,14 @@ static int efx_init_rx_buffers_page(stru
+
+ page_addr += sizeof(struct efx_rx_page_state);
+ dma_addr += sizeof(struct efx_rx_page_state);
++ page_offset = sizeof(struct efx_rx_page_state);
+
+ split:
+ index = rx_queue->added_count & rx_queue->ptr_mask;
+ rx_buf = efx_rx_buffer(rx_queue, index);
+ rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN;
+ rx_buf->u.page = page;
++ rx_buf->page_offset = page_offset + EFX_PAGE_IP_ALIGN;
+ rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN;
+ rx_buf->is_page = true;
+ ++rx_queue->added_count;
+@@ -236,6 +235,7 @@ static int efx_init_rx_buffers_page(stru
+ get_page(page);
+ dma_addr += (PAGE_SIZE >> 1);
+ page_addr += (PAGE_SIZE >> 1);
++ page_offset += (PAGE_SIZE >> 1);
+ ++count;
+ goto split;
+ }
--- /dev/null
+From 454d85d509053208d0a38e75626e362f55944930 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <bhutchings@solarflare.com>
+Date: Fri, 24 Jun 2011 20:26:44 +0100
+Subject: sfc: Fix loop condition for efx_filter_search() when !for_insert
+
+
+From: Ben Hutchings <bhutchings@solarflare.com>
+
+[ Upstream commit 4017dbdc14af1903dc9fcba4d08b89c02325069d ]
+
+efx_filter_remove_filter() fails to remove inserted filters in some cases.
+
+For example:
+
+ 1. Two filters A and B have specifications that result in an initial
+ hash collision.
+ 2. A is inserted first, followed by B.
+ 3. An attempt to remove B first succeeds, but if A is removed first
+ a subsequent attempt to remove B fails.
+
+When searching for an existing filter (!for_insert),
+efx_filter_search() must always continue to the maximum search depth
+for the given type rather than stopping at the first unused entry.
+
+Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/sfc/filter.c | 39 +++++++++++++++++++++++----------------
+ 1 file changed, 23 insertions(+), 16 deletions(-)
+
+--- a/drivers/net/sfc/filter.c
++++ b/drivers/net/sfc/filter.c
+@@ -335,28 +335,35 @@ static int efx_filter_search(struct efx_
+ bool for_insert, int *depth_required)
+ {
+ unsigned hash, incr, filter_idx, depth, depth_max;
+- struct efx_filter_spec *cmp;
+
+ hash = efx_filter_hash(key);
+ incr = efx_filter_increment(key);
+- depth_max = (spec->priority <= EFX_FILTER_PRI_HINT ?
+- FILTER_CTL_SRCH_HINT_MAX : FILTER_CTL_SRCH_MAX);
+
+- for (depth = 1, filter_idx = hash & (table->size - 1);
+- depth <= depth_max && test_bit(filter_idx, table->used_bitmap);
+- ++depth) {
+- cmp = &table->spec[filter_idx];
+- if (efx_filter_equal(spec, cmp))
+- goto found;
++ filter_idx = hash & (table->size - 1);
++ depth = 1;
++ depth_max = (for_insert ?
++ (spec->priority <= EFX_FILTER_PRI_HINT ?
++ FILTER_CTL_SRCH_HINT_MAX : FILTER_CTL_SRCH_MAX) :
++ table->search_depth[spec->type]);
++
++ for (;;) {
++ /* Return success if entry is used and matches this spec
++ * or entry is unused and we are trying to insert.
++ */
++ if (test_bit(filter_idx, table->used_bitmap) ?
++ efx_filter_equal(spec, &table->spec[filter_idx]) :
++ for_insert) {
++ *depth_required = depth;
++ return filter_idx;
++ }
++
++ /* Return failure if we reached the maximum search depth */
++ if (depth == depth_max)
++ return for_insert ? -EBUSY : -ENOENT;
++
+ filter_idx = (filter_idx + incr) & (table->size - 1);
++ ++depth;
+ }
+- if (!for_insert)
+- return -ENOENT;
+- if (depth > depth_max)
+- return -EBUSY;
+-found:
+- *depth_required = depth;
+- return filter_idx;
+ }
+
+ /* Construct/deconstruct external filter IDs */
--- /dev/null
+From aac26712035cb1db1409ad52a9e2c00c4452a39e Mon Sep 17 00:00:00 2001
+From: Steve Hodgson <shodgson@solarflare.com>
+Date: Wed, 22 Jun 2011 12:11:33 +0100
+Subject: sfc: Fix Siena mac statistics on big endian platforms
+
+
+From: Steve Hodgson <shodgson@solarflare.com>
+
+[ Upstream commit a659b2a94d87add999229ecd9f2f56817d5d737b ]
+
+[bwh: Use __force in the one place it's needed]
+Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/sfc/siena.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/sfc/siena.c
++++ b/drivers/net/sfc/siena.c
+@@ -372,14 +372,13 @@ static void siena_remove_nic(struct efx_
+ efx->nic_data = NULL;
+ }
+
+-#define STATS_GENERATION_INVALID ((u64)(-1))
++#define STATS_GENERATION_INVALID ((__force __le64)(-1))
+
+ static int siena_try_update_nic_stats(struct efx_nic *efx)
+ {
+- u64 *dma_stats;
++ __le64 *dma_stats;
+ struct efx_mac_stats *mac_stats;
+- u64 generation_start;
+- u64 generation_end;
++ __le64 generation_start, generation_end;
+
+ mac_stats = &efx->mac_stats;
+ dma_stats = (u64 *)efx->stats_buffer.addr;
+@@ -390,7 +389,7 @@ static int siena_try_update_nic_stats(st
+ rmb();
+
+ #define MAC_STAT(M, D) \
+- mac_stats->M = dma_stats[MC_CMD_MAC_ ## D]
++ mac_stats->M = le64_to_cpu(dma_stats[MC_CMD_MAC_ ## D])
+
+ MAC_STAT(tx_bytes, TX_BYTES);
+ MAC_STAT(tx_bad_bytes, TX_BAD_BYTES);
+@@ -460,7 +459,8 @@ static int siena_try_update_nic_stats(st
+ MAC_STAT(rx_internal_error, RX_INTERNAL_ERROR_PKTS);
+ mac_stats->rx_good_lt64 = 0;
+
+- efx->n_rx_nodesc_drop_cnt = dma_stats[MC_CMD_MAC_RX_NODESC_DROPS];
++ efx->n_rx_nodesc_drop_cnt =
++ le64_to_cpu(dma_stats[MC_CMD_MAC_RX_NODESC_DROPS]);
+
+ #undef MAC_STAT
+
+@@ -489,7 +489,7 @@ static void siena_update_nic_stats(struc
+
+ static void siena_start_nic_stats(struct efx_nic *efx)
+ {
+- u64 *dma_stats = (u64 *)efx->stats_buffer.addr;
++ __le64 *dma_stats = efx->stats_buffer.addr;
+
+ dma_stats[MC_CMD_MAC_GENERATION_END] = STATS_GENERATION_INVALID;
+
--- /dev/null
+From 4b98c03ffda282768c7dd09c35783fce1f8cd050 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <bhutchings@solarflare.com>
+Date: Sat, 1 Dec 2012 02:21:17 +0000
+Subject: sfc: Fix timekeeping in efx_mcdi_poll()
+
+
+From: Ben Hutchings <bhutchings@solarflare.com>
+
+[ Upstream commit ebf98e797b4e26ad52ace1511a0b503ee60a6cd4 ]
+
+efx_mcdi_poll() uses get_seconds() to read the current time and to
+implement a polling timeout. The use of this function was chosen
+partly because it could easily be replaced in a co-sim environment
+with a macro that read the simulated time.
+
+Unfortunately the real get_seconds() returns the system time (real
+time) which is subject to adjustment by e.g. ntpd. If the system time
+is adjusted forward during a polled MCDI operation, the effective
+timeout can be shorter than the intended 10 seconds, resulting in a
+spurious failure. It is also possible for a backward adjustment to
+delay detection of a areal failure.
+
+Use jiffies instead, and change MCDI_RPC_TIMEOUT to be denominated in
+jiffies. Also correct rounding of the timeout: check time > finish
+(or rather time_after(time, finish)) and not time >= finish.
+
+Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
+[bwh: Backported to 3.0: adjust context]
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/sfc/mcdi.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/sfc/mcdi.c
++++ b/drivers/net/sfc/mcdi.c
+@@ -30,7 +30,7 @@
+ #define REBOOT_FLAG_PORT0 0x3f8
+ #define REBOOT_FLAG_PORT1 0x3fc
+
+-#define MCDI_RPC_TIMEOUT 10 /*seconds */
++#define MCDI_RPC_TIMEOUT (10 * HZ)
+
+ #define MCDI_PDU(efx) \
+ (efx_port_num(efx) ? CMD_PDU_PORT1 : CMD_PDU_PORT0)
+@@ -120,7 +120,7 @@ static void efx_mcdi_copyout(struct efx_
+ static int efx_mcdi_poll(struct efx_nic *efx)
+ {
+ struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+- unsigned int time, finish;
++ unsigned long time, finish;
+ unsigned int respseq, respcmd, error;
+ unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
+ unsigned int rc, spins;
+@@ -136,7 +136,7 @@ static int efx_mcdi_poll(struct efx_nic
+ * and poll once a jiffy (approximately)
+ */
+ spins = TICK_USEC;
+- finish = get_seconds() + MCDI_RPC_TIMEOUT;
++ finish = jiffies + MCDI_RPC_TIMEOUT;
+
+ while (1) {
+ if (spins != 0) {
+@@ -146,7 +146,7 @@ static int efx_mcdi_poll(struct efx_nic
+ schedule_timeout_uninterruptible(1);
+ }
+
+- time = get_seconds();
++ time = jiffies;
+
+ rmb();
+ efx_readd(efx, ®, pdu);
+@@ -158,7 +158,7 @@ static int efx_mcdi_poll(struct efx_nic
+ EFX_DWORD_FIELD(reg, MCDI_HEADER_RESPONSE))
+ break;
+
+- if (time >= finish)
++ if (time_after(time, finish))
+ return -ETIMEDOUT;
+ }
+
+@@ -250,7 +250,7 @@ static int efx_mcdi_await_completion(str
+ if (wait_event_timeout(
+ mcdi->wq,
+ atomic_read(&mcdi->state) == MCDI_STATE_COMPLETED,
+- msecs_to_jiffies(MCDI_RPC_TIMEOUT * 1000)) == 0)
++ MCDI_RPC_TIMEOUT) == 0)
+ return -ETIMEDOUT;
+
+ /* Check if efx_mcdi_set_mode() switched us back to polled completions.
--- /dev/null
+From ef691ef73fa43298c5499ff6eaec8256115edaf0 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <bhutchings@solarflare.com>
+Date: Mon, 23 May 2011 12:18:45 +0100
+Subject: sfc: Fix two causes of flush failure
+
+
+From: Ben Hutchings <bhutchings@solarflare.com>
+
+[ Upstream commits a606f4325dca6950996abbae452d33f2af095f39,
+ d5e8cc6c946e0857826dcfbb3585068858445bfe,
+ 525d9e824018cd7cc8d8d44832ddcd363abfe6e1 ]
+
+The TX DMA engine issues upstream read requests when there is room in
+the TX FIFO for the completion. However, the fetches for the rest of
+the packet might be delayed by any back pressure. Since a flush must
+wait for an EOP, the entire flush may be delayed by back pressure.
+
+Mitigate this by disabling flow control before the flushes are
+started. Since PF and VF flushes run in parallel introduce
+fc_disable, a reference count of the number of flushes outstanding.
+
+The same principle could be applied to Falcon, but that
+would bring with it its own testing.
+
+We sometimes hit a "failed to flush" timeout on some TX queues, but the
+flushes have completed and the flush completion events seem to go missing.
+In this case, we can check the TX_DESC_PTR_TBL register and drain the
+queues if the flushes had finished.
+
+Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
+[bwh: Backported to 3.0:
+ - Call efx_nic_type::finish_flush() on both success and failure paths
+ - Check the TX_DESC_PTR_TBL registers in the polling loop
+ - Declare efx_mcdi_set_mac() extern]
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/sfc/falcon.c | 2 ++
+ drivers/net/sfc/mcdi.h | 1 +
+ drivers/net/sfc/mcdi_mac.c | 4 +++-
+ drivers/net/sfc/net_driver.h | 6 ++++++
+ drivers/net/sfc/nic.c | 21 ++++++++++++++++++---
+ drivers/net/sfc/nic.h | 2 ++
+ drivers/net/sfc/siena.c | 15 ++++++++++++++-
+ 7 files changed, 46 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/sfc/falcon.c
++++ b/drivers/net/sfc/falcon.c
+@@ -1714,6 +1714,7 @@ const struct efx_nic_type falcon_a1_nic_
+ .remove_port = falcon_remove_port,
+ .handle_global_event = falcon_handle_global_event,
+ .prepare_flush = falcon_prepare_flush,
++ .finish_flush = efx_port_dummy_op_void,
+ .update_stats = falcon_update_nic_stats,
+ .start_stats = falcon_start_nic_stats,
+ .stop_stats = falcon_stop_nic_stats,
+@@ -1755,6 +1756,7 @@ const struct efx_nic_type falcon_b0_nic_
+ .remove_port = falcon_remove_port,
+ .handle_global_event = falcon_handle_global_event,
+ .prepare_flush = falcon_prepare_flush,
++ .finish_flush = efx_port_dummy_op_void,
+ .update_stats = falcon_update_nic_stats,
+ .start_stats = falcon_start_nic_stats,
+ .stop_stats = falcon_stop_nic_stats,
+--- a/drivers/net/sfc/mcdi.h
++++ b/drivers/net/sfc/mcdi.h
+@@ -126,5 +126,6 @@ extern int efx_mcdi_wol_filter_set_magic
+ extern int efx_mcdi_wol_filter_get_magic(struct efx_nic *efx, int *id_out);
+ extern int efx_mcdi_wol_filter_remove(struct efx_nic *efx, int id);
+ extern int efx_mcdi_wol_filter_reset(struct efx_nic *efx);
++extern int efx_mcdi_set_mac(struct efx_nic *efx);
+
+ #endif /* EFX_MCDI_H */
+--- a/drivers/net/sfc/mcdi_mac.c
++++ b/drivers/net/sfc/mcdi_mac.c
+@@ -13,7 +13,7 @@
+ #include "mcdi.h"
+ #include "mcdi_pcol.h"
+
+-static int efx_mcdi_set_mac(struct efx_nic *efx)
++int efx_mcdi_set_mac(struct efx_nic *efx)
+ {
+ u32 reject, fcntl;
+ u8 cmdbytes[MC_CMD_SET_MAC_IN_LEN];
+@@ -45,6 +45,8 @@ static int efx_mcdi_set_mac(struct efx_n
+ }
+ if (efx->wanted_fc & EFX_FC_AUTO)
+ fcntl = MC_CMD_FCNTL_AUTO;
++ if (efx->fc_disable)
++ fcntl = MC_CMD_FCNTL_OFF;
+
+ MCDI_SET_DWORD(cmdbytes, SET_MAC_IN_FCNTL, fcntl);
+
+--- a/drivers/net/sfc/net_driver.h
++++ b/drivers/net/sfc/net_driver.h
+@@ -690,6 +690,9 @@ struct efx_filter_state;
+ * @promiscuous: Promiscuous flag. Protected by netif_tx_lock.
+ * @multicast_hash: Multicast hash table
+ * @wanted_fc: Wanted flow control flags
++ * @fc_disable: When non-zero flow control is disabled. Typically used to
++ * ensure that network back pressure doesn't delay dma queue flushes.
++ * Serialised by the rtnl lock.
+ * @mac_work: Work item for changing MAC promiscuity and multicast hash
+ * @loopback_mode: Loopback status
+ * @loopback_modes: Supported loopback mode bitmask
+@@ -783,6 +786,7 @@ struct efx_nic {
+ bool promiscuous;
+ union efx_multicast_hash multicast_hash;
+ u8 wanted_fc;
++ unsigned fc_disable;
+
+ atomic_t rx_reset;
+ enum efx_loopback_mode loopback_mode;
+@@ -834,6 +838,7 @@ static inline unsigned int efx_port_num(
+ * @remove_port: Free resources allocated by probe_port()
+ * @handle_global_event: Handle a "global" event (may be %NULL)
+ * @prepare_flush: Prepare the hardware for flushing the DMA queues
++ * @finish_flush: Clean up after flushing the DMA queues
+ * @update_stats: Update statistics not provided by event handling
+ * @start_stats: Start the regular fetching of statistics
+ * @stop_stats: Stop the regular fetching of statistics
+@@ -879,6 +884,7 @@ struct efx_nic_type {
+ void (*remove_port)(struct efx_nic *efx);
+ bool (*handle_global_event)(struct efx_channel *channel, efx_qword_t *);
+ void (*prepare_flush)(struct efx_nic *efx);
++ void (*finish_flush)(struct efx_nic *efx);
+ void (*update_stats)(struct efx_nic *efx);
+ void (*start_stats)(struct efx_nic *efx);
+ void (*stop_stats)(struct efx_nic *efx);
+--- a/drivers/net/sfc/nic.c
++++ b/drivers/net/sfc/nic.c
+@@ -1260,13 +1260,27 @@ int efx_nic_flush_queues(struct efx_nic
+ }
+ efx_for_each_possible_channel_tx_queue(tx_queue, channel) {
+ if (tx_queue->initialised &&
+- tx_queue->flushed != FLUSH_DONE)
+- ++tx_pending;
++ tx_queue->flushed != FLUSH_DONE) {
++ efx_oword_t txd_ptr_tbl;
++
++ efx_reado_table(efx, &txd_ptr_tbl,
++ FR_BZ_TX_DESC_PTR_TBL,
++ tx_queue->queue);
++ if (EFX_OWORD_FIELD(txd_ptr_tbl,
++ FRF_AZ_TX_DESCQ_FLUSH) ||
++ EFX_OWORD_FIELD(txd_ptr_tbl,
++ FRF_AZ_TX_DESCQ_EN))
++ ++tx_pending;
++ else
++ tx_queue->flushed = FLUSH_DONE;
++ }
+ }
+ }
+
+- if (rx_pending == 0 && tx_pending == 0)
++ if (rx_pending == 0 && tx_pending == 0) {
++ efx->type->finish_flush(efx);
+ return 0;
++ }
+
+ msleep(EFX_FLUSH_INTERVAL);
+ efx_poll_flush_events(efx);
+@@ -1292,6 +1306,7 @@ int efx_nic_flush_queues(struct efx_nic
+ }
+ }
+
++ efx->type->finish_flush(efx);
+ return -ETIMEDOUT;
+ }
+
+--- a/drivers/net/sfc/nic.h
++++ b/drivers/net/sfc/nic.h
+@@ -211,6 +211,8 @@ extern void falcon_irq_ack_a1(struct efx
+
+ /* Global Resources */
+ extern int efx_nic_flush_queues(struct efx_nic *efx);
++extern void siena_prepare_flush(struct efx_nic *efx);
++extern void siena_finish_flush(struct efx_nic *efx);
+ extern void falcon_start_nic_stats(struct efx_nic *efx);
+ extern void falcon_stop_nic_stats(struct efx_nic *efx);
+ extern void falcon_setup_xaui(struct efx_nic *efx);
+--- a/drivers/net/sfc/siena.c
++++ b/drivers/net/sfc/siena.c
+@@ -135,6 +135,18 @@ static void siena_remove_port(struct efx
+ efx_nic_free_buffer(efx, &efx->stats_buffer);
+ }
+
++void siena_prepare_flush(struct efx_nic *efx)
++{
++ if (efx->fc_disable++ == 0)
++ efx_mcdi_set_mac(efx);
++}
++
++void siena_finish_flush(struct efx_nic *efx)
++{
++ if (--efx->fc_disable == 0)
++ efx_mcdi_set_mac(efx);
++}
++
+ static const struct efx_nic_register_test siena_register_tests[] = {
+ { FR_AZ_ADR_REGION,
+ EFX_OWORD32(0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF) },
+@@ -590,7 +602,8 @@ const struct efx_nic_type siena_a0_nic_t
+ .reset = siena_reset_hw,
+ .probe_port = siena_probe_port,
+ .remove_port = siena_remove_port,
+- .prepare_flush = efx_port_dummy_op_void,
++ .prepare_flush = siena_prepare_flush,
++ .finish_flush = siena_finish_flush,
+ .update_stats = siena_update_nic_stats,
+ .start_stats = siena_start_nic_stats,
+ .stop_stats = siena_stop_nic_stats,
--- /dev/null
+From 10da6986dd9307f9e0bdfa68204ae00650936bbb Mon Sep 17 00:00:00 2001
+From: Daniel Pieczko <dpieczko@solarflare.com>
+Date: Wed, 17 Oct 2012 13:21:23 +0100
+Subject: sfc: lock TX queues when calling netif_device_detach()
+
+
+From: Daniel Pieczko <dpieczko@solarflare.com>
+
+[ Upstream commit c2f3b8e3a44b6fe9e36704e30157ebe1a88c08b1 ]
+
+The assertion of netif_device_present() at the top of
+efx_hard_start_xmit() may fail if we don't do this.
+
+Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
+[bwh: Backported to 3.0: adjust context]
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/sfc/efx.c | 4 ++--
+ drivers/net/sfc/efx.h | 13 +++++++++++++
+ drivers/net/sfc/selftest.c | 2 +-
+ 3 files changed, 16 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/sfc/efx.c
++++ b/drivers/net/sfc/efx.c
+@@ -2106,7 +2106,7 @@ int efx_reset(struct efx_nic *efx, enum
+ netif_info(efx, drv, efx->net_dev, "resetting (%s)\n",
+ RESET_TYPE(method));
+
+- netif_device_detach(efx->net_dev);
++ efx_device_detach_sync(efx);
+ efx_reset_down(efx, method);
+
+ rc = efx->type->reset(efx, method);
+@@ -2565,7 +2565,7 @@ static int efx_pm_freeze(struct device *
+
+ efx->state = STATE_FINI;
+
+- netif_device_detach(efx->net_dev);
++ efx_device_detach_sync(efx);
+
+ efx_stop_all(efx);
+ efx_fini_channels(efx);
+--- a/drivers/net/sfc/efx.h
++++ b/drivers/net/sfc/efx.h
+@@ -150,4 +150,17 @@ extern void efx_link_status_changed(stru
+ extern void efx_link_set_advertising(struct efx_nic *efx, u32);
+ extern void efx_link_set_wanted_fc(struct efx_nic *efx, u8);
+
++static inline void efx_device_detach_sync(struct efx_nic *efx)
++{
++ struct net_device *dev = efx->net_dev;
++
++ /* Lock/freeze all TX queues so that we can be sure the
++ * TX scheduler is stopped when we're done and before
++ * netif_device_present() becomes false.
++ */
++ netif_tx_lock(dev);
++ netif_device_detach(dev);
++ netif_tx_unlock(dev);
++}
++
+ #endif /* EFX_EFX_H */
+--- a/drivers/net/sfc/selftest.c
++++ b/drivers/net/sfc/selftest.c
+@@ -698,7 +698,7 @@ int efx_selftest(struct efx_nic *efx, st
+ /* Detach the device so the kernel doesn't transmit during the
+ * loopback test and the watchdog timeout doesn't fire.
+ */
+- netif_device_detach(efx->net_dev);
++ efx_device_detach_sync(efx);
+
+ mutex_lock(&efx->mac_lock);
+ if (efx->loopback_modes) {
--- /dev/null
+From fde2b4efe81bc60bfe85638284817fb4e9a0ad59 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <bhutchings@solarflare.com>
+Date: Wed, 27 Feb 2013 16:50:38 +0000
+Subject: sfc: Only use TX push if a single descriptor is to be written
+
+
+From: Ben Hutchings <bhutchings@solarflare.com>
+
+[ Upstream commit fae8563b25f73dc584a07bcda7a82750ff4f7672 ]
+
+Using TX push when notifying the NIC of multiple new descriptors in
+the ring will very occasionally cause the TX DMA engine to re-use an
+old descriptor. This can result in a duplicated or partly duplicated
+packet (new headers with old data), or an IOMMU page fault. This does
+not happen when the pushed descriptor is the only one written.
+
+TX push also provides little latency benefit when a packet requires
+more than one descriptor.
+
+Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/sfc/nic.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/sfc/nic.c
++++ b/drivers/net/sfc/nic.c
+@@ -370,7 +370,8 @@ efx_may_push_tx_desc(struct efx_tx_queue
+ return false;
+
+ tx_queue->empty_read_count = 0;
+- return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0;
++ return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0
++ && tx_queue->write_count - write_count == 1;
+ }
+
+ /* For each entry inserted into the software descriptor ring, create a
--- /dev/null
+From 58f74c7701b81362e5eb2552f6e37cfa1e9a2437 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <bhutchings@solarflare.com>
+Date: Thu, 20 Dec 2012 18:48:20 +0000
+Subject: sfc: Properly sync RX DMA buffer when it is not the last in the page
+
+
+From: Ben Hutchings <bhutchings@solarflare.com>
+
+[ Upstream commit 3a68f19d7afb80f548d016effbc6ed52643a8085 ]
+
+We may currently allocate two RX DMA buffers to a page, and only unmap
+the page when the second is completed. We do not sync the first RX
+buffer to be completed; this can result in packet loss or corruption
+if the last RX buffer completed in a NAPI poll is the first in a page
+and is not DMA-coherent. (In the middle of a NAPI poll, we will
+handle the following RX completion and unmap the page *before* looking
+at the content of the first buffer.)
+
+Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
+[bwh: Backported to 3.0: adjust context]
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/sfc/rx.c | 15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/sfc/rx.c
++++ b/drivers/net/sfc/rx.c
+@@ -245,7 +245,8 @@ static int efx_init_rx_buffers_page(stru
+ }
+
+ static void efx_unmap_rx_buffer(struct efx_nic *efx,
+- struct efx_rx_buffer *rx_buf)
++ struct efx_rx_buffer *rx_buf,
++ unsigned int used_len)
+ {
+ if (rx_buf->is_page && rx_buf->u.page) {
+ struct efx_rx_page_state *state;
+@@ -256,6 +257,10 @@ static void efx_unmap_rx_buffer(struct e
+ state->dma_addr,
+ efx_rx_buf_size(efx),
+ PCI_DMA_FROMDEVICE);
++ } else if (used_len) {
++ dma_sync_single_for_cpu(&efx->pci_dev->dev,
++ rx_buf->dma_addr, used_len,
++ DMA_FROM_DEVICE);
+ }
+ } else if (!rx_buf->is_page && rx_buf->u.skb) {
+ pci_unmap_single(efx->pci_dev, rx_buf->dma_addr,
+@@ -278,7 +283,7 @@ static void efx_free_rx_buffer(struct ef
+ static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue,
+ struct efx_rx_buffer *rx_buf)
+ {
+- efx_unmap_rx_buffer(rx_queue->efx, rx_buf);
++ efx_unmap_rx_buffer(rx_queue->efx, rx_buf, 0);
+ efx_free_rx_buffer(rx_queue->efx, rx_buf);
+ }
+
+@@ -549,10 +554,10 @@ void efx_rx_packet(struct efx_rx_queue *
+ goto out;
+ }
+
+- /* Release card resources - assumes all RX buffers consumed in-order
+- * per RX queue
++ /* Release and/or sync DMA mapping - assumes all RX buffers
++ * consumed in-order per RX queue
+ */
+- efx_unmap_rx_buffer(efx, rx_buf);
++ efx_unmap_rx_buffer(efx, rx_buf, len);
+
+ /* Prefetch nice and early so data will (hopefully) be in cache by
+ * the time we look at it.