Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorDavid S. Miller <davem@davemloft.net>
Wed, 10 Dec 2014 20:48:20 +0000 (15:48 -0500)
committerDavid S. Miller <davem@davemloft.net>
Wed, 10 Dec 2014 20:48:20 +0000 (15:48 -0500)
Conflicts:
drivers/net/ethernet/amd/xgbe/xgbe-desc.c
drivers/net/ethernet/renesas/sh_eth.c

Overlapping changes in both conflict cases.

Signed-off-by: David S. Miller <davem@davemloft.net>
20 files changed:
1  2 
arch/x86/net/bpf_jit_comp.c
drivers/net/bonding/bond_netlink.c
drivers/net/ethernet/amd/xgbe/xgbe-desc.c
drivers/net/ethernet/amd/xgbe/xgbe-drv.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/pxa168_eth.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/xen-netfront.c
include/uapi/linux/Kbuild
net/core/rtnetlink.c
net/ipv4/tcp_ipv4.c
net/ipv6/tcp_ipv6.c
net/openvswitch/flow_netlink.c
net/sched/Kconfig

@@@ -24,7 -24,7 +24,7 @@@ extern u8 sk_load_byte_positive_offset[
  extern u8 sk_load_word_negative_offset[], sk_load_half_negative_offset[];
  extern u8 sk_load_byte_negative_offset[];
  
 -static inline u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len)
 +static u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len)
  {
        if (len == 1)
                *ptr = bytes;
  #define EMIT4_off32(b1, b2, b3, b4, off) \
        do {EMIT4(b1, b2, b3, b4); EMIT(off, 4); } while (0)
  
 -static inline bool is_imm8(int value)
 +static bool is_imm8(int value)
  {
        return value <= 127 && value >= -128;
  }
  
 -static inline bool is_simm32(s64 value)
 +static bool is_simm32(s64 value)
  {
        return value == (s64) (s32) value;
  }
@@@ -94,7 -94,7 +94,7 @@@ static int bpf_size_to_x86_bytes(int bp
  #define X86_JGE 0x7D
  #define X86_JG  0x7F
  
 -static inline void bpf_flush_icache(void *start, void *end)
 +static void bpf_flush_icache(void *start, void *end)
  {
        mm_segment_t old_fs = get_fs();
  
@@@ -133,24 -133,24 +133,24 @@@ static const int reg2hex[] = 
   * which need extra byte of encoding.
   * rax,rcx,...,rbp have simpler encoding
   */
 -static inline bool is_ereg(u32 reg)
 +static bool is_ereg(u32 reg)
  {
 -      if (reg == BPF_REG_5 || reg == AUX_REG ||
 -          (reg >= BPF_REG_7 && reg <= BPF_REG_9))
 -              return true;
 -      else
 -              return false;
 +      return (1 << reg) & (BIT(BPF_REG_5) |
 +                           BIT(AUX_REG) |
 +                           BIT(BPF_REG_7) |
 +                           BIT(BPF_REG_8) |
 +                           BIT(BPF_REG_9));
  }
  
  /* add modifiers if 'reg' maps to x64 registers r8..r15 */
 -static inline u8 add_1mod(u8 byte, u32 reg)
 +static u8 add_1mod(u8 byte, u32 reg)
  {
        if (is_ereg(reg))
                byte |= 1;
        return byte;
  }
  
 -static inline u8 add_2mod(u8 byte, u32 r1, u32 r2)
 +static u8 add_2mod(u8 byte, u32 r1, u32 r2)
  {
        if (is_ereg(r1))
                byte |= 1;
  }
  
  /* encode 'dst_reg' register into x64 opcode 'byte' */
 -static inline u8 add_1reg(u8 byte, u32 dst_reg)
 +static u8 add_1reg(u8 byte, u32 dst_reg)
  {
        return byte + reg2hex[dst_reg];
  }
  
  /* encode 'dst_reg' and 'src_reg' registers into x64 opcode 'byte' */
 -static inline u8 add_2reg(u8 byte, u32 dst_reg, u32 src_reg)
 +static u8 add_2reg(u8 byte, u32 dst_reg, u32 src_reg)
  {
        return byte + reg2hex[dst_reg] + (reg2hex[src_reg] << 3);
  }
@@@ -178,7 -178,7 +178,7 @@@ static void jit_fill_hole(void *area, u
  }
  
  struct jit_context {
-       unsigned int cleanup_addr; /* epilogue code offset */
+       int cleanup_addr; /* epilogue code offset */
        bool seen_ld_abs;
  };
  
@@@ -192,6 -192,7 +192,7 @@@ static int do_jit(struct bpf_prog *bpf_
        struct bpf_insn *insn = bpf_prog->insnsi;
        int insn_cnt = bpf_prog->len;
        bool seen_ld_abs = ctx->seen_ld_abs | (oldproglen == 0);
+       bool seen_exit = false;
        u8 temp[BPF_MAX_INSN_SIZE + BPF_INSN_SAFETY];
        int i;
        int proglen = 0;
@@@ -854,10 -855,11 +855,11 @@@ common_load
                        goto common_load;
  
                case BPF_JMP | BPF_EXIT:
-                       if (i != insn_cnt - 1) {
+                       if (seen_exit) {
                                jmp_offset = ctx->cleanup_addr - addrs[i];
                                goto emit_jmp;
                        }
+                       seen_exit = true;
                        /* update cleanup_addr */
                        ctx->cleanup_addr = proglen;
                        /* mov rbx, qword ptr [rbp-X] */
@@@ -17,7 -17,7 +17,7 @@@
  #include <linux/if_ether.h>
  #include <net/netlink.h>
  #include <net/rtnetlink.h>
 -#include "bonding.h"
 +#include <net/bonding.h>
  
  static size_t bond_get_slave_size(const struct net_device *bond_dev,
                                  const struct net_device *slave_dev)
@@@ -225,7 -225,12 +225,12 @@@ static int bond_changelink(struct net_d
  
                bond_option_arp_ip_targets_clear(bond);
                nla_for_each_nested(attr, data[IFLA_BOND_ARP_IP_TARGET], rem) {
-                       __be32 target = nla_get_be32(attr);
+                       __be32 target;
+                       if (nla_len(attr) < sizeof(target))
+                               return -EINVAL;
+                       target = nla_get_be32(attr);
  
                        bond_opt_initval(&newval, (__force u64)target);
                        err = __bond_opt_set(bond, BOND_OPT_ARP_TARGETS,
  #include "xgbe.h"
  #include "xgbe-common.h"
  
 -static void xgbe_unmap_skb(struct xgbe_prv_data *, struct xgbe_ring_data *);
 +static void xgbe_unmap_rdata(struct xgbe_prv_data *, struct xgbe_ring_data *);
  
  static void xgbe_free_ring(struct xgbe_prv_data *pdata,
                           struct xgbe_ring *ring)
        if (ring->rdata) {
                for (i = 0; i < ring->rdesc_count; i++) {
                        rdata = XGBE_GET_DESC_DATA(ring, i);
 -                      xgbe_unmap_skb(pdata, rdata);
 +                      xgbe_unmap_rdata(pdata, rdata);
                }
  
                kfree(ring->rdata);
                ring->rdata = NULL;
        }
  
 +      if (ring->rx_hdr_pa.pages) {
 +              dma_unmap_page(pdata->dev, ring->rx_hdr_pa.pages_dma,
 +                             ring->rx_hdr_pa.pages_len, DMA_FROM_DEVICE);
 +              put_page(ring->rx_hdr_pa.pages);
 +
 +              ring->rx_hdr_pa.pages = NULL;
 +              ring->rx_hdr_pa.pages_len = 0;
 +              ring->rx_hdr_pa.pages_offset = 0;
 +              ring->rx_hdr_pa.pages_dma = 0;
 +      }
 +
 +      if (ring->rx_buf_pa.pages) {
 +              dma_unmap_page(pdata->dev, ring->rx_buf_pa.pages_dma,
 +                             ring->rx_buf_pa.pages_len, DMA_FROM_DEVICE);
 +              put_page(ring->rx_buf_pa.pages);
 +
 +              ring->rx_buf_pa.pages = NULL;
 +              ring->rx_buf_pa.pages_len = 0;
 +              ring->rx_buf_pa.pages_offset = 0;
 +              ring->rx_buf_pa.pages_dma = 0;
 +      }
 +
        if (ring->rdesc) {
                dma_free_coherent(pdata->dev,
                                  (sizeof(struct xgbe_ring_desc) *
@@@ -255,96 -233,6 +255,96 @@@ err_ring
        return ret;
  }
  
 +static int xgbe_alloc_pages(struct xgbe_prv_data *pdata,
 +                          struct xgbe_page_alloc *pa, gfp_t gfp, int order)
 +{
 +      struct page *pages = NULL;
 +      dma_addr_t pages_dma;
 +      int ret;
 +
 +      /* Try to obtain pages, decreasing order if necessary */
 +      gfp |= __GFP_COLD | __GFP_COMP;
 +      while (order >= 0) {
 +              pages = alloc_pages(gfp, order);
 +              if (pages)
 +                      break;
 +
 +              order--;
 +      }
 +      if (!pages)
 +              return -ENOMEM;
 +
 +      /* Map the pages */
 +      pages_dma = dma_map_page(pdata->dev, pages, 0,
 +                               PAGE_SIZE << order, DMA_FROM_DEVICE);
 +      ret = dma_mapping_error(pdata->dev, pages_dma);
 +      if (ret) {
 +              put_page(pages);
 +              return ret;
 +      }
 +
 +      pa->pages = pages;
 +      pa->pages_len = PAGE_SIZE << order;
 +      pa->pages_offset = 0;
 +      pa->pages_dma = pages_dma;
 +
 +      return 0;
 +}
 +
 +static void xgbe_set_buffer_data(struct xgbe_buffer_data *bd,
 +                               struct xgbe_page_alloc *pa,
 +                               unsigned int len)
 +{
 +      get_page(pa->pages);
 +      bd->pa = *pa;
 +
 +      bd->dma = pa->pages_dma + pa->pages_offset;
 +      bd->dma_len = len;
 +
 +      pa->pages_offset += len;
 +      if ((pa->pages_offset + len) > pa->pages_len) {
 +              /* This data descriptor is responsible for unmapping page(s) */
 +              bd->pa_unmap = *pa;
 +
 +              /* Get a new allocation next time */
 +              pa->pages = NULL;
 +              pa->pages_len = 0;
 +              pa->pages_offset = 0;
 +              pa->pages_dma = 0;
 +      }
 +}
 +
 +static int xgbe_map_rx_buffer(struct xgbe_prv_data *pdata,
 +                            struct xgbe_ring *ring,
 +                            struct xgbe_ring_data *rdata)
 +{
 +      int order, ret;
 +
 +      if (!ring->rx_hdr_pa.pages) {
 +              ret = xgbe_alloc_pages(pdata, &ring->rx_hdr_pa, GFP_ATOMIC, 0);
 +              if (ret)
 +                      return ret;
 +      }
 +
 +      if (!ring->rx_buf_pa.pages) {
 +              order = max_t(int, PAGE_ALLOC_COSTLY_ORDER - 1, 0);
 +              ret = xgbe_alloc_pages(pdata, &ring->rx_buf_pa, GFP_ATOMIC,
 +                                     order);
 +              if (ret)
 +                      return ret;
 +      }
 +
 +      /* Set up the header page info */
 +      xgbe_set_buffer_data(&rdata->rx.hdr, &ring->rx_hdr_pa,
 +                           XGBE_SKB_ALLOC_SIZE);
 +
 +      /* Set up the buffer page info */
 +      xgbe_set_buffer_data(&rdata->rx.buf, &ring->rx_buf_pa,
 +                           pdata->rx_buf_size);
 +
 +      return 0;
 +}
 +
  static void xgbe_wrapper_tx_descriptor_init(struct xgbe_prv_data *pdata)
  {
        struct xgbe_hw_if *hw_if = &pdata->hw_if;
  
                ring->cur = 0;
                ring->dirty = 0;
 -              ring->tx.queue_stopped = 0;
 +              memset(&ring->tx, 0, sizeof(ring->tx));
  
                hw_if->tx_desc_init(channel);
        }
@@@ -393,7 -281,8 +393,7 @@@ static void xgbe_wrapper_rx_descriptor_
        struct xgbe_ring *ring;
        struct xgbe_ring_desc *rdesc;
        struct xgbe_ring_data *rdata;
 -      dma_addr_t rdesc_dma, skb_dma;
 -      struct sk_buff *skb = NULL;
 +      dma_addr_t rdesc_dma;
        unsigned int i, j;
  
        DBGPR("-->xgbe_wrapper_rx_descriptor_init\n");
                        rdata->rdesc = rdesc;
                        rdata->rdesc_dma = rdesc_dma;
  
 -                      /* Allocate skb & assign to each rdesc */
 -                      skb = dev_alloc_skb(pdata->rx_buf_size);
 -                      if (skb == NULL)
 -                              break;
 -                      skb_dma = dma_map_single(pdata->dev, skb->data,
 -                                               pdata->rx_buf_size,
 -                                               DMA_FROM_DEVICE);
 -                      if (dma_mapping_error(pdata->dev, skb_dma)) {
 -                              netdev_alert(pdata->netdev,
 -                                           "failed to do the dma map\n");
 -                              dev_kfree_skb_any(skb);
 +                      if (xgbe_map_rx_buffer(pdata, ring, rdata))
                                break;
 -                      }
 -                      rdata->skb = skb;
 -                      rdata->skb_dma = skb_dma;
 -                      rdata->skb_dma_len = pdata->rx_buf_size;
  
                        rdesc++;
                        rdesc_dma += sizeof(struct xgbe_ring_desc);
  
                ring->cur = 0;
                ring->dirty = 0;
 -              ring->rx.realloc_index = 0;
 -              ring->rx.realloc_threshold = 0;
 +              memset(&ring->rx, 0, sizeof(ring->rx));
  
                hw_if->rx_desc_init(channel);
        }
        DBGPR("<--xgbe_wrapper_rx_descriptor_init\n");
  }
  
 -static void xgbe_unmap_skb(struct xgbe_prv_data *pdata,
 -                         struct xgbe_ring_data *rdata)
 +static void xgbe_unmap_rdata(struct xgbe_prv_data *pdata,
 +                           struct xgbe_ring_data *rdata)
  {
        if (rdata->skb_dma) {
                if (rdata->mapped_as_page) {
                rdata->skb = NULL;
        }
  
 -      rdata->tso_header = 0;
 -      rdata->len = 0;
 +      if (rdata->rx.hdr.pa.pages)
 +              put_page(rdata->rx.hdr.pa.pages);
 +
 +      if (rdata->rx.hdr.pa_unmap.pages) {
 +              dma_unmap_page(pdata->dev, rdata->rx.hdr.pa_unmap.pages_dma,
 +                             rdata->rx.hdr.pa_unmap.pages_len,
 +                             DMA_FROM_DEVICE);
 +              put_page(rdata->rx.hdr.pa_unmap.pages);
 +      }
 +
 +      if (rdata->rx.buf.pa.pages)
 +              put_page(rdata->rx.buf.pa.pages);
 +
 +      if (rdata->rx.buf.pa_unmap.pages) {
 +              dma_unmap_page(pdata->dev, rdata->rx.buf.pa_unmap.pages_dma,
 +                             rdata->rx.buf.pa_unmap.pages_len,
 +                             DMA_FROM_DEVICE);
 +              put_page(rdata->rx.buf.pa_unmap.pages);
 +      }
 +
 +      memset(&rdata->tx, 0, sizeof(rdata->tx));
 +      memset(&rdata->rx, 0, sizeof(rdata->rx));
 +
-       rdata->interrupt = 0;
        rdata->mapped_as_page = 0;
  
        if (rdata->state_saved) {
@@@ -531,6 -413,7 +530,6 @@@ static int xgbe_map_tx_skb(struct xgbe_
                }
                rdata->skb_dma = skb_dma;
                rdata->skb_dma_len = packet->header_len;
 -              rdata->tso_header = 1;
  
                offset = packet->header_len;
  
                }
        }
  
-       /* Save the skb address in the last entry */
+       /* Save the skb address in the last entry. We always have some data
+        * that has been mapped so rdata is always advanced past the last
+        * piece of mapped data - use the entry pointed to by cur_index - 1.
+        */
+       rdata = XGBE_GET_DESC_DATA(ring, cur_index - 1);
        rdata->skb = skb;
  
        /* Save the number of descriptor entries used */
  err_out:
        while (start_index < cur_index) {
                rdata = XGBE_GET_DESC_DATA(ring, start_index++);
 -              xgbe_unmap_skb(pdata, rdata);
 +              xgbe_unmap_rdata(pdata, rdata);
        }
  
        DBGPR("<--xgbe_map_tx_skb: count=0\n");
        return 0;
  }
  
 -static void xgbe_realloc_skb(struct xgbe_channel *channel)
 +static void xgbe_realloc_rx_buffer(struct xgbe_channel *channel)
  {
        struct xgbe_prv_data *pdata = channel->pdata;
        struct xgbe_hw_if *hw_if = &pdata->hw_if;
        struct xgbe_ring *ring = channel->rx_ring;
        struct xgbe_ring_data *rdata;
 -      struct sk_buff *skb = NULL;
 -      dma_addr_t skb_dma;
        int i;
  
 -      DBGPR("-->xgbe_realloc_skb: rx_ring->rx.realloc_index = %u\n",
 +      DBGPR("-->xgbe_realloc_rx_buffer: rx_ring->rx.realloc_index = %u\n",
              ring->rx.realloc_index);
  
        for (i = 0; i < ring->dirty; i++) {
                rdata = XGBE_GET_DESC_DATA(ring, ring->rx.realloc_index);
  
                /* Reset rdata values */
 -              xgbe_unmap_skb(pdata, rdata);
 +              xgbe_unmap_rdata(pdata, rdata);
  
 -              /* Allocate skb & assign to each rdesc */
 -              skb = dev_alloc_skb(pdata->rx_buf_size);
 -              if (skb == NULL)
 +              if (xgbe_map_rx_buffer(pdata, ring, rdata))
                        break;
 -              skb_dma = dma_map_single(pdata->dev, skb->data,
 -                                       pdata->rx_buf_size, DMA_FROM_DEVICE);
 -              if (dma_mapping_error(pdata->dev, skb_dma)) {
 -                      netdev_alert(pdata->netdev,
 -                                   "failed to do the dma map\n");
 -                      dev_kfree_skb_any(skb);
 -                      break;
 -              }
 -              rdata->skb = skb;
 -              rdata->skb_dma = skb_dma;
 -              rdata->skb_dma_len = pdata->rx_buf_size;
  
                hw_if->rx_desc_reset(rdata);
  
        }
        ring->dirty = 0;
  
 -      DBGPR("<--xgbe_realloc_skb\n");
 +      DBGPR("<--xgbe_realloc_rx_buffer\n");
  }
  
  void xgbe_init_function_ptrs_desc(struct xgbe_desc_if *desc_if)
        desc_if->alloc_ring_resources = xgbe_alloc_ring_resources;
        desc_if->free_ring_resources = xgbe_free_ring_resources;
        desc_if->map_tx_skb = xgbe_map_tx_skb;
 -      desc_if->realloc_skb = xgbe_realloc_skb;
 -      desc_if->unmap_skb = xgbe_unmap_skb;
 +      desc_if->realloc_rx_buffer = xgbe_realloc_rx_buffer;
 +      desc_if->unmap_rdata = xgbe_unmap_rdata;
        desc_if->wrapper_tx_desc_init = xgbe_wrapper_tx_descriptor_init;
        desc_if->wrapper_rx_desc_init = xgbe_wrapper_rx_descriptor_init;
  
   *     THE POSSIBILITY OF SUCH DAMAGE.
   */
  
 +#include <linux/platform_device.h>
  #include <linux/spinlock.h>
  #include <linux/tcp.h>
  #include <linux/if_vlan.h>
  #include "xgbe.h"
  #include "xgbe-common.h"
  
 -static int xgbe_poll(struct napi_struct *, int);
 +static int xgbe_one_poll(struct napi_struct *, int);
 +static int xgbe_all_poll(struct napi_struct *, int);
  static void xgbe_set_rx_mode(struct net_device *);
  
 +static int xgbe_alloc_channels(struct xgbe_prv_data *pdata)
 +{
 +      struct xgbe_channel *channel_mem, *channel;
 +      struct xgbe_ring *tx_ring, *rx_ring;
 +      unsigned int count, i;
 +      int ret = -ENOMEM;
 +
 +      count = max_t(unsigned int, pdata->tx_ring_count, pdata->rx_ring_count);
 +
 +      channel_mem = kcalloc(count, sizeof(struct xgbe_channel), GFP_KERNEL);
 +      if (!channel_mem)
 +              goto err_channel;
 +
 +      tx_ring = kcalloc(pdata->tx_ring_count, sizeof(struct xgbe_ring),
 +                        GFP_KERNEL);
 +      if (!tx_ring)
 +              goto err_tx_ring;
 +
 +      rx_ring = kcalloc(pdata->rx_ring_count, sizeof(struct xgbe_ring),
 +                        GFP_KERNEL);
 +      if (!rx_ring)
 +              goto err_rx_ring;
 +
 +      for (i = 0, channel = channel_mem; i < count; i++, channel++) {
 +              snprintf(channel->name, sizeof(channel->name), "channel-%d", i);
 +              channel->pdata = pdata;
 +              channel->queue_index = i;
 +              channel->dma_regs = pdata->xgmac_regs + DMA_CH_BASE +
 +                                  (DMA_CH_INC * i);
 +
 +              if (pdata->per_channel_irq) {
 +                      /* Get the DMA interrupt (offset 1) */
 +                      ret = platform_get_irq(pdata->pdev, i + 1);
 +                      if (ret < 0) {
 +                              netdev_err(pdata->netdev,
 +                                         "platform_get_irq %u failed\n",
 +                                         i + 1);
 +                              goto err_irq;
 +                      }
 +
 +                      channel->dma_irq = ret;
 +              }
 +
 +              if (i < pdata->tx_ring_count) {
 +                      spin_lock_init(&tx_ring->lock);
 +                      channel->tx_ring = tx_ring++;
 +              }
 +
 +              if (i < pdata->rx_ring_count) {
 +                      spin_lock_init(&rx_ring->lock);
 +                      channel->rx_ring = rx_ring++;
 +              }
 +
 +              DBGPR("  %s: queue=%u, dma_regs=%p, dma_irq=%d, tx=%p, rx=%p\n",
 +                    channel->name, channel->queue_index, channel->dma_regs,
 +                    channel->dma_irq, channel->tx_ring, channel->rx_ring);
 +      }
 +
 +      pdata->channel = channel_mem;
 +      pdata->channel_count = count;
 +
 +      return 0;
 +
 +err_irq:
 +      kfree(rx_ring);
 +
 +err_rx_ring:
 +      kfree(tx_ring);
 +
 +err_tx_ring:
 +      kfree(channel_mem);
 +
 +err_channel:
 +      return ret;
 +}
 +
 +static void xgbe_free_channels(struct xgbe_prv_data *pdata)
 +{
 +      if (!pdata->channel)
 +              return;
 +
 +      kfree(pdata->channel->rx_ring);
 +      kfree(pdata->channel->tx_ring);
 +      kfree(pdata->channel);
 +
 +      pdata->channel = NULL;
 +      pdata->channel_count = 0;
 +}
 +
  static inline unsigned int xgbe_tx_avail_desc(struct xgbe_ring *ring)
  {
        return (ring->rdesc_count - (ring->cur - ring->dirty));
  }
  
 +static int xgbe_maybe_stop_tx_queue(struct xgbe_channel *channel,
 +                                  struct xgbe_ring *ring, unsigned int count)
 +{
 +      struct xgbe_prv_data *pdata = channel->pdata;
 +
 +      if (count > xgbe_tx_avail_desc(ring)) {
 +              DBGPR("  Tx queue stopped, not enough descriptors available\n");
 +              netif_stop_subqueue(pdata->netdev, channel->queue_index);
 +              ring->tx.queue_stopped = 1;
 +
 +              /* If we haven't notified the hardware because of xmit_more
 +               * support, tell it now
 +               */
 +              if (ring->tx.xmit_more)
 +                      pdata->hw_if.tx_start_xmit(channel, ring);
 +
 +              return NETDEV_TX_BUSY;
 +      }
 +
 +      return 0;
 +}
 +
  static int xgbe_calc_rx_buf_size(struct net_device *netdev, unsigned int mtu)
  {
        unsigned int rx_buf_size;
        }
  
        rx_buf_size = mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
 -      if (rx_buf_size < XGBE_RX_MIN_BUF_SIZE)
 -              rx_buf_size = XGBE_RX_MIN_BUF_SIZE;
 +      rx_buf_size = clamp_val(rx_buf_size, XGBE_RX_MIN_BUF_SIZE, PAGE_SIZE);
 +
        rx_buf_size = (rx_buf_size + XGBE_RX_BUF_ALIGN - 1) &
                      ~(XGBE_RX_BUF_ALIGN - 1);
  
@@@ -326,7 -213,11 +326,7 @@@ static irqreturn_t xgbe_isr(int irq, vo
        if (!dma_isr)
                goto isr_done;
  
 -      DBGPR("-->xgbe_isr\n");
 -
        DBGPR("  DMA_ISR = %08x\n", dma_isr);
 -      DBGPR("  DMA_DS0 = %08x\n", XGMAC_IOREAD(pdata, DMA_DSR0));
 -      DBGPR("  DMA_DS1 = %08x\n", XGMAC_IOREAD(pdata, DMA_DSR1));
  
        for (i = 0; i < pdata->channel_count; i++) {
                if (!(dma_isr & (1 << i)))
                dma_ch_isr = XGMAC_DMA_IOREAD(channel, DMA_CH_SR);
                DBGPR("  DMA_CH%u_ISR = %08x\n", i, dma_ch_isr);
  
 +              /* If we get a TI or RI interrupt that means per channel DMA
 +               * interrupts are not enabled, so we use the private data napi
 +               * structure, not the per channel napi structure
 +               */
                if (XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, TI) ||
                    XGMAC_GET_BITS(dma_ch_isr, DMA_CH_SR, RI)) {
                        if (napi_schedule_prep(&pdata->napi)) {
  
        DBGPR("  DMA_ISR = %08x\n", XGMAC_IOREAD(pdata, DMA_ISR));
  
 -      DBGPR("<--xgbe_isr\n");
 -
  isr_done:
        return IRQ_HANDLED;
  }
  
 +static irqreturn_t xgbe_dma_isr(int irq, void *data)
 +{
 +      struct xgbe_channel *channel = data;
 +
 +      /* Per channel DMA interrupts are enabled, so we use the per
 +       * channel napi structure and not the private data napi structure
 +       */
 +      if (napi_schedule_prep(&channel->napi)) {
 +              /* Disable Tx and Rx interrupts */
 +              disable_irq_nosync(channel->dma_irq);
 +
 +              /* Turn on polling */
 +              __napi_schedule(&channel->napi);
 +      }
 +
 +      return IRQ_HANDLED;
 +}
 +
  static enum hrtimer_restart xgbe_tx_timer(struct hrtimer *timer)
  {
        struct xgbe_channel *channel = container_of(timer,
                                                    tx_timer);
        struct xgbe_ring *ring = channel->tx_ring;
        struct xgbe_prv_data *pdata = channel->pdata;
 +      struct napi_struct *napi;
        unsigned long flags;
  
        DBGPR("-->xgbe_tx_timer\n");
  
 +      napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi;
 +
        spin_lock_irqsave(&ring->lock, flags);
  
 -      if (napi_schedule_prep(&pdata->napi)) {
 +      if (napi_schedule_prep(napi)) {
                /* Disable Tx and Rx interrupts */
 -              xgbe_disable_rx_tx_ints(pdata);
 +              if (pdata->per_channel_irq)
 +                      disable_irq(channel->dma_irq);
 +              else
 +                      xgbe_disable_rx_tx_ints(pdata);
  
                /* Turn on polling */
 -              __napi_schedule(&pdata->napi);
 +              __napi_schedule(napi);
        }
  
        channel->tx_timer_active = 0;
@@@ -565,46 -430,18 +565,46 @@@ void xgbe_get_all_hw_features(struct xg
  
  static void xgbe_napi_enable(struct xgbe_prv_data *pdata, unsigned int add)
  {
 -      if (add)
 -              netif_napi_add(pdata->netdev, &pdata->napi, xgbe_poll,
 -                             NAPI_POLL_WEIGHT);
 -      napi_enable(&pdata->napi);
 +      struct xgbe_channel *channel;
 +      unsigned int i;
 +
 +      if (pdata->per_channel_irq) {
 +              channel = pdata->channel;
 +              for (i = 0; i < pdata->channel_count; i++, channel++) {
 +                      if (add)
 +                              netif_napi_add(pdata->netdev, &channel->napi,
 +                                             xgbe_one_poll, NAPI_POLL_WEIGHT);
 +
 +                      napi_enable(&channel->napi);
 +              }
 +      } else {
 +              if (add)
 +                      netif_napi_add(pdata->netdev, &pdata->napi,
 +                                     xgbe_all_poll, NAPI_POLL_WEIGHT);
 +
 +              napi_enable(&pdata->napi);
 +      }
  }
  
  static void xgbe_napi_disable(struct xgbe_prv_data *pdata, unsigned int del)
  {
 -      napi_disable(&pdata->napi);
 +      struct xgbe_channel *channel;
 +      unsigned int i;
 +
 +      if (pdata->per_channel_irq) {
 +              channel = pdata->channel;
 +              for (i = 0; i < pdata->channel_count; i++, channel++) {
 +                      napi_disable(&channel->napi);
  
 -      if (del)
 -              netif_napi_del(&pdata->napi);
 +                      if (del)
 +                              netif_napi_del(&channel->napi);
 +              }
 +      } else {
 +              napi_disable(&pdata->napi);
 +
 +              if (del)
 +                      netif_napi_del(&pdata->napi);
 +      }
  }
  
  void xgbe_init_tx_coalesce(struct xgbe_prv_data *pdata)
@@@ -635,7 -472,7 +635,7 @@@ void xgbe_init_rx_coalesce(struct xgbe_
        DBGPR("<--xgbe_init_rx_coalesce\n");
  }
  
 -static void xgbe_free_tx_skbuff(struct xgbe_prv_data *pdata)
 +static void xgbe_free_tx_data(struct xgbe_prv_data *pdata)
  {
        struct xgbe_desc_if *desc_if = &pdata->desc_if;
        struct xgbe_channel *channel;
        struct xgbe_ring_data *rdata;
        unsigned int i, j;
  
 -      DBGPR("-->xgbe_free_tx_skbuff\n");
 +      DBGPR("-->xgbe_free_tx_data\n");
  
        channel = pdata->channel;
        for (i = 0; i < pdata->channel_count; i++, channel++) {
  
                for (j = 0; j < ring->rdesc_count; j++) {
                        rdata = XGBE_GET_DESC_DATA(ring, j);
 -                      desc_if->unmap_skb(pdata, rdata);
 +                      desc_if->unmap_rdata(pdata, rdata);
                }
        }
  
 -      DBGPR("<--xgbe_free_tx_skbuff\n");
 +      DBGPR("<--xgbe_free_tx_data\n");
  }
  
 -static void xgbe_free_rx_skbuff(struct xgbe_prv_data *pdata)
 +static void xgbe_free_rx_data(struct xgbe_prv_data *pdata)
  {
        struct xgbe_desc_if *desc_if = &pdata->desc_if;
        struct xgbe_channel *channel;
        struct xgbe_ring_data *rdata;
        unsigned int i, j;
  
 -      DBGPR("-->xgbe_free_rx_skbuff\n");
 +      DBGPR("-->xgbe_free_rx_data\n");
  
        channel = pdata->channel;
        for (i = 0; i < pdata->channel_count; i++, channel++) {
  
                for (j = 0; j < ring->rdesc_count; j++) {
                        rdata = XGBE_GET_DESC_DATA(ring, j);
 -                      desc_if->unmap_skb(pdata, rdata);
 +                      desc_if->unmap_rdata(pdata, rdata);
                }
        }
  
 -      DBGPR("<--xgbe_free_rx_skbuff\n");
 +      DBGPR("<--xgbe_free_rx_data\n");
  }
  
  static void xgbe_adjust_link(struct net_device *netdev)
@@@ -898,10 -735,7 +898,10 @@@ static int xgbe_start(struct xgbe_prv_d
  static void xgbe_stop(struct xgbe_prv_data *pdata)
  {
        struct xgbe_hw_if *hw_if = &pdata->hw_if;
 +      struct xgbe_channel *channel;
        struct net_device *netdev = pdata->netdev;
 +      struct netdev_queue *txq;
 +      unsigned int i;
  
        DBGPR("-->xgbe_stop\n");
  
        hw_if->disable_tx(pdata);
        hw_if->disable_rx(pdata);
  
 +      channel = pdata->channel;
 +      for (i = 0; i < pdata->channel_count; i++, channel++) {
 +              if (!channel->tx_ring)
 +                      continue;
 +
 +              txq = netdev_get_tx_queue(netdev, channel->queue_index);
 +              netdev_tx_reset_queue(txq);
 +      }
 +
        DBGPR("<--xgbe_stop\n");
  }
  
  static void xgbe_restart_dev(struct xgbe_prv_data *pdata, unsigned int reset)
  {
 +      struct xgbe_channel *channel;
        struct xgbe_hw_if *hw_if = &pdata->hw_if;
 +      unsigned int i;
  
        DBGPR("-->xgbe_restart_dev\n");
  
                return;
  
        xgbe_stop(pdata);
 -      synchronize_irq(pdata->irq_number);
 +      synchronize_irq(pdata->dev_irq);
 +      if (pdata->per_channel_irq) {
 +              channel = pdata->channel;
 +              for (i = 0; i < pdata->channel_count; i++, channel++)
 +                      synchronize_irq(channel->dma_irq);
 +      }
  
 -      xgbe_free_tx_skbuff(pdata);
 -      xgbe_free_rx_skbuff(pdata);
 +      xgbe_free_tx_data(pdata);
 +      xgbe_free_rx_data(pdata);
  
        /* Issue software reset to device if requested */
        if (reset)
@@@ -1190,12 -1008,6 +1190,12 @@@ static int xgbe_prep_tso(struct sk_buf
              packet->tcp_header_len, packet->tcp_payload_len);
        DBGPR("  packet->mss=%u\n", packet->mss);
  
 +      /* Update the number of packets that will ultimately be transmitted
 +       * along with the extra bytes for each extra packet
 +       */
 +      packet->tx_packets = skb_shinfo(skb)->gso_segs;
 +      packet->tx_bytes += (packet->tx_packets - 1) * packet->header_len;
 +
        return 0;
  }
  
@@@ -1221,22 -1033,17 +1221,22 @@@ static void xgbe_packet_info(struct xgb
        unsigned int len;
        unsigned int i;
  
 +      packet->skb = skb;
 +
        context_desc = 0;
        packet->rdesc_count = 0;
  
 +      packet->tx_packets = 1;
 +      packet->tx_bytes = skb->len;
 +
        if (xgbe_is_tso(skb)) {
 -              /* TSO requires an extra desriptor if mss is different */
 +              /* TSO requires an extra descriptor if mss is different */
                if (skb_shinfo(skb)->gso_size != ring->tx.cur_mss) {
                        context_desc = 1;
                        packet->rdesc_count++;
                }
  
 -              /* TSO requires an extra desriptor for TSO header */
 +              /* TSO requires an extra descriptor for TSO header */
                packet->rdesc_count++;
  
                XGMAC_SET_BITS(packet->attributes, TX_PACKET_ATTRIBUTES,
@@@ -1284,8 -1091,6 +1284,8 @@@ static int xgbe_open(struct net_device 
        struct xgbe_prv_data *pdata = netdev_priv(netdev);
        struct xgbe_hw_if *hw_if = &pdata->hw_if;
        struct xgbe_desc_if *desc_if = &pdata->desc_if;
 +      struct xgbe_channel *channel = NULL;
 +      unsigned int i = 0;
        int ret;
  
        DBGPR("-->xgbe_open\n");
                goto err_ptpclk;
        pdata->rx_buf_size = ret;
  
 +      /* Allocate the channel and ring structures */
 +      ret = xgbe_alloc_channels(pdata);
 +      if (ret)
 +              goto err_ptpclk;
 +
        /* Allocate the ring descriptors and buffers */
        ret = desc_if->alloc_ring_resources(pdata);
        if (ret)
 -              goto err_ptpclk;
 +              goto err_channels;
  
        /* Initialize the device restart and Tx timestamp work struct */
        INIT_WORK(&pdata->restart_work, xgbe_restart);
        INIT_WORK(&pdata->tx_tstamp_work, xgbe_tx_tstamp);
  
        /* Request interrupts */
 -      ret = devm_request_irq(pdata->dev, netdev->irq, xgbe_isr, 0,
 +      ret = devm_request_irq(pdata->dev, pdata->dev_irq, xgbe_isr, 0,
                               netdev->name, pdata);
        if (ret) {
                netdev_alert(netdev, "error requesting irq %d\n",
 -                           pdata->irq_number);
 -              goto err_irq;
 +                           pdata->dev_irq);
 +              goto err_rings;
 +      }
 +
 +      if (pdata->per_channel_irq) {
 +              channel = pdata->channel;
 +              for (i = 0; i < pdata->channel_count; i++, channel++) {
 +                      snprintf(channel->dma_irq_name,
 +                               sizeof(channel->dma_irq_name) - 1,
 +                               "%s-TxRx-%u", netdev_name(netdev),
 +                               channel->queue_index);
 +
 +                      ret = devm_request_irq(pdata->dev, channel->dma_irq,
 +                                             xgbe_dma_isr, 0,
 +                                             channel->dma_irq_name, channel);
 +                      if (ret) {
 +                              netdev_alert(netdev,
 +                                           "error requesting irq %d\n",
 +                                           channel->dma_irq);
 +                              goto err_irq;
 +                      }
 +              }
        }
 -      pdata->irq_number = netdev->irq;
  
        ret = xgbe_start(pdata);
        if (ret)
  err_start:
        hw_if->exit(pdata);
  
 -      devm_free_irq(pdata->dev, pdata->irq_number, pdata);
 -      pdata->irq_number = 0;
 -
  err_irq:
 +      if (pdata->per_channel_irq) {
 +              /* Using an unsigned int, 'i' will go to UINT_MAX and exit */
 +              for (i--, channel--; i < pdata->channel_count; i--, channel--)
 +                      devm_free_irq(pdata->dev, channel->dma_irq, channel);
 +      }
 +
 +      devm_free_irq(pdata->dev, pdata->dev_irq, pdata);
 +
 +err_rings:
        desc_if->free_ring_resources(pdata);
  
 +err_channels:
 +      xgbe_free_channels(pdata);
 +
  err_ptpclk:
        clk_disable_unprepare(pdata->ptpclk);
  
@@@ -1400,8 -1172,6 +1400,8 @@@ static int xgbe_close(struct net_devic
        struct xgbe_prv_data *pdata = netdev_priv(netdev);
        struct xgbe_hw_if *hw_if = &pdata->hw_if;
        struct xgbe_desc_if *desc_if = &pdata->desc_if;
 +      struct xgbe_channel *channel;
 +      unsigned int i;
  
        DBGPR("-->xgbe_close\n");
  
        /* Issue software reset to device */
        hw_if->exit(pdata);
  
 -      /* Free all the ring data */
 +      /* Free the ring descriptors and buffers */
        desc_if->free_ring_resources(pdata);
  
 -      /* Release the interrupt */
 -      if (pdata->irq_number != 0) {
 -              devm_free_irq(pdata->dev, pdata->irq_number, pdata);
 -              pdata->irq_number = 0;
 +      /* Release the interrupts */
 +      devm_free_irq(pdata->dev, pdata->dev_irq, pdata);
 +      if (pdata->per_channel_irq) {
 +              channel = pdata->channel;
 +              for (i = 0; i < pdata->channel_count; i++, channel++)
 +                      devm_free_irq(pdata->dev, channel->dma_irq, channel);
        }
  
 +      /* Free the channel and ring structures */
 +      xgbe_free_channels(pdata);
 +
        /* Disable the clocks */
        clk_disable_unprepare(pdata->ptpclk);
        clk_disable_unprepare(pdata->sysclk);
@@@ -1445,14 -1210,12 +1445,14 @@@ static int xgbe_xmit(struct sk_buff *sk
        struct xgbe_channel *channel;
        struct xgbe_ring *ring;
        struct xgbe_packet_data *packet;
 +      struct netdev_queue *txq;
        unsigned long flags;
        int ret;
  
        DBGPR("-->xgbe_xmit: skb->len = %d\n", skb->len);
  
        channel = pdata->channel + skb->queue_mapping;
 +      txq = netdev_get_tx_queue(netdev, channel->queue_index);
        ring = channel->tx_ring;
        packet = &ring->packet_data;
  
        xgbe_packet_info(pdata, ring, skb, packet);
  
        /* Check that there are enough descriptors available */
 -      if (packet->rdesc_count > xgbe_tx_avail_desc(ring)) {
 -              DBGPR("  Tx queue stopped, not enough descriptors available\n");
 -              netif_stop_subqueue(netdev, channel->queue_index);
 -              ring->tx.queue_stopped = 1;
 -              ret = NETDEV_TX_BUSY;
 +      ret = xgbe_maybe_stop_tx_queue(channel, ring, packet->rdesc_count);
 +      if (ret)
                goto tx_netdev_return;
 -      }
  
        ret = xgbe_prep_tso(skb, packet);
        if (ret) {
  
        xgbe_prep_tx_tstamp(pdata, skb, packet);
  
 +      /* Report on the actual number of bytes (to be) sent */
 +      netdev_tx_sent_queue(txq, packet->tx_bytes);
 +
        /* Configure required descriptor fields for transmission */
 -      hw_if->pre_xmit(channel);
 +      hw_if->dev_xmit(channel);
  
  #ifdef XGMAC_ENABLE_TX_PKT_DUMP
        xgbe_print_pkt(netdev, skb, true);
  #endif
  
 +      /* Stop the queue in advance if there may not be enough descriptors */
 +      xgbe_maybe_stop_tx_queue(channel, ring, XGBE_TX_MAX_DESCS);
 +
 +      ret = NETDEV_TX_OK;
 +
  tx_netdev_return:
        spin_unlock_irqrestore(&ring->lock, flags);
  
@@@ -1661,20 -1420,14 +1661,20 @@@ static int xgbe_vlan_rx_kill_vid(struc
  static void xgbe_poll_controller(struct net_device *netdev)
  {
        struct xgbe_prv_data *pdata = netdev_priv(netdev);
 +      struct xgbe_channel *channel;
 +      unsigned int i;
  
        DBGPR("-->xgbe_poll_controller\n");
  
 -      disable_irq(pdata->irq_number);
 -
 -      xgbe_isr(pdata->irq_number, pdata);
 -
 -      enable_irq(pdata->irq_number);
 +      if (pdata->per_channel_irq) {
 +              channel = pdata->channel;
 +              for (i = 0; i < pdata->channel_count; i++, channel++)
 +                      xgbe_dma_isr(channel->dma_irq, channel);
 +      } else {
 +              disable_irq(pdata->dev_irq);
 +              xgbe_isr(pdata->dev_irq, pdata);
 +              enable_irq(pdata->dev_irq);
 +      }
  
        DBGPR("<--xgbe_poll_controller\n");
  }
@@@ -1712,21 -1465,12 +1712,21 @@@ static int xgbe_set_features(struct net
  {
        struct xgbe_prv_data *pdata = netdev_priv(netdev);
        struct xgbe_hw_if *hw_if = &pdata->hw_if;
 -      netdev_features_t rxcsum, rxvlan, rxvlan_filter;
 +      netdev_features_t rxhash, rxcsum, rxvlan, rxvlan_filter;
 +      int ret = 0;
  
 +      rxhash = pdata->netdev_features & NETIF_F_RXHASH;
        rxcsum = pdata->netdev_features & NETIF_F_RXCSUM;
        rxvlan = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_RX;
        rxvlan_filter = pdata->netdev_features & NETIF_F_HW_VLAN_CTAG_FILTER;
  
 +      if ((features & NETIF_F_RXHASH) && !rxhash)
 +              ret = hw_if->enable_rss(pdata);
 +      else if (!(features & NETIF_F_RXHASH) && rxhash)
 +              ret = hw_if->disable_rss(pdata);
 +      if (ret)
 +              return ret;
 +
        if ((features & NETIF_F_RXCSUM) && !rxcsum)
                hw_if->enable_rx_csum(pdata);
        else if (!(features & NETIF_F_RXCSUM) && rxcsum)
@@@ -1780,7 -1524,7 +1780,7 @@@ static void xgbe_rx_refresh(struct xgbe
        struct xgbe_ring *ring = channel->rx_ring;
        struct xgbe_ring_data *rdata;
  
 -      desc_if->realloc_skb(channel);
 +      desc_if->realloc_rx_buffer(channel);
  
        /* Update the Rx Tail Pointer Register with address of
         * the last cleaned entry */
                          lower_32_bits(rdata->rdesc_dma));
  }
  
 +static struct sk_buff *xgbe_create_skb(struct xgbe_prv_data *pdata,
 +                                     struct xgbe_ring_data *rdata,
 +                                     unsigned int *len)
 +{
 +      struct net_device *netdev = pdata->netdev;
 +      struct sk_buff *skb;
 +      u8 *packet;
 +      unsigned int copy_len;
 +
 +      skb = netdev_alloc_skb_ip_align(netdev, rdata->rx.hdr.dma_len);
 +      if (!skb)
 +              return NULL;
 +
 +      packet = page_address(rdata->rx.hdr.pa.pages) +
 +               rdata->rx.hdr.pa.pages_offset;
 +      copy_len = (rdata->rx.hdr_len) ? rdata->rx.hdr_len : *len;
 +      copy_len = min(rdata->rx.hdr.dma_len, copy_len);
 +      skb_copy_to_linear_data(skb, packet, copy_len);
 +      skb_put(skb, copy_len);
 +
 +      *len -= copy_len;
 +
 +      return skb;
 +}
 +
  static int xgbe_tx_poll(struct xgbe_channel *channel)
  {
        struct xgbe_prv_data *pdata = channel->pdata;
        struct xgbe_ring_data *rdata;
        struct xgbe_ring_desc *rdesc;
        struct net_device *netdev = pdata->netdev;
 +      struct netdev_queue *txq;
        unsigned long flags;
        int processed = 0;
 +      unsigned int tx_packets = 0, tx_bytes = 0;
  
        DBGPR("-->xgbe_tx_poll\n");
  
        if (!ring)
                return 0;
  
 +      txq = netdev_get_tx_queue(netdev, channel->queue_index);
 +
        spin_lock_irqsave(&ring->lock, flags);
  
        while ((processed < XGBE_TX_DESC_MAX_PROC) &&
-              (ring->dirty < ring->cur)) {
+              (ring->dirty != ring->cur)) {
                rdata = XGBE_GET_DESC_DATA(ring, ring->dirty);
                rdesc = rdata->rdesc;
  
                if (!hw_if->tx_complete(rdesc))
                        break;
  
 +              /* Make sure descriptor fields are read after reading the OWN
 +               * bit */
 +              rmb();
 +
  #ifdef XGMAC_ENABLE_TX_DESC_DUMP
                xgbe_dump_tx_desc(ring, ring->dirty, 1, 0);
  #endif
  
 +              if (hw_if->is_last_desc(rdesc)) {
 +                      tx_packets += rdata->tx.packets;
 +                      tx_bytes += rdata->tx.bytes;
 +              }
 +
                /* Free the SKB and reset the descriptor for re-use */
 -              desc_if->unmap_skb(pdata, rdata);
 +              desc_if->unmap_rdata(pdata, rdata);
                hw_if->tx_desc_reset(rdata);
  
                processed++;
                ring->dirty++;
        }
  
 +      if (!processed)
 +              goto unlock;
 +
 +      netdev_tx_completed_queue(txq, tx_packets, tx_bytes);
 +
        if ((ring->tx.queue_stopped == 1) &&
            (xgbe_tx_avail_desc(ring) > XGBE_TX_DESC_MIN_FREE)) {
                ring->tx.queue_stopped = 0;
 -              netif_wake_subqueue(netdev, channel->queue_index);
 +              netif_tx_wake_queue(txq);
        }
  
        DBGPR("<--xgbe_tx_poll: processed=%d\n", processed);
  
 +unlock:
        spin_unlock_irqrestore(&ring->lock, flags);
  
        return processed;
@@@ -1894,7 -1594,6 +1894,7 @@@ static int xgbe_rx_poll(struct xgbe_cha
        struct xgbe_ring_data *rdata;
        struct xgbe_packet_data *packet;
        struct net_device *netdev = pdata->netdev;
 +      struct napi_struct *napi;
        struct sk_buff *skb;
        struct skb_shared_hwtstamps *hwtstamps;
        unsigned int incomplete, error, context_next, context;
        if (!ring)
                return 0;
  
 +      napi = (pdata->per_channel_irq) ? &channel->napi : &pdata->napi;
 +
        rdata = XGBE_GET_DESC_DATA(ring, ring->cur);
        packet = &ring->packet_data;
        while (packet_count < budget) {
@@@ -1944,6 -1641,10 +1944,6 @@@ read_again
                ring->cur++;
                ring->dirty++;
  
 -              dma_unmap_single(pdata->dev, rdata->skb_dma,
 -                               rdata->skb_dma_len, DMA_FROM_DEVICE);
 -              rdata->skb_dma = 0;
 -
                incomplete = XGMAC_GET_BITS(packet->attributes,
                                            RX_PACKET_ATTRIBUTES,
                                            INCOMPLETE);
                }
  
                if (!context) {
 -                      put_len = rdata->len - len;
 -                      if (skb) {
 -                              if (pskb_expand_head(skb, 0, put_len,
 -                                                   GFP_ATOMIC)) {
 -                                      DBGPR("pskb_expand_head error\n");
 -                                      if (incomplete) {
 -                                              error = 1;
 -                                              goto read_again;
 -                                      }
 -
 -                                      dev_kfree_skb(skb);
 -                                      goto next_packet;
 +                      put_len = rdata->rx.len - len;
 +                      len += put_len;
 +
 +                      if (!skb) {
 +                              dma_sync_single_for_cpu(pdata->dev,
 +                                                      rdata->rx.hdr.dma,
 +                                                      rdata->rx.hdr.dma_len,
 +                                                      DMA_FROM_DEVICE);
 +
 +                              skb = xgbe_create_skb(pdata, rdata, &put_len);
 +                              if (!skb) {
 +                                      error = 1;
 +                                      goto skip_data;
                                }
 -                              memcpy(skb_tail_pointer(skb), rdata->skb->data,
 -                                     put_len);
 -                      } else {
 -                              skb = rdata->skb;
 -                              rdata->skb = NULL;
                        }
 -                      skb_put(skb, put_len);
 -                      len += put_len;
 +
 +                      if (put_len) {
 +                              dma_sync_single_for_cpu(pdata->dev,
 +                                                      rdata->rx.buf.dma,
 +                                                      rdata->rx.buf.dma_len,
 +                                                      DMA_FROM_DEVICE);
 +
 +                              skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
 +                                              rdata->rx.buf.pa.pages,
 +                                              rdata->rx.buf.pa.pages_offset,
 +                                              put_len, rdata->rx.buf.dma_len);
 +                              rdata->rx.buf.pa.pages = NULL;
 +                      }
                }
  
 +skip_data:
                if (incomplete || context_next)
                        goto read_again;
  
 -              /* Stray Context Descriptor? */
                if (!skb)
                        goto next_packet;
  
                        hwtstamps->hwtstamp = ns_to_ktime(nsec);
                }
  
 +              if (XGMAC_GET_BITS(packet->attributes,
 +                                 RX_PACKET_ATTRIBUTES, RSS_HASH))
 +                      skb_set_hash(skb, packet->rss_hash,
 +                                   packet->rss_hash_type);
 +
                skb->dev = netdev;
                skb->protocol = eth_type_trans(skb, netdev);
                skb_record_rx_queue(skb, channel->queue_index);
 -              skb_mark_napi_id(skb, &pdata->napi);
 +              skb_mark_napi_id(skb, napi);
  
                netdev->last_rx = jiffies;
 -              napi_gro_receive(&pdata->napi, skb);
 +              napi_gro_receive(napi, skb);
  
  next_packet:
                packet_count++;
        return packet_count;
  }
  
 -static int xgbe_poll(struct napi_struct *napi, int budget)
 +static int xgbe_one_poll(struct napi_struct *napi, int budget)
 +{
 +      struct xgbe_channel *channel = container_of(napi, struct xgbe_channel,
 +                                                  napi);
 +      int processed = 0;
 +
 +      DBGPR("-->xgbe_one_poll: budget=%d\n", budget);
 +
 +      /* Cleanup Tx ring first */
 +      xgbe_tx_poll(channel);
 +
 +      /* Process Rx ring next */
 +      processed = xgbe_rx_poll(channel, budget);
 +
 +      /* If we processed everything, we are done */
 +      if (processed < budget) {
 +              /* Turn off polling */
 +              napi_complete(napi);
 +
 +              /* Enable Tx and Rx interrupts */
 +              enable_irq(channel->dma_irq);
 +      }
 +
 +      DBGPR("<--xgbe_one_poll: received = %d\n", processed);
 +
 +      return processed;
 +}
 +
 +static int xgbe_all_poll(struct napi_struct *napi, int budget)
  {
        struct xgbe_prv_data *pdata = container_of(napi, struct xgbe_prv_data,
                                                   napi);
        int processed, last_processed;
        unsigned int i;
  
 -      DBGPR("-->xgbe_poll: budget=%d\n", budget);
 +      DBGPR("-->xgbe_all_poll: budget=%d\n", budget);
  
        processed = 0;
        ring_budget = budget / pdata->rx_ring_count;
                xgbe_enable_rx_tx_ints(pdata);
        }
  
 -      DBGPR("<--xgbe_poll: received = %d\n", processed);
 +      DBGPR("<--xgbe_all_poll: received = %d\n", processed);
  
        return processed;
  }
@@@ -2151,10 -1812,10 +2151,10 @@@ void xgbe_dump_tx_desc(struct xgbe_rin
        while (count--) {
                rdata = XGBE_GET_DESC_DATA(ring, idx);
                rdesc = rdata->rdesc;
 -              DBGPR("TX_NORMAL_DESC[%d %s] = %08x:%08x:%08x:%08x\n", idx,
 -                    (flag == 1) ? "QUEUED FOR TX" : "TX BY DEVICE",
 -                    le32_to_cpu(rdesc->desc0), le32_to_cpu(rdesc->desc1),
 -                    le32_to_cpu(rdesc->desc2), le32_to_cpu(rdesc->desc3));
 +              pr_alert("TX_NORMAL_DESC[%d %s] = %08x:%08x:%08x:%08x\n", idx,
 +                       (flag == 1) ? "QUEUED FOR TX" : "TX BY DEVICE",
 +                       le32_to_cpu(rdesc->desc0), le32_to_cpu(rdesc->desc1),
 +                       le32_to_cpu(rdesc->desc2), le32_to_cpu(rdesc->desc3));
                idx++;
        }
  }
  void xgbe_dump_rx_desc(struct xgbe_ring *ring, struct xgbe_ring_desc *desc,
                       unsigned int idx)
  {
 -      DBGPR("RX_NORMAL_DESC[%d RX BY DEVICE] = %08x:%08x:%08x:%08x\n", idx,
 -            le32_to_cpu(desc->desc0), le32_to_cpu(desc->desc1),
 -            le32_to_cpu(desc->desc2), le32_to_cpu(desc->desc3));
 +      pr_alert("RX_NORMAL_DESC[%d RX BY DEVICE] = %08x:%08x:%08x:%08x\n", idx,
 +               le32_to_cpu(desc->desc0), le32_to_cpu(desc->desc1),
 +               le32_to_cpu(desc->desc2), le32_to_cpu(desc->desc3));
  }
  
  void xgbe_print_pkt(struct net_device *netdev, struct sk_buff *skb, bool tx_rx)
@@@ -45,6 -45,7 +45,7 @@@
  #include <net/ip.h>
  #include <net/ipv6.h>
  #include <net/tcp.h>
+ #include <net/vxlan.h>
  #include <net/checksum.h>
  #include <net/ip6_checksum.h>
  #include <linux/workqueue.h>
@@@ -1931,7 -1932,7 +1932,7 @@@ irqreturn_t bnx2x_interrupt(int irq, vo
                        for_each_cos_in_tx_queue(fp, cos)
                                prefetch(fp->txdata_ptr[cos]->tx_cons_sb);
                        prefetch(&fp->sb_running_index[SM_RX_ID]);
 -                      napi_schedule(&bnx2x_fp(bp, fp->index, napi));
 +                      napi_schedule_irqoff(&bnx2x_fp(bp, fp->index, napi));
                        status &= ~mask;
                }
        }
@@@ -3163,8 -3164,6 +3164,8 @@@ static void bnx2x_pf_q_prep_general(str
                gen_init->mtu = bp->dev->mtu;
  
        gen_init->cos = cos;
 +
 +      gen_init->fp_hsi = ETH_FP_HSI_VERSION;
  }
  
  static void bnx2x_pf_rx_q_prep(struct bnx2x *bp,
@@@ -12539,7 -12538,7 +12540,7 @@@ static int bnx2x_validate_addr(struct n
  }
  
  static int bnx2x_get_phys_port_id(struct net_device *netdev,
 -                                struct netdev_phys_port_id *ppid)
 +                                struct netdev_phys_item_id *ppid)
  {
        struct bnx2x *bp = netdev_priv(netdev);
  
        return 0;
  }
  
+ static bool bnx2x_gso_check(struct sk_buff *skb, struct net_device *dev)
+ {
+       return vxlan_gso_check(skb);
+ }
  static const struct net_device_ops bnx2x_netdev_ops = {
        .ndo_open               = bnx2x_open,
        .ndo_stop               = bnx2x_close,
  #endif
        .ndo_get_phys_port_id   = bnx2x_get_phys_port_id,
        .ndo_set_vf_link_state  = bnx2x_set_vf_link_state,
+       .ndo_gso_check          = bnx2x_gso_check,
  };
  
  static int bnx2x_set_coherency_mask(struct bnx2x *bp)
  #include "cxgb4_uld.h"
  
  #define T4FW_VERSION_MAJOR 0x01
- #define T4FW_VERSION_MINOR 0x0B
- #define T4FW_VERSION_MICRO 0x1B
+ #define T4FW_VERSION_MINOR 0x0C
+ #define T4FW_VERSION_MICRO 0x19
  #define T4FW_VERSION_BUILD 0x00
  
  #define T5FW_VERSION_MAJOR 0x01
- #define T5FW_VERSION_MINOR 0x0B
- #define T5FW_VERSION_MICRO 0x1B
+ #define T5FW_VERSION_MINOR 0x0C
+ #define T5FW_VERSION_MICRO 0x19
  #define T5FW_VERSION_BUILD 0x00
  
  #define CH_WARN(adap, fmt, ...) dev_warn(adap->pdev_dev, fmt, ## __VA_ARGS__)
@@@ -222,12 -222,6 +222,12 @@@ struct tp_err_stats 
        u32 ofldCongDefer;
  };
  
 +struct sge_params {
 +      u32 hps;                        /* host page size for our PF/VF */
 +      u32 eq_qpp;                     /* egress queues/page for our PF/VF */
 +      u32 iq_qpp;                     /* egress queues/page for our PF/VF */
 +};
 +
  struct tp_params {
        unsigned int ntxchan;        /* # of Tx channels */
        unsigned int tre;            /* log2 of core clocks per TP tick */
@@@ -291,7 -285,6 +291,7 @@@ enum chip_type 
  };
  
  struct adapter_params {
 +      struct sge_params sge;
        struct tp_params  tp;
        struct vpd_params vpd;
        struct pci_params pci;
  #include "t4fw_api.h"
  
  #define FW_VERSION(chip) ( \
 -              FW_HDR_FW_VER_MAJOR_GET(chip##FW_VERSION_MAJOR) | \
 -              FW_HDR_FW_VER_MINOR_GET(chip##FW_VERSION_MINOR) | \
 -              FW_HDR_FW_VER_MICRO_GET(chip##FW_VERSION_MICRO) | \
 -              FW_HDR_FW_VER_BUILD_GET(chip##FW_VERSION_BUILD))
 +              FW_HDR_FW_VER_MAJOR_G(chip##FW_VERSION_MAJOR) | \
 +              FW_HDR_FW_VER_MINOR_G(chip##FW_VERSION_MINOR) | \
 +              FW_HDR_FW_VER_MICRO_G(chip##FW_VERSION_MICRO) | \
 +              FW_HDR_FW_VER_BUILD_G(chip##FW_VERSION_BUILD))
  #define FW_INTFVER(chip, intf) (FW_HDR_INTFVER_##intf)
  
  struct fw_info {
@@@ -361,7 -354,7 +361,7 @@@ struct link_config 
        unsigned char  link_ok;          /* link up? */
  };
  
 -#define FW_LEN16(fw_struct) FW_CMD_LEN16(sizeof(fw_struct) / 16)
 +#define FW_LEN16(fw_struct) FW_CMD_LEN16_V(sizeof(fw_struct) / 16)
  
  enum {
        MAX_ETH_QSETS = 32,           /* # of Ethernet Tx/Rx queue sets */
@@@ -438,8 -431,7 +438,8 @@@ struct sge_fl {                     /* 
        struct rx_sw_desc *sdesc;   /* address of SW Rx descriptor ring */
        __be64 *desc;               /* address of HW Rx descriptor ring */
        dma_addr_t addr;            /* bus address of HW ring start */
 -      u64 udb;                    /* BAR2 offset of User Doorbell area */
 +      void __iomem *bar2_addr;    /* address of BAR2 Queue registers */
 +      unsigned int bar2_qid;      /* Queue ID for BAR2 Queue registers */
  };
  
  /* A packet gather list */
@@@ -469,8 -461,7 +469,8 @@@ struct sge_rspq {                   /* 
        u16 abs_id;                 /* absolute SGE id for the response q */
        __be64 *desc;               /* address of HW response ring */
        dma_addr_t phys_addr;       /* physical address of the ring */
 -      u64 udb;                    /* BAR2 offset of User Doorbell area */
 +      void __iomem *bar2_addr;    /* address of BAR2 Queue registers */
 +      unsigned int bar2_qid;      /* Queue ID for BAR2 Queue registers */
        unsigned int iqe_len;       /* entry size */
        unsigned int size;          /* capacity of response queue */
        struct adapter *adap;
@@@ -528,8 -519,7 +528,8 @@@ struct sge_txq 
        int db_disabled;
        unsigned short db_pidx;
        unsigned short db_pidx_inc;
 -      u64 udb;                    /* BAR2 offset of User Doorbell area */
 +      void __iomem *bar2_addr;    /* address of BAR2 Queue registers */
 +      unsigned int bar2_qid;      /* Queue ID for BAR2 Queue registers */
  };
  
  struct sge_eth_txq {                /* state for an SGE Ethernet Tx queue */
@@@ -1005,15 -995,6 +1005,15 @@@ int t4_prep_fw(struct adapter *adap, st
               const u8 *fw_data, unsigned int fw_size,
               struct fw_hdr *card_fw, enum dev_state state, int *reset);
  int t4_prep_adapter(struct adapter *adapter);
 +
 +enum t4_bar2_qtype { T4_BAR2_QTYPE_EGRESS, T4_BAR2_QTYPE_INGRESS };
 +int t4_bar2_sge_qregs(struct adapter *adapter,
 +                    unsigned int qid,
 +                    enum t4_bar2_qtype qtype,
 +                    u64 *pbar2_qoffset,
 +                    unsigned int *pbar2_qid);
 +
 +int t4_init_sge_params(struct adapter *adapter);
  int t4_init_tp_params(struct adapter *adap);
  int t4_filter_field_shift(const struct adapter *adap, int filter_sel);
  int t4_port_init(struct adapter *adap, int mbox, int pf, int vf);
@@@ -1104,5 -1085,4 +1104,5 @@@ void t4_db_dropped(struct adapter *adap
  int t4_fwaddrspace_write(struct adapter *adap, unsigned int mbox,
                         u32 addr, u32 val);
  void t4_sge_decode_idma_state(struct adapter *adapter, int state);
 +void t4_free_mem(void *addr);
  #endif /* __CXGB4_H__ */
@@@ -61,7 -61,6 +61,7 @@@
  #include <net/neighbour.h>
  #include <net/netevent.h>
  #include <net/addrconf.h>
 +#include <net/bonding.h>
  #include <asm/uaccess.h>
  
  #include "cxgb4.h"
  #include "t4_msg.h"
  #include "t4fw_api.h"
  #include "cxgb4_dcb.h"
 +#include "cxgb4_debugfs.h"
  #include "l2t.h"
  
 -#include <../drivers/net/bonding/bonding.h>
 -
  #ifdef DRV_VERSION
  #undef DRV_VERSION
  #endif
@@@ -141,7 -141,7 +141,7 @@@ static unsigned int pfvfres_pmask(struc
         * Give PF's access to all of the ports.
         */
        if (vf == 0)
 -              return FW_PFVF_CMD_PMASK_MASK;
 +              return FW_PFVF_CMD_PMASK_M;
  
        /*
         * For VFs, we'll assign them access to the ports based purely on the
@@@ -210,25 -210,114 +210,25 @@@ struct filter_entry 
                         NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP |\
                         NETIF_MSG_RX_ERR | NETIF_MSG_TX_ERR)
  
 -#define CH_DEVICE(devid, data) { PCI_VDEVICE(CHELSIO, devid), (data) }
 -
 -static const struct pci_device_id cxgb4_pci_tbl[] = {
 -      CH_DEVICE(0xa000, 0),  /* PE10K */
 -      CH_DEVICE(0x4001, -1),
 -      CH_DEVICE(0x4002, -1),
 -      CH_DEVICE(0x4003, -1),
 -      CH_DEVICE(0x4004, -1),
 -      CH_DEVICE(0x4005, -1),
 -      CH_DEVICE(0x4006, -1),
 -      CH_DEVICE(0x4007, -1),
 -      CH_DEVICE(0x4008, -1),
 -      CH_DEVICE(0x4009, -1),
 -      CH_DEVICE(0x400a, -1),
 -      CH_DEVICE(0x400d, -1),
 -      CH_DEVICE(0x400e, -1),
 -      CH_DEVICE(0x4080, -1),
 -      CH_DEVICE(0x4081, -1),
 -      CH_DEVICE(0x4082, -1),
 -      CH_DEVICE(0x4083, -1),
 -      CH_DEVICE(0x4084, -1),
 -      CH_DEVICE(0x4085, -1),
 -      CH_DEVICE(0x4086, -1),
 -      CH_DEVICE(0x4087, -1),
 -      CH_DEVICE(0x4088, -1),
 -      CH_DEVICE(0x4401, 4),
 -      CH_DEVICE(0x4402, 4),
 -      CH_DEVICE(0x4403, 4),
 -      CH_DEVICE(0x4404, 4),
 -      CH_DEVICE(0x4405, 4),
 -      CH_DEVICE(0x4406, 4),
 -      CH_DEVICE(0x4407, 4),
 -      CH_DEVICE(0x4408, 4),
 -      CH_DEVICE(0x4409, 4),
 -      CH_DEVICE(0x440a, 4),
 -      CH_DEVICE(0x440d, 4),
 -      CH_DEVICE(0x440e, 4),
 -      CH_DEVICE(0x4480, 4),
 -      CH_DEVICE(0x4481, 4),
 -      CH_DEVICE(0x4482, 4),
 -      CH_DEVICE(0x4483, 4),
 -      CH_DEVICE(0x4484, 4),
 -      CH_DEVICE(0x4485, 4),
 -      CH_DEVICE(0x4486, 4),
 -      CH_DEVICE(0x4487, 4),
 -      CH_DEVICE(0x4488, 4),
 -      CH_DEVICE(0x5001, 4),
 -      CH_DEVICE(0x5002, 4),
 -      CH_DEVICE(0x5003, 4),
 -      CH_DEVICE(0x5004, 4),
 -      CH_DEVICE(0x5005, 4),
 -      CH_DEVICE(0x5006, 4),
 -      CH_DEVICE(0x5007, 4),
 -      CH_DEVICE(0x5008, 4),
 -      CH_DEVICE(0x5009, 4),
 -      CH_DEVICE(0x500A, 4),
 -      CH_DEVICE(0x500B, 4),
 -      CH_DEVICE(0x500C, 4),
 -      CH_DEVICE(0x500D, 4),
 -      CH_DEVICE(0x500E, 4),
 -      CH_DEVICE(0x500F, 4),
 -      CH_DEVICE(0x5010, 4),
 -      CH_DEVICE(0x5011, 4),
 -      CH_DEVICE(0x5012, 4),
 -      CH_DEVICE(0x5013, 4),
 -      CH_DEVICE(0x5014, 4),
 -      CH_DEVICE(0x5015, 4),
 -      CH_DEVICE(0x5080, 4),
 -      CH_DEVICE(0x5081, 4),
 -      CH_DEVICE(0x5082, 4),
 -      CH_DEVICE(0x5083, 4),
 -      CH_DEVICE(0x5084, 4),
 -      CH_DEVICE(0x5085, 4),
 -      CH_DEVICE(0x5086, 4),
 -      CH_DEVICE(0x5087, 4),
 -      CH_DEVICE(0x5088, 4),
 -      CH_DEVICE(0x5401, 4),
 -      CH_DEVICE(0x5402, 4),
 -      CH_DEVICE(0x5403, 4),
 -      CH_DEVICE(0x5404, 4),
 -      CH_DEVICE(0x5405, 4),
 -      CH_DEVICE(0x5406, 4),
 -      CH_DEVICE(0x5407, 4),
 -      CH_DEVICE(0x5408, 4),
 -      CH_DEVICE(0x5409, 4),
 -      CH_DEVICE(0x540A, 4),
 -      CH_DEVICE(0x540B, 4),
 -      CH_DEVICE(0x540C, 4),
 -      CH_DEVICE(0x540D, 4),
 -      CH_DEVICE(0x540E, 4),
 -      CH_DEVICE(0x540F, 4),
 -      CH_DEVICE(0x5410, 4),
 -      CH_DEVICE(0x5411, 4),
 -      CH_DEVICE(0x5412, 4),
 -      CH_DEVICE(0x5413, 4),
 -      CH_DEVICE(0x5414, 4),
 -      CH_DEVICE(0x5415, 4),
 -      CH_DEVICE(0x5480, 4),
 -      CH_DEVICE(0x5481, 4),
 -      CH_DEVICE(0x5482, 4),
 -      CH_DEVICE(0x5483, 4),
 -      CH_DEVICE(0x5484, 4),
 -      CH_DEVICE(0x5485, 4),
 -      CH_DEVICE(0x5486, 4),
 -      CH_DEVICE(0x5487, 4),
 -      CH_DEVICE(0x5488, 4),
 -      { 0, }
 -};
 +/* Macros needed to support the PCI Device ID Table ...
 + */
 +#define CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN \
 +      static struct pci_device_id cxgb4_pci_tbl[] = {
 +#define CH_PCI_DEVICE_ID_FUNCTION 0x4
 +
 +/* Include PCI Device IDs for both PF4 and PF0-3 so our PCI probe() routine is
 + * called for both.
 + */
 +#define CH_PCI_DEVICE_ID_FUNCTION2 0x0
 +
 +#define CH_PCI_ID_TABLE_ENTRY(devid) \
 +              {PCI_VDEVICE(CHELSIO, (devid)), 4}
 +
 +#define CH_PCI_DEVICE_ID_TABLE_DEFINE_END \
 +              { 0, } \
 +      }
 +
 +#include "t4_pci_id_tbl.h"
  
  #define FW4_FNAME "cxgb4/t4fw.bin"
  #define FW5_FNAME "cxgb4/t5fw.bin"
@@@ -423,10 -512,9 +423,10 @@@ static void dcb_tx_queue_prio_enable(st
                u32 name, value;
                int err;
  
 -              name = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) |
 -                      FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_EQ_DCBPRIO_ETH) |
 -                      FW_PARAMS_PARAM_YZ(txq->q.cntxt_id));
 +              name = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DMAQ) |
 +                      FW_PARAMS_PARAM_X_V(
 +                              FW_PARAMS_PARAM_DMAQ_EQ_DCBPRIO_ETH) |
 +                      FW_PARAMS_PARAM_YZ_V(txq->q.cntxt_id));
                value = enable ? i : 0xffffffff;
  
                /* Since we can be called while atomic (from "interrupt
@@@ -621,7 -709,7 +621,7 @@@ EXPORT_SYMBOL(cxgb4_dcb_enabled)
  /* Handle a Data Center Bridging update message from the firmware. */
  static void dcb_rpl(struct adapter *adap, const struct fw_port_cmd *pcmd)
  {
 -      int port = FW_PORT_CMD_PORTID_GET(ntohl(pcmd->op_to_portid));
 +      int port = FW_PORT_CMD_PORTID_G(ntohl(pcmd->op_to_portid));
        struct net_device *dev = adap->port[port];
        int old_dcb_enabled = cxgb4_dcb_enabled(dev);
        int new_dcb_enabled;
@@@ -744,17 -832,17 +744,17 @@@ static int fwevtq_handler(struct sge_rs
  
  #ifdef CONFIG_CHELSIO_T4_DCB
                const struct fw_port_cmd *pcmd = (const void *)p->data;
 -              unsigned int cmd = FW_CMD_OP_GET(ntohl(pcmd->op_to_portid));
 +              unsigned int cmd = FW_CMD_OP_G(ntohl(pcmd->op_to_portid));
                unsigned int action =
 -                      FW_PORT_CMD_ACTION_GET(ntohl(pcmd->action_to_len16));
 +                      FW_PORT_CMD_ACTION_G(ntohl(pcmd->action_to_len16));
  
                if (cmd == FW_PORT_CMD &&
                    action == FW_PORT_ACTION_GET_PORT_INFO) {
 -                      int port = FW_PORT_CMD_PORTID_GET(
 +                      int port = FW_PORT_CMD_PORTID_G(
                                        be32_to_cpu(pcmd->op_to_portid));
                        struct net_device *dev = q->adap->port[port];
                        int state_input = ((pcmd->u.info.dcbxdis_pkd &
 -                                          FW_PORT_CMD_DCBXDIS)
 +                                          FW_PORT_CMD_DCBXDIS_F)
                                           ? CXGB4_DCB_INPUT_FW_DISABLED
                                           : CXGB4_DCB_INPUT_FW_ENABLED);
  
@@@ -1199,7 -1287,7 +1199,7 @@@ void *t4_alloc_mem(size_t size
  /*
   * Free memory allocated through alloc_mem().
   */
 -static void t4_free_mem(void *addr)
 +void t4_free_mem(void *addr)
  {
        if (is_vmalloc_addr(addr))
                vfree(addr);
@@@ -1251,52 -1339,52 +1251,52 @@@ static int set_filter_wr(struct adapte
         * filter specification structure but for now it's easiest to simply
         * put this fairly direct code in line ...
         */
 -      fwr->op_pkd = htonl(FW_WR_OP(FW_FILTER_WR));
 -      fwr->len16_pkd = htonl(FW_WR_LEN16(sizeof(*fwr)/16));
 +      fwr->op_pkd = htonl(FW_WR_OP_V(FW_FILTER_WR));
 +      fwr->len16_pkd = htonl(FW_WR_LEN16_V(sizeof(*fwr)/16));
        fwr->tid_to_iq =
 -              htonl(V_FW_FILTER_WR_TID(ftid) |
 -                    V_FW_FILTER_WR_RQTYPE(f->fs.type) |
 -                    V_FW_FILTER_WR_NOREPLY(0) |
 -                    V_FW_FILTER_WR_IQ(f->fs.iq));
 +              htonl(FW_FILTER_WR_TID_V(ftid) |
 +                    FW_FILTER_WR_RQTYPE_V(f->fs.type) |
 +                    FW_FILTER_WR_NOREPLY_V(0) |
 +                    FW_FILTER_WR_IQ_V(f->fs.iq));
        fwr->del_filter_to_l2tix =
 -              htonl(V_FW_FILTER_WR_RPTTID(f->fs.rpttid) |
 -                    V_FW_FILTER_WR_DROP(f->fs.action == FILTER_DROP) |
 -                    V_FW_FILTER_WR_DIRSTEER(f->fs.dirsteer) |
 -                    V_FW_FILTER_WR_MASKHASH(f->fs.maskhash) |
 -                    V_FW_FILTER_WR_DIRSTEERHASH(f->fs.dirsteerhash) |
 -                    V_FW_FILTER_WR_LPBK(f->fs.action == FILTER_SWITCH) |
 -                    V_FW_FILTER_WR_DMAC(f->fs.newdmac) |
 -                    V_FW_FILTER_WR_SMAC(f->fs.newsmac) |
 -                    V_FW_FILTER_WR_INSVLAN(f->fs.newvlan == VLAN_INSERT ||
 +              htonl(FW_FILTER_WR_RPTTID_V(f->fs.rpttid) |
 +                    FW_FILTER_WR_DROP_V(f->fs.action == FILTER_DROP) |
 +                    FW_FILTER_WR_DIRSTEER_V(f->fs.dirsteer) |
 +                    FW_FILTER_WR_MASKHASH_V(f->fs.maskhash) |
 +                    FW_FILTER_WR_DIRSTEERHASH_V(f->fs.dirsteerhash) |
 +                    FW_FILTER_WR_LPBK_V(f->fs.action == FILTER_SWITCH) |
 +                    FW_FILTER_WR_DMAC_V(f->fs.newdmac) |
 +                    FW_FILTER_WR_SMAC_V(f->fs.newsmac) |
 +                    FW_FILTER_WR_INSVLAN_V(f->fs.newvlan == VLAN_INSERT ||
                                             f->fs.newvlan == VLAN_REWRITE) |
 -                    V_FW_FILTER_WR_RMVLAN(f->fs.newvlan == VLAN_REMOVE ||
 +                    FW_FILTER_WR_RMVLAN_V(f->fs.newvlan == VLAN_REMOVE ||
                                            f->fs.newvlan == VLAN_REWRITE) |
 -                    V_FW_FILTER_WR_HITCNTS(f->fs.hitcnts) |
 -                    V_FW_FILTER_WR_TXCHAN(f->fs.eport) |
 -                    V_FW_FILTER_WR_PRIO(f->fs.prio) |
 -                    V_FW_FILTER_WR_L2TIX(f->l2t ? f->l2t->idx : 0));
 +                    FW_FILTER_WR_HITCNTS_V(f->fs.hitcnts) |
 +                    FW_FILTER_WR_TXCHAN_V(f->fs.eport) |
 +                    FW_FILTER_WR_PRIO_V(f->fs.prio) |
 +                    FW_FILTER_WR_L2TIX_V(f->l2t ? f->l2t->idx : 0));
        fwr->ethtype = htons(f->fs.val.ethtype);
        fwr->ethtypem = htons(f->fs.mask.ethtype);
        fwr->frag_to_ovlan_vldm =
 -              (V_FW_FILTER_WR_FRAG(f->fs.val.frag) |
 -               V_FW_FILTER_WR_FRAGM(f->fs.mask.frag) |
 -               V_FW_FILTER_WR_IVLAN_VLD(f->fs.val.ivlan_vld) |
 -               V_FW_FILTER_WR_OVLAN_VLD(f->fs.val.ovlan_vld) |
 -               V_FW_FILTER_WR_IVLAN_VLDM(f->fs.mask.ivlan_vld) |
 -               V_FW_FILTER_WR_OVLAN_VLDM(f->fs.mask.ovlan_vld));
 +              (FW_FILTER_WR_FRAG_V(f->fs.val.frag) |
 +               FW_FILTER_WR_FRAGM_V(f->fs.mask.frag) |
 +               FW_FILTER_WR_IVLAN_VLD_V(f->fs.val.ivlan_vld) |
 +               FW_FILTER_WR_OVLAN_VLD_V(f->fs.val.ovlan_vld) |
 +               FW_FILTER_WR_IVLAN_VLDM_V(f->fs.mask.ivlan_vld) |
 +               FW_FILTER_WR_OVLAN_VLDM_V(f->fs.mask.ovlan_vld));
        fwr->smac_sel = 0;
        fwr->rx_chan_rx_rpl_iq =
 -              htons(V_FW_FILTER_WR_RX_CHAN(0) |
 -                    V_FW_FILTER_WR_RX_RPL_IQ(adapter->sge.fw_evtq.abs_id));
 +              htons(FW_FILTER_WR_RX_CHAN_V(0) |
 +                    FW_FILTER_WR_RX_RPL_IQ_V(adapter->sge.fw_evtq.abs_id));
        fwr->maci_to_matchtypem =
 -              htonl(V_FW_FILTER_WR_MACI(f->fs.val.macidx) |
 -                    V_FW_FILTER_WR_MACIM(f->fs.mask.macidx) |
 -                    V_FW_FILTER_WR_FCOE(f->fs.val.fcoe) |
 -                    V_FW_FILTER_WR_FCOEM(f->fs.mask.fcoe) |
 -                    V_FW_FILTER_WR_PORT(f->fs.val.iport) |
 -                    V_FW_FILTER_WR_PORTM(f->fs.mask.iport) |
 -                    V_FW_FILTER_WR_MATCHTYPE(f->fs.val.matchtype) |
 -                    V_FW_FILTER_WR_MATCHTYPEM(f->fs.mask.matchtype));
 +              htonl(FW_FILTER_WR_MACI_V(f->fs.val.macidx) |
 +                    FW_FILTER_WR_MACIM_V(f->fs.mask.macidx) |
 +                    FW_FILTER_WR_FCOE_V(f->fs.val.fcoe) |
 +                    FW_FILTER_WR_FCOEM_V(f->fs.mask.fcoe) |
 +                    FW_FILTER_WR_PORT_V(f->fs.val.iport) |
 +                    FW_FILTER_WR_PORTM_V(f->fs.mask.iport) |
 +                    FW_FILTER_WR_MATCHTYPE_V(f->fs.val.matchtype) |
 +                    FW_FILTER_WR_MATCHTYPEM_V(f->fs.mask.matchtype));
        fwr->ptcl = f->fs.val.proto;
        fwr->ptclm = f->fs.mask.proto;
        fwr->ttyp = f->fs.val.tos;
@@@ -1527,14 -1615,14 +1527,14 @@@ static void get_drvinfo(struct net_devi
        if (adapter->params.fw_vers)
                snprintf(info->fw_version, sizeof(info->fw_version),
                        "%u.%u.%u.%u, TP %u.%u.%u.%u",
 -                      FW_HDR_FW_VER_MAJOR_GET(adapter->params.fw_vers),
 -                      FW_HDR_FW_VER_MINOR_GET(adapter->params.fw_vers),
 -                      FW_HDR_FW_VER_MICRO_GET(adapter->params.fw_vers),
 -                      FW_HDR_FW_VER_BUILD_GET(adapter->params.fw_vers),
 -                      FW_HDR_FW_VER_MAJOR_GET(adapter->params.tp_vers),
 -                      FW_HDR_FW_VER_MINOR_GET(adapter->params.tp_vers),
 -                      FW_HDR_FW_VER_MICRO_GET(adapter->params.tp_vers),
 -                      FW_HDR_FW_VER_BUILD_GET(adapter->params.tp_vers));
 +                      FW_HDR_FW_VER_MAJOR_G(adapter->params.fw_vers),
 +                      FW_HDR_FW_VER_MINOR_G(adapter->params.fw_vers),
 +                      FW_HDR_FW_VER_MICRO_G(adapter->params.fw_vers),
 +                      FW_HDR_FW_VER_BUILD_G(adapter->params.fw_vers),
 +                      FW_HDR_FW_VER_MAJOR_G(adapter->params.tp_vers),
 +                      FW_HDR_FW_VER_MINOR_G(adapter->params.tp_vers),
 +                      FW_HDR_FW_VER_MICRO_G(adapter->params.tp_vers),
 +                      FW_HDR_FW_VER_BUILD_G(adapter->params.tp_vers));
  }
  
  static void get_strings(struct net_device *dev, u32 stringset, u8 *data)
@@@ -2354,9 -2442,13 +2354,13 @@@ static unsigned int from_fw_linkcaps(un
                     SUPPORTED_10000baseKR_Full | SUPPORTED_1000baseKX_Full |
                     SUPPORTED_10000baseKX4_Full;
        else if (type == FW_PORT_TYPE_FIBER_XFI ||
-                type == FW_PORT_TYPE_FIBER_XAUI || type == FW_PORT_TYPE_SFP)
+                type == FW_PORT_TYPE_FIBER_XAUI || type == FW_PORT_TYPE_SFP) {
                v |= SUPPORTED_FIBRE;
-       else if (type == FW_PORT_TYPE_BP40_BA)
+               if (caps & FW_PORT_CAP_SPEED_1G)
+                       v |= SUPPORTED_1000baseT_Full;
+               if (caps & FW_PORT_CAP_SPEED_10G)
+                       v |= SUPPORTED_10000baseT_Full;
+       } else if (type == FW_PORT_TYPE_BP40_BA)
                v |= SUPPORTED_40000baseSR4_Full;
  
        if (caps & FW_PORT_CAP_ANEG)
@@@ -2629,10 -2721,9 +2633,10 @@@ static int set_rspq_intr_params(struct 
                new_idx = closest_thres(&adap->sge, cnt);
                if (q->desc && q->pktcnt_idx != new_idx) {
                        /* the queue has already been created, update it */
 -                      v = FW_PARAMS_MNEM(FW_PARAMS_MNEM_DMAQ) |
 -                          FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DMAQ_IQ_INTCNTTHRESH) |
 -                          FW_PARAMS_PARAM_YZ(q->cntxt_id);
 +                      v = FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DMAQ) |
 +                          FW_PARAMS_PARAM_X_V(
 +                                      FW_PARAMS_PARAM_DMAQ_IQ_INTCNTTHRESH) |
 +                          FW_PARAMS_PARAM_YZ_V(q->cntxt_id);
                        err = t4_set_params(adap, adap->fn, adap->fn, 0, 1, &v,
                                            &new_idx);
                        if (err)
@@@ -2846,7 -2937,7 +2850,7 @@@ static int set_flash(struct net_device 
        int ret;
        const struct firmware *fw;
        struct adapter *adap = netdev2adap(netdev);
 -      unsigned int mbox = FW_PCIE_FW_MASTER_MASK + 1;
 +      unsigned int mbox = PCIE_FW_MASTER_M + 1;
  
        ef->data[sizeof(ef->data) - 1] = '\0';
        ret = request_firmware(&fw, ef->data, adap->pdev_dev);
@@@ -2923,35 -3014,21 +2927,35 @@@ static u32 get_rss_table_size(struct ne
        return pi->rss_size;
  }
  
 -static int get_rss_table(struct net_device *dev, u32 *p, u8 *key)
 +static int get_rss_table(struct net_device *dev, u32 *p, u8 *key, u8 *hfunc)
  {
        const struct port_info *pi = netdev_priv(dev);
        unsigned int n = pi->rss_size;
  
 +      if (hfunc)
 +              *hfunc = ETH_RSS_HASH_TOP;
 +      if (!p)
 +              return 0;
        while (n--)
                p[n] = pi->rss[n];
        return 0;
  }
  
 -static int set_rss_table(struct net_device *dev, const u32 *p, const u8 *key)
 +static int set_rss_table(struct net_device *dev, const u32 *p, const u8 *key,
 +                       const u8 hfunc)
  {
        unsigned int i;
        struct port_info *pi = netdev_priv(dev);
  
 +      /* We require at least one supported parameter to be changed and no
 +       * change in any of the unsupported parameters
 +       */
 +      if (key ||
 +          (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
 +              return -EOPNOTSUPP;
 +      if (!p)
 +              return 0;
 +
        for (i = 0; i < pi->rss_size; i++)
                pi->rss[i] = p[i];
        if (pi->adapter->flags & FULL_INIT_DONE)
@@@ -2971,45 -3048,45 +2975,45 @@@ static int get_rxnfc(struct net_device 
                info->data = 0;
                switch (info->flow_type) {
                case TCP_V4_FLOW:
 -                      if (v & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN)
 +                      if (v & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN_F)
                                info->data = RXH_IP_SRC | RXH_IP_DST |
                                             RXH_L4_B_0_1 | RXH_L4_B_2_3;
 -                      else if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN)
 +                      else if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN_F)
                                info->data = RXH_IP_SRC | RXH_IP_DST;
                        break;
                case UDP_V4_FLOW:
 -                      if ((v & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN) &&
 -                          (v & FW_RSS_VI_CONFIG_CMD_UDPEN))
 +                      if ((v & FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN_F) &&
 +                          (v & FW_RSS_VI_CONFIG_CMD_UDPEN_F))
                                info->data = RXH_IP_SRC | RXH_IP_DST |
                                             RXH_L4_B_0_1 | RXH_L4_B_2_3;
 -                      else if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN)
 +                      else if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN_F)
                                info->data = RXH_IP_SRC | RXH_IP_DST;
                        break;
                case SCTP_V4_FLOW:
                case AH_ESP_V4_FLOW:
                case IPV4_FLOW:
 -                      if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN)
 +                      if (v & FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN_F)
                                info->data = RXH_IP_SRC | RXH_IP_DST;
                        break;
                case TCP_V6_FLOW:
 -                      if (v & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN)
 +                      if (v & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN_F)
                                info->data = RXH_IP_SRC | RXH_IP_DST |
                                             RXH_L4_B_0_1 | RXH_L4_B_2_3;
 -                      else if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN)
 +                      else if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN_F)
                                info->data = RXH_IP_SRC | RXH_IP_DST;
                        break;
                case UDP_V6_FLOW:
 -                      if ((v & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN) &&
 -                          (v & FW_RSS_VI_CONFIG_CMD_UDPEN))
 +                      if ((v & FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN_F) &&
 +                          (v & FW_RSS_VI_CONFIG_CMD_UDPEN_F))
                                info->data = RXH_IP_SRC | RXH_IP_DST |
                                             RXH_L4_B_0_1 | RXH_L4_B_2_3;
 -                      else if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN)
 +                      else if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN_F)
                                info->data = RXH_IP_SRC | RXH_IP_DST;
                        break;
                case SCTP_V6_FLOW:
                case AH_ESP_V6_FLOW:
                case IPV6_FLOW:
 -                      if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN)
 +                      if (v & FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN_F)
                                info->data = RXH_IP_SRC | RXH_IP_DST;
                        break;
                }
@@@ -3054,14 -3131,102 +3058,14 @@@ static const struct ethtool_ops cxgb_et
        .flash_device      = set_flash,
  };
  
 -/*
 - * debugfs support
 - */
 -static ssize_t mem_read(struct file *file, char __user *buf, size_t count,
 -                      loff_t *ppos)
 -{
 -      loff_t pos = *ppos;
 -      loff_t avail = file_inode(file)->i_size;
 -      unsigned int mem = (uintptr_t)file->private_data & 3;
 -      struct adapter *adap = file->private_data - mem;
 -      __be32 *data;
 -      int ret;
 -
 -      if (pos < 0)
 -              return -EINVAL;
 -      if (pos >= avail)
 -              return 0;
 -      if (count > avail - pos)
 -              count = avail - pos;
 -
 -      data = t4_alloc_mem(count);
 -      if (!data)
 -              return -ENOMEM;
 -
 -      spin_lock(&adap->win0_lock);
 -      ret = t4_memory_rw(adap, 0, mem, pos, count, data, T4_MEMORY_READ);
 -      spin_unlock(&adap->win0_lock);
 -      if (ret) {
 -              t4_free_mem(data);
 -              return ret;
 -      }
 -      ret = copy_to_user(buf, data, count);
 -
 -      t4_free_mem(data);
 -      if (ret)
 -              return -EFAULT;
 -
 -      *ppos = pos + count;
 -      return count;
 -}
 -
 -static const struct file_operations mem_debugfs_fops = {
 -      .owner   = THIS_MODULE,
 -      .open    = simple_open,
 -      .read    = mem_read,
 -      .llseek  = default_llseek,
 -};
 -
 -static void add_debugfs_mem(struct adapter *adap, const char *name,
 -                          unsigned int idx, unsigned int size_mb)
 -{
 -      struct dentry *de;
 -
 -      de = debugfs_create_file(name, S_IRUSR, adap->debugfs_root,
 -                               (void *)adap + idx, &mem_debugfs_fops);
 -      if (de && de->d_inode)
 -              de->d_inode->i_size = size_mb << 20;
 -}
 -
  static int setup_debugfs(struct adapter *adap)
  {
 -      int i;
 -      u32 size;
 -
        if (IS_ERR_OR_NULL(adap->debugfs_root))
                return -1;
  
 -      i = t4_read_reg(adap, MA_TARGET_MEM_ENABLE);
 -      if (i & EDRAM0_ENABLE) {
 -              size = t4_read_reg(adap, MA_EDRAM0_BAR);
 -              add_debugfs_mem(adap, "edc0", MEM_EDC0, EDRAM_SIZE_GET(size));
 -      }
 -      if (i & EDRAM1_ENABLE) {
 -              size = t4_read_reg(adap, MA_EDRAM1_BAR);
 -              add_debugfs_mem(adap, "edc1", MEM_EDC1, EDRAM_SIZE_GET(size));
 -      }
 -      if (is_t4(adap->params.chip)) {
 -              size = t4_read_reg(adap, MA_EXT_MEMORY_BAR);
 -              if (i & EXT_MEM_ENABLE)
 -                      add_debugfs_mem(adap, "mc", MEM_MC,
 -                                      EXT_MEM_SIZE_GET(size));
 -      } else {
 -              if (i & EXT_MEM_ENABLE) {
 -                      size = t4_read_reg(adap, MA_EXT_MEMORY_BAR);
 -                      add_debugfs_mem(adap, "mc0", MEM_MC0,
 -                                      EXT_MEM_SIZE_GET(size));
 -              }
 -              if (i & EXT_MEM1_ENABLE) {
 -                      size = t4_read_reg(adap, MA_EXT_MEMORY1_BAR);
 -                      add_debugfs_mem(adap, "mc1", MEM_MC1,
 -                                      EXT_MEM_SIZE_GET(size));
 -              }
 -      }
 -      if (adap->l2t)
 -              debugfs_create_file("l2t", S_IRUSR, adap->debugfs_root, adap,
 -                                  &t4_l2t_fops);
 +#ifdef CONFIG_DEBUG_FS
 +      t4_setup_debugfs(adap);
 +#endif
        return 0;
  }
  
@@@ -3343,9 -3508,9 +3347,9 @@@ int cxgb4_clip_get(const struct net_dev
  
        adap = netdev2adap(dev);
        memset(&c, 0, sizeof(c));
 -      c.op_to_write = htonl(FW_CMD_OP(FW_CLIP_CMD) |
 -                      FW_CMD_REQUEST | FW_CMD_WRITE);
 -      c.alloc_to_len16 = htonl(F_FW_CLIP_CMD_ALLOC | FW_LEN16(c));
 +      c.op_to_write = htonl(FW_CMD_OP_V(FW_CLIP_CMD) |
 +                      FW_CMD_REQUEST_F | FW_CMD_WRITE_F);
 +      c.alloc_to_len16 = htonl(FW_CLIP_CMD_ALLOC_F | FW_LEN16(c));
        c.ip_hi = *(__be64 *)(lip->s6_addr);
        c.ip_lo = *(__be64 *)(lip->s6_addr + 8);
        return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false);
@@@ -3360,9 -3525,9 +3364,9 @@@ int cxgb4_clip_release(const struct net
  
        adap = netdev2adap(dev);
        memset(&c, 0, sizeof(c));
 -      c.op_to_write = htonl(FW_CMD_OP(FW_CLIP_CMD) |
 -                      FW_CMD_REQUEST | FW_CMD_READ);
 -      c.alloc_to_len16 = htonl(F_FW_CLIP_CMD_FREE | FW_LEN16(c));
 +      c.op_to_write = htonl(FW_CMD_OP_V(FW_CLIP_CMD) |
 +                      FW_CMD_REQUEST_F | FW_CMD_READ_F);
 +      c.alloc_to_len16 = htonl(FW_CLIP_CMD_FREE_F | FW_LEN16(c));
        c.ip_hi = *(__be64 *)(lip->s6_addr);
        c.ip_lo = *(__be64 *)(lip->s6_addr + 8);
        return t4_wr_mbox_meat(adap, adap->mbox, &c, sizeof(c), &c, false);
@@@ -3403,7 -3568,7 +3407,7 @@@ int cxgb4_create_server(const struct ne
        req->local_ip = sip;
        req->peer_ip = htonl(0);
        chan = rxq_to_chan(&adap->sge, queue);
 -      req->opt0 = cpu_to_be64(TX_CHAN(chan));
 +      req->opt0 = cpu_to_be64(TX_CHAN_V(chan));
        req->opt1 = cpu_to_be64(CONN_POLICY_ASK |
                                SYN_RSS_ENABLE | SYN_RSS_QUEUE(queue));
        ret = t4_mgmt_tx(adap, skb);
@@@ -3446,7 -3611,7 +3450,7 @@@ int cxgb4_create_server6(const struct n
        req->peer_ip_hi = cpu_to_be64(0);
        req->peer_ip_lo = cpu_to_be64(0);
        chan = rxq_to_chan(&adap->sge, queue);
 -      req->opt0 = cpu_to_be64(TX_CHAN(chan));
 +      req->opt0 = cpu_to_be64(TX_CHAN_V(chan));
        req->opt1 = cpu_to_be64(CONN_POLICY_ASK |
                                SYN_RSS_ENABLE | SYN_RSS_QUEUE(queue));
        ret = t4_mgmt_tx(adap, skb);
@@@ -3728,7 -3893,7 +3732,7 @@@ int cxgb4_read_tpte(struct net_device *
  {
        struct adapter *adap;
        u32 offset, memtype, memaddr;
 -      u32 edc0_size, edc1_size, mc0_size, mc1_size;
 +      u32 edc0_size, edc1_size, mc0_size, mc1_size, size;
        u32 edc0_end, edc1_end, mc0_end, mc1_end;
        int ret;
  
         * and EDC1.  Some cards will have neither MC0 nor MC1, most cards have
         * MC0, and some have both MC0 and MC1.
         */
 -      edc0_size = EDRAM_SIZE_GET(t4_read_reg(adap, MA_EDRAM0_BAR)) << 20;
 -      edc1_size = EDRAM_SIZE_GET(t4_read_reg(adap, MA_EDRAM1_BAR)) << 20;
 -      mc0_size = EXT_MEM_SIZE_GET(t4_read_reg(adap, MA_EXT_MEMORY_BAR)) << 20;
 +      size = t4_read_reg(adap, MA_EDRAM0_BAR_A);
 +      edc0_size = EDRAM0_SIZE_G(size) << 20;
 +      size = t4_read_reg(adap, MA_EDRAM1_BAR_A);
 +      edc1_size = EDRAM1_SIZE_G(size) << 20;
 +      size = t4_read_reg(adap, MA_EXT_MEMORY0_BAR_A);
 +      mc0_size = EXT_MEM0_SIZE_G(size) << 20;
  
        edc0_end = edc0_size;
        edc1_end = edc0_end + edc1_size;
                        /* T4 only has a single memory channel */
                        goto err;
                } else {
 -                      mc1_size = EXT_MEM_SIZE_GET(
 -                                      t4_read_reg(adap,
 -                                                  MA_EXT_MEMORY1_BAR)) << 20;
 +                      size = t4_read_reg(adap, MA_EXT_MEMORY1_BAR_A);
 +                      mc1_size = EXT_MEM1_SIZE_G(size) << 20;
                        mc1_end = mc0_end + mc1_size;
                        if (offset < mc1_end) {
                                memtype = MEM_MC1;
@@@ -3805,22 -3968,6 +3809,22 @@@ u64 cxgb4_read_sge_timestamp(struct net
  }
  EXPORT_SYMBOL(cxgb4_read_sge_timestamp);
  
 +int cxgb4_bar2_sge_qregs(struct net_device *dev,
 +                       unsigned int qid,
 +                       enum cxgb4_bar2_qtype qtype,
 +                       u64 *pbar2_qoffset,
 +                       unsigned int *pbar2_qid)
 +{
 +      return t4_bar2_sge_qregs(netdev2adap(dev),
 +                               qid,
 +                               (qtype == CXGB4_BAR2_QTYPE_EGRESS
 +                                ? T4_BAR2_QTYPE_EGRESS
 +                                : T4_BAR2_QTYPE_INGRESS),
 +                               pbar2_qoffset,
 +                               pbar2_qid);
 +}
 +EXPORT_SYMBOL(cxgb4_bar2_sge_qregs);
 +
  static struct pci_driver cxgb4_driver;
  
  static void check_neigh_update(struct neighbour *neigh)
@@@ -4003,18 -4150,31 +4007,18 @@@ static void process_db_drop(struct work
                u32 dropped_db = t4_read_reg(adap, 0x010ac);
                u16 qid = (dropped_db >> 15) & 0x1ffff;
                u16 pidx_inc = dropped_db & 0x1fff;
 -              unsigned int s_qpp;
 -              unsigned short udb_density;
 -              unsigned long qpshift;
 -              int page;
 -              u32 udb;
 +              u64 bar2_qoffset;
 +              unsigned int bar2_qid;
 +              int ret;
  
 -              dev_warn(adap->pdev_dev,
 -                       "Dropped DB 0x%x qid %d bar2 %d coalesce %d pidx %d\n",
 -                       dropped_db, qid,
 -                       (dropped_db >> 14) & 1,
 -                       (dropped_db >> 13) & 1,
 -                       pidx_inc);
 -
 -              drain_db_fifo(adap, 1);
 -
 -              s_qpp = QUEUESPERPAGEPF1 * adap->fn;
 -              udb_density = 1 << QUEUESPERPAGEPF0_GET(t4_read_reg(adap,
 -                              SGE_EGRESS_QUEUES_PER_PAGE_PF) >> s_qpp);
 -              qpshift = PAGE_SHIFT - ilog2(udb_density);
 -              udb = qid << qpshift;
 -              udb &= PAGE_MASK;
 -              page = udb / PAGE_SIZE;
 -              udb += (qid - (page * udb_density)) * 128;
 -
 -              writel(PIDX(pidx_inc),  adap->bar2 + udb + 8);
 +              ret = t4_bar2_sge_qregs(adap, qid, T4_BAR2_QTYPE_EGRESS,
 +                                      &bar2_qoffset, &bar2_qid);
 +              if (ret)
 +                      dev_err(adap->pdev_dev, "doorbell drop recovery: "
 +                              "qid=%d, pidx_inc=%d\n", qid, pidx_inc);
 +              else
 +                      writel(PIDX_T5(pidx_inc) | QID(bar2_qid),
 +                             adap->bar2 + bar2_qoffset + SGE_UDB_KDOORBELL);
  
                /* Re-enable BAR2 WC */
                t4_set_reg_field(adap, 0x10b0, 1<<15, 1<<15);
@@@ -4072,8 -4232,12 +4076,8 @@@ static void uld_attach(struct adapter *
        lli.adapter_type = adap->params.chip;
        lli.iscsi_iolen = MAXRXDATA_GET(t4_read_reg(adap, TP_PARA_REG2));
        lli.cclk_ps = 1000000000 / adap->params.vpd.cclk;
 -      lli.udb_density = 1 << QUEUESPERPAGEPF0_GET(
 -                      t4_read_reg(adap, SGE_EGRESS_QUEUES_PER_PAGE_PF) >>
 -                      (adap->fn * 4));
 -      lli.ucq_density = 1 << QUEUESPERPAGEPF0_GET(
 -                      t4_read_reg(adap, SGE_INGRESS_QUEUES_PER_PAGE_PF) >>
 -                      (adap->fn * 4));
 +      lli.udb_density = 1 << adap->params.sge.eq_qpp;
 +      lli.ucq_density = 1 << adap->params.sge.iq_qpp;
        lli.filt_mode = adap->params.tp.vlan_pri_map;
        /* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */
        for (i = 0; i < NCHAN; i++)
@@@ -4235,7 -4399,8 +4239,7 @@@ static int clip_add(struct net_device *
        if (cxgb4_netdev(event_dev)) {
                switch (event) {
                case NETDEV_UP:
 -                      ret = cxgb4_clip_get(event_dev,
 -                              (const struct in6_addr *)ifa->addr.s6_addr);
 +                      ret = cxgb4_clip_get(event_dev, &ifa->addr);
                        if (ret < 0) {
                                rcu_read_unlock();
                                return ret;
                        ret = NOTIFY_OK;
                        break;
                case NETDEV_DOWN:
 -                      cxgb4_clip_release(event_dev,
 -                              (const struct in6_addr *)ifa->addr.s6_addr);
 +                      cxgb4_clip_release(event_dev, &ifa->addr);
                        ret = NOTIFY_OK;
                        break;
                default:
@@@ -4312,7 -4478,8 +4316,7 @@@ static int update_dev_clip(struct net_d
  
        read_lock_bh(&idev->lock);
        list_for_each_entry(ifa, &idev->addr_list, if_list) {
 -              ret = cxgb4_clip_get(dev,
 -                              (const struct in6_addr *)ifa->addr.s6_addr);
 +              ret = cxgb4_clip_get(dev, &ifa->addr);
                if (ret < 0)
                        break;
        }
@@@ -4793,14 -4960,14 +4797,14 @@@ static u32 t4_read_pcie_cfg4(struct ada
         */
        memset(&ldst_cmd, 0, sizeof(ldst_cmd));
        ldst_cmd.op_to_addrspace =
 -              htonl(FW_CMD_OP(FW_LDST_CMD) |
 -                    FW_CMD_REQUEST |
 -                    FW_CMD_READ |
 -                    FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FUNC_PCIE));
 +              htonl(FW_CMD_OP_V(FW_LDST_CMD) |
 +                    FW_CMD_REQUEST_F |
 +                    FW_CMD_READ_F |
 +                    FW_LDST_CMD_ADDRSPACE_V(FW_LDST_ADDRSPC_FUNC_PCIE));
        ldst_cmd.cycles_to_len16 = htonl(FW_LEN16(ldst_cmd));
 -      ldst_cmd.u.pcie.select_naccess = FW_LDST_CMD_NACCESS(1);
 +      ldst_cmd.u.pcie.select_naccess = FW_LDST_CMD_NACCESS_V(1);
        ldst_cmd.u.pcie.ctrl_to_fn =
 -              (FW_LDST_CMD_LC | FW_LDST_CMD_FN(adap->fn));
 +              (FW_LDST_CMD_LC_F | FW_LDST_CMD_FN_V(adap->fn));
        ldst_cmd.u.pcie.r = reg;
        ret = t4_wr_mbox(adap, adap->mbox, &ldst_cmd, sizeof(ldst_cmd),
                         &ldst_cmd);
@@@ -4887,8 -5054,8 +4891,8 @@@ static int adap_init1(struct adapter *a
  
        /* get device capabilities */
        memset(c, 0, sizeof(*c));
 -      c->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
 -                             FW_CMD_REQUEST | FW_CMD_READ);
 +      c->op_to_write = htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) |
 +                             FW_CMD_REQUEST_F | FW_CMD_READ_F);
        c->cfvalid_to_len16 = htonl(FW_LEN16(*c));
        ret = t4_wr_mbox(adap, adap->fn, c, sizeof(*c), c);
        if (ret < 0)
                dev_err(adap->pdev_dev, "virtualization ACLs not supported");
                return ret;
        }
 -      c->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
 -                             FW_CMD_REQUEST | FW_CMD_WRITE);
 +      c->op_to_write = htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) |
 +                             FW_CMD_REQUEST_F | FW_CMD_WRITE_F);
        ret = t4_wr_mbox(adap, adap->fn, c, sizeof(*c), NULL);
        if (ret < 0)
                return ret;
  
        ret = t4_config_glbl_rss(adap, adap->fn,
                                 FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL,
 -                               FW_RSS_GLB_CONFIG_CMD_TNLMAPEN |
 -                               FW_RSS_GLB_CONFIG_CMD_TNLALLLKP);
 +                               FW_RSS_GLB_CONFIG_CMD_TNLMAPEN_F |
 +                               FW_RSS_GLB_CONFIG_CMD_TNLALLLKP_F);
        if (ret < 0)
                return ret;
  
@@@ -5074,8 -5241,8 +5078,8 @@@ static int adap_init0_config(struct ada
                if (cf->size >= FLASH_CFG_MAX_SIZE)
                        ret = -ENOMEM;
                else {
 -                      params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
 -                           FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CF));
 +                      params[0] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) |
 +                           FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_CF));
                        ret = t4_query_params(adapter, adapter->mbox,
                                              adapter->fn, 0, 1, params, val);
                        if (ret == 0) {
                                size_t size = cf->size & ~0x3;
                                __be32 *data = (__be32 *)cf->data;
  
 -                              mtype = FW_PARAMS_PARAM_Y_GET(val[0]);
 -                              maddr = FW_PARAMS_PARAM_Z_GET(val[0]) << 16;
 +                              mtype = FW_PARAMS_PARAM_Y_G(val[0]);
 +                              maddr = FW_PARAMS_PARAM_Z_G(val[0]) << 16;
  
                                spin_lock(&adapter->win0_lock);
                                ret = t4_memory_rw(adapter, 0, mtype, maddr,
         */
        memset(&caps_cmd, 0, sizeof(caps_cmd));
        caps_cmd.op_to_write =
 -              htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
 -                    FW_CMD_REQUEST |
 -                    FW_CMD_READ);
 +              htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) |
 +                    FW_CMD_REQUEST_F |
 +                    FW_CMD_READ_F);
        caps_cmd.cfvalid_to_len16 =
 -              htonl(FW_CAPS_CONFIG_CMD_CFVALID |
 -                    FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) |
 -                    FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(maddr >> 16) |
 +              htonl(FW_CAPS_CONFIG_CMD_CFVALID_F |
 +                    FW_CAPS_CONFIG_CMD_MEMTYPE_CF_V(mtype) |
 +                    FW_CAPS_CONFIG_CMD_MEMADDR64K_CF_V(maddr >> 16) |
                      FW_LEN16(caps_cmd));
        ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd),
                         &caps_cmd);
        if (ret == -ENOENT) {
                memset(&caps_cmd, 0, sizeof(caps_cmd));
                caps_cmd.op_to_write =
 -                      htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
 -                                      FW_CMD_REQUEST |
 -                                      FW_CMD_READ);
 +                      htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) |
 +                                      FW_CMD_REQUEST_F |
 +                                      FW_CMD_READ_F);
                caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
                ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd,
                                sizeof(caps_cmd), &caps_cmd);
         * And now tell the firmware to use the configuration we just loaded.
         */
        caps_cmd.op_to_write =
 -              htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
 -                    FW_CMD_REQUEST |
 -                    FW_CMD_WRITE);
 +              htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) |
 +                    FW_CMD_REQUEST_F |
 +                    FW_CMD_WRITE_F);
        caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
        ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd),
                         NULL);
@@@ -5249,8 -5416,8 +5253,8 @@@ static int adap_init0_no_config(struct 
         * Get device capabilities and select which we'll be using.
         */
        memset(&caps_cmd, 0, sizeof(caps_cmd));
 -      caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
 -                                   FW_CMD_REQUEST | FW_CMD_READ);
 +      caps_cmd.op_to_write = htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) |
 +                                   FW_CMD_REQUEST_F | FW_CMD_READ_F);
        caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
        ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd),
                         &caps_cmd);
                dev_err(adapter->pdev_dev, "virtualization ACLs not supported");
                goto bye;
        }
 -      caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
 -                            FW_CMD_REQUEST | FW_CMD_WRITE);
 +      caps_cmd.op_to_write = htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) |
 +                            FW_CMD_REQUEST_F | FW_CMD_WRITE_F);
        ret = t4_wr_mbox(adapter, adapter->mbox, &caps_cmd, sizeof(caps_cmd),
                         NULL);
        if (ret < 0)
        adapter->flags |= RSS_TNLALLLOOKUP;
        ret = t4_config_glbl_rss(adapter, adapter->mbox,
                                 FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL,
 -                               FW_RSS_GLB_CONFIG_CMD_TNLMAPEN |
 -                               FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ |
 +                               FW_RSS_GLB_CONFIG_CMD_TNLMAPEN_F |
 +                               FW_RSS_GLB_CONFIG_CMD_HASHTOEPLITZ_F |
                                 ((adapter->flags & RSS_TNLALLLOOKUP) ?
 -                                      FW_RSS_GLB_CONFIG_CMD_TNLALLLKP : 0));
 +                                      FW_RSS_GLB_CONFIG_CMD_TNLALLLKP_F : 0));
        if (ret < 0)
                goto bye;
  
                          PFRES_NEQ, PFRES_NETHCTRL,
                          PFRES_NIQFLINT, PFRES_NIQ,
                          PFRES_TC, PFRES_NVI,
 -                        FW_PFVF_CMD_CMASK_MASK,
 +                        FW_PFVF_CMD_CMASK_M,
                          pfvfres_pmask(adapter, adapter->fn, 0),
                          PFRES_NEXACTF,
                          PFRES_R_CAPS, PFRES_WX_CAPS);
                                                  VFRES_NEQ, VFRES_NETHCTRL,
                                                  VFRES_NIQFLINT, VFRES_NIQ,
                                                  VFRES_TC, VFRES_NVI,
 -                                                FW_PFVF_CMD_CMASK_MASK,
 +                                                FW_PFVF_CMD_CMASK_M,
                                                  pfvfres_pmask(
                                                  adapter, pf, vf),
                                                  VFRES_NEXACTF,
@@@ -5612,8 -5779,8 +5616,8 @@@ static int adap_init0(struct adapter *a
         * and portvec ...
         */
        v =
 -          FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
 -          FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_PORTVEC);
 +          FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) |
 +          FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_PORTVEC);
        ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 1, &v, &port_vec);
        if (ret < 0)
                goto bye;
        } else {
                dev_info(adap->pdev_dev, "Coming up as MASTER: "\
                         "Initializing adapter\n");
 -
                /*
                 * If the firmware doesn't support Configuration
                 * Files warn user and exit,
                         * Find out whether we're dealing with a version of
                         * the firmware which has configuration file support.
                         */
 -                      params[0] = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
 -                                   FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CF));
 +                      params[0] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) |
 +                                   FW_PARAMS_PARAM_X_V(
 +                                           FW_PARAMS_PARAM_DEV_CF));
                        ret = t4_query_params(adap, adap->mbox, adap->fn, 0, 1,
                                              params, val);
  
         * Grab some of our basic fundamental operating parameters.
         */
  #define FW_PARAM_DEV(param) \
 -      (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \
 -      FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param))
 +      (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) | \
 +      FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_##param))
  
  #define FW_PARAM_PFVF(param) \
 -      FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \
 -      FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param)|  \
 -      FW_PARAMS_PARAM_Y(0) | \
 -      FW_PARAMS_PARAM_Z(0)
 +      FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_PFVF) | \
 +      FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_PFVF_##param)|  \
 +      FW_PARAMS_PARAM_Y_V(0) | \
 +      FW_PARAMS_PARAM_Z_V(0)
  
        params[0] = FW_PARAM_PFVF(EQ_START);
        params[1] = FW_PARAM_PFVF(L2T_START);
         * to manage.
         */
        memset(&caps_cmd, 0, sizeof(caps_cmd));
 -      caps_cmd.op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
 -                                   FW_CMD_REQUEST | FW_CMD_READ);
 +      caps_cmd.op_to_write = htonl(FW_CMD_OP_V(FW_CAPS_CONFIG_CMD) |
 +                                   FW_CMD_REQUEST_F | FW_CMD_READ_F);
        caps_cmd.cfvalid_to_len16 = htonl(FW_LEN16(caps_cmd));
        ret = t4_wr_mbox(adap, adap->mbox, &caps_cmd, sizeof(caps_cmd),
                         &caps_cmd);
                t4_load_mtus(adap, adap->params.mtus, adap->params.a_wnd,
                             adap->params.b_wnd);
        }
 +      t4_init_sge_params(adap);
        t4_init_tp_params(adap);
        adap->flags |= FW_OK;
        return 0;
@@@ -188,9 -188,9 +188,9 @@@ static void t4_report_fw_error(struct a
        u32 pcie_fw;
  
        pcie_fw = t4_read_reg(adap, MA_PCIE_FW);
 -      if (pcie_fw & FW_PCIE_FW_ERR)
 +      if (pcie_fw & PCIE_FW_ERR)
                dev_err(adap->pdev_dev, "Firmware reports adapter error: %s\n",
 -                      reason[FW_PCIE_FW_EVAL_GET(pcie_fw)]);
 +                      reason[PCIE_FW_EVAL_G(pcie_fw)]);
  }
  
  /*
@@@ -310,17 -310,16 +310,17 @@@ int t4_wr_mbox_meat(struct adapter *ada
                        }
  
                        res = t4_read_reg64(adap, data_reg);
 -                      if (FW_CMD_OP_GET(res >> 32) == FW_DEBUG_CMD) {
 +                      if (FW_CMD_OP_G(res >> 32) == FW_DEBUG_CMD) {
                                fw_asrt(adap, data_reg);
 -                              res = FW_CMD_RETVAL(EIO);
 -                      } else if (rpl)
 +                              res = FW_CMD_RETVAL_V(EIO);
 +                      } else if (rpl) {
                                get_mbox_rpl(adap, rpl, size / 8, data_reg);
 +                      }
  
 -                      if (FW_CMD_RETVAL_GET((int)res))
 +                      if (FW_CMD_RETVAL_G((int)res))
                                dump_mbox(adap, mbox, data_reg);
                        t4_write_reg(adap, ctl_reg, 0);
 -                      return -FW_CMD_RETVAL_GET((int)res);
 +                      return -FW_CMD_RETVAL_G((int)res);
                }
        }
  
@@@ -484,12 -483,12 +484,12 @@@ int t4_memory_rw(struct adapter *adap, 
         * MEM_MC0  = 2 -- For T5
         * MEM_MC1  = 3 -- For T5
         */
 -      edc_size  = EDRAM_SIZE_GET(t4_read_reg(adap, MA_EDRAM0_BAR));
 +      edc_size  = EDRAM0_SIZE_G(t4_read_reg(adap, MA_EDRAM0_BAR_A));
        if (mtype != MEM_MC1)
                memoffset = (mtype * (edc_size * 1024 * 1024));
        else {
 -              mc_size = EXT_MEM_SIZE_GET(t4_read_reg(adap,
 -                                                     MA_EXT_MEMORY_BAR));
 +              mc_size = EXT_MEM0_SIZE_G(t4_read_reg(adap,
 +                                                    MA_EXT_MEMORY1_BAR_A));
                memoffset = (MEM_MC0 * edc_size + mc_size) * 1024 * 1024;
        }
  
@@@ -711,8 -710,8 +711,8 @@@ int get_vpd_params(struct adapter *adap
         * Ask firmware for the Core Clock since it knows how to translate the
         * Reference Clock ('V2') VPD field into a Core Clock value ...
         */
 -      cclk_param = (FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) |
 -                    FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_CCLK));
 +      cclk_param = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_DEV) |
 +                    FW_PARAMS_PARAM_X_V(FW_PARAMS_PARAM_DEV_CCLK));
        ret = t4_query_params(adapter, adapter->mbox, 0, 0,
                              1, &cclk_param, &cclk_val);
  
@@@ -993,10 -992,10 +993,10 @@@ static int should_install_fs_fw(struct 
  install:
        dev_err(adap->pdev_dev, "firmware on card (%u.%u.%u.%u) is %s, "
                "installing firmware %u.%u.%u.%u on card.\n",
 -              FW_HDR_FW_VER_MAJOR_GET(c), FW_HDR_FW_VER_MINOR_GET(c),
 -              FW_HDR_FW_VER_MICRO_GET(c), FW_HDR_FW_VER_BUILD_GET(c), reason,
 -              FW_HDR_FW_VER_MAJOR_GET(k), FW_HDR_FW_VER_MINOR_GET(k),
 -              FW_HDR_FW_VER_MICRO_GET(k), FW_HDR_FW_VER_BUILD_GET(k));
 +              FW_HDR_FW_VER_MAJOR_G(c), FW_HDR_FW_VER_MINOR_G(c),
 +              FW_HDR_FW_VER_MICRO_G(c), FW_HDR_FW_VER_BUILD_G(c), reason,
 +              FW_HDR_FW_VER_MAJOR_G(k), FW_HDR_FW_VER_MINOR_G(k),
 +              FW_HDR_FW_VER_MICRO_G(k), FW_HDR_FW_VER_BUILD_G(k));
  
        return 1;
  }
@@@ -1068,12 -1067,12 +1068,12 @@@ int t4_prep_fw(struct adapter *adap, st
                        "driver compiled with %d.%d.%d.%d, "
                        "card has %d.%d.%d.%d, filesystem has %d.%d.%d.%d\n",
                        state,
 -                      FW_HDR_FW_VER_MAJOR_GET(d), FW_HDR_FW_VER_MINOR_GET(d),
 -                      FW_HDR_FW_VER_MICRO_GET(d), FW_HDR_FW_VER_BUILD_GET(d),
 -                      FW_HDR_FW_VER_MAJOR_GET(c), FW_HDR_FW_VER_MINOR_GET(c),
 -                      FW_HDR_FW_VER_MICRO_GET(c), FW_HDR_FW_VER_BUILD_GET(c),
 -                      FW_HDR_FW_VER_MAJOR_GET(k), FW_HDR_FW_VER_MINOR_GET(k),
 -                      FW_HDR_FW_VER_MICRO_GET(k), FW_HDR_FW_VER_BUILD_GET(k));
 +                      FW_HDR_FW_VER_MAJOR_G(d), FW_HDR_FW_VER_MINOR_G(d),
 +                      FW_HDR_FW_VER_MICRO_G(d), FW_HDR_FW_VER_BUILD_G(d),
 +                      FW_HDR_FW_VER_MAJOR_G(c), FW_HDR_FW_VER_MINOR_G(c),
 +                      FW_HDR_FW_VER_MICRO_G(c), FW_HDR_FW_VER_BUILD_G(c),
 +                      FW_HDR_FW_VER_MAJOR_G(k), FW_HDR_FW_VER_MINOR_G(k),
 +                      FW_HDR_FW_VER_MICRO_G(k), FW_HDR_FW_VER_BUILD_G(k));
                ret = EINVAL;
                goto bye;
        }
@@@ -1132,6 -1131,27 +1132,27 @@@ unsigned int t4_flash_cfg_addr(struct a
                return FLASH_CFG_START;
  }
  
+ /* Return TRUE if the specified firmware matches the adapter.  I.e. T4
+  * firmware for T4 adapters, T5 firmware for T5 adapters, etc.  We go ahead
+  * and emit an error message for mismatched firmware to save our caller the
+  * effort ...
+  */
+ static bool t4_fw_matches_chip(const struct adapter *adap,
+                              const struct fw_hdr *hdr)
+ {
+       /* The expression below will return FALSE for any unsupported adapter
+        * which will keep us "honest" in the future ...
+        */
+       if ((is_t4(adap->params.chip) && hdr->chip == FW_HDR_CHIP_T4) ||
+           (is_t5(adap->params.chip) && hdr->chip == FW_HDR_CHIP_T5))
+               return true;
+       dev_err(adap->pdev_dev,
+               "FW image (%d) is not suitable for this adapter (%d)\n",
+               hdr->chip, CHELSIO_CHIP_VERSION(adap->params.chip));
+       return false;
+ }
  /**
   *    t4_load_fw - download firmware
   *    @adap: the adapter
@@@ -1171,6 -1191,8 +1192,8 @@@ int t4_load_fw(struct adapter *adap, co
                        FW_MAX_SIZE);
                return -EFBIG;
        }
+       if (!t4_fw_matches_chip(adap, hdr))
+               return -EINVAL;
  
        for (csum = 0, i = 0; i < size / sizeof(csum); i++)
                csum += ntohl(p[i]);
@@@ -1213,8 -1235,6 +1236,8 @@@ out
        if (ret)
                dev_err(adap->pdev_dev, "firmware download failed, error %d\n",
                        ret);
 +      else
 +              ret = t4_get_fw_version(adap, &adap->params.fw_vers);
        return ret;
  }
  
@@@ -1239,7 -1259,7 +1262,7 @@@ int t4_link_start(struct adapter *adap
                  struct link_config *lc)
  {
        struct fw_port_cmd c;
 -      unsigned int fc = 0, mdi = FW_PORT_MDI(FW_PORT_MDI_AUTO);
 +      unsigned int fc = 0, mdi = FW_PORT_CAP_MDI_V(FW_PORT_CAP_MDI_AUTO);
  
        lc->link_ok = 0;
        if (lc->requested_fc & PAUSE_RX)
                fc |= FW_PORT_CAP_FC_TX;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_portid = htonl(FW_CMD_OP(FW_PORT_CMD) | FW_CMD_REQUEST |
 -                             FW_CMD_EXEC | FW_PORT_CMD_PORTID(port));
 -      c.action_to_len16 = htonl(FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) |
 +      c.op_to_portid = htonl(FW_CMD_OP_V(FW_PORT_CMD) | FW_CMD_REQUEST_F |
 +                             FW_CMD_EXEC_F | FW_PORT_CMD_PORTID_V(port));
 +      c.action_to_len16 = htonl(FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_L1_CFG) |
                                  FW_LEN16(c));
  
        if (!(lc->supported & FW_PORT_CAP_ANEG)) {
@@@ -1278,9 -1298,9 +1301,9 @@@ int t4_restart_aneg(struct adapter *ada
        struct fw_port_cmd c;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_portid = htonl(FW_CMD_OP(FW_PORT_CMD) | FW_CMD_REQUEST |
 -                             FW_CMD_EXEC | FW_PORT_CMD_PORTID(port));
 -      c.action_to_len16 = htonl(FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) |
 +      c.op_to_portid = htonl(FW_CMD_OP_V(FW_PORT_CMD) | FW_CMD_REQUEST_F |
 +                             FW_CMD_EXEC_F | FW_PORT_CMD_PORTID_V(port));
 +      c.action_to_len16 = htonl(FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_L1_CFG) |
                                  FW_LEN16(c));
        c.u.l1cfg.rcap = htonl(FW_PORT_CAP_ANEG);
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
@@@ -1566,7 -1586,7 +1589,7 @@@ static void cim_intr_handler(struct ada
  
        int fat;
  
 -      if (t4_read_reg(adapter, MA_PCIE_FW) & FW_PCIE_FW_ERR)
 +      if (t4_read_reg(adapter, MA_PCIE_FW) & PCIE_FW_ERR)
                t4_report_fw_error(adapter);
  
        fat = t4_handle_intr_status(adapter, CIM_HOST_INT_CAUSE,
@@@ -2074,9 -2094,9 +2097,9 @@@ int t4_config_rss_range(struct adapter 
        struct fw_rss_ind_tbl_cmd cmd;
  
        memset(&cmd, 0, sizeof(cmd));
 -      cmd.op_to_viid = htonl(FW_CMD_OP(FW_RSS_IND_TBL_CMD) |
 -                             FW_CMD_REQUEST | FW_CMD_WRITE |
 -                             FW_RSS_IND_TBL_CMD_VIID(viid));
 +      cmd.op_to_viid = htonl(FW_CMD_OP_V(FW_RSS_IND_TBL_CMD) |
 +                             FW_CMD_REQUEST_F | FW_CMD_WRITE_F |
 +                             FW_RSS_IND_TBL_CMD_VIID_V(viid));
        cmd.retval_len16 = htonl(FW_LEN16(cmd));
  
        /* each fw_rss_ind_tbl_cmd takes up to 32 entries */
                while (nq > 0) {
                        unsigned int v;
  
 -                      v = FW_RSS_IND_TBL_CMD_IQ0(*rsp);
 +                      v = FW_RSS_IND_TBL_CMD_IQ0_V(*rsp);
                        if (++rsp >= rsp_end)
                                rsp = rspq;
 -                      v |= FW_RSS_IND_TBL_CMD_IQ1(*rsp);
 +                      v |= FW_RSS_IND_TBL_CMD_IQ1_V(*rsp);
                        if (++rsp >= rsp_end)
                                rsp = rspq;
 -                      v |= FW_RSS_IND_TBL_CMD_IQ2(*rsp);
 +                      v |= FW_RSS_IND_TBL_CMD_IQ2_V(*rsp);
                        if (++rsp >= rsp_end)
                                rsp = rspq;
  
@@@ -2129,14 -2149,14 +2152,14 @@@ int t4_config_glbl_rss(struct adapter *
        struct fw_rss_glb_config_cmd c;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_write = htonl(FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) |
 -                            FW_CMD_REQUEST | FW_CMD_WRITE);
 +      c.op_to_write = htonl(FW_CMD_OP_V(FW_RSS_GLB_CONFIG_CMD) |
 +                            FW_CMD_REQUEST_F | FW_CMD_WRITE_F);
        c.retval_len16 = htonl(FW_LEN16(c));
        if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_MANUAL) {
 -              c.u.manual.mode_pkd = htonl(FW_RSS_GLB_CONFIG_CMD_MODE(mode));
 +              c.u.manual.mode_pkd = htonl(FW_RSS_GLB_CONFIG_CMD_MODE_V(mode));
        } else if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL) {
                c.u.basicvirtual.mode_pkd =
 -                      htonl(FW_RSS_GLB_CONFIG_CMD_MODE(mode));
 +                      htonl(FW_RSS_GLB_CONFIG_CMD_MODE_V(mode));
                c.u.basicvirtual.synmapen_to_hashtoeplitz = htonl(flags);
        } else
                return -EINVAL;
@@@ -2556,18 -2576,18 +2579,18 @@@ int t4_wol_pat_enable(struct adapter *a
  void t4_mk_filtdelwr(unsigned int ftid, struct fw_filter_wr *wr, int qid)
  {
        memset(wr, 0, sizeof(*wr));
 -      wr->op_pkd = htonl(FW_WR_OP(FW_FILTER_WR));
 -      wr->len16_pkd = htonl(FW_WR_LEN16(sizeof(*wr) / 16));
 -      wr->tid_to_iq = htonl(V_FW_FILTER_WR_TID(ftid) |
 -                      V_FW_FILTER_WR_NOREPLY(qid < 0));
 -      wr->del_filter_to_l2tix = htonl(F_FW_FILTER_WR_DEL_FILTER);
 +      wr->op_pkd = htonl(FW_WR_OP_V(FW_FILTER_WR));
 +      wr->len16_pkd = htonl(FW_WR_LEN16_V(sizeof(*wr) / 16));
 +      wr->tid_to_iq = htonl(FW_FILTER_WR_TID_V(ftid) |
 +                      FW_FILTER_WR_NOREPLY_V(qid < 0));
 +      wr->del_filter_to_l2tix = htonl(FW_FILTER_WR_DEL_FILTER_F);
        if (qid >= 0)
 -              wr->rx_chan_rx_rpl_iq = htons(V_FW_FILTER_WR_RX_RPL_IQ(qid));
 +              wr->rx_chan_rx_rpl_iq = htons(FW_FILTER_WR_RX_RPL_IQ_V(qid));
  }
  
  #define INIT_CMD(var, cmd, rd_wr) do { \
 -      (var).op_to_write = htonl(FW_CMD_OP(FW_##cmd##_CMD) | \
 -                                FW_CMD_REQUEST | FW_CMD_##rd_wr); \
 +      (var).op_to_write = htonl(FW_CMD_OP_V(FW_##cmd##_CMD) | \
 +                                FW_CMD_REQUEST_F | FW_CMD_##rd_wr##_F); \
        (var).retval_len16 = htonl(FW_LEN16(var)); \
  } while (0)
  
@@@ -2577,9 -2597,9 +2600,9 @@@ int t4_fwaddrspace_write(struct adapte
        struct fw_ldst_cmd c;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_addrspace = htonl(FW_CMD_OP(FW_LDST_CMD) | FW_CMD_REQUEST |
 -                          FW_CMD_WRITE |
 -                          FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FIRMWARE));
 +      c.op_to_addrspace = htonl(FW_CMD_OP_V(FW_LDST_CMD) | FW_CMD_REQUEST_F |
 +                          FW_CMD_WRITE_F |
 +                          FW_LDST_CMD_ADDRSPACE_V(FW_LDST_ADDRSPC_FIRMWARE));
        c.cycles_to_len16 = htonl(FW_LEN16(c));
        c.u.addrval.addr = htonl(addr);
        c.u.addrval.val = htonl(val);
@@@ -2605,11 -2625,11 +2628,11 @@@ int t4_mdio_rd(struct adapter *adap, un
        struct fw_ldst_cmd c;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_addrspace = htonl(FW_CMD_OP(FW_LDST_CMD) | FW_CMD_REQUEST |
 -              FW_CMD_READ | FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_MDIO));
 +      c.op_to_addrspace = htonl(FW_CMD_OP_V(FW_LDST_CMD) | FW_CMD_REQUEST_F |
 +              FW_CMD_READ_F | FW_LDST_CMD_ADDRSPACE_V(FW_LDST_ADDRSPC_MDIO));
        c.cycles_to_len16 = htonl(FW_LEN16(c));
 -      c.u.mdio.paddr_mmd = htons(FW_LDST_CMD_PADDR(phy_addr) |
 -                                 FW_LDST_CMD_MMD(mmd));
 +      c.u.mdio.paddr_mmd = htons(FW_LDST_CMD_PADDR_V(phy_addr) |
 +                                 FW_LDST_CMD_MMD_V(mmd));
        c.u.mdio.raddr = htons(reg);
  
        ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
@@@ -2635,11 -2655,11 +2658,11 @@@ int t4_mdio_wr(struct adapter *adap, un
        struct fw_ldst_cmd c;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_addrspace = htonl(FW_CMD_OP(FW_LDST_CMD) | FW_CMD_REQUEST |
 -              FW_CMD_WRITE | FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_MDIO));
 +      c.op_to_addrspace = htonl(FW_CMD_OP_V(FW_LDST_CMD) | FW_CMD_REQUEST_F |
 +              FW_CMD_WRITE_F | FW_LDST_CMD_ADDRSPACE_V(FW_LDST_ADDRSPC_MDIO));
        c.cycles_to_len16 = htonl(FW_LEN16(c));
 -      c.u.mdio.paddr_mmd = htons(FW_LDST_CMD_PADDR(phy_addr) |
 -                                 FW_LDST_CMD_MMD(mmd));
 +      c.u.mdio.paddr_mmd = htons(FW_LDST_CMD_PADDR_V(phy_addr) |
 +                                 FW_LDST_CMD_MMD_V(mmd));
        c.u.mdio.raddr = htons(reg);
        c.u.mdio.rval = htons(val);
  
@@@ -2776,13 -2796,13 +2799,13 @@@ retry
        memset(&c, 0, sizeof(c));
        INIT_CMD(c, HELLO, WRITE);
        c.err_to_clearinit = htonl(
 -              FW_HELLO_CMD_MASTERDIS(master == MASTER_CANT) |
 -              FW_HELLO_CMD_MASTERFORCE(master == MASTER_MUST) |
 -              FW_HELLO_CMD_MBMASTER(master == MASTER_MUST ? mbox :
 -                                    FW_HELLO_CMD_MBMASTER_MASK) |
 -              FW_HELLO_CMD_MBASYNCNOT(evt_mbox) |
 -              FW_HELLO_CMD_STAGE(fw_hello_cmd_stage_os) |
 -              FW_HELLO_CMD_CLEARINIT);
 +              FW_HELLO_CMD_MASTERDIS_V(master == MASTER_CANT) |
 +              FW_HELLO_CMD_MASTERFORCE_V(master == MASTER_MUST) |
 +              FW_HELLO_CMD_MBMASTER_V(master == MASTER_MUST ? mbox :
 +                                    FW_HELLO_CMD_MBMASTER_M) |
 +              FW_HELLO_CMD_MBASYNCNOT_V(evt_mbox) |
 +              FW_HELLO_CMD_STAGE_V(fw_hello_cmd_stage_os) |
 +              FW_HELLO_CMD_CLEARINIT_F);
  
        /*
         * Issue the HELLO command to the firmware.  If it's not successful
        if (ret < 0) {
                if ((ret == -EBUSY || ret == -ETIMEDOUT) && retries-- > 0)
                        goto retry;
 -              if (t4_read_reg(adap, MA_PCIE_FW) & FW_PCIE_FW_ERR)
 +              if (t4_read_reg(adap, MA_PCIE_FW) & PCIE_FW_ERR)
                        t4_report_fw_error(adap);
                return ret;
        }
  
        v = ntohl(c.err_to_clearinit);
 -      master_mbox = FW_HELLO_CMD_MBMASTER_GET(v);
 +      master_mbox = FW_HELLO_CMD_MBMASTER_G(v);
        if (state) {
 -              if (v & FW_HELLO_CMD_ERR)
 +              if (v & FW_HELLO_CMD_ERR_F)
                        *state = DEV_STATE_ERR;
 -              else if (v & FW_HELLO_CMD_INIT)
 +              else if (v & FW_HELLO_CMD_INIT_F)
                        *state = DEV_STATE_INIT;
                else
                        *state = DEV_STATE_UNINIT;
         * and we wouldn't want to fail pointlessly.  (This can happen when an
         * OS loads lots of different drivers rapidly at the same time).  In
         * this case, the Master PF returned by the firmware will be
 -       * FW_PCIE_FW_MASTER_MASK so the test below will work ...
 +       * PCIE_FW_MASTER_M so the test below will work ...
         */
 -      if ((v & (FW_HELLO_CMD_ERR|FW_HELLO_CMD_INIT)) == 0 &&
 +      if ((v & (FW_HELLO_CMD_ERR_F|FW_HELLO_CMD_INIT_F)) == 0 &&
            master_mbox != mbox) {
                int waiting = FW_CMD_HELLO_TIMEOUT;
  
                         * our retries ...
                         */
                        pcie_fw = t4_read_reg(adap, MA_PCIE_FW);
 -                      if (!(pcie_fw & (FW_PCIE_FW_ERR|FW_PCIE_FW_INIT))) {
 +                      if (!(pcie_fw & (PCIE_FW_ERR|PCIE_FW_INIT))) {
                                if (waiting <= 0) {
                                        if (retries-- > 0)
                                                goto retry;
                         * report errors preferentially.
                         */
                        if (state) {
 -                              if (pcie_fw & FW_PCIE_FW_ERR)
 +                              if (pcie_fw & PCIE_FW_ERR)
                                        *state = DEV_STATE_ERR;
 -                              else if (pcie_fw & FW_PCIE_FW_INIT)
 +                              else if (pcie_fw & PCIE_FW_INIT)
                                        *state = DEV_STATE_INIT;
                        }
  
                         * there's not a valid Master PF, grab its identity
                         * for our caller.
                         */
 -                      if (master_mbox == FW_PCIE_FW_MASTER_MASK &&
 -                          (pcie_fw & FW_PCIE_FW_MASTER_VLD))
 -                              master_mbox = FW_PCIE_FW_MASTER_GET(pcie_fw);
 +                      if (master_mbox == PCIE_FW_MASTER_M &&
 +                          (pcie_fw & PCIE_FW_MASTER_VLD))
 +                              master_mbox = PCIE_FW_MASTER_G(pcie_fw);
                        break;
                }
        }
@@@ -2942,7 -2962,7 +2965,7 @@@ int t4_fw_reset(struct adapter *adap, u
   *    Issues a RESET command to firmware (if desired) with a HALT indication
   *    and then puts the microprocessor into RESET state.  The RESET command
   *    will only be issued if a legitimate mailbox is provided (mbox <=
 - *    FW_PCIE_FW_MASTER_MASK).
 + *    PCIE_FW_MASTER_M).
   *
   *    This is generally used in order for the host to safely manipulate the
   *    adapter without fear of conflicting with whatever the firmware might
@@@ -2957,13 -2977,13 +2980,13 @@@ static int t4_fw_halt(struct adapter *a
         * If a legitimate mailbox is provided, issue a RESET command
         * with a HALT indication.
         */
 -      if (mbox <= FW_PCIE_FW_MASTER_MASK) {
 +      if (mbox <= PCIE_FW_MASTER_M) {
                struct fw_reset_cmd c;
  
                memset(&c, 0, sizeof(c));
                INIT_CMD(c, RESET, WRITE);
                c.val = htonl(PIORST | PIORSTMODE);
 -              c.halt_pkd = htonl(FW_RESET_CMD_HALT(1U));
 +              c.halt_pkd = htonl(FW_RESET_CMD_HALT_F);
                ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
        }
  
         */
        if (ret == 0 || force) {
                t4_set_reg_field(adap, CIM_BOOT_CFG, UPCRST, UPCRST);
 -              t4_set_reg_field(adap, PCIE_FW, FW_PCIE_FW_HALT,
 -                               FW_PCIE_FW_HALT);
 +              t4_set_reg_field(adap, PCIE_FW, PCIE_FW_HALT_F,
 +                               PCIE_FW_HALT_F);
        }
  
        /*
@@@ -3022,7 -3042,7 +3045,7 @@@ static int t4_fw_restart(struct adapte
                 * doing it automatically, we need to clear the PCIE_FW.HALT
                 * bit.
                 */
 -              t4_set_reg_field(adap, PCIE_FW, FW_PCIE_FW_HALT, 0);
 +              t4_set_reg_field(adap, PCIE_FW, PCIE_FW_HALT_F, 0);
  
                /*
                 * If we've been given a valid mailbox, first try to get the
                 * valid mailbox or the RESET command failed, fall back to
                 * hitting the chip with a hammer.
                 */
 -              if (mbox <= FW_PCIE_FW_MASTER_MASK) {
 +              if (mbox <= PCIE_FW_MASTER_M) {
                        t4_set_reg_field(adap, CIM_BOOT_CFG, UPCRST, 0);
                        msleep(100);
                        if (t4_fw_reset(adap, mbox,
  
                t4_set_reg_field(adap, CIM_BOOT_CFG, UPCRST, 0);
                for (ms = 0; ms < FW_CMD_MAX_TIMEOUT; ) {
 -                      if (!(t4_read_reg(adap, PCIE_FW) & FW_PCIE_FW_HALT))
 +                      if (!(t4_read_reg(adap, PCIE_FW) & PCIE_FW_HALT_F))
                                return 0;
                        msleep(100);
                        ms += 100;
@@@ -3083,6 -3103,9 +3106,9 @@@ int t4_fw_upgrade(struct adapter *adap
        const struct fw_hdr *fw_hdr = (const struct fw_hdr *)fw_data;
        int reset, ret;
  
+       if (!t4_fw_matches_chip(adap, fw_hdr))
+               return -EINVAL;
        ret = t4_fw_halt(adap, mbox, force);
        if (ret < 0 && !force)
                return ret;
@@@ -3253,9 -3276,9 +3279,9 @@@ int t4_query_params(struct adapter *ada
                return -EINVAL;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_vfn = htonl(FW_CMD_OP(FW_PARAMS_CMD) | FW_CMD_REQUEST |
 -                          FW_CMD_READ | FW_PARAMS_CMD_PFN(pf) |
 -                          FW_PARAMS_CMD_VFN(vf));
 +      c.op_to_vfn = htonl(FW_CMD_OP_V(FW_PARAMS_CMD) | FW_CMD_REQUEST_F |
 +                          FW_CMD_READ_F | FW_PARAMS_CMD_PFN_V(pf) |
 +                          FW_PARAMS_CMD_VFN_V(vf));
        c.retval_len16 = htonl(FW_LEN16(c));
        for (i = 0; i < nparams; i++, p += 2)
                *p = htonl(*params++);
@@@ -3293,10 -3316,10 +3319,10 @@@ int t4_set_params_nosleep(struct adapte
                return -EINVAL;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_vfn = cpu_to_be32(FW_CMD_OP(FW_PARAMS_CMD) |
 -                              FW_CMD_REQUEST | FW_CMD_WRITE |
 -                              FW_PARAMS_CMD_PFN(pf) |
 -                              FW_PARAMS_CMD_VFN(vf));
 +      c.op_to_vfn = cpu_to_be32(FW_CMD_OP_V(FW_PARAMS_CMD) |
 +                              FW_CMD_REQUEST_F | FW_CMD_WRITE_F |
 +                              FW_PARAMS_CMD_PFN_V(pf) |
 +                              FW_PARAMS_CMD_VFN_V(vf));
        c.retval_len16 = cpu_to_be32(FW_LEN16(c));
  
        while (nparams--) {
@@@ -3331,9 -3354,9 +3357,9 @@@ int t4_set_params(struct adapter *adap
                return -EINVAL;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_vfn = htonl(FW_CMD_OP(FW_PARAMS_CMD) | FW_CMD_REQUEST |
 -                          FW_CMD_WRITE | FW_PARAMS_CMD_PFN(pf) |
 -                          FW_PARAMS_CMD_VFN(vf));
 +      c.op_to_vfn = htonl(FW_CMD_OP_V(FW_PARAMS_CMD) | FW_CMD_REQUEST_F |
 +                          FW_CMD_WRITE_F | FW_PARAMS_CMD_PFN_V(pf) |
 +                          FW_PARAMS_CMD_VFN_V(vf));
        c.retval_len16 = htonl(FW_LEN16(c));
        while (nparams--) {
                *p++ = htonl(*params++);
@@@ -3373,20 -3396,20 +3399,20 @@@ int t4_cfg_pfvf(struct adapter *adap, u
        struct fw_pfvf_cmd c;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_vfn = htonl(FW_CMD_OP(FW_PFVF_CMD) | FW_CMD_REQUEST |
 -                          FW_CMD_WRITE | FW_PFVF_CMD_PFN(pf) |
 -                          FW_PFVF_CMD_VFN(vf));
 +      c.op_to_vfn = htonl(FW_CMD_OP_V(FW_PFVF_CMD) | FW_CMD_REQUEST_F |
 +                          FW_CMD_WRITE_F | FW_PFVF_CMD_PFN_V(pf) |
 +                          FW_PFVF_CMD_VFN_V(vf));
        c.retval_len16 = htonl(FW_LEN16(c));
 -      c.niqflint_niq = htonl(FW_PFVF_CMD_NIQFLINT(rxqi) |
 -                             FW_PFVF_CMD_NIQ(rxq));
 -      c.type_to_neq = htonl(FW_PFVF_CMD_CMASK(cmask) |
 -                             FW_PFVF_CMD_PMASK(pmask) |
 -                             FW_PFVF_CMD_NEQ(txq));
 -      c.tc_to_nexactf = htonl(FW_PFVF_CMD_TC(tc) | FW_PFVF_CMD_NVI(vi) |
 -                              FW_PFVF_CMD_NEXACTF(nexact));
 -      c.r_caps_to_nethctrl = htonl(FW_PFVF_CMD_R_CAPS(rcaps) |
 -                                   FW_PFVF_CMD_WX_CAPS(wxcaps) |
 -                                   FW_PFVF_CMD_NETHCTRL(txq_eth_ctrl));
 +      c.niqflint_niq = htonl(FW_PFVF_CMD_NIQFLINT_V(rxqi) |
 +                             FW_PFVF_CMD_NIQ_V(rxq));
 +      c.type_to_neq = htonl(FW_PFVF_CMD_CMASK_V(cmask) |
 +                             FW_PFVF_CMD_PMASK_V(pmask) |
 +                             FW_PFVF_CMD_NEQ_V(txq));
 +      c.tc_to_nexactf = htonl(FW_PFVF_CMD_TC_V(tc) | FW_PFVF_CMD_NVI_V(vi) |
 +                              FW_PFVF_CMD_NEXACTF_V(nexact));
 +      c.r_caps_to_nethctrl = htonl(FW_PFVF_CMD_R_CAPS_V(rcaps) |
 +                                   FW_PFVF_CMD_WX_CAPS_V(wxcaps) |
 +                                   FW_PFVF_CMD_NETHCTRL_V(txq_eth_ctrl));
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
  }
  
@@@ -3415,11 -3438,11 +3441,11 @@@ int t4_alloc_vi(struct adapter *adap, u
        struct fw_vi_cmd c;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_vfn = htonl(FW_CMD_OP(FW_VI_CMD) | FW_CMD_REQUEST |
 -                          FW_CMD_WRITE | FW_CMD_EXEC |
 -                          FW_VI_CMD_PFN(pf) | FW_VI_CMD_VFN(vf));
 -      c.alloc_to_len16 = htonl(FW_VI_CMD_ALLOC | FW_LEN16(c));
 -      c.portid_pkd = FW_VI_CMD_PORTID(port);
 +      c.op_to_vfn = htonl(FW_CMD_OP_V(FW_VI_CMD) | FW_CMD_REQUEST_F |
 +                          FW_CMD_WRITE_F | FW_CMD_EXEC_F |
 +                          FW_VI_CMD_PFN_V(pf) | FW_VI_CMD_VFN_V(vf));
 +      c.alloc_to_len16 = htonl(FW_VI_CMD_ALLOC_F | FW_LEN16(c));
 +      c.portid_pkd = FW_VI_CMD_PORTID_V(port);
        c.nmac = nmac - 1;
  
        ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
                }
        }
        if (rss_size)
 -              *rss_size = FW_VI_CMD_RSSSIZE_GET(ntohs(c.rsssize_pkd));
 -      return FW_VI_CMD_VIID_GET(ntohs(c.type_viid));
 +              *rss_size = FW_VI_CMD_RSSSIZE_G(ntohs(c.rsssize_pkd));
 +      return FW_VI_CMD_VIID_G(ntohs(c.type_viid));
  }
  
  /**
@@@ -3468,23 -3491,23 +3494,23 @@@ int t4_set_rxmode(struct adapter *adap
        if (mtu < 0)
                mtu = FW_RXMODE_MTU_NO_CHG;
        if (promisc < 0)
 -              promisc = FW_VI_RXMODE_CMD_PROMISCEN_MASK;
 +              promisc = FW_VI_RXMODE_CMD_PROMISCEN_M;
        if (all_multi < 0)
 -              all_multi = FW_VI_RXMODE_CMD_ALLMULTIEN_MASK;
 +              all_multi = FW_VI_RXMODE_CMD_ALLMULTIEN_M;
        if (bcast < 0)
 -              bcast = FW_VI_RXMODE_CMD_BROADCASTEN_MASK;
 +              bcast = FW_VI_RXMODE_CMD_BROADCASTEN_M;
        if (vlanex < 0)
 -              vlanex = FW_VI_RXMODE_CMD_VLANEXEN_MASK;
 +              vlanex = FW_VI_RXMODE_CMD_VLANEXEN_M;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_viid = htonl(FW_CMD_OP(FW_VI_RXMODE_CMD) | FW_CMD_REQUEST |
 -                           FW_CMD_WRITE | FW_VI_RXMODE_CMD_VIID(viid));
 +      c.op_to_viid = htonl(FW_CMD_OP_V(FW_VI_RXMODE_CMD) | FW_CMD_REQUEST_F |
 +                           FW_CMD_WRITE_F | FW_VI_RXMODE_CMD_VIID_V(viid));
        c.retval_len16 = htonl(FW_LEN16(c));
 -      c.mtu_to_vlanexen = htonl(FW_VI_RXMODE_CMD_MTU(mtu) |
 -                                FW_VI_RXMODE_CMD_PROMISCEN(promisc) |
 -                                FW_VI_RXMODE_CMD_ALLMULTIEN(all_multi) |
 -                                FW_VI_RXMODE_CMD_BROADCASTEN(bcast) |
 -                                FW_VI_RXMODE_CMD_VLANEXEN(vlanex));
 +      c.mtu_to_vlanexen = htonl(FW_VI_RXMODE_CMD_MTU_V(mtu) |
 +                                FW_VI_RXMODE_CMD_PROMISCEN_V(promisc) |
 +                                FW_VI_RXMODE_CMD_ALLMULTIEN_V(all_multi) |
 +                                FW_VI_RXMODE_CMD_BROADCASTEN_V(bcast) |
 +                                FW_VI_RXMODE_CMD_VLANEXEN_V(vlanex));
        return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok);
  }
  
@@@ -3525,15 -3548,15 +3551,15 @@@ int t4_alloc_mac_filt(struct adapter *a
                return -EINVAL;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_viid = htonl(FW_CMD_OP(FW_VI_MAC_CMD) | FW_CMD_REQUEST |
 -                           FW_CMD_WRITE | (free ? FW_CMD_EXEC : 0) |
 -                           FW_VI_MAC_CMD_VIID(viid));
 -      c.freemacs_to_len16 = htonl(FW_VI_MAC_CMD_FREEMACS(free) |
 -                                  FW_CMD_LEN16((naddr + 2) / 2));
 +      c.op_to_viid = htonl(FW_CMD_OP_V(FW_VI_MAC_CMD) | FW_CMD_REQUEST_F |
 +                           FW_CMD_WRITE_F | (free ? FW_CMD_EXEC_F : 0) |
 +                           FW_VI_MAC_CMD_VIID_V(viid));
 +      c.freemacs_to_len16 = htonl(FW_VI_MAC_CMD_FREEMACS_V(free) |
 +                                  FW_CMD_LEN16_V((naddr + 2) / 2));
  
        for (i = 0, p = c.u.exact; i < naddr; i++, p++) {
 -              p->valid_to_idx = htons(FW_VI_MAC_CMD_VALID |
 -                                    FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
 +              p->valid_to_idx = htons(FW_VI_MAC_CMD_VALID_F |
 +                                    FW_VI_MAC_CMD_IDX_V(FW_VI_MAC_ADD_MAC));
                memcpy(p->macaddr, addr[i], sizeof(p->macaddr));
        }
  
                return ret;
  
        for (i = 0, p = c.u.exact; i < naddr; i++, p++) {
 -              u16 index = FW_VI_MAC_CMD_IDX_GET(ntohs(p->valid_to_idx));
 +              u16 index = FW_VI_MAC_CMD_IDX_G(ntohs(p->valid_to_idx));
  
                if (idx)
                        idx[i] = index >= max_naddr ? 0xffff : index;
@@@ -3588,17 -3611,17 +3614,17 @@@ int t4_change_mac(struct adapter *adap
        mode = add_smt ? FW_VI_MAC_SMT_AND_MPSTCAM : FW_VI_MAC_MPS_TCAM_ENTRY;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_viid = htonl(FW_CMD_OP(FW_VI_MAC_CMD) | FW_CMD_REQUEST |
 -                           FW_CMD_WRITE | FW_VI_MAC_CMD_VIID(viid));
 -      c.freemacs_to_len16 = htonl(FW_CMD_LEN16(1));
 -      p->valid_to_idx = htons(FW_VI_MAC_CMD_VALID |
 -                              FW_VI_MAC_CMD_SMAC_RESULT(mode) |
 -                              FW_VI_MAC_CMD_IDX(idx));
 +      c.op_to_viid = htonl(FW_CMD_OP_V(FW_VI_MAC_CMD) | FW_CMD_REQUEST_F |
 +                           FW_CMD_WRITE_F | FW_VI_MAC_CMD_VIID_V(viid));
 +      c.freemacs_to_len16 = htonl(FW_CMD_LEN16_V(1));
 +      p->valid_to_idx = htons(FW_VI_MAC_CMD_VALID_F |
 +                              FW_VI_MAC_CMD_SMAC_RESULT_V(mode) |
 +                              FW_VI_MAC_CMD_IDX_V(idx));
        memcpy(p->macaddr, addr, sizeof(p->macaddr));
  
        ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
        if (ret == 0) {
 -              ret = FW_VI_MAC_CMD_IDX_GET(ntohs(p->valid_to_idx));
 +              ret = FW_VI_MAC_CMD_IDX_G(ntohs(p->valid_to_idx));
                if (ret >= max_mac_addr)
                        ret = -ENOMEM;
        }
@@@ -3622,11 -3645,11 +3648,11 @@@ int t4_set_addr_hash(struct adapter *ad
        struct fw_vi_mac_cmd c;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_viid = htonl(FW_CMD_OP(FW_VI_MAC_CMD) | FW_CMD_REQUEST |
 -                           FW_CMD_WRITE | FW_VI_ENABLE_CMD_VIID(viid));
 -      c.freemacs_to_len16 = htonl(FW_VI_MAC_CMD_HASHVECEN |
 -                                  FW_VI_MAC_CMD_HASHUNIEN(ucast) |
 -                                  FW_CMD_LEN16(1));
 +      c.op_to_viid = htonl(FW_CMD_OP_V(FW_VI_MAC_CMD) | FW_CMD_REQUEST_F |
 +                           FW_CMD_WRITE_F | FW_VI_ENABLE_CMD_VIID_V(viid));
 +      c.freemacs_to_len16 = htonl(FW_VI_MAC_CMD_HASHVECEN_F |
 +                                  FW_VI_MAC_CMD_HASHUNIEN_V(ucast) |
 +                                  FW_CMD_LEN16_V(1));
        c.u.hash.hashvec = cpu_to_be64(vec);
        return t4_wr_mbox_meat(adap, mbox, &c, sizeof(c), NULL, sleep_ok);
  }
@@@ -3649,12 -3672,12 +3675,12 @@@ int t4_enable_vi_params(struct adapter 
        struct fw_vi_enable_cmd c;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST |
 -                           FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid));
 +      c.op_to_viid = htonl(FW_CMD_OP_V(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST_F |
 +                           FW_CMD_EXEC_F | FW_VI_ENABLE_CMD_VIID_V(viid));
  
 -      c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_IEN(rx_en) |
 -                             FW_VI_ENABLE_CMD_EEN(tx_en) | FW_LEN16(c) |
 -                             FW_VI_ENABLE_CMD_DCB_INFO(dcb_en));
 +      c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_IEN_V(rx_en) |
 +                             FW_VI_ENABLE_CMD_EEN_V(tx_en) | FW_LEN16(c) |
 +                             FW_VI_ENABLE_CMD_DCB_INFO_V(dcb_en));
        return t4_wr_mbox_ns(adap, mbox, &c, sizeof(c), NULL);
  }
  
@@@ -3689,9 -3712,9 +3715,9 @@@ int t4_identify_port(struct adapter *ad
        struct fw_vi_enable_cmd c;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_viid = htonl(FW_CMD_OP(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST |
 -                           FW_CMD_EXEC | FW_VI_ENABLE_CMD_VIID(viid));
 -      c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_LED | FW_LEN16(c));
 +      c.op_to_viid = htonl(FW_CMD_OP_V(FW_VI_ENABLE_CMD) | FW_CMD_REQUEST_F |
 +                           FW_CMD_EXEC_F | FW_VI_ENABLE_CMD_VIID_V(viid));
 +      c.ien_to_len16 = htonl(FW_VI_ENABLE_CMD_LED_F | FW_LEN16(c));
        c.blinkdur = htons(nblinks);
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
  }
@@@ -3716,11 -3739,11 +3742,11 @@@ int t4_iq_free(struct adapter *adap, un
        struct fw_iq_cmd c;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_vfn = htonl(FW_CMD_OP(FW_IQ_CMD) | FW_CMD_REQUEST |
 -                          FW_CMD_EXEC | FW_IQ_CMD_PFN(pf) |
 -                          FW_IQ_CMD_VFN(vf));
 -      c.alloc_to_len16 = htonl(FW_IQ_CMD_FREE | FW_LEN16(c));
 -      c.type_to_iqandstindex = htonl(FW_IQ_CMD_TYPE(iqtype));
 +      c.op_to_vfn = htonl(FW_CMD_OP_V(FW_IQ_CMD) | FW_CMD_REQUEST_F |
 +                          FW_CMD_EXEC_F | FW_IQ_CMD_PFN_V(pf) |
 +                          FW_IQ_CMD_VFN_V(vf));
 +      c.alloc_to_len16 = htonl(FW_IQ_CMD_FREE_F | FW_LEN16(c));
 +      c.type_to_iqandstindex = htonl(FW_IQ_CMD_TYPE_V(iqtype));
        c.iqid = htons(iqid);
        c.fl0id = htons(fl0id);
        c.fl1id = htons(fl1id);
@@@ -3743,11 -3766,11 +3769,11 @@@ int t4_eth_eq_free(struct adapter *adap
        struct fw_eq_eth_cmd c;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_vfn = htonl(FW_CMD_OP(FW_EQ_ETH_CMD) | FW_CMD_REQUEST |
 -                          FW_CMD_EXEC | FW_EQ_ETH_CMD_PFN(pf) |
 -                          FW_EQ_ETH_CMD_VFN(vf));
 -      c.alloc_to_len16 = htonl(FW_EQ_ETH_CMD_FREE | FW_LEN16(c));
 -      c.eqid_pkd = htonl(FW_EQ_ETH_CMD_EQID(eqid));
 +      c.op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_ETH_CMD) | FW_CMD_REQUEST_F |
 +                          FW_CMD_EXEC_F | FW_EQ_ETH_CMD_PFN_V(pf) |
 +                          FW_EQ_ETH_CMD_VFN_V(vf));
 +      c.alloc_to_len16 = htonl(FW_EQ_ETH_CMD_FREE_F | FW_LEN16(c));
 +      c.eqid_pkd = htonl(FW_EQ_ETH_CMD_EQID_V(eqid));
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
  }
  
@@@ -3767,11 -3790,11 +3793,11 @@@ int t4_ctrl_eq_free(struct adapter *ada
        struct fw_eq_ctrl_cmd c;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_vfn = htonl(FW_CMD_OP(FW_EQ_CTRL_CMD) | FW_CMD_REQUEST |
 -                          FW_CMD_EXEC | FW_EQ_CTRL_CMD_PFN(pf) |
 -                          FW_EQ_CTRL_CMD_VFN(vf));
 -      c.alloc_to_len16 = htonl(FW_EQ_CTRL_CMD_FREE | FW_LEN16(c));
 -      c.cmpliqid_eqid = htonl(FW_EQ_CTRL_CMD_EQID(eqid));
 +      c.op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_CTRL_CMD) | FW_CMD_REQUEST_F |
 +                          FW_CMD_EXEC_F | FW_EQ_CTRL_CMD_PFN_V(pf) |
 +                          FW_EQ_CTRL_CMD_VFN_V(vf));
 +      c.alloc_to_len16 = htonl(FW_EQ_CTRL_CMD_FREE_F | FW_LEN16(c));
 +      c.cmpliqid_eqid = htonl(FW_EQ_CTRL_CMD_EQID_V(eqid));
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
  }
  
@@@ -3791,11 -3814,11 +3817,11 @@@ int t4_ofld_eq_free(struct adapter *ada
        struct fw_eq_ofld_cmd c;
  
        memset(&c, 0, sizeof(c));
 -      c.op_to_vfn = htonl(FW_CMD_OP(FW_EQ_OFLD_CMD) | FW_CMD_REQUEST |
 -                          FW_CMD_EXEC | FW_EQ_OFLD_CMD_PFN(pf) |
 -                          FW_EQ_OFLD_CMD_VFN(vf));
 -      c.alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_FREE | FW_LEN16(c));
 -      c.eqid_pkd = htonl(FW_EQ_OFLD_CMD_EQID(eqid));
 +      c.op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_OFLD_CMD) | FW_CMD_REQUEST_F |
 +                          FW_CMD_EXEC_F | FW_EQ_OFLD_CMD_PFN_V(pf) |
 +                          FW_EQ_OFLD_CMD_VFN_V(vf));
 +      c.alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_FREE_F | FW_LEN16(c));
 +      c.eqid_pkd = htonl(FW_EQ_OFLD_CMD_EQID_V(eqid));
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
  }
  
@@@ -3813,25 -3836,25 +3839,25 @@@ int t4_handle_fw_rpl(struct adapter *ad
        if (opcode == FW_PORT_CMD) {    /* link/module state change message */
                int speed = 0, fc = 0;
                const struct fw_port_cmd *p = (void *)rpl;
 -              int chan = FW_PORT_CMD_PORTID_GET(ntohl(p->op_to_portid));
 +              int chan = FW_PORT_CMD_PORTID_G(ntohl(p->op_to_portid));
                int port = adap->chan_map[chan];
                struct port_info *pi = adap2pinfo(adap, port);
                struct link_config *lc = &pi->link_cfg;
                u32 stat = ntohl(p->u.info.lstatus_to_modtype);
 -              int link_ok = (stat & FW_PORT_CMD_LSTATUS) != 0;
 -              u32 mod = FW_PORT_CMD_MODTYPE_GET(stat);
 +              int link_ok = (stat & FW_PORT_CMD_LSTATUS_F) != 0;
 +              u32 mod = FW_PORT_CMD_MODTYPE_G(stat);
  
 -              if (stat & FW_PORT_CMD_RXPAUSE)
 +              if (stat & FW_PORT_CMD_RXPAUSE_F)
                        fc |= PAUSE_RX;
 -              if (stat & FW_PORT_CMD_TXPAUSE)
 +              if (stat & FW_PORT_CMD_TXPAUSE_F)
                        fc |= PAUSE_TX;
 -              if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_100M))
 +              if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_100M))
                        speed = 100;
 -              else if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_1G))
 +              else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_1G))
                        speed = 1000;
 -              else if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_10G))
 +              else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_10G))
                        speed = 10000;
 -              else if (stat & FW_PORT_CMD_LSPEED(FW_PORT_CAP_SPEED_40G))
 +              else if (stat & FW_PORT_CMD_LSPEED_V(FW_PORT_CAP_SPEED_40G))
                        speed = 40000;
  
                if (link_ok != lc->link_ok || speed != lc->speed ||
@@@ -4004,126 -4027,6 +4030,126 @@@ int t4_prep_adapter(struct adapter *ada
        return 0;
  }
  
 +/**
 + *    t4_bar2_sge_qregs - return BAR2 SGE Queue register information
 + *    @adapter: the adapter
 + *    @qid: the Queue ID
 + *    @qtype: the Ingress or Egress type for @qid
 + *    @pbar2_qoffset: BAR2 Queue Offset
 + *    @pbar2_qid: BAR2 Queue ID or 0 for Queue ID inferred SGE Queues
 + *
 + *    Returns the BAR2 SGE Queue Registers information associated with the
 + *    indicated Absolute Queue ID.  These are passed back in return value
 + *    pointers.  @qtype should be T4_BAR2_QTYPE_EGRESS for Egress Queue
 + *    and T4_BAR2_QTYPE_INGRESS for Ingress Queues.
 + *
 + *    This may return an error which indicates that BAR2 SGE Queue
 + *    registers aren't available.  If an error is not returned, then the
 + *    following values are returned:
 + *
 + *      *@pbar2_qoffset: the BAR2 Offset of the @qid Registers
 + *      *@pbar2_qid: the BAR2 SGE Queue ID or 0 of @qid
 + *
 + *    If the returned BAR2 Queue ID is 0, then BAR2 SGE registers which
 + *    require the "Inferred Queue ID" ability may be used.  E.g. the
 + *    Write Combining Doorbell Buffer. If the BAR2 Queue ID is not 0,
 + *    then these "Inferred Queue ID" register may not be used.
 + */
 +int t4_bar2_sge_qregs(struct adapter *adapter,
 +                    unsigned int qid,
 +                    enum t4_bar2_qtype qtype,
 +                    u64 *pbar2_qoffset,
 +                    unsigned int *pbar2_qid)
 +{
 +      unsigned int page_shift, page_size, qpp_shift, qpp_mask;
 +      u64 bar2_page_offset, bar2_qoffset;
 +      unsigned int bar2_qid, bar2_qid_offset, bar2_qinferred;
 +
 +      /* T4 doesn't support BAR2 SGE Queue registers.
 +       */
 +      if (is_t4(adapter->params.chip))
 +              return -EINVAL;
 +
 +      /* Get our SGE Page Size parameters.
 +       */
 +      page_shift = adapter->params.sge.hps + 10;
 +      page_size = 1 << page_shift;
 +
 +      /* Get the right Queues per Page parameters for our Queue.
 +       */
 +      qpp_shift = (qtype == T4_BAR2_QTYPE_EGRESS
 +                   ? adapter->params.sge.eq_qpp
 +                   : adapter->params.sge.iq_qpp);
 +      qpp_mask = (1 << qpp_shift) - 1;
 +
 +      /*  Calculate the basics of the BAR2 SGE Queue register area:
 +       *  o The BAR2 page the Queue registers will be in.
 +       *  o The BAR2 Queue ID.
 +       *  o The BAR2 Queue ID Offset into the BAR2 page.
 +       */
 +      bar2_page_offset = ((qid >> qpp_shift) << page_shift);
 +      bar2_qid = qid & qpp_mask;
 +      bar2_qid_offset = bar2_qid * SGE_UDB_SIZE;
 +
 +      /* If the BAR2 Queue ID Offset is less than the Page Size, then the
 +       * hardware will infer the Absolute Queue ID simply from the writes to
 +       * the BAR2 Queue ID Offset within the BAR2 Page (and we need to use a
 +       * BAR2 Queue ID of 0 for those writes).  Otherwise, we'll simply
 +       * write to the first BAR2 SGE Queue Area within the BAR2 Page with
 +       * the BAR2 Queue ID and the hardware will infer the Absolute Queue ID
 +       * from the BAR2 Page and BAR2 Queue ID.
 +       *
 +       * One important censequence of this is that some BAR2 SGE registers
 +       * have a "Queue ID" field and we can write the BAR2 SGE Queue ID
 +       * there.  But other registers synthesize the SGE Queue ID purely
 +       * from the writes to the registers -- the Write Combined Doorbell
 +       * Buffer is a good example.  These BAR2 SGE Registers are only
 +       * available for those BAR2 SGE Register areas where the SGE Absolute
 +       * Queue ID can be inferred from simple writes.
 +       */
 +      bar2_qoffset = bar2_page_offset;
 +      bar2_qinferred = (bar2_qid_offset < page_size);
 +      if (bar2_qinferred) {
 +              bar2_qoffset += bar2_qid_offset;
 +              bar2_qid = 0;
 +      }
 +
 +      *pbar2_qoffset = bar2_qoffset;
 +      *pbar2_qid = bar2_qid;
 +      return 0;
 +}
 +
 +/**
 + *    t4_init_sge_params - initialize adap->params.sge
 + *    @adapter: the adapter
 + *
 + *    Initialize various fields of the adapter's SGE Parameters structure.
 + */
 +int t4_init_sge_params(struct adapter *adapter)
 +{
 +      struct sge_params *sge_params = &adapter->params.sge;
 +      u32 hps, qpp;
 +      unsigned int s_hps, s_qpp;
 +
 +      /* Extract the SGE Page Size for our PF.
 +       */
 +      hps = t4_read_reg(adapter, SGE_HOST_PAGE_SIZE);
 +      s_hps = (HOSTPAGESIZEPF0_S +
 +               (HOSTPAGESIZEPF1_S - HOSTPAGESIZEPF0_S) * adapter->fn);
 +      sge_params->hps = ((hps >> s_hps) & HOSTPAGESIZEPF0_M);
 +
 +      /* Extract the SGE Egress and Ingess Queues Per Page for our PF.
 +       */
 +      s_qpp = (QUEUESPERPAGEPF0_S +
 +              (QUEUESPERPAGEPF1_S - QUEUESPERPAGEPF0_S) * adapter->fn);
 +      qpp = t4_read_reg(adapter, SGE_EGRESS_QUEUES_PER_PAGE_PF);
 +      sge_params->eq_qpp = ((qpp >> s_qpp) & QUEUESPERPAGEPF0_MASK);
 +      qpp = t4_read_reg(adapter, SGE_INGRESS_QUEUES_PER_PAGE_PF);
 +      sge_params->iq_qpp = ((qpp >> s_qpp) & QUEUESPERPAGEPF0_MASK);
 +
 +      return 0;
 +}
 +
  /**
   *      t4_init_tp_params - initialize adap->params.tp
   *      @adap: the adapter
@@@ -4244,11 -4147,11 +4270,11 @@@ int t4_port_init(struct adapter *adap, 
                while ((adap->params.portvec & (1 << j)) == 0)
                        j++;
  
 -              c.op_to_portid = htonl(FW_CMD_OP(FW_PORT_CMD) |
 -                                     FW_CMD_REQUEST | FW_CMD_READ |
 -                                     FW_PORT_CMD_PORTID(j));
 +              c.op_to_portid = htonl(FW_CMD_OP_V(FW_PORT_CMD) |
 +                                     FW_CMD_REQUEST_F | FW_CMD_READ_F |
 +                                     FW_PORT_CMD_PORTID_V(j));
                c.action_to_len16 = htonl(
 -                      FW_PORT_CMD_ACTION(FW_PORT_ACTION_GET_PORT_INFO) |
 +                      FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_GET_PORT_INFO) |
                        FW_LEN16(c));
                ret = t4_wr_mbox(adap, mbox, &c, sizeof(c), &c);
                if (ret)
                adap->port[i]->dev_port = j;
  
                ret = ntohl(c.u.info.lstatus_to_modtype);
 -              p->mdio_addr = (ret & FW_PORT_CMD_MDIOCAP) ?
 -                      FW_PORT_CMD_MDIOADDR_GET(ret) : -1;
 -              p->port_type = FW_PORT_CMD_PTYPE_GET(ret);
 +              p->mdio_addr = (ret & FW_PORT_CMD_MDIOCAP_F) ?
 +                      FW_PORT_CMD_MDIOADDR_G(ret) : -1;
 +              p->port_type = FW_PORT_CMD_PTYPE_G(ret);
                p->mod_type = FW_PORT_MOD_TYPE_NA;
  
 -              rvc.op_to_viid = htonl(FW_CMD_OP(FW_RSS_VI_CONFIG_CMD) |
 -                                     FW_CMD_REQUEST | FW_CMD_READ |
 +              rvc.op_to_viid = htonl(FW_CMD_OP_V(FW_RSS_VI_CONFIG_CMD) |
 +                                     FW_CMD_REQUEST_F | FW_CMD_READ_F |
                                       FW_RSS_VI_CONFIG_CMD_VIID(p->viid));
                rvc.retval_len16 = htonl(FW_LEN16(rvc));
                ret = t4_wr_mbox(adap, mbox, &rvc, sizeof(rvc), &rvc);
  /* Various constants */
  
  /* Coalescing */
- #define MVNETA_TXDONE_COAL_PKTS               16
+ #define MVNETA_TXDONE_COAL_PKTS               1
  #define MVNETA_RX_COAL_PKTS           32
  #define MVNETA_RX_COAL_USEC           100
  
@@@ -1721,6 -1721,7 +1721,7 @@@ static int mvneta_tx(struct sk_buff *sk
        u16 txq_id = skb_get_queue_mapping(skb);
        struct mvneta_tx_queue *txq = &pp->txqs[txq_id];
        struct mvneta_tx_desc *tx_desc;
+       int len = skb->len;
        int frags = 0;
        u32 tx_cmd;
  
@@@ -1788,7 -1789,7 +1789,7 @@@ out
  
                u64_stats_update_begin(&stats->syncp);
                stats->tx_packets++;
-               stats->tx_bytes  += skb->len;
+               stats->tx_bytes  += len;
                u64_stats_update_end(&stats->syncp);
        } else {
                dev->stats.tx_dropped++;
@@@ -2558,10 -2559,11 +2559,10 @@@ static void mvneta_adjust_link(struct n
                                MVNETA_GMAC_FORCE_LINK_DOWN);
                        mvreg_write(pp, MVNETA_GMAC_AUTONEG_CONFIG, val);
                        mvneta_port_up(pp);
 -                      netdev_info(pp->dev, "link up\n");
                } else {
                        mvneta_port_down(pp);
 -                      netdev_info(pp->dev, "link down\n");
                }
 +              phy_print_status(phydev);
        }
  }
  
  #define SDMA_CMD_ERD          (1 << 7)
  
  /* Bit definitions of the Port Config Reg */
 +#define PCR_DUPLEX_FULL               (1 << 15)
  #define PCR_HS                        (1 << 12)
  #define PCR_EN                        (1 << 7)
  #define PCR_PM                        (1 << 0)
  /* Bit definitions of the Port Config Extend Reg */
  #define PCXR_2BSM             (1 << 28)
  #define PCXR_DSCP_EN          (1 << 21)
 +#define PCXR_RMII_EN          (1 << 20)
 +#define PCXR_AN_SPEED_DIS     (1 << 19)
 +#define PCXR_SPEED_100                (1 << 18)
  #define PCXR_MFL_1518         (0 << 14)
  #define PCXR_MFL_1536         (1 << 14)
  #define PCXR_MFL_2048         (2 << 14)
  #define PCXR_MFL_64K          (3 << 14)
 +#define PCXR_FLOWCTL_DIS      (1 << 12)
  #define PCXR_FLP              (1 << 11)
 +#define PCXR_AN_FLOWCTL_DIS   (1 << 10)
 +#define PCXR_AN_DUPLEX_DIS    (1 << 9)
  #define PCXR_PRIO_TX_OFF      3
  #define PCXR_TX_HIGH_PRI      (7 << PCXR_PRIO_TX_OFF)
  
  #define LINK_UP                       (1 << 3)
  
  /* Bit definitions for work to be done */
 -#define WORK_LINK             (1 << 0)
  #define WORK_TX_DONE          (1 << 1)
  
  /*
@@@ -203,9 -197,6 +203,9 @@@ struct tx_desc 
  struct pxa168_eth_private {
        int port_num;           /* User Ethernet port number    */
        int phy_addr;
 +      int phy_speed;
 +      int phy_duplex;
 +      phy_interface_t phy_intf;
  
        int rx_resource_err;    /* Rx ring resource error flag */
  
@@@ -278,11 -269,11 +278,11 @@@ enum hash_table_entry 
  static int pxa168_get_settings(struct net_device *dev, struct ethtool_cmd *cmd);
  static int pxa168_set_settings(struct net_device *dev, struct ethtool_cmd *cmd);
  static int pxa168_init_hw(struct pxa168_eth_private *pep);
 +static int pxa168_init_phy(struct net_device *dev);
  static void eth_port_reset(struct net_device *dev);
  static void eth_port_start(struct net_device *dev);
  static int pxa168_eth_open(struct net_device *dev);
  static int pxa168_eth_stop(struct net_device *dev);
 -static int ethernet_phy_setup(struct net_device *dev);
  
  static inline u32 rdl(struct pxa168_eth_private *pep, int offset)
  {
@@@ -314,6 -305,26 +314,6 @@@ static void abort_dma(struct pxa168_eth
                netdev_err(pep->dev, "%s : DMA Stuck\n", __func__);
  }
  
 -static int ethernet_phy_get(struct pxa168_eth_private *pep)
 -{
 -      unsigned int reg_data;
 -
 -      reg_data = rdl(pep, PHY_ADDRESS);
 -
 -      return (reg_data >> (5 * pep->port_num)) & 0x1f;
 -}
 -
 -static void ethernet_phy_set_addr(struct pxa168_eth_private *pep, int phy_addr)
 -{
 -      u32 reg_data;
 -      int addr_shift = 5 * pep->port_num;
 -
 -      reg_data = rdl(pep, PHY_ADDRESS);
 -      reg_data &= ~(0x1f << addr_shift);
 -      reg_data |= (phy_addr & 0x1f) << addr_shift;
 -      wrl(pep, PHY_ADDRESS, reg_data);
 -}
 -
  static void rxq_refill(struct net_device *dev)
  {
        struct pxa168_eth_private *pep = netdev_priv(dev);
@@@ -644,7 -655,14 +644,7 @@@ static void eth_port_start(struct net_d
        struct pxa168_eth_private *pep = netdev_priv(dev);
        int tx_curr_desc, rx_curr_desc;
  
 -      /* Perform PHY reset, if there is a PHY. */
 -      if (pep->phy != NULL) {
 -              struct ethtool_cmd cmd;
 -
 -              pxa168_get_settings(pep->dev, &cmd);
 -              phy_init_hw(pep->phy);
 -              pxa168_set_settings(pep->dev, &cmd);
 -      }
 +      phy_start(pep->phy);
  
        /* Assignment of Tx CTRP of given queue */
        tx_curr_desc = pep->tx_curr_desc_q;
@@@ -699,8 -717,6 +699,8 @@@ static void eth_port_reset(struct net_d
        val = rdl(pep, PORT_CONFIG);
        val &= ~PCR_EN;
        wrl(pep, PORT_CONFIG, val);
 +
 +      phy_stop(pep->phy);
  }
  
  /*
@@@ -868,9 -884,43 +868,9 @@@ static int pxa168_eth_collect_events(st
        }
        if (icr & ICR_RXBUF)
                ret = 1;
 -      if (icr & ICR_MII_CH) {
 -              pep->work_todo |= WORK_LINK;
 -              ret = 1;
 -      }
        return ret;
  }
  
 -static void handle_link_event(struct pxa168_eth_private *pep)
 -{
 -      struct net_device *dev = pep->dev;
 -      u32 port_status;
 -      int speed;
 -      int duplex;
 -      int fc;
 -
 -      port_status = rdl(pep, PORT_STATUS);
 -      if (!(port_status & LINK_UP)) {
 -              if (netif_carrier_ok(dev)) {
 -                      netdev_info(dev, "link down\n");
 -                      netif_carrier_off(dev);
 -                      txq_reclaim(dev, 1);
 -              }
 -              return;
 -      }
 -      if (port_status & PORT_SPEED_100)
 -              speed = 100;
 -      else
 -              speed = 10;
 -
 -      duplex = (port_status & FULL_DUPLEX) ? 1 : 0;
 -      fc = (port_status & FLOW_CONTROL_DISABLED) ? 0 : 1;
 -      netdev_info(dev, "link up, %d Mb/s, %s duplex, flow control %sabled\n",
 -                  speed, duplex ? "full" : "half", fc ? "en" : "dis");
 -      if (!netif_carrier_ok(dev))
 -              netif_carrier_on(dev);
 -}
 -
  static irqreturn_t pxa168_eth_int_handler(int irq, void *dev_id)
  {
        struct net_device *dev = (struct net_device *)dev_id;
@@@ -928,11 -978,8 +928,11 @@@ static int set_port_config_ext(struct p
                skb_size = PCXR_MFL_64K;
  
        /* Extended Port Configuration */
 -      wrl(pep,
 -          PORT_CONFIG_EXT, PCXR_2BSM | /* Two byte prefix aligns IP hdr */
 +      wrl(pep, PORT_CONFIG_EXT,
 +          PCXR_AN_SPEED_DIS |          /* Disable HW AN */
 +          PCXR_AN_DUPLEX_DIS |
 +          PCXR_AN_FLOWCTL_DIS |
 +          PCXR_2BSM |                  /* Two byte prefix aligns IP hdr */
            PCXR_DSCP_EN |               /* Enable DSCP in IP */
            skb_size | PCXR_FLP |        /* do not force link pass */
            PCXR_TX_HIGH_PRI);           /* Transmit - high priority queue */
        return 0;
  }
  
 +static void pxa168_eth_adjust_link(struct net_device *dev)
 +{
 +      struct pxa168_eth_private *pep = netdev_priv(dev);
 +      struct phy_device *phy = pep->phy;
 +      u32 cfg, cfg_o = rdl(pep, PORT_CONFIG);
 +      u32 cfgext, cfgext_o = rdl(pep, PORT_CONFIG_EXT);
 +
 +      cfg = cfg_o & ~PCR_DUPLEX_FULL;
 +      cfgext = cfgext_o & ~(PCXR_SPEED_100 | PCXR_FLOWCTL_DIS | PCXR_RMII_EN);
 +
 +      if (phy->interface == PHY_INTERFACE_MODE_RMII)
 +              cfgext |= PCXR_RMII_EN;
 +      if (phy->speed == SPEED_100)
 +              cfgext |= PCXR_SPEED_100;
 +      if (phy->duplex)
 +              cfg |= PCR_DUPLEX_FULL;
 +      if (!phy->pause)
 +              cfgext |= PCXR_FLOWCTL_DIS;
 +
 +      /* Bail out if there has nothing changed */
 +      if (cfg == cfg_o && cfgext == cfgext_o)
 +              return;
 +
 +      wrl(pep, PORT_CONFIG, cfg);
 +      wrl(pep, PORT_CONFIG_EXT, cfgext);
 +
 +      phy_print_status(phy);
 +}
 +
 +static int pxa168_init_phy(struct net_device *dev)
 +{
 +      struct pxa168_eth_private *pep = netdev_priv(dev);
 +      struct ethtool_cmd cmd;
 +      int err;
 +
 +      if (pep->phy)
 +              return 0;
 +
 +      pep->phy = mdiobus_scan(pep->smi_bus, pep->phy_addr);
 +      if (!pep->phy)
 +              return -ENODEV;
 +
 +      err = phy_connect_direct(dev, pep->phy, pxa168_eth_adjust_link,
 +                               pep->phy_intf);
 +      if (err)
 +              return err;
 +
 +      err = pxa168_get_settings(dev, &cmd);
 +      if (err)
 +              return err;
 +
 +      cmd.phy_address = pep->phy_addr;
 +      cmd.speed = pep->phy_speed;
 +      cmd.duplex = pep->phy_duplex;
 +      cmd.advertising = PHY_BASIC_FEATURES;
 +      cmd.autoneg = AUTONEG_ENABLE;
 +
 +      if (cmd.speed != 0)
 +              cmd.autoneg = AUTONEG_DISABLE;
 +
 +      return pxa168_set_settings(dev, &cmd);
 +}
 +
  static int pxa168_init_hw(struct pxa168_eth_private *pep)
  {
        int err = 0;
@@@ -1149,10 -1133,6 +1149,10 @@@ static int pxa168_eth_open(struct net_d
        struct pxa168_eth_private *pep = netdev_priv(dev);
        int err;
  
 +      err = pxa168_init_phy(dev);
 +      if (err)
 +              return err;
 +
        err = request_irq(dev->irq, pxa168_eth_int_handler, 0, dev->name, dev);
        if (err) {
                dev_err(&dev->dev, "can't assign irq\n");
        pep->rx_used_desc_q = 0;
        pep->rx_curr_desc_q = 0;
        netif_carrier_off(dev);
-       eth_port_start(dev);
        napi_enable(&pep->napi);
+       eth_port_start(dev);
        return 0;
  out_free_rx_skb:
        rxq_deinit(dev);
@@@ -1251,6 -1231,10 +1251,6 @@@ static int pxa168_rx_poll(struct napi_s
        struct net_device *dev = pep->dev;
        int work_done = 0;
  
 -      if (unlikely(pep->work_todo & WORK_LINK)) {
 -              pep->work_todo &= ~(WORK_LINK);
 -              handle_link_event(pep);
 -      }
        /*
         * We call txq_reclaim every time since in NAPI interupts are disabled
         * and due to this we miss the TX_DONE interrupt,which is not updated in
@@@ -1373,6 -1357,77 +1373,6 @@@ static int pxa168_eth_do_ioctl(struct n
        return -EOPNOTSUPP;
  }
  
 -static struct phy_device *phy_scan(struct pxa168_eth_private *pep, int phy_addr)
 -{
 -      struct mii_bus *bus = pep->smi_bus;
 -      struct phy_device *phydev;
 -      int start;
 -      int num;
 -      int i;
 -
 -      if (phy_addr == PXA168_ETH_PHY_ADDR_DEFAULT) {
 -              /* Scan entire range */
 -              start = ethernet_phy_get(pep);
 -              num = 32;
 -      } else {
 -              /* Use phy addr specific to platform */
 -              start = phy_addr & 0x1f;
 -              num = 1;
 -      }
 -      phydev = NULL;
 -      for (i = 0; i < num; i++) {
 -              int addr = (start + i) & 0x1f;
 -              if (bus->phy_map[addr] == NULL)
 -                      mdiobus_scan(bus, addr);
 -
 -              if (phydev == NULL) {
 -                      phydev = bus->phy_map[addr];
 -                      if (phydev != NULL)
 -                              ethernet_phy_set_addr(pep, addr);
 -              }
 -      }
 -
 -      return phydev;
 -}
 -
 -static void phy_init(struct pxa168_eth_private *pep)
 -{
 -      struct phy_device *phy = pep->phy;
 -
 -      phy_attach(pep->dev, dev_name(&phy->dev), PHY_INTERFACE_MODE_MII);
 -
 -      if (pep->pd && pep->pd->speed != 0) {
 -              phy->autoneg = AUTONEG_DISABLE;
 -              phy->advertising = 0;
 -              phy->speed = pep->pd->speed;
 -              phy->duplex = pep->pd->duplex;
 -      } else {
 -              phy->autoneg = AUTONEG_ENABLE;
 -              phy->speed = 0;
 -              phy->duplex = 0;
 -              phy->supported &= PHY_BASIC_FEATURES;
 -              phy->advertising = phy->supported | ADVERTISED_Autoneg;
 -      }
 -
 -      phy_start_aneg(phy);
 -}
 -
 -static int ethernet_phy_setup(struct net_device *dev)
 -{
 -      struct pxa168_eth_private *pep = netdev_priv(dev);
 -
 -      if (pep->pd && pep->pd->init)
 -              pep->pd->init();
 -
 -      pep->phy = phy_scan(pep, pep->phy_addr & 0x1f);
 -      if (pep->phy != NULL)
 -              phy_init(pep);
 -
 -      update_hash_table_mac_address(pep, NULL, dev->dev_addr);
 -
 -      return 0;
 -}
 -
  static int pxa168_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
  {
        struct pxa168_eth_private *pep = netdev_priv(dev);
@@@ -1450,14 -1505,16 +1450,14 @@@ static int pxa168_eth_probe(struct plat
        pep = netdev_priv(dev);
        pep->dev = dev;
        pep->clk = clk;
 +
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 -      if (res == NULL) {
 -              err = -ENODEV;
 -              goto err_netdev;
 -      }
        pep->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(pep->base)) {
                err = -ENOMEM;
                goto err_netdev;
        }
 +
        res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        BUG_ON(!res);
        dev->irq = res->start;
  
                pep->port_num = pep->pd->port_number;
                pep->phy_addr = pep->pd->phy_addr;
 +              pep->phy_speed = pep->pd->speed;
 +              pep->phy_duplex = pep->pd->duplex;
 +              pep->phy_intf = pep->pd->intf;
 +
 +              if (pep->pd->init)
 +                      pep->pd->init();
        } else if (pdev->dev.of_node) {
                of_property_read_u32(pdev->dev.of_node, "port-id",
                                     &pep->port_num);
  
                np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
 -              if (np)
 -                      of_property_read_u32(np, "reg", &pep->phy_addr);
 +              if (!np) {
 +                      dev_err(&pdev->dev, "missing phy-handle\n");
 +                      return -EINVAL;
 +              }
 +              of_property_read_u32(np, "reg", &pep->phy_addr);
 +              pep->phy_intf = of_get_phy_mode(pdev->dev.of_node);
        }
  
        /* Hardware supports only 3 ports */
        if (err)
                goto err_free_mdio;
  
 -      pxa168_init_hw(pep);
 -      err = ethernet_phy_setup(dev);
 -      if (err)
 -              goto err_mdiobus;
        SET_NETDEV_DEV(dev, &pdev->dev);
 +      pxa168_init_hw(pep);
        err = register_netdev(dev);
        if (err)
                goto err_mdiobus;
@@@ -1571,13 -1621,13 +1571,13 @@@ static int pxa168_eth_remove(struct pla
                                  pep->htpr, pep->htpr_dma);
                pep->htpr = NULL;
        }
 +      if (pep->phy)
 +              phy_disconnect(pep->phy);
        if (pep->clk) {
                clk_disable(pep->clk);
                clk_put(pep->clk);
                pep->clk = NULL;
        }
 -      if (pep->phy != NULL)
 -              phy_detach(pep->phy);
  
        iounmap(pep->base);
        pep->base = NULL;
@@@ -1290,6 -1290,14 +1290,6 @@@ static void rx_set_checksum(struct sky2
                     ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
  }
  
 -/*
 - * Fixed initial key as seed to RSS.
 - */
 -static const uint32_t rss_init_key[10] = {
 -      0x7c3351da, 0x51c5cf4e, 0x44adbdd1, 0xe8d38d18, 0x48897c43,
 -      0xb1d60e7e, 0x6a3dd760, 0x01a2e453, 0x16f46f13, 0x1a0e7b30
 -};
 -
  /* Enable/disable receive hash calculation (RSS) */
  static void rx_set_rss(struct net_device *dev, netdev_features_t features)
  {
  
        /* Program RSS initial values */
        if (features & NETIF_F_RXHASH) {
 +              u32 rss_key[10];
 +
 +              netdev_rss_key_fill(rss_key, sizeof(rss_key));
                for (i = 0; i < nkeys; i++)
                        sky2_write32(hw, SK_REG(sky2->port, RSS_KEY + i * 4),
 -                                   rss_init_key[i]);
 +                                   rss_key[i]);
  
                /* Need to turn on (undocumented) flag to make hashing work  */
                sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T),
@@@ -1361,9 -1366,7 +1361,9 @@@ static void sky2_rx_clean(struct sky2_p
  {
        unsigned i;
  
 -      memset(sky2->rx_le, 0, RX_LE_BYTES);
 +      if (sky2->rx_le)
 +              memset(sky2->rx_le, 0, RX_LE_BYTES);
 +
        for (i = 0; i < sky2->rx_pending; i++) {
                struct rx_ring_info *re = sky2->rx_ring + i;
  
@@@ -2416,6 -2419,7 +2416,7 @@@ static int sky2_change_mtu(struct net_d
  
        imask = sky2_read32(hw, B0_IMSK);
        sky2_write32(hw, B0_IMSK, 0);
+       sky2_read32(hw, B0_IMSK);
  
        dev->trans_start = jiffies;     /* prevent tx timeout */
        napi_disable(&hw->napi);
@@@ -3484,8 -3488,8 +3485,8 @@@ static void sky2_all_down(struct sky2_h
        int i;
  
        if (hw->flags & SKY2_HW_IRQ_SETUP) {
-               sky2_read32(hw, B0_IMSK);
                sky2_write32(hw, B0_IMSK, 0);
+               sky2_read32(hw, B0_IMSK);
  
                synchronize_irq(hw->pdev->irq);
                napi_disable(&hw->napi);
@@@ -1,6 -1,5 +1,6 @@@
  /*  SuperH Ethernet device driver
   *
 + *  Copyright (C) 2014  Renesas Electronics Corporation
   *  Copyright (C) 2006-2012 Nobuhiro Iwamatsu
   *  Copyright (C) 2008-2014 Renesas Solutions Corp.
   *  Copyright (C) 2013-2014 Cogent Embedded, Inc.
@@@ -918,21 -917,13 +918,13 @@@ static int sh_eth_reset(struct net_devi
        return ret;
  }
  
- #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
  static void sh_eth_set_receive_align(struct sk_buff *skb)
  {
-       int reserve;
+       uintptr_t reserve = (uintptr_t)skb->data & (SH_ETH_RX_ALIGN - 1);
  
-       reserve = SH4_SKB_RX_ALIGN - ((u32)skb->data & (SH4_SKB_RX_ALIGN - 1));
        if (reserve)
-               skb_reserve(skb, reserve);
+               skb_reserve(skb, SH_ETH_RX_ALIGN - reserve);
  }
- #else
- static void sh_eth_set_receive_align(struct sk_buff *skb)
- {
-       skb_reserve(skb, SH2_SH3_SKB_RX_ALIGN);
- }
- #endif
  
  
  /* CPU <-> EDMAC endian convert */
@@@ -1120,6 -1111,7 +1112,7 @@@ static void sh_eth_ring_format(struct n
        struct sh_eth_txdesc *txdesc = NULL;
        int rx_ringsize = sizeof(*rxdesc) * mdp->num_rx_ring;
        int tx_ringsize = sizeof(*txdesc) * mdp->num_tx_ring;
+       int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1;
  
        mdp->cur_rx = 0;
        mdp->cur_tx = 0;
        for (i = 0; i < mdp->num_rx_ring; i++) {
                /* skb */
                mdp->rx_skbuff[i] = NULL;
-               skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz);
+               skb = netdev_alloc_skb(ndev, skbuff_size);
                mdp->rx_skbuff[i] = skb;
                if (skb == NULL)
                        break;
-               dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
-                              DMA_FROM_DEVICE);
                sh_eth_set_receive_align(skb);
  
                /* RX descriptor */
                rxdesc = &mdp->rx_ring[i];
 -              rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
+               /* The size of the buffer is a multiple of 16 bytes. */
+               rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
+               dma_map_single(&ndev->dev, skb->data, rxdesc->buffer_length,
+                              DMA_FROM_DEVICE);
 +              rxdesc->addr = virt_to_phys(skb->data);
                rxdesc->status = cpu_to_edmac(mdp, RD_RACT | RD_RFP);
  
-               /* The size of the buffer is 16 byte boundary. */
-               rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
                /* Rx descriptor address set */
                if (i == 0) {
                        sh_eth_write(ndev, mdp->rx_desc_dma, RDLAR);
@@@ -1395,13 -1387,11 +1388,14 @@@ static int sh_eth_rx(struct net_device 
  
        int entry = mdp->cur_rx % mdp->num_rx_ring;
        int boguscnt = (mdp->dirty_rx + mdp->num_rx_ring) - mdp->cur_rx;
 +      int limit;
        struct sk_buff *skb;
        u16 pkt_len = 0;
        u32 desc_status;
+       int skbuff_size = mdp->rx_buf_sz + SH_ETH_RX_ALIGN - 1;
  
 +      boguscnt = min(boguscnt, *quota);
 +      limit = boguscnt;
        rxdesc = &mdp->rx_ring[entry];
        while (!(rxdesc->status & cpu_to_edmac(mdp, RD_RACT))) {
                desc_status = edmac_to_cpu(mdp, rxdesc->status);
                if (--boguscnt < 0)
                        break;
  
 -              if (*quota <= 0)
 -                      break;
 -
 -              (*quota)--;
 -
                if (!(desc_status & RDFEND))
                        ndev->stats.rx_length_errors++;
  
                        if (mdp->cd->rpadir)
                                skb_reserve(skb, NET_IP_ALIGN);
                        dma_sync_single_for_cpu(&ndev->dev, rxdesc->addr,
-                                               mdp->rx_buf_sz,
+                                               ALIGN(mdp->rx_buf_sz, 16),
                                                DMA_FROM_DEVICE);
                        skb_put(skb, pkt_len);
                        skb->protocol = eth_type_trans(skb, ndev);
                rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
  
                if (mdp->rx_skbuff[entry] == NULL) {
-                       skb = netdev_alloc_skb(ndev, mdp->rx_buf_sz);
+                       skb = netdev_alloc_skb(ndev, skbuff_size);
                        mdp->rx_skbuff[entry] = skb;
                        if (skb == NULL)
                                break;  /* Better luck next round. */
-                       dma_map_single(&ndev->dev, skb->data, mdp->rx_buf_sz,
-                                      DMA_FROM_DEVICE);
                        sh_eth_set_receive_align(skb);
+                       dma_map_single(&ndev->dev, skb->data,
+                                      rxdesc->buffer_length, DMA_FROM_DEVICE);
  
                        skb_checksum_none_assert(skb);
 -                      rxdesc->addr = virt_to_phys(PTR_ALIGN(skb->data, 4));
 +                      rxdesc->addr = virt_to_phys(skb->data);
                }
                if (entry >= mdp->num_rx_ring - 1)
                        rxdesc->status |=
                sh_eth_write(ndev, EDRRR_R, EDRRR);
        }
  
 +      *quota -= limit - boguscnt - 1;
 +
        return *quota <= 0;
  }
  
@@@ -2043,6 -2036,8 +2037,8 @@@ static int sh_eth_open(struct net_devic
        if (ret)
                goto out_free_irq;
  
+       mdp->is_opened = 1;
        return ret;
  
  out_free_irq:
@@@ -2132,6 -2127,36 +2128,36 @@@ static int sh_eth_start_xmit(struct sk_
        return NETDEV_TX_OK;
  }
  
+ static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
+ {
+       struct sh_eth_private *mdp = netdev_priv(ndev);
+       if (sh_eth_is_rz_fast_ether(mdp))
+               return &ndev->stats;
+       if (!mdp->is_opened)
+               return &ndev->stats;
+       ndev->stats.tx_dropped += sh_eth_read(ndev, TROCR);
+       sh_eth_write(ndev, 0, TROCR);   /* (write clear) */
+       ndev->stats.collisions += sh_eth_read(ndev, CDCR);
+       sh_eth_write(ndev, 0, CDCR);    /* (write clear) */
+       ndev->stats.tx_carrier_errors += sh_eth_read(ndev, LCCR);
+       sh_eth_write(ndev, 0, LCCR);    /* (write clear) */
+       if (sh_eth_is_gether(mdp)) {
+               ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CERCR);
+               sh_eth_write(ndev, 0, CERCR);   /* (write clear) */
+               ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CEECR);
+               sh_eth_write(ndev, 0, CEECR);   /* (write clear) */
+       } else {
+               ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CNDCR);
+               sh_eth_write(ndev, 0, CNDCR);   /* (write clear) */
+       }
+       return &ndev->stats;
+ }
  /* device close function */
  static int sh_eth_close(struct net_device *ndev)
  {
        sh_eth_write(ndev, 0, EDTRR);
        sh_eth_write(ndev, 0, EDRRR);
  
+       sh_eth_get_stats(ndev);
        /* PHY Disconnect */
        if (mdp->phydev) {
                phy_stop(mdp->phydev);
  
        pm_runtime_put_sync(&mdp->pdev->dev);
  
-       return 0;
- }
- static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
- {
-       struct sh_eth_private *mdp = netdev_priv(ndev);
-       if (sh_eth_is_rz_fast_ether(mdp))
-               return &ndev->stats;
-       pm_runtime_get_sync(&mdp->pdev->dev);
-       ndev->stats.tx_dropped += sh_eth_read(ndev, TROCR);
-       sh_eth_write(ndev, 0, TROCR);   /* (write clear) */
-       ndev->stats.collisions += sh_eth_read(ndev, CDCR);
-       sh_eth_write(ndev, 0, CDCR);    /* (write clear) */
-       ndev->stats.tx_carrier_errors += sh_eth_read(ndev, LCCR);
-       sh_eth_write(ndev, 0, LCCR);    /* (write clear) */
-       if (sh_eth_is_gether(mdp)) {
-               ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CERCR);
-               sh_eth_write(ndev, 0, CERCR);   /* (write clear) */
-               ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CEECR);
-               sh_eth_write(ndev, 0, CEECR);   /* (write clear) */
-       } else {
-               ndev->stats.tx_carrier_errors += sh_eth_read(ndev, CNDCR);
-               sh_eth_write(ndev, 0, CNDCR);   /* (write clear) */
-       }
-       pm_runtime_put_sync(&mdp->pdev->dev);
+       mdp->is_opened = 0;
  
-       return &ndev->stats;
+       return 0;
  }
  
  /* ioctl to device function */
@@@ -2747,7 -2746,6 +2747,7 @@@ static const struct of_device_id sh_eth
        { .compatible = "renesas,ether-r8a7779", .data = &r8a777x_data },
        { .compatible = "renesas,ether-r8a7790", .data = &r8a779x_data },
        { .compatible = "renesas,ether-r8a7791", .data = &r8a779x_data },
 +      { .compatible = "renesas,ether-r8a7793", .data = &r8a779x_data },
        { .compatible = "renesas,ether-r8a7794", .data = &r8a779x_data },
        { .compatible = "renesas,ether-r7s72100", .data = &r7s72100_data },
        { }
@@@ -2771,6 -2769,10 +2771,6 @@@ static int sh_eth_drv_probe(struct plat
  
        /* get base addr */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 -      if (unlikely(res == NULL)) {
 -              dev_err(&pdev->dev, "invalid resource\n");
 -              return -EINVAL;
 -      }
  
        ndev = alloc_etherdev(sizeof(struct sh_eth_private));
        if (!ndev)
        pm_runtime_enable(&pdev->dev);
        pm_runtime_get_sync(&pdev->dev);
  
 -      /* The sh Ether-specific entries in the device structure. */
 -      ndev->base_addr = res->start;
        devno = pdev->id;
        if (devno < 0)
                devno = 0;
                goto out_release;
        }
  
 +      ndev->base_addr = res->start;
 +
        spin_lock_init(&mdp->lock);
        mdp->pdev = pdev;
  
                }
        }
  
 +      if (mdp->cd->rmiimode)
 +              sh_eth_write(ndev, 0x1, RMIIMODE);
 +
        /* MDIO bus init */
        ret = sh_mdio_init(mdp, pd);
        if (ret) {
@@@ -2974,7 -2973,6 +2974,7 @@@ static struct platform_device_id sh_eth
        { "r8a777x-ether", (kernel_ulong_t)&r8a777x_data },
        { "r8a7790-ether", (kernel_ulong_t)&r8a779x_data },
        { "r8a7791-ether", (kernel_ulong_t)&r8a779x_data },
 +      { "r8a7793-ether", (kernel_ulong_t)&r8a779x_data },
        { "r8a7794-ether", (kernel_ulong_t)&r8a779x_data },
        { }
  };
  #include <linux/of.h>
  #include <linux/of_net.h>
  #include <linux/of_device.h>
 +
  #include "stmmac.h"
 +#include "stmmac_platform.h"
  
  static const struct of_device_id stmmac_dt_ids[] = {
 -#ifdef CONFIG_DWMAC_MESON
 +      /* SoC specific glue layers should come before generic bindings */
        { .compatible = "amlogic,meson6-dwmac", .data = &meson6_dwmac_data},
 -#endif
 -#ifdef CONFIG_DWMAC_SUNXI
        { .compatible = "allwinner,sun7i-a20-gmac", .data = &sun7i_gmac_data},
 -#endif
 -#ifdef CONFIG_DWMAC_STI
        { .compatible = "st,stih415-dwmac", .data = &stih4xx_dwmac_data},
        { .compatible = "st,stih416-dwmac", .data = &stih4xx_dwmac_data},
        { .compatible = "st,stid127-dwmac", .data = &stid127_dwmac_data},
        { .compatible = "st,stih407-dwmac", .data = &stih4xx_dwmac_data},
 -#endif
 -#ifdef CONFIG_DWMAC_SOCFPGA
        { .compatible = "altr,socfpga-stmmac", .data = &socfpga_gmac_data },
 -#endif
 -      /* SoC specific glue layers should come before generic bindings */
        { .compatible = "st,spear600-gmac"},
        { .compatible = "snps,dwmac-3.610"},
        { .compatible = "snps,dwmac-3.70a"},
@@@ -51,11 -57,7 +51,11 @@@ MODULE_DEVICE_TABLE(of, stmmac_dt_ids)
  
  #ifdef CONFIG_OF
  
 -/* This function validates the number of Multicast filtering bins specified
 +/**
 + * dwmac1000_validate_mcast_bins - validates the number of Multicast filter bins
 + * @mcast_bins: Multicast filtering bins
 + * Description:
 + * this function validates the number of Multicast filtering bins specified
   * by the configuration through the device tree. The Synopsys GMAC supports
   * 64 bins, 128 bins, or 256 bins. "bins" refer to the division of CRC
   * number space. 64 bins correspond to 6 bits of the CRC, 128 corresponds
@@@ -81,11 -83,7 +81,11 @@@ static int dwmac1000_validate_mcast_bin
        return x;
  }
  
 -/* This function validates the number of Unicast address entries supported
 +/**
 + * dwmac1000_validate_ucast_entries - validate the Unicast address entries
 + * @ucast_entries: number of Unicast address entries
 + * Description:
 + * This function validates the number of Unicast address entries supported
   * by a particular Synopsys 10/100/1000 controller. The Synopsys controller
   * supports 1, 32, 64, or 128 Unicast filter entries for it's Unicast filter
   * logic. This function validates a valid, supported configuration is
@@@ -111,15 -109,6 +111,15 @@@ static int dwmac1000_validate_ucast_ent
        return x;
  }
  
 +/**
 + * stmmac_probe_config_dt - parse device-tree driver parameters
 + * @pdev: platform_device structure
 + * @plat: driver data platform structure
 + * @mac: MAC address to use
 + * Description:
 + * this function is to read the driver parameters from device-tree and
 + * set some private fields that will be used by the main at runtime.
 + */
  static int stmmac_probe_config_dt(struct platform_device *pdev,
                                  struct plat_stmmacenet_data *plat,
                                  const char **mac)
@@@ -253,11 -242,11 +253,11 @@@ static int stmmac_probe_config_dt(struc
  #endif /* CONFIG_OF */
  
  /**
 - * stmmac_pltfr_probe
 + * stmmac_pltfr_probe - platform driver probe.
   * @pdev: platform device pointer
 - * Description: platform_device probe function. It allocates
 - * the necessary resources and invokes the main to init
 - * the net device, register the mdio bus etc.
 + * Description: platform_device probe function. It is to allocate
 + * the necessary platform resources, invoke custom helper (if required) and
 + * invoke the main probe function.
   */
  static int stmmac_pltfr_probe(struct platform_device *pdev)
  {
  
        plat_dat = dev_get_platdata(&pdev->dev);
  
+       if (!plat_dat)
+               plat_dat = devm_kzalloc(&pdev->dev,
+                                       sizeof(struct plat_stmmacenet_data),
+                                       GFP_KERNEL);
+       if (!plat_dat) {
+               pr_err("%s: ERROR: no memory", __func__);
+               return  -ENOMEM;
+       }
        /* Set default value for multicast hash bins */
        plat_dat->multicast_filter_bins = HASH_TABLE_SIZE;
  
        plat_dat->unicast_filter_entries = 1;
  
        if (pdev->dev.of_node) {
-               if (!plat_dat)
-                       plat_dat = devm_kzalloc(&pdev->dev,
-                                       sizeof(struct plat_stmmacenet_data),
-                                       GFP_KERNEL);
-               if (!plat_dat) {
-                       pr_err("%s: ERROR: no memory", __func__);
-                       return  -ENOMEM;
-               }
                ret = stmmac_probe_config_dt(pdev, plat_dat, &mac);
                if (ret) {
                        pr_err("%s: main dt probe failed", __func__);
@@@ -380,14 -369,7 +380,14 @@@ static int stmmac_pltfr_remove(struct p
        return ret;
  }
  
 -#ifdef CONFIG_PM
 +#ifdef CONFIG_PM_SLEEP
 +/**
 + * stmmac_pltfr_suspend
 + * @dev: device pointer
 + * Description: this function is invoked when suspend the driver and it direcly
 + * call the main suspend function and then, if required, on some platform, it
 + * can call an exit helper.
 + */
  static int stmmac_pltfr_suspend(struct device *dev)
  {
        int ret;
        return ret;
  }
  
 +/**
 + * stmmac_pltfr_resume
 + * @dev: device pointer
 + * Description: this function is invoked when resume the driver before calling
 + * the main resume function, on some platforms, it can call own init helper
 + * if required.
 + */
  static int stmmac_pltfr_resume(struct device *dev)
  {
        struct net_device *ndev = dev_get_drvdata(dev);
  
        return stmmac_resume(ndev);
  }
 -
 -#endif /* CONFIG_PM */
 +#endif /* CONFIG_PM_SLEEP */
  
  static SIMPLE_DEV_PM_OPS(stmmac_pltfr_pm_ops,
 -                      stmmac_pltfr_suspend, stmmac_pltfr_resume);
 +                       stmmac_pltfr_suspend, stmmac_pltfr_resume);
  
 -struct platform_driver stmmac_pltfr_driver = {
 +static struct platform_driver stmmac_pltfr_driver = {
        .probe = stmmac_pltfr_probe,
        .remove = stmmac_pltfr_remove,
        .driver = {
                   .owner = THIS_MODULE,
                   .pm = &stmmac_pltfr_pm_ops,
                   .of_match_table = of_match_ptr(stmmac_dt_ids),
 -                 },
 +      },
  };
  
 +module_platform_driver(stmmac_pltfr_driver);
 +
  MODULE_DESCRIPTION("STMMAC 10/100/1000 Ethernet PLATFORM driver");
  MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>");
  MODULE_LICENSE("GPL");
@@@ -77,9 -77,7 +77,9 @@@ struct netfront_cb 
  
  #define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE)
  #define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
 -#define TX_MAX_TARGET min_t(int, NET_TX_RING_SIZE, 256)
 +
 +/* Minimum number of Rx slots (includes slot for GSO metadata). */
 +#define NET_RX_SLOTS_MIN (XEN_NETIF_NR_SLOTS_MIN + 1)
  
  /* Queue name is interface name with "-qNNN" appended */
  #define QUEUE_NAME_SIZE (IFNAMSIZ + 6)
@@@ -139,6 -137,13 +139,6 @@@ struct netfront_queue 
        struct xen_netif_rx_front_ring rx;
        int rx_ring_ref;
  
 -      /* Receive-ring batched refills. */
 -#define RX_MIN_TARGET 8
 -#define RX_DFL_MIN_TARGET 64
 -#define RX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256)
 -      unsigned rx_min_target, rx_max_target, rx_target;
 -      struct sk_buff_head rx_batch;
 -
        struct timer_list rx_refill_timer;
  
        struct sk_buff *rx_skbs[NET_RX_RING_SIZE];
@@@ -246,7 -251,7 +246,7 @@@ static void rx_refill_timeout(unsigned 
  static int netfront_tx_slot_available(struct netfront_queue *queue)
  {
        return (queue->tx.req_prod_pvt - queue->tx.rsp_cons) <
 -              (TX_MAX_TARGET - MAX_SKB_FRAGS - 2);
 +              (NET_TX_RING_SIZE - MAX_SKB_FRAGS - 2);
  }
  
  static void xennet_maybe_wake_tx(struct netfront_queue *queue)
                netif_tx_wake_queue(netdev_get_tx_queue(dev, queue->id));
  }
  
 -static void xennet_alloc_rx_buffers(struct netfront_queue *queue)
 +
 +static struct sk_buff *xennet_alloc_one_rx_buffer(struct netfront_queue *queue)
  {
 -      unsigned short id;
        struct sk_buff *skb;
        struct page *page;
 -      int i, batch_target, notify;
 -      RING_IDX req_prod = queue->rx.req_prod_pvt;
 -      grant_ref_t ref;
 -      unsigned long pfn;
 -      void *vaddr;
 -      struct xen_netif_rx_request *req;
 -
 -      if (unlikely(!netif_carrier_ok(queue->info->netdev)))
 -              return;
  
 -      /*
 -       * Allocate skbuffs greedily, even though we batch updates to the
 -       * receive ring. This creates a less bursty demand on the memory
 -       * allocator, so should reduce the chance of failed allocation requests
 -       * both for ourself and for other kernel subsystems.
 -       */
 -      batch_target = queue->rx_target - (req_prod - queue->rx.rsp_cons);
 -      for (i = skb_queue_len(&queue->rx_batch); i < batch_target; i++) {
 -              skb = __netdev_alloc_skb(queue->info->netdev,
 -                                       RX_COPY_THRESHOLD + NET_IP_ALIGN,
 -                                       GFP_ATOMIC | __GFP_NOWARN);
 -              if (unlikely(!skb))
 -                      goto no_skb;
 -
 -              /* Align ip header to a 16 bytes boundary */
 -              skb_reserve(skb, NET_IP_ALIGN);
 -
 -              page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
 -              if (!page) {
 -                      kfree_skb(skb);
 -no_skb:
 -                      /* Could not allocate any skbuffs. Try again later. */
 -                      mod_timer(&queue->rx_refill_timer,
 -                                jiffies + (HZ/10));
 -
 -                      /* Any skbuffs queued for refill? Force them out. */
 -                      if (i != 0)
 -                              goto refill;
 -                      break;
 -              }
 +      skb = __netdev_alloc_skb(queue->info->netdev,
 +                               RX_COPY_THRESHOLD + NET_IP_ALIGN,
 +                               GFP_ATOMIC | __GFP_NOWARN);
 +      if (unlikely(!skb))
 +              return NULL;
  
 -              skb_add_rx_frag(skb, 0, page, 0, 0, PAGE_SIZE);
 -              __skb_queue_tail(&queue->rx_batch, skb);
 +      page = alloc_page(GFP_ATOMIC | __GFP_NOWARN);
 +      if (!page) {
 +              kfree_skb(skb);
 +              return NULL;
        }
 +      skb_add_rx_frag(skb, 0, page, 0, 0, PAGE_SIZE);
 +
 +      /* Align ip header to a 16 bytes boundary */
 +      skb_reserve(skb, NET_IP_ALIGN);
 +      skb->dev = queue->info->netdev;
 +
 +      return skb;
 +}
  
 -      /* Is the batch large enough to be worthwhile? */
 -      if (i < (queue->rx_target/2)) {
 -              if (req_prod > queue->rx.sring->req_prod)
 -                      goto push;
 +
 +static void xennet_alloc_rx_buffers(struct netfront_queue *queue)
 +{
 +      RING_IDX req_prod = queue->rx.req_prod_pvt;
 +      int notify;
 +
 +      if (unlikely(!netif_carrier_ok(queue->info->netdev)))
                return;
 -      }
  
 -      /* Adjust our fill target if we risked running out of buffers. */
 -      if (((req_prod - queue->rx.sring->rsp_prod) < (queue->rx_target / 4)) &&
 -          ((queue->rx_target *= 2) > queue->rx_max_target))
 -              queue->rx_target = queue->rx_max_target;
 +      for (req_prod = queue->rx.req_prod_pvt;
 +           req_prod - queue->rx.rsp_cons < NET_RX_RING_SIZE;
 +           req_prod++) {
 +              struct sk_buff *skb;
 +              unsigned short id;
 +              grant_ref_t ref;
 +              unsigned long pfn;
 +              struct xen_netif_rx_request *req;
  
 - refill:
 -      for (i = 0; ; i++) {
 -              skb = __skb_dequeue(&queue->rx_batch);
 -              if (skb == NULL)
 +              skb = xennet_alloc_one_rx_buffer(queue);
 +              if (!skb)
                        break;
  
 -              skb->dev = queue->info->netdev;
 -
 -              id = xennet_rxidx(req_prod + i);
 +              id = xennet_rxidx(req_prod);
  
                BUG_ON(queue->rx_skbs[id]);
                queue->rx_skbs[id] = skb;
                queue->grant_rx_ref[id] = ref;
  
                pfn = page_to_pfn(skb_frag_page(&skb_shinfo(skb)->frags[0]));
 -              vaddr = page_address(skb_frag_page(&skb_shinfo(skb)->frags[0]));
  
 -              req = RING_GET_REQUEST(&queue->rx, req_prod + i);
 +              req = RING_GET_REQUEST(&queue->rx, req_prod);
                gnttab_grant_foreign_access_ref(ref,
                                                queue->info->xbdev->otherend_id,
                                                pfn_to_mfn(pfn),
                req->gref = ref;
        }
  
 +      queue->rx.req_prod_pvt = req_prod;
 +
 +      /* Not enough requests? Try again later. */
 +      if (req_prod - queue->rx.rsp_cons < NET_RX_SLOTS_MIN) {
 +              mod_timer(&queue->rx_refill_timer, jiffies + (HZ/10));
 +              return;
 +      }
 +
        wmb();          /* barrier so backend seens requests */
  
 -      /* Above is a suitable barrier to ensure backend will see requests. */
 -      queue->rx.req_prod_pvt = req_prod + i;
 - push:
        RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&queue->rx, notify);
        if (notify)
                notify_remote_via_irq(queue->rx_irq);
@@@ -473,9 -496,6 +473,6 @@@ static void xennet_make_frags(struct sk
                len = skb_frag_size(frag);
                offset = frag->page_offset;
  
-               /* Data must not cross a page boundary. */
-               BUG_ON(len + offset > PAGE_SIZE<<compound_order(page));
                /* Skip unused frames from start of page */
                page += offset >> PAGE_SHIFT;
                offset &= ~PAGE_MASK;
                while (len > 0) {
                        unsigned long bytes;
  
-                       BUG_ON(offset >= PAGE_SIZE);
                        bytes = PAGE_SIZE - offset;
                        if (bytes > len)
                                bytes = len;
@@@ -609,6 -627,9 +604,9 @@@ static int xennet_start_xmit(struct sk_
                                    slots, skb->len);
                if (skb_linearize(skb))
                        goto drop;
+               data = skb->data;
+               offset = offset_in_page(data);
+               len = skb_headlen(skb);
        }
  
        spin_lock_irqsave(&queue->tx_lock, flags);
@@@ -1047,6 -1068,13 +1045,6 @@@ err
  
        work_done -= handle_incoming_queue(queue, &rxq);
  
 -      /* If we get a callback with very few responses, reduce fill target. */
 -      /* NB. Note exponential increase, linear decrease. */
 -      if (((queue->rx.req_prod_pvt - queue->rx.sring->rsp_prod) >
 -           ((3*queue->rx_target) / 4)) &&
 -          (--queue->rx_target < queue->rx_min_target))
 -              queue->rx_target = queue->rx_min_target;
 -
        xennet_alloc_rx_buffers(queue);
  
        if (work_done < budget) {
@@@ -1613,6 -1641,11 +1611,6 @@@ static int xennet_init_queue(struct net
        spin_lock_init(&queue->tx_lock);
        spin_lock_init(&queue->rx_lock);
  
 -      skb_queue_head_init(&queue->rx_batch);
 -      queue->rx_target     = RX_DFL_MIN_TARGET;
 -      queue->rx_min_target = RX_DFL_MIN_TARGET;
 -      queue->rx_max_target = RX_MAX_TARGET;
 -
        init_timer(&queue->rx_refill_timer);
        queue->rx_refill_timer.data = (unsigned long)queue;
        queue->rx_refill_timer.function = rx_refill_timeout;
        }
  
        /* A grant for every tx ring slot */
 -      if (gnttab_alloc_grant_references(TX_MAX_TARGET,
 +      if (gnttab_alloc_grant_references(NET_TX_RING_SIZE,
                                          &queue->gref_tx_head) < 0) {
                pr_alert("can't alloc tx grant refs\n");
                err = -ENOMEM;
        }
  
        /* A grant for every rx ring slot */
 -      if (gnttab_alloc_grant_references(RX_MAX_TARGET,
 +      if (gnttab_alloc_grant_references(NET_RX_RING_SIZE,
                                          &queue->gref_rx_head) < 0) {
                pr_alert("can't alloc rx grant refs\n");
                err = -ENOMEM;
@@@ -2111,18 -2144,30 +2109,18 @@@ static const struct ethtool_ops xennet_
  };
  
  #ifdef CONFIG_SYSFS
 -static ssize_t show_rxbuf_min(struct device *dev,
 -                            struct device_attribute *attr, char *buf)
 +static ssize_t show_rxbuf(struct device *dev,
 +                        struct device_attribute *attr, char *buf)
  {
 -      struct net_device *netdev = to_net_dev(dev);
 -      struct netfront_info *info = netdev_priv(netdev);
 -      unsigned int num_queues = netdev->real_num_tx_queues;
 -
 -      if (num_queues)
 -              return sprintf(buf, "%u\n", info->queues[0].rx_min_target);
 -      else
 -              return sprintf(buf, "%u\n", RX_MIN_TARGET);
 +      return sprintf(buf, "%lu\n", NET_RX_RING_SIZE);
  }
  
 -static ssize_t store_rxbuf_min(struct device *dev,
 -                             struct device_attribute *attr,
 -                             const char *buf, size_t len)
 +static ssize_t store_rxbuf(struct device *dev,
 +                         struct device_attribute *attr,
 +                         const char *buf, size_t len)
  {
 -      struct net_device *netdev = to_net_dev(dev);
 -      struct netfront_info *np = netdev_priv(netdev);
 -      unsigned int num_queues = netdev->real_num_tx_queues;
        char *endp;
        unsigned long target;
 -      unsigned int i;
 -      struct netfront_queue *queue;
  
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
        if (endp == buf)
                return -EBADMSG;
  
 -      if (target < RX_MIN_TARGET)
 -              target = RX_MIN_TARGET;
 -      if (target > RX_MAX_TARGET)
 -              target = RX_MAX_TARGET;
 +      /* rxbuf_min and rxbuf_max are no longer configurable. */
  
 -      for (i = 0; i < num_queues; ++i) {
 -              queue = &np->queues[i];
 -              spin_lock_bh(&queue->rx_lock);
 -              if (target > queue->rx_max_target)
 -                      queue->rx_max_target = target;
 -              queue->rx_min_target = target;
 -              if (target > queue->rx_target)
 -                      queue->rx_target = target;
 -
 -              xennet_alloc_rx_buffers(queue);
 -
 -              spin_unlock_bh(&queue->rx_lock);
 -      }
        return len;
  }
  
 -static ssize_t show_rxbuf_max(struct device *dev,
 -                            struct device_attribute *attr, char *buf)
 -{
 -      struct net_device *netdev = to_net_dev(dev);
 -      struct netfront_info *info = netdev_priv(netdev);
 -      unsigned int num_queues = netdev->real_num_tx_queues;
 -
 -      if (num_queues)
 -              return sprintf(buf, "%u\n", info->queues[0].rx_max_target);
 -      else
 -              return sprintf(buf, "%u\n", RX_MAX_TARGET);
 -}
 -
 -static ssize_t store_rxbuf_max(struct device *dev,
 -                             struct device_attribute *attr,
 -                             const char *buf, size_t len)
 -{
 -      struct net_device *netdev = to_net_dev(dev);
 -      struct netfront_info *np = netdev_priv(netdev);
 -      unsigned int num_queues = netdev->real_num_tx_queues;
 -      char *endp;
 -      unsigned long target;
 -      unsigned int i = 0;
 -      struct netfront_queue *queue = NULL;
 -
 -      if (!capable(CAP_NET_ADMIN))
 -              return -EPERM;
 -
 -      target = simple_strtoul(buf, &endp, 0);
 -      if (endp == buf)
 -              return -EBADMSG;
 -
 -      if (target < RX_MIN_TARGET)
 -              target = RX_MIN_TARGET;
 -      if (target > RX_MAX_TARGET)
 -              target = RX_MAX_TARGET;
 -
 -      for (i = 0; i < num_queues; ++i) {
 -              queue = &np->queues[i];
 -              spin_lock_bh(&queue->rx_lock);
 -              if (target < queue->rx_min_target)
 -                      queue->rx_min_target = target;
 -              queue->rx_max_target = target;
 -              if (target < queue->rx_target)
 -                      queue->rx_target = target;
 -
 -              xennet_alloc_rx_buffers(queue);
 -
 -              spin_unlock_bh(&queue->rx_lock);
 -      }
 -      return len;
 -}
 -
 -static ssize_t show_rxbuf_cur(struct device *dev,
 -                            struct device_attribute *attr, char *buf)
 -{
 -      struct net_device *netdev = to_net_dev(dev);
 -      struct netfront_info *info = netdev_priv(netdev);
 -      unsigned int num_queues = netdev->real_num_tx_queues;
 -
 -      if (num_queues)
 -              return sprintf(buf, "%u\n", info->queues[0].rx_target);
 -      else
 -              return sprintf(buf, "0\n");
 -}
 -
  static struct device_attribute xennet_attrs[] = {
 -      __ATTR(rxbuf_min, S_IRUGO|S_IWUSR, show_rxbuf_min, store_rxbuf_min),
 -      __ATTR(rxbuf_max, S_IRUGO|S_IWUSR, show_rxbuf_max, store_rxbuf_max),
 -      __ATTR(rxbuf_cur, S_IRUGO, show_rxbuf_cur, NULL),
 +      __ATTR(rxbuf_min, S_IRUGO|S_IWUSR, show_rxbuf, store_rxbuf),
 +      __ATTR(rxbuf_max, S_IRUGO|S_IWUSR, show_rxbuf, store_rxbuf),
 +      __ATTR(rxbuf_cur, S_IRUGO, show_rxbuf, NULL),
  };
  
  static int xennet_sysfs_addif(struct net_device *netdev)
@@@ -37,27 -37,27 +37,27 @@@ header-y += aio_abi.
  header-y += apm_bios.h
  header-y += arcfb.h
  header-y += atalk.h
 -header-y += atm.h
 -header-y += atm_eni.h
 -header-y += atm_he.h
 -header-y += atm_idt77105.h
 -header-y += atm_nicstar.h
 -header-y += atm_tcp.h
 -header-y += atm_zatm.h
  header-y += atmapi.h
  header-y += atmarp.h
  header-y += atmbr2684.h
  header-y += atmclip.h
  header-y += atmdev.h
 +header-y += atm_eni.h
 +header-y += atm.h
 +header-y += atm_he.h
 +header-y += atm_idt77105.h
  header-y += atmioc.h
  header-y += atmlec.h
  header-y += atmmpc.h
 +header-y += atm_nicstar.h
  header-y += atmppp.h
  header-y += atmsap.h
  header-y += atmsvc.h
 +header-y += atm_tcp.h
 +header-y += atm_zatm.h
  header-y += audit.h
 -header-y += auto_fs.h
  header-y += auto_fs4.h
 +header-y += auto_fs.h
  header-y += auxvec.h
  header-y += ax25.h
  header-y += b1lli.h
@@@ -67,8 -67,8 +67,8 @@@ header-y += bfs_fs.
  header-y += binfmts.h
  header-y += blkpg.h
  header-y += blktrace_api.h
 -header-y += bpf.h
  header-y += bpf_common.h
 +header-y += bpf.h
  header-y += bpqether.h
  header-y += bsg.h
  header-y += btrfs.h
@@@ -93,21 -93,21 +93,21 @@@ header-y += cyclades.
  header-y += cycx_cfm.h
  header-y += dcbnl.h
  header-y += dccp.h
 -header-y += dlm.h
 +header-y += dlmconstants.h
  header-y += dlm_device.h
 +header-y += dlm.h
  header-y += dlm_netlink.h
  header-y += dlm_plock.h
 -header-y += dlmconstants.h
  header-y += dm-ioctl.h
  header-y += dm-log-userspace.h
  header-y += dn.h
  header-y += dqblk_xfs.h
  header-y += edd.h
  header-y += efs_fs_sb.h
 +header-y += elfcore.h
  header-y += elf-em.h
  header-y += elf-fdpic.h
  header-y += elf.h
 -header-y += elfcore.h
  header-y += errno.h
  header-y += errqueue.h
  header-y += ethtool.h
@@@ -131,15 -131,15 +131,15 @@@ header-y += fsl_hypervisor.
  header-y += fuse.h
  header-y += futex.h
  header-y += gameport.h
 -header-y += gen_stats.h
  header-y += genetlink.h
 +header-y += gen_stats.h
  header-y += gfs2_ondisk.h
  header-y += gigaset_dev.h
 -header-y += hdlc.h
  header-y += hdlcdrv.h
 +header-y += hdlc.h
  header-y += hdreg.h
 -header-y += hid.h
  header-y += hiddev.h
 +header-y += hid.h
  header-y += hidraw.h
  header-y += hpet.h
  header-y += hsr_netlink.h
@@@ -151,6 -151,7 +151,6 @@@ header-y += i2o-dev.
  header-y += i8k.h
  header-y += icmp.h
  header-y += icmpv6.h
 -header-y += if.h
  header-y += if_addr.h
  header-y += if_addrlabel.h
  header-y += if_alg.h
@@@ -164,7 -165,6 +164,7 @@@ header-y += if_ether.
  header-y += if_fc.h
  header-y += if_fddi.h
  header-y += if_frad.h
 +header-y += if.h
  header-y += if_hippi.h
  header-y += if_infiniband.h
  header-y += if_link.h
@@@ -182,40 -182,40 +182,40 @@@ header-y += if_tunnel.
  header-y += if_vlan.h
  header-y += if_x25.h
  header-y += igmp.h
 -header-y += in.h
  header-y += in6.h
 -header-y += in_route.h
  header-y += inet_diag.h
 +header-y += in.h
  header-y += inotify.h
  header-y += input.h
 +header-y += in_route.h
  header-y += ioctl.h
 -header-y += ip.h
  header-y += ip6_tunnel.h
 -header-y += ip_vs.h
  header-y += ipc.h
 +header-y += ip.h
  header-y += ipmi.h
  header-y += ipmi_msgdefs.h
  header-y += ipsec.h
  header-y += ipv6.h
  header-y += ipv6_route.h
 +header-y += ip_vs.h
  header-y += ipx.h
  header-y += irda.h
  header-y += irqnr.h
 -header-y += isdn.h
  header-y += isdn_divertif.h
 -header-y += isdn_ppp.h
 +header-y += isdn.h
  header-y += isdnif.h
 +header-y += isdn_ppp.h
  header-y += iso_fs.h
 -header-y += ivtv.h
  header-y += ivtvfb.h
 +header-y += ivtv.h
  header-y += ixjuser.h
  header-y += jffs2.h
  header-y += joystick.h
 -header-y += kd.h
  header-y += kdev_t.h
 -header-y += kernel-page-flags.h
 -header-y += kernel.h
 +header-y += kd.h
  header-y += kernelcapi.h
 +header-y += kernel.h
 +header-y += kernel-page-flags.h
  header-y += kexec.h
  header-y += keyboard.h
  header-y += keyctl.h
@@@ -231,7 -231,6 +231,7 @@@ ifneq ($(wildcard $(srctree)/arch/$(SRC
  header-y += kvm_para.h
  endif
  
 +header-y += hw_breakpoint.h
  header-y += l2tp.h
  header-y += libc-compat.h
  header-y += limits.h
@@@ -256,43 -255,43 +256,43 @@@ header-y += mman.
  header-y += mmtimer.h
  header-y += mpls.h
  header-y += mqueue.h
 -header-y += mroute.h
  header-y += mroute6.h
 +header-y += mroute.h
  header-y += msdos_fs.h
  header-y += msg.h
  header-y += mtio.h
 -header-y += n_r3964.h
  header-y += nbd.h
 -header-y += ncp.h
  header-y += ncp_fs.h
 +header-y += ncp.h
  header-y += ncp_mount.h
  header-y += ncp_no.h
  header-y += neighbour.h
 -header-y += net.h
 -header-y += net_dropmon.h
 -header-y += net_tstamp.h
  header-y += netconf.h
  header-y += netdevice.h
 -header-y += netlink_diag.h
 -header-y += netfilter.h
 +header-y += net_dropmon.h
  header-y += netfilter_arp.h
  header-y += netfilter_bridge.h
  header-y += netfilter_decnet.h
 +header-y += netfilter.h
  header-y += netfilter_ipv4.h
  header-y += netfilter_ipv6.h
 +header-y += net.h
 +header-y += netlink_diag.h
  header-y += netlink.h
  header-y += netrom.h
 +header-y += net_tstamp.h
  header-y += nfc.h
 -header-y += nfs.h
  header-y += nfs2.h
  header-y += nfs3.h
  header-y += nfs4.h
  header-y += nfs4_mount.h
 +header-y += nfsacl.h
  header-y += nfs_fs.h
 +header-y += nfs.h
  header-y += nfs_idmap.h
  header-y += nfs_mount.h
 -header-y += nfsacl.h
  header-y += nl80211.h
 +header-y += n_r3964.h
  header-y += nubus.h
  header-y += nvme.h
  header-y += nvram.h
@@@ -312,16 -311,16 +312,16 @@@ header-y += pfkeyv2.
  header-y += pg.h
  header-y += phantom.h
  header-y += phonet.h
 +header-y += pktcdvd.h
  header-y += pkt_cls.h
  header-y += pkt_sched.h
 -header-y += pktcdvd.h
  header-y += pmu.h
  header-y += poll.h
  header-y += posix_types.h
  header-y += ppdev.h
  header-y += ppp-comp.h
 -header-y += ppp-ioctl.h
  header-y += ppp_defs.h
 +header-y += ppp-ioctl.h
  header-y += pps.h
  header-y += prctl.h
  header-y += psci.h
@@@ -353,13 -352,13 +353,13 @@@ header-y += seccomp.
  header-y += securebits.h
  header-y += selinux_netlink.h
  header-y += sem.h
 -header-y += serial.h
  header-y += serial_core.h
 +header-y += serial.h
  header-y += serial_reg.h
  header-y += serio.h
  header-y += shm.h
 -header-y += signal.h
  header-y += signalfd.h
 +header-y += signal.h
  header-y += smiapp.h
  header-y += snmp.h
  header-y += sock_diag.h
@@@ -368,8 -367,8 +368,8 @@@ header-y += sockios.
  header-y += som.h
  header-y += sonet.h
  header-y += sonypi.h
 -header-y += sound.h
  header-y += soundcard.h
 +header-y += sound.h
  header-y += stat.h
  header-y += stddef.h
  header-y += string.h
@@@ -388,12 -387,11 +388,12 @@@ header-y += time.
  header-y += times.h
  header-y += timex.h
  header-y += tiocl.h
 -header-y += tipc.h
  header-y += tipc_config.h
 +header-y += tipc_netlink.h
 +header-y += tipc.h
  header-y += toshiba.h
 -header-y += tty.h
  header-y += tty_flags.h
 +header-y += tty.h
  header-y += types.h
  header-y += udf_fs_i.h
  header-y += udp.h
@@@ -429,7 -427,7 +429,7 @@@ header-y += virtio_net.
  header-y += virtio_pci.h
  header-y += virtio_ring.h
  header-y += virtio_rng.h
- header=y += vm_sockets.h
+ header-y += vm_sockets.h
  header-y += vt.h
  header-y += wait.h
  header-y += wanrouter.h
@@@ -439,5 -437,6 +439,5 @@@ header-y += wireless.
  header-y += x25.h
  header-y += xattr.h
  header-y += xfrm.h
 -header-y += hw_breakpoint.h
  header-y += zorro.h
  header-y += zorro_ids.h
diff --combined net/core/rtnetlink.c
@@@ -36,7 -36,6 +36,7 @@@
  #include <linux/mutex.h>
  #include <linux/if_addr.h>
  #include <linux/if_bridge.h>
 +#include <linux/if_vlan.h>
  #include <linux/pci.h>
  #include <linux/etherdevice.h>
  
@@@ -44,7 -43,6 +44,7 @@@
  
  #include <linux/inet.h>
  #include <linux/netdevice.h>
 +#include <net/switchdev.h>
  #include <net/ip.h>
  #include <net/protocol.h>
  #include <net/arp.h>
@@@ -870,8 -868,7 +870,8 @@@ static noinline size_t if_nlmsg_size(co
               + rtnl_port_size(dev, ext_filter_mask) /* IFLA_VF_PORTS + IFLA_PORT_SELF */
               + rtnl_link_get_size(dev) /* IFLA_LINKINFO */
               + rtnl_link_get_af_size(dev) /* IFLA_AF_SPEC */
 -             + nla_total_size(MAX_PHYS_PORT_ID_LEN); /* IFLA_PHYS_PORT_ID */
 +             + nla_total_size(MAX_PHYS_ITEM_ID_LEN) /* IFLA_PHYS_PORT_ID */
 +             + nla_total_size(MAX_PHYS_ITEM_ID_LEN); /* IFLA_PHYS_SWITCH_ID */
  }
  
  static int rtnl_vf_ports_fill(struct sk_buff *skb, struct net_device *dev)
@@@ -955,7 -952,7 +955,7 @@@ static int rtnl_port_fill(struct sk_buf
  static int rtnl_phys_port_id_fill(struct sk_buff *skb, struct net_device *dev)
  {
        int err;
 -      struct netdev_phys_port_id ppid;
 +      struct netdev_phys_item_id ppid;
  
        err = dev_get_phys_port_id(dev, &ppid);
        if (err) {
        return 0;
  }
  
 +static int rtnl_phys_switch_id_fill(struct sk_buff *skb, struct net_device *dev)
 +{
 +      int err;
 +      struct netdev_phys_item_id psid;
 +
 +      err = netdev_switch_parent_id_get(dev, &psid);
 +      if (err) {
 +              if (err == -EOPNOTSUPP)
 +                      return 0;
 +              return err;
 +      }
 +
 +      if (nla_put(skb, IFLA_PHYS_SWITCH_ID, psid.id_len, psid.id))
 +              return -EMSGSIZE;
 +
 +      return 0;
 +}
 +
  static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                            int type, u32 pid, u32 seq, u32 change,
                            unsigned int flags, u32 ext_filter_mask)
        if (rtnl_phys_port_id_fill(skb, dev))
                goto nla_put_failure;
  
 +      if (rtnl_phys_switch_id_fill(skb, dev))
 +              goto nla_put_failure;
 +
        attr = nla_reserve(skb, IFLA_STATS,
                        sizeof(struct rtnl_link_stats));
        if (attr == NULL)
@@@ -1220,9 -1196,8 +1220,9 @@@ static const struct nla_policy ifla_pol
        [IFLA_PROMISCUITY]      = { .type = NLA_U32 },
        [IFLA_NUM_TX_QUEUES]    = { .type = NLA_U32 },
        [IFLA_NUM_RX_QUEUES]    = { .type = NLA_U32 },
 -      [IFLA_PHYS_PORT_ID]     = { .type = NLA_BINARY, .len = MAX_PHYS_PORT_ID_LEN },
 +      [IFLA_PHYS_PORT_ID]     = { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN },
        [IFLA_CARRIER_CHANGES]  = { .type = NLA_U32 },  /* ignored */
 +      [IFLA_PHYS_SWITCH_ID]   = { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN },
  };
  
  static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
@@@ -1523,6 -1498,7 +1523,7 @@@ static int do_setlink(const struct sk_b
                        goto errout;
                }
                if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN)) {
+                       put_net(net);
                        err = -EPERM;
                        goto errout;
                }
@@@ -2245,8 -2221,8 +2246,8 @@@ static int rtnl_dump_all(struct sk_buf
        return skb->len;
  }
  
 -void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change,
 -                gfp_t flags)
 +struct sk_buff *rtmsg_ifinfo_build_skb(int type, struct net_device *dev,
 +                                     unsigned int change, gfp_t flags)
  {
        struct net *net = dev_net(dev);
        struct sk_buff *skb;
                kfree_skb(skb);
                goto errout;
        }
 -      rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, flags);
 -      return;
 +      return skb;
  errout:
        if (err < 0)
                rtnl_set_sk_err(net, RTNLGRP_LINK, err);
 +      return NULL;
 +}
 +
 +void rtmsg_ifinfo_send(struct sk_buff *skb, struct net_device *dev, gfp_t flags)
 +{
 +      struct net *net = dev_net(dev);
 +
 +      rtnl_notify(skb, net, 0, RTNLGRP_LINK, NULL, flags);
 +}
 +
 +void rtmsg_ifinfo(int type, struct net_device *dev, unsigned int change,
 +                gfp_t flags)
 +{
 +      struct sk_buff *skb;
 +
 +      skb = rtmsg_ifinfo_build_skb(type, dev, change, flags);
 +      if (skb)
 +              rtmsg_ifinfo_send(skb, dev, flags);
  }
  EXPORT_SYMBOL(rtmsg_ifinfo);
  
@@@ -2354,7 -2313,7 +2355,7 @@@ errout
  int ndo_dflt_fdb_add(struct ndmsg *ndm,
                     struct nlattr *tb[],
                     struct net_device *dev,
 -                   const unsigned char *addr,
 +                   const unsigned char *addr, u16 vid,
                     u16 flags)
  {
        int err = -EINVAL;
  }
  EXPORT_SYMBOL(ndo_dflt_fdb_add);
  
 +static int fdb_vid_parse(struct nlattr *vlan_attr, u16 *p_vid)
 +{
 +      u16 vid = 0;
 +
 +      if (vlan_attr) {
 +              if (nla_len(vlan_attr) != sizeof(u16)) {
 +                      pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid vlan\n");
 +                      return -EINVAL;
 +              }
 +
 +              vid = nla_get_u16(vlan_attr);
 +
 +              if (!vid || vid >= VLAN_VID_MASK) {
 +                      pr_info("PF_BRIDGE: RTM_NEWNEIGH with invalid vlan id %d\n",
 +                              vid);
 +                      return -EINVAL;
 +              }
 +      }
 +      *p_vid = vid;
 +      return 0;
 +}
 +
  static int rtnl_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh)
  {
        struct net *net = sock_net(skb->sk);
        struct nlattr *tb[NDA_MAX+1];
        struct net_device *dev;
        u8 *addr;
 +      u16 vid;
        int err;
  
        err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL);
  
        addr = nla_data(tb[NDA_LLADDR]);
  
 +      err = fdb_vid_parse(tb[NDA_VLAN], &vid);
 +      if (err)
 +              return err;
 +
        err = -EOPNOTSUPP;
  
        /* Support fdb on master device the net/bridge default case */
                struct net_device *br_dev = netdev_master_upper_dev_get(dev);
                const struct net_device_ops *ops = br_dev->netdev_ops;
  
 -              err = ops->ndo_fdb_add(ndm, tb, dev, addr, nlh->nlmsg_flags);
 +              err = ops->ndo_fdb_add(ndm, tb, dev, addr, vid,
 +                                     nlh->nlmsg_flags);
                if (err)
                        goto out;
                else
        if ((ndm->ndm_flags & NTF_SELF)) {
                if (dev->netdev_ops->ndo_fdb_add)
                        err = dev->netdev_ops->ndo_fdb_add(ndm, tb, dev, addr,
 +                                                         vid,
                                                           nlh->nlmsg_flags);
                else
 -                      err = ndo_dflt_fdb_add(ndm, tb, dev, addr,
 +                      err = ndo_dflt_fdb_add(ndm, tb, dev, addr, vid,
                                               nlh->nlmsg_flags);
  
                if (!err) {
@@@ -2480,7 -2410,7 +2481,7 @@@ out
  int ndo_dflt_fdb_del(struct ndmsg *ndm,
                     struct nlattr *tb[],
                     struct net_device *dev,
 -                   const unsigned char *addr)
 +                   const unsigned char *addr, u16 vid)
  {
        int err = -EINVAL;
  
@@@ -2509,7 -2439,6 +2510,7 @@@ static int rtnl_fdb_del(struct sk_buff 
        struct net_device *dev;
        int err = -EINVAL;
        __u8 *addr;
 +      u16 vid;
  
        if (!netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
  
        addr = nla_data(tb[NDA_LLADDR]);
  
 +      err = fdb_vid_parse(tb[NDA_VLAN], &vid);
 +      if (err)
 +              return err;
 +
        err = -EOPNOTSUPP;
  
        /* Support fdb on master device the net/bridge default case */
                const struct net_device_ops *ops = br_dev->netdev_ops;
  
                if (ops->ndo_fdb_del)
 -                      err = ops->ndo_fdb_del(ndm, tb, dev, addr);
 +                      err = ops->ndo_fdb_del(ndm, tb, dev, addr, vid);
  
                if (err)
                        goto out;
        /* Embedded bridge, macvlan, and any other device support */
        if (ndm->ndm_flags & NTF_SELF) {
                if (dev->netdev_ops->ndo_fdb_del)
 -                      err = dev->netdev_ops->ndo_fdb_del(ndm, tb, dev, addr);
 +                      err = dev->netdev_ops->ndo_fdb_del(ndm, tb, dev, addr,
 +                                                         vid);
                else
 -                      err = ndo_dflt_fdb_del(ndm, tb, dev, addr);
 +                      err = ndo_dflt_fdb_del(ndm, tb, dev, addr, vid);
  
                if (!err) {
                        rtnl_fdb_notify(dev, addr, RTM_DELNEIGH);
@@@ -2704,22 -2628,12 +2705,22 @@@ static int rtnl_fdb_dump(struct sk_buf
        return skb->len;
  }
  
 +static int brport_nla_put_flag(struct sk_buff *skb, u32 flags, u32 mask,
 +                             unsigned int attrnum, unsigned int flag)
 +{
 +      if (mask & flag)
 +              return nla_put_u8(skb, attrnum, !!(flags & flag));
 +      return 0;
 +}
 +
  int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
 -                          struct net_device *dev, u16 mode)
 +                          struct net_device *dev, u16 mode,
 +                          u32 flags, u32 mask)
  {
        struct nlmsghdr *nlh;
        struct ifinfomsg *ifm;
        struct nlattr *br_afspec;
 +      struct nlattr *protinfo;
        u8 operstate = netif_running(dev) ? dev->operstate : IF_OPER_DOWN;
        struct net_device *br_dev = netdev_master_upper_dev_get(dev);
  
        if (!br_afspec)
                goto nla_put_failure;
  
 -      if (nla_put_u16(skb, IFLA_BRIDGE_FLAGS, BRIDGE_FLAGS_SELF) ||
 -          nla_put_u16(skb, IFLA_BRIDGE_MODE, mode)) {
 +      if (nla_put_u16(skb, IFLA_BRIDGE_FLAGS, BRIDGE_FLAGS_SELF)) {
                nla_nest_cancel(skb, br_afspec);
                goto nla_put_failure;
        }
 +
 +      if (mode != BRIDGE_MODE_UNDEF) {
 +              if (nla_put_u16(skb, IFLA_BRIDGE_MODE, mode)) {
 +                      nla_nest_cancel(skb, br_afspec);
 +                      goto nla_put_failure;
 +              }
 +      }
        nla_nest_end(skb, br_afspec);
  
 +      protinfo = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED);
 +      if (!protinfo)
 +              goto nla_put_failure;
 +
 +      if (brport_nla_put_flag(skb, flags, mask,
 +                              IFLA_BRPORT_MODE, BR_HAIRPIN_MODE) ||
 +          brport_nla_put_flag(skb, flags, mask,
 +                              IFLA_BRPORT_GUARD, BR_BPDU_GUARD) ||
 +          brport_nla_put_flag(skb, flags, mask,
 +                              IFLA_BRPORT_FAST_LEAVE,
 +                              BR_MULTICAST_FAST_LEAVE) ||
 +          brport_nla_put_flag(skb, flags, mask,
 +                              IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK) ||
 +          brport_nla_put_flag(skb, flags, mask,
 +                              IFLA_BRPORT_LEARNING, BR_LEARNING) ||
 +          brport_nla_put_flag(skb, flags, mask,
 +                              IFLA_BRPORT_LEARNING_SYNC, BR_LEARNING_SYNC) ||
 +          brport_nla_put_flag(skb, flags, mask,
 +                              IFLA_BRPORT_UNICAST_FLOOD, BR_FLOOD) ||
 +          brport_nla_put_flag(skb, flags, mask,
 +                              IFLA_BRPORT_PROXYARP, BR_PROXYARP)) {
 +              nla_nest_cancel(skb, protinfo);
 +              goto nla_put_failure;
 +      }
 +
 +      nla_nest_end(skb, protinfo);
 +
        return nlmsg_end(skb, nlh);
  nla_put_failure:
        nlmsg_cancel(skb, nlh);
diff --combined net/ipv4/tcp_ipv4.c
@@@ -623,6 -623,7 +623,7 @@@ static void tcp_v4_send_reset(struct so
        arg.iov[0].iov_base = (unsigned char *)&rep;
        arg.iov[0].iov_len  = sizeof(rep.th);
  
+       net = sk ? sock_net(sk) : dev_net(skb_dst(skb)->dev);
  #ifdef CONFIG_TCP_MD5SIG
        hash_location = tcp_parse_md5sig_option(th);
        if (!sk && hash_location) {
                 * Incoming packet is checked with md5 hash with finding key,
                 * no RST generated if md5 hash doesn't match.
                 */
-               sk1 = __inet_lookup_listener(dev_net(skb_dst(skb)->dev),
+               sk1 = __inet_lookup_listener(net,
                                             &tcp_hashinfo, ip_hdr(skb)->saddr,
                                             th->source, ip_hdr(skb)->daddr,
                                             ntohs(th->source), inet_iif(skb));
        if (sk)
                arg.bound_dev_if = sk->sk_bound_dev_if;
  
-       net = dev_net(skb_dst(skb)->dev);
        arg.tos = ip_hdr(skb)->tos;
        ip_send_unicast_reply(net, skb, &TCP_SKB_CB(skb)->header.h4.opt,
                              ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
@@@ -1432,7 -1432,6 +1432,7 @@@ int tcp_v4_do_rcv(struct sock *sk, stru
                struct dst_entry *dst = sk->sk_rx_dst;
  
                sock_rps_save_rxhash(sk, skb);
 +              sk_mark_napi_id(sk, skb);
                if (dst) {
                        if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif ||
                            dst->ops->check(dst, 0) == NULL) {
  
                if (nsk != sk) {
                        sock_rps_save_rxhash(nsk, skb);
 +                      sk_mark_napi_id(sk, skb);
                        if (tcp_child_process(sk, nsk, skb)) {
                                rsk = nsk;
                                goto reset;
@@@ -1666,7 -1664,7 +1666,7 @@@ process
        if (sk_filter(sk, skb))
                goto discard_and_relse;
  
 -      sk_mark_napi_id(sk, skb);
 +      sk_incoming_cpu_update(sk);
        skb->dev = NULL;
  
        bh_lock_sock_nested(sk);
diff --combined net/ipv6/tcp_ipv6.c
@@@ -787,16 -787,16 +787,16 @@@ static const struct tcp_request_sock_op
        .queue_hash_add =       inet6_csk_reqsk_queue_hash_add,
  };
  
- static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win,
-                                u32 tsval, u32 tsecr, int oif,
-                                struct tcp_md5sig_key *key, int rst, u8 tclass,
-                                u32 label)
+ static void tcp_v6_send_response(struct sock *sk, struct sk_buff *skb, u32 seq,
+                                u32 ack, u32 win, u32 tsval, u32 tsecr,
+                                int oif, struct tcp_md5sig_key *key, int rst,
+                                u8 tclass, u32 label)
  {
        const struct tcphdr *th = tcp_hdr(skb);
        struct tcphdr *t1;
        struct sk_buff *buff;
        struct flowi6 fl6;
-       struct net *net = dev_net(skb_dst(skb)->dev);
+       struct net *net = sk ? sock_net(sk) : dev_net(skb_dst(skb)->dev);
        struct sock *ctl_sk = net->ipv6.tcp_sk;
        unsigned int tot_len = sizeof(struct tcphdr);
        struct dst_entry *dst;
@@@ -946,7 -946,7 +946,7 @@@ static void tcp_v6_send_reset(struct so
                          (th->doff << 2);
  
        oif = sk ? sk->sk_bound_dev_if : 0;
-       tcp_v6_send_response(skb, seq, ack_seq, 0, 0, 0, oif, key, 1, 0, 0);
+       tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, oif, key, 1, 0, 0);
  
  #ifdef CONFIG_TCP_MD5SIG
  release_sk1:
  #endif
  }
  
- static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
-                           u32 win, u32 tsval, u32 tsecr, int oif,
+ static void tcp_v6_send_ack(struct sock *sk, struct sk_buff *skb, u32 seq,
+                           u32 ack, u32 win, u32 tsval, u32 tsecr, int oif,
                            struct tcp_md5sig_key *key, u8 tclass,
                            u32 label)
  {
-       tcp_v6_send_response(skb, seq, ack, win, tsval, tsecr, oif, key, 0, tclass,
-                            label);
+       tcp_v6_send_response(sk, skb, seq, ack, win, tsval, tsecr, oif, key, 0,
+                            tclass, label);
  }
  
  static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
        struct inet_timewait_sock *tw = inet_twsk(sk);
        struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
  
-       tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
+       tcp_v6_send_ack(sk, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
                        tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
                        tcp_time_stamp + tcptw->tw_ts_offset,
                        tcptw->tw_ts_recent, tw->tw_bound_dev_if, tcp_twsk_md5_key(tcptw),
@@@ -986,10 -986,10 +986,10 @@@ static void tcp_v6_reqsk_send_ack(struc
        /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV
         * sk->sk_state == TCP_SYN_RECV -> for Fast Open.
         */
-       tcp_v6_send_ack(skb, (sk->sk_state == TCP_LISTEN) ?
+       tcp_v6_send_ack(sk, skb, (sk->sk_state == TCP_LISTEN) ?
                        tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt,
-                       tcp_rsk(req)->rcv_nxt,
-                       req->rcv_wnd, tcp_time_stamp, req->ts_recent, sk->sk_bound_dev_if,
+                       tcp_rsk(req)->rcv_nxt, req->rcv_wnd,
+                       tcp_time_stamp, req->ts_recent, sk->sk_bound_dev_if,
                        tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr),
                        0, 0);
  }
@@@ -1296,7 -1296,6 +1296,7 @@@ static int tcp_v6_do_rcv(struct sock *s
                struct dst_entry *dst = sk->sk_rx_dst;
  
                sock_rps_save_rxhash(sk, skb);
 +              sk_mark_napi_id(sk, skb);
                if (dst) {
                        if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif ||
                            dst->ops->check(dst, np->rx_dst_cookie) == NULL) {
                 */
                if (nsk != sk) {
                        sock_rps_save_rxhash(nsk, skb);
 +                      sk_mark_napi_id(sk, skb);
                        if (tcp_child_process(sk, nsk, skb))
                                goto reset;
                        if (opt_skb)
@@@ -1459,7 -1457,7 +1459,7 @@@ process
        if (sk_filter(sk, skb))
                goto discard_and_relse;
  
 -      sk_mark_napi_id(sk, skb);
 +      sk_incoming_cpu_update(sk);
        skb->dev = NULL;
  
        bh_lock_sock_nested(sk);
  #include <net/ip.h>
  #include <net/ipv6.h>
  #include <net/ndisc.h>
 +#include <net/mpls.h>
  
  #include "flow_netlink.h"
  
 -static void update_range__(struct sw_flow_match *match,
 -                         size_t offset, size_t size, bool is_mask)
 +static void update_range(struct sw_flow_match *match,
 +                       size_t offset, size_t size, bool is_mask)
  {
 -      struct sw_flow_key_range *range = NULL;
 +      struct sw_flow_key_range *range;
        size_t start = rounddown(offset, sizeof(long));
        size_t end = roundup(offset + size, sizeof(long));
  
        if (!is_mask)
                range = &match->range;
 -      else if (match->mask)
 +      else
                range = &match->mask->range;
  
 -      if (!range)
 -              return;
 -
        if (range->start == range->end) {
                range->start = start;
                range->end = end;
  
  #define SW_FLOW_KEY_PUT(match, field, value, is_mask) \
        do { \
 -              update_range__(match, offsetof(struct sw_flow_key, field),  \
 -                                   sizeof((match)->key->field), is_mask); \
 -              if (is_mask) {                                              \
 -                      if ((match)->mask)                                  \
 -                              (match)->mask->key.field = value;           \
 -              } else {                                                    \
 +              update_range(match, offsetof(struct sw_flow_key, field),    \
 +                           sizeof((match)->key->field), is_mask);         \
 +              if (is_mask)                                                \
 +                      (match)->mask->key.field = value;                   \
 +              else                                                        \
                        (match)->key->field = value;                        \
 -              }                                                           \
        } while (0)
  
  #define SW_FLOW_KEY_MEMCPY_OFFSET(match, offset, value_p, len, is_mask)           \
        do {                                                                \
 -              update_range__(match, offset, len, is_mask);                \
 +              update_range(match, offset, len, is_mask);                  \
                if (is_mask)                                                \
                        memcpy((u8 *)&(match)->mask->key + offset, value_p, \
 -                             len);                                        \
 +                             len);                                       \
                else                                                        \
                        memcpy((u8 *)(match)->key + offset, value_p, len);  \
        } while (0)
        SW_FLOW_KEY_MEMCPY_OFFSET(match, offsetof(struct sw_flow_key, field), \
                                  value_p, len, is_mask)
  
 -#define SW_FLOW_KEY_MEMSET_FIELD(match, field, value, is_mask) \
 -      do { \
 -              update_range__(match, offsetof(struct sw_flow_key, field),  \
 -                                   sizeof((match)->key->field), is_mask); \
 -              if (is_mask) {                                              \
 -                      if ((match)->mask)                                  \
 -                              memset((u8 *)&(match)->mask->key.field, value,\
 -                                     sizeof((match)->mask->key.field));   \
 -              } else {                                                    \
 +#define SW_FLOW_KEY_MEMSET_FIELD(match, field, value, is_mask)                    \
 +      do {                                                                \
 +              update_range(match, offsetof(struct sw_flow_key, field),    \
 +                           sizeof((match)->key->field), is_mask);         \
 +              if (is_mask)                                                \
 +                      memset((u8 *)&(match)->mask->key.field, value,      \
 +                             sizeof((match)->mask->key.field));           \
 +              else                                                        \
                        memset((u8 *)&(match)->key->field, value,           \
                               sizeof((match)->key->field));                \
 -              }                                                           \
        } while (0)
  
  static bool match_validate(const struct sw_flow_match *match,
 -                         u64 key_attrs, u64 mask_attrs)
 +                         u64 key_attrs, u64 mask_attrs, bool log)
  {
        u64 key_expected = 1 << OVS_KEY_ATTR_ETHERNET;
        u64 mask_allowed = key_attrs;  /* At most allow all key attributes */
                        | (1 << OVS_KEY_ATTR_ICMP)
                        | (1 << OVS_KEY_ATTR_ICMPV6)
                        | (1 << OVS_KEY_ATTR_ARP)
 -                      | (1 << OVS_KEY_ATTR_ND));
 +                      | (1 << OVS_KEY_ATTR_ND)
 +                      | (1 << OVS_KEY_ATTR_MPLS));
  
        /* Always allowed mask fields. */
        mask_allowed |= ((1 << OVS_KEY_ATTR_TUNNEL)
        if (match->key->eth.type == htons(ETH_P_ARP)
                        || match->key->eth.type == htons(ETH_P_RARP)) {
                key_expected |= 1 << OVS_KEY_ATTR_ARP;
-               if (match->mask && (match->mask->key.tp.src == htons(0xff)))
+               if (match->mask && (match->mask->key.eth.type == htons(0xffff)))
                        mask_allowed |= 1 << OVS_KEY_ATTR_ARP;
        }
  
 +      if (eth_p_mpls(match->key->eth.type)) {
 +              key_expected |= 1 << OVS_KEY_ATTR_MPLS;
 +              if (match->mask && (match->mask->key.eth.type == htons(0xffff)))
 +                      mask_allowed |= 1 << OVS_KEY_ATTR_MPLS;
 +      }
 +
        if (match->key->eth.type == htons(ETH_P_IP)) {
                key_expected |= 1 << OVS_KEY_ATTR_IPV4;
                if (match->mask && (match->mask->key.eth.type == htons(0xffff)))
                                                htons(NDISC_NEIGHBOUR_SOLICITATION) ||
                                    match->key->tp.src == htons(NDISC_NEIGHBOUR_ADVERTISEMENT)) {
                                        key_expected |= 1 << OVS_KEY_ATTR_ND;
-                                       if (match->mask && (match->mask->key.tp.src == htons(0xffff)))
+                                       if (match->mask && (match->mask->key.tp.src == htons(0xff)))
                                                mask_allowed |= 1 << OVS_KEY_ATTR_ND;
                                }
                        }
  
        if ((key_attrs & key_expected) != key_expected) {
                /* Key attributes check failed. */
 -              OVS_NLERR("Missing expected key attributes (key_attrs=%llx, expected=%llx).\n",
 -                              (unsigned long long)key_attrs, (unsigned long long)key_expected);
 +              OVS_NLERR(log, "Missing key (keys=%llx, expected=%llx)",
 +                        (unsigned long long)key_attrs,
 +                        (unsigned long long)key_expected);
                return false;
        }
  
        if ((mask_attrs & mask_allowed) != mask_attrs) {
                /* Mask attributes check failed. */
 -              OVS_NLERR("Contain more than allowed mask fields (mask_attrs=%llx, mask_allowed=%llx).\n",
 -                              (unsigned long long)mask_attrs, (unsigned long long)mask_allowed);
 +              OVS_NLERR(log, "Unexpected mask (mask=%llx, allowed=%llx)",
 +                        (unsigned long long)mask_attrs,
 +                        (unsigned long long)mask_allowed);
                return false;
        }
  
        return true;
  }
  
 +size_t ovs_tun_key_attr_size(void)
 +{
 +      /* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider
 +       * updating this function.
 +       */
 +      return    nla_total_size(8)    /* OVS_TUNNEL_KEY_ATTR_ID */
 +              + nla_total_size(4)    /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */
 +              + nla_total_size(4)    /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */
 +              + nla_total_size(1)    /* OVS_TUNNEL_KEY_ATTR_TOS */
 +              + nla_total_size(1)    /* OVS_TUNNEL_KEY_ATTR_TTL */
 +              + nla_total_size(0)    /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */
 +              + nla_total_size(0)    /* OVS_TUNNEL_KEY_ATTR_CSUM */
 +              + nla_total_size(0)    /* OVS_TUNNEL_KEY_ATTR_OAM */
 +              + nla_total_size(256)  /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */
 +              + nla_total_size(2)    /* OVS_TUNNEL_KEY_ATTR_TP_SRC */
 +              + nla_total_size(2);   /* OVS_TUNNEL_KEY_ATTR_TP_DST */
 +}
 +
 +size_t ovs_key_attr_size(void)
 +{
 +      /* Whenever adding new OVS_KEY_ FIELDS, we should consider
 +       * updating this function.
 +       */
 +      BUILD_BUG_ON(OVS_KEY_ATTR_TUNNEL_INFO != 22);
 +
 +      return    nla_total_size(4)   /* OVS_KEY_ATTR_PRIORITY */
 +              + nla_total_size(0)   /* OVS_KEY_ATTR_TUNNEL */
 +                + ovs_tun_key_attr_size()
 +              + nla_total_size(4)   /* OVS_KEY_ATTR_IN_PORT */
 +              + nla_total_size(4)   /* OVS_KEY_ATTR_SKB_MARK */
 +              + nla_total_size(4)   /* OVS_KEY_ATTR_DP_HASH */
 +              + nla_total_size(4)   /* OVS_KEY_ATTR_RECIRC_ID */
 +              + nla_total_size(12)  /* OVS_KEY_ATTR_ETHERNET */
 +              + nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */
 +              + nla_total_size(4)   /* OVS_KEY_ATTR_VLAN */
 +              + nla_total_size(0)   /* OVS_KEY_ATTR_ENCAP */
 +              + nla_total_size(2)   /* OVS_KEY_ATTR_ETHERTYPE */
 +              + nla_total_size(40)  /* OVS_KEY_ATTR_IPV6 */
 +              + nla_total_size(2)   /* OVS_KEY_ATTR_ICMPV6 */
 +              + nla_total_size(28); /* OVS_KEY_ATTR_ND */
 +}
 +
  /* The size of the argument for each %OVS_KEY_ATTR_* Netlink attribute.  */
  static const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
        [OVS_KEY_ATTR_ENCAP] = -1,
        [OVS_KEY_ATTR_RECIRC_ID] = sizeof(u32),
        [OVS_KEY_ATTR_DP_HASH] = sizeof(u32),
        [OVS_KEY_ATTR_TUNNEL] = -1,
 +      [OVS_KEY_ATTR_MPLS] = sizeof(struct ovs_key_mpls),
  };
  
  static bool is_all_zero(const u8 *fp, size_t size)
  
  static int __parse_flow_nlattrs(const struct nlattr *attr,
                                const struct nlattr *a[],
 -                              u64 *attrsp, bool nz)
 +                              u64 *attrsp, bool log, bool nz)
  {
        const struct nlattr *nla;
        u64 attrs;
                int expected_len;
  
                if (type > OVS_KEY_ATTR_MAX) {
 -                      OVS_NLERR("Unknown key attribute (type=%d, max=%d).\n",
 +                      OVS_NLERR(log, "Key type %d is out of range max %d",
                                  type, OVS_KEY_ATTR_MAX);
                        return -EINVAL;
                }
  
                if (attrs & (1 << type)) {
 -                      OVS_NLERR("Duplicate key attribute (type %d).\n", type);
 +                      OVS_NLERR(log, "Duplicate key (type %d).", type);
                        return -EINVAL;
                }
  
                expected_len = ovs_key_lens[type];
                if (nla_len(nla) != expected_len && expected_len != -1) {
 -                      OVS_NLERR("Key attribute has unexpected length (type=%d"
 -                                ", length=%d, expected=%d).\n", type,
 -                                nla_len(nla), expected_len);
 +                      OVS_NLERR(log, "Key %d has unexpected len %d expected %d",
 +                                type, nla_len(nla), expected_len);
                        return -EINVAL;
                }
  
                }
        }
        if (rem) {
 -              OVS_NLERR("Message has %d unknown bytes.\n", rem);
 +              OVS_NLERR(log, "Message has %d unknown bytes.", rem);
                return -EINVAL;
        }
  
  }
  
  static int parse_flow_mask_nlattrs(const struct nlattr *attr,
 -                                 const struct nlattr *a[], u64 *attrsp)
 +                                 const struct nlattr *a[], u64 *attrsp,
 +                                 bool log)
  {
 -      return __parse_flow_nlattrs(attr, a, attrsp, true);
 +      return __parse_flow_nlattrs(attr, a, attrsp, log, true);
  }
  
  static int parse_flow_nlattrs(const struct nlattr *attr,
 -                            const struct nlattr *a[], u64 *attrsp)
 +                            const struct nlattr *a[], u64 *attrsp,
 +                            bool log)
  {
 -      return __parse_flow_nlattrs(attr, a, attrsp, false);
 +      return __parse_flow_nlattrs(attr, a, attrsp, log, false);
 +}
 +
 +static int genev_tun_opt_from_nlattr(const struct nlattr *a,
 +                                   struct sw_flow_match *match, bool is_mask,
 +                                   bool log)
 +{
 +      unsigned long opt_key_offset;
 +
 +      if (nla_len(a) > sizeof(match->key->tun_opts)) {
 +              OVS_NLERR(log, "Geneve option length err (len %d, max %zu).",
 +                        nla_len(a), sizeof(match->key->tun_opts));
 +              return -EINVAL;
 +      }
 +
 +      if (nla_len(a) % 4 != 0) {
 +              OVS_NLERR(log, "Geneve opt len %d is not a multiple of 4.",
 +                        nla_len(a));
 +              return -EINVAL;
 +      }
 +
 +      /* We need to record the length of the options passed
 +       * down, otherwise packets with the same format but
 +       * additional options will be silently matched.
 +       */
 +      if (!is_mask) {
 +              SW_FLOW_KEY_PUT(match, tun_opts_len, nla_len(a),
 +                              false);
 +      } else {
 +              /* This is somewhat unusual because it looks at
 +               * both the key and mask while parsing the
 +               * attributes (and by extension assumes the key
 +               * is parsed first). Normally, we would verify
 +               * that each is the correct length and that the
 +               * attributes line up in the validate function.
 +               * However, that is difficult because this is
 +               * variable length and we won't have the
 +               * information later.
 +               */
 +              if (match->key->tun_opts_len != nla_len(a)) {
 +                      OVS_NLERR(log, "Geneve option len %d != mask len %d",
 +                                match->key->tun_opts_len, nla_len(a));
 +                      return -EINVAL;
 +              }
 +
 +              SW_FLOW_KEY_PUT(match, tun_opts_len, 0xff, true);
 +      }
 +
 +      opt_key_offset = (unsigned long)GENEVE_OPTS((struct sw_flow_key *)0,
 +                                                  nla_len(a));
 +      SW_FLOW_KEY_MEMCPY_OFFSET(match, opt_key_offset, nla_data(a),
 +                                nla_len(a), is_mask);
 +      return 0;
  }
  
  static int ipv4_tun_from_nlattr(const struct nlattr *attr,
 -                              struct sw_flow_match *match, bool is_mask)
 +                              struct sw_flow_match *match, bool is_mask,
 +                              bool log)
  {
        struct nlattr *a;
        int rem;
        bool ttl = false;
        __be16 tun_flags = 0;
 -      unsigned long opt_key_offset;
  
        nla_for_each_nested(a, attr, rem) {
                int type = nla_type(a);
 +              int err;
 +
                static const u32 ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
                        [OVS_TUNNEL_KEY_ATTR_ID] = sizeof(u64),
                        [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = sizeof(u32),
                        [OVS_TUNNEL_KEY_ATTR_TTL] = 1,
                        [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = 0,
                        [OVS_TUNNEL_KEY_ATTR_CSUM] = 0,
 +                      [OVS_TUNNEL_KEY_ATTR_TP_SRC] = sizeof(u16),
 +                      [OVS_TUNNEL_KEY_ATTR_TP_DST] = sizeof(u16),
                        [OVS_TUNNEL_KEY_ATTR_OAM] = 0,
                        [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = -1,
                };
  
                if (type > OVS_TUNNEL_KEY_ATTR_MAX) {
 -                      OVS_NLERR("Unknown IPv4 tunnel attribute (type=%d, max=%d).\n",
 -                      type, OVS_TUNNEL_KEY_ATTR_MAX);
 +                      OVS_NLERR(log, "Tunnel attr %d out of range max %d",
 +                                type, OVS_TUNNEL_KEY_ATTR_MAX);
                        return -EINVAL;
                }
  
                if (ovs_tunnel_key_lens[type] != nla_len(a) &&
                    ovs_tunnel_key_lens[type] != -1) {
 -                      OVS_NLERR("IPv4 tunnel attribute type has unexpected "
 -                                " length (type=%d, length=%d, expected=%d).\n",
 +                      OVS_NLERR(log, "Tunnel attr %d has unexpected len %d expected %d",
                                  type, nla_len(a), ovs_tunnel_key_lens[type]);
                        return -EINVAL;
                }
                case OVS_TUNNEL_KEY_ATTR_CSUM:
                        tun_flags |= TUNNEL_CSUM;
                        break;
 +              case OVS_TUNNEL_KEY_ATTR_TP_SRC:
 +                      SW_FLOW_KEY_PUT(match, tun_key.tp_src,
 +                                      nla_get_be16(a), is_mask);
 +                      break;
 +              case OVS_TUNNEL_KEY_ATTR_TP_DST:
 +                      SW_FLOW_KEY_PUT(match, tun_key.tp_dst,
 +                                      nla_get_be16(a), is_mask);
 +                      break;
                case OVS_TUNNEL_KEY_ATTR_OAM:
                        tun_flags |= TUNNEL_OAM;
                        break;
                case OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS:
 -                      tun_flags |= TUNNEL_OPTIONS_PRESENT;
 -                      if (nla_len(a) > sizeof(match->key->tun_opts)) {
 -                              OVS_NLERR("Geneve option length exceeds maximum size (len %d, max %zu).\n",
 -                                        nla_len(a),
 -                                        sizeof(match->key->tun_opts));
 -                              return -EINVAL;
 -                      }
 -
 -                      if (nla_len(a) % 4 != 0) {
 -                              OVS_NLERR("Geneve option length is not a multiple of 4 (len %d).\n",
 -                                        nla_len(a));
 -                              return -EINVAL;
 -                      }
 -
 -                      /* We need to record the length of the options passed
 -                       * down, otherwise packets with the same format but
 -                       * additional options will be silently matched.
 -                       */
 -                      if (!is_mask) {
 -                              SW_FLOW_KEY_PUT(match, tun_opts_len, nla_len(a),
 -                                              false);
 -                      } else {
 -                              /* This is somewhat unusual because it looks at
 -                               * both the key and mask while parsing the
 -                               * attributes (and by extension assumes the key
 -                               * is parsed first). Normally, we would verify
 -                               * that each is the correct length and that the
 -                               * attributes line up in the validate function.
 -                               * However, that is difficult because this is
 -                               * variable length and we won't have the
 -                               * information later.
 -                               */
 -                              if (match->key->tun_opts_len != nla_len(a)) {
 -                                      OVS_NLERR("Geneve option key length (%d) is different from mask length (%d).",
 -                                                match->key->tun_opts_len,
 -                                                nla_len(a));
 -                                      return -EINVAL;
 -                              }
 -
 -                              SW_FLOW_KEY_PUT(match, tun_opts_len, 0xff,
 -                                              true);
 -                      }
 +                      err = genev_tun_opt_from_nlattr(a, match, is_mask, log);
 +                      if (err)
 +                              return err;
  
 -                      opt_key_offset = (unsigned long)GENEVE_OPTS(
 -                                        (struct sw_flow_key *)0,
 -                                        nla_len(a));
 -                      SW_FLOW_KEY_MEMCPY_OFFSET(match, opt_key_offset,
 -                                                nla_data(a), nla_len(a),
 -                                                is_mask);
 +                      tun_flags |= TUNNEL_OPTIONS_PRESENT;
                        break;
                default:
 -                      OVS_NLERR("Unknown IPv4 tunnel attribute (%d).\n",
 +                      OVS_NLERR(log, "Unknown IPv4 tunnel attribute %d",
                                  type);
                        return -EINVAL;
                }
        SW_FLOW_KEY_PUT(match, tun_key.tun_flags, tun_flags, is_mask);
  
        if (rem > 0) {
 -              OVS_NLERR("IPv4 tunnel attribute has %d unknown bytes.\n", rem);
 +              OVS_NLERR(log, "IPv4 tunnel attribute has %d unknown bytes.",
 +                        rem);
                return -EINVAL;
        }
  
        if (!is_mask) {
                if (!match->key->tun_key.ipv4_dst) {
 -                      OVS_NLERR("IPv4 tunnel destination address is zero.\n");
 +                      OVS_NLERR(log, "IPv4 tunnel dst address is zero");
                        return -EINVAL;
                }
  
                if (!ttl) {
 -                      OVS_NLERR("IPv4 tunnel TTL not specified.\n");
 +                      OVS_NLERR(log, "IPv4 tunnel TTL not specified.");
                        return -EINVAL;
                }
        }
@@@ -581,12 -514,6 +581,12 @@@ static int __ipv4_tun_to_nlattr(struct 
        if ((output->tun_flags & TUNNEL_CSUM) &&
            nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_CSUM))
                return -EMSGSIZE;
 +      if (output->tp_src &&
 +          nla_put_be16(skb, OVS_TUNNEL_KEY_ATTR_TP_SRC, output->tp_src))
 +              return -EMSGSIZE;
 +      if (output->tp_dst &&
 +          nla_put_be16(skb, OVS_TUNNEL_KEY_ATTR_TP_DST, output->tp_dst))
 +              return -EMSGSIZE;
        if ((output->tun_flags & TUNNEL_OAM) &&
            nla_put_flag(skb, OVS_TUNNEL_KEY_ATTR_OAM))
                return -EMSGSIZE;
        return 0;
  }
  
 -
  static int ipv4_tun_to_nlattr(struct sk_buff *skb,
                              const struct ovs_key_ipv4_tunnel *output,
                              const struct geneve_opt *tun_opts,
        return 0;
  }
  
 +int ovs_nla_put_egress_tunnel_key(struct sk_buff *skb,
 +                                const struct ovs_tunnel_info *egress_tun_info)
 +{
 +      return __ipv4_tun_to_nlattr(skb, &egress_tun_info->tunnel,
 +                                  egress_tun_info->options,
 +                                  egress_tun_info->options_len);
 +}
 +
  static int metadata_from_nlattrs(struct sw_flow_match *match,  u64 *attrs,
 -                               const struct nlattr **a, bool is_mask)
 +                               const struct nlattr **a, bool is_mask,
 +                               bool log)
  {
        if (*attrs & (1 << OVS_KEY_ATTR_DP_HASH)) {
                u32 hash_val = nla_get_u32(a[OVS_KEY_ATTR_DP_HASH]);
        if (*attrs & (1 << OVS_KEY_ATTR_IN_PORT)) {
                u32 in_port = nla_get_u32(a[OVS_KEY_ATTR_IN_PORT]);
  
 -              if (is_mask)
 +              if (is_mask) {
                        in_port = 0xffffffff; /* Always exact match in_port. */
 -              else if (in_port >= DP_MAX_PORTS)
 +              } else if (in_port >= DP_MAX_PORTS) {
 +                      OVS_NLERR(log, "Port %d exceeds max allowable %d",
 +                                in_port, DP_MAX_PORTS);
                        return -EINVAL;
 +              }
  
                SW_FLOW_KEY_PUT(match, phy.in_port, in_port, is_mask);
                *attrs &= ~(1 << OVS_KEY_ATTR_IN_PORT);
        }
        if (*attrs & (1 << OVS_KEY_ATTR_TUNNEL)) {
                if (ipv4_tun_from_nlattr(a[OVS_KEY_ATTR_TUNNEL], match,
 -                                       is_mask))
 +                                       is_mask, log))
                        return -EINVAL;
                *attrs &= ~(1 << OVS_KEY_ATTR_TUNNEL);
        }
  }
  
  static int ovs_key_from_nlattrs(struct sw_flow_match *match, u64 attrs,
 -                              const struct nlattr **a, bool is_mask)
 +                              const struct nlattr **a, bool is_mask,
 +                              bool log)
  {
        int err;
 -      u64 orig_attrs = attrs;
  
 -      err = metadata_from_nlattrs(match, &attrs, a, is_mask);
 +      err = metadata_from_nlattrs(match, &attrs, a, is_mask, log);
        if (err)
                return err;
  
                tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
                if (!(tci & htons(VLAN_TAG_PRESENT))) {
                        if (is_mask)
 -                              OVS_NLERR("VLAN TCI mask does not have exact match for VLAN_TAG_PRESENT bit.\n");
 +                              OVS_NLERR(log, "VLAN TCI mask does not have exact match for VLAN_TAG_PRESENT bit.");
                        else
 -                              OVS_NLERR("VLAN TCI does not have VLAN_TAG_PRESENT bit set.\n");
 +                              OVS_NLERR(log, "VLAN TCI does not have VLAN_TAG_PRESENT bit set.");
  
                        return -EINVAL;
                }
  
                SW_FLOW_KEY_PUT(match, eth.tci, tci, is_mask);
                attrs &= ~(1 << OVS_KEY_ATTR_VLAN);
 -      } else if (!is_mask)
 -              SW_FLOW_KEY_PUT(match, eth.tci, htons(0xffff), true);
 +      }
  
        if (attrs & (1 << OVS_KEY_ATTR_ETHERTYPE)) {
                __be16 eth_type;
                        /* Always exact match EtherType. */
                        eth_type = htons(0xffff);
                } else if (ntohs(eth_type) < ETH_P_802_3_MIN) {
 -                      OVS_NLERR("EtherType is less than minimum (type=%x, min=%x).\n",
 -                                      ntohs(eth_type), ETH_P_802_3_MIN);
 +                      OVS_NLERR(log, "EtherType %x is less than min %x",
 +                                ntohs(eth_type), ETH_P_802_3_MIN);
                        return -EINVAL;
                }
  
  
                ipv4_key = nla_data(a[OVS_KEY_ATTR_IPV4]);
                if (!is_mask && ipv4_key->ipv4_frag > OVS_FRAG_TYPE_MAX) {
 -                      OVS_NLERR("Unknown IPv4 fragment type (value=%d, max=%d).\n",
 -                              ipv4_key->ipv4_frag, OVS_FRAG_TYPE_MAX);
 +                      OVS_NLERR(log, "IPv4 frag type %d is out of range max %d",
 +                                ipv4_key->ipv4_frag, OVS_FRAG_TYPE_MAX);
                        return -EINVAL;
                }
                SW_FLOW_KEY_PUT(match, ip.proto,
  
                ipv6_key = nla_data(a[OVS_KEY_ATTR_IPV6]);
                if (!is_mask && ipv6_key->ipv6_frag > OVS_FRAG_TYPE_MAX) {
 -                      OVS_NLERR("Unknown IPv6 fragment type (value=%d, max=%d).\n",
 -                              ipv6_key->ipv6_frag, OVS_FRAG_TYPE_MAX);
 +                      OVS_NLERR(log, "IPv6 frag type %d is out of range max %d",
 +                                ipv6_key->ipv6_frag, OVS_FRAG_TYPE_MAX);
                        return -EINVAL;
                }
  
                if (!is_mask && ipv6_key->ipv6_label & htonl(0xFFF00000)) {
 -                      OVS_NLERR("IPv6 flow label %x is out of range (max=%x).\n",
 +                      OVS_NLERR(log, "IPv6 flow label %x is out of range (max=%x).\n",
                                  ntohl(ipv6_key->ipv6_label), (1 << 20) - 1);
                        return -EINVAL;
                }
  
                arp_key = nla_data(a[OVS_KEY_ATTR_ARP]);
                if (!is_mask && (arp_key->arp_op & htons(0xff00))) {
 -                      OVS_NLERR("Unknown ARP opcode (opcode=%d).\n",
 +                      OVS_NLERR(log, "Unknown ARP opcode (opcode=%d).",
                                  arp_key->arp_op);
                        return -EINVAL;
                }
                attrs &= ~(1 << OVS_KEY_ATTR_ARP);
        }
  
 +      if (attrs & (1 << OVS_KEY_ATTR_MPLS)) {
 +              const struct ovs_key_mpls *mpls_key;
 +
 +              mpls_key = nla_data(a[OVS_KEY_ATTR_MPLS]);
 +              SW_FLOW_KEY_PUT(match, mpls.top_lse,
 +                              mpls_key->mpls_lse, is_mask);
 +
 +              attrs &= ~(1 << OVS_KEY_ATTR_MPLS);
 +       }
 +
        if (attrs & (1 << OVS_KEY_ATTR_TCP)) {
                const struct ovs_key_tcp *tcp_key;
  
        }
  
        if (attrs & (1 << OVS_KEY_ATTR_TCP_FLAGS)) {
 -              if (orig_attrs & (1 << OVS_KEY_ATTR_IPV4)) {
 -                      SW_FLOW_KEY_PUT(match, tp.flags,
 -                                      nla_get_be16(a[OVS_KEY_ATTR_TCP_FLAGS]),
 -                                      is_mask);
 -              } else {
 -                      SW_FLOW_KEY_PUT(match, tp.flags,
 -                                      nla_get_be16(a[OVS_KEY_ATTR_TCP_FLAGS]),
 -                                      is_mask);
 -              }
 +              SW_FLOW_KEY_PUT(match, tp.flags,
 +                              nla_get_be16(a[OVS_KEY_ATTR_TCP_FLAGS]),
 +                              is_mask);
                attrs &= ~(1 << OVS_KEY_ATTR_TCP_FLAGS);
        }
  
                attrs &= ~(1 << OVS_KEY_ATTR_ND);
        }
  
 -      if (attrs != 0)
 +      if (attrs != 0) {
 +              OVS_NLERR(log, "Unknown key attributes %llx",
 +                        (unsigned long long)attrs);
                return -EINVAL;
 +      }
  
        return 0;
  }
@@@ -948,14 -858,10 +948,14 @@@ static void mask_set_nlattr(struct nlat
   * of this flow.
   * @mask: Optional. Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink
   * attribute specifies the mask field of the wildcarded flow.
 + * @log: Boolean to allow kernel error logging.  Normally true, but when
 + * probing for feature compatibility this should be passed in as false to
 + * suppress unnecessary error logging.
   */
  int ovs_nla_get_match(struct sw_flow_match *match,
 -                    const struct nlattr *key,
 -                    const struct nlattr *mask)
 +                    const struct nlattr *nla_key,
 +                    const struct nlattr *nla_mask,
 +                    bool log)
  {
        const struct nlattr *a[OVS_KEY_ATTR_MAX + 1];
        const struct nlattr *encap;
        bool encap_valid = false;
        int err;
  
 -      err = parse_flow_nlattrs(key, a, &key_attrs);
 +      err = parse_flow_nlattrs(nla_key, a, &key_attrs, log);
        if (err)
                return err;
  
  
                if (!((key_attrs & (1 << OVS_KEY_ATTR_VLAN)) &&
                      (key_attrs & (1 << OVS_KEY_ATTR_ENCAP)))) {
 -                      OVS_NLERR("Invalid Vlan frame.\n");
 +                      OVS_NLERR(log, "Invalid Vlan frame.");
                        return -EINVAL;
                }
  
                encap_valid = true;
  
                if (tci & htons(VLAN_TAG_PRESENT)) {
 -                      err = parse_flow_nlattrs(encap, a, &key_attrs);
 +                      err = parse_flow_nlattrs(encap, a, &key_attrs, log);
                        if (err)
                                return err;
                } else if (!tci) {
                        /* Corner case for truncated 802.1Q header. */
                        if (nla_len(encap)) {
 -                              OVS_NLERR("Truncated 802.1Q header has non-zero encap attribute.\n");
 +                              OVS_NLERR(log, "Truncated 802.1Q header has non-zero encap attribute.");
                                return -EINVAL;
                        }
                } else {
 -                      OVS_NLERR("Encap attribute is set for a non-VLAN frame.\n");
 +                      OVS_NLERR(log, "Encap attr is set for non-VLAN frame");
                        return  -EINVAL;
                }
        }
  
 -      err = ovs_key_from_nlattrs(match, key_attrs, a, false);
 +      err = ovs_key_from_nlattrs(match, key_attrs, a, false, log);
        if (err)
                return err;
  
 -      if (match->mask && !mask) {
 -              /* Create an exact match mask. We need to set to 0xff all the
 -               * 'match->mask' fields that have been touched in 'match->key'.
 -               * We cannot simply memset 'match->mask', because padding bytes
 -               * and fields not specified in 'match->key' should be left to 0.
 -               * Instead, we use a stream of netlink attributes, copied from
 -               * 'key' and set to 0xff: ovs_key_from_nlattrs() will take care
 -               * of filling 'match->mask' appropriately.
 -               */
 -              newmask = kmemdup(key, nla_total_size(nla_len(key)),
 -                                GFP_KERNEL);
 -              if (!newmask)
 -                      return -ENOMEM;
 +      if (match->mask) {
 +              if (!nla_mask) {
 +                      /* Create an exact match mask. We need to set to 0xff
 +                       * all the 'match->mask' fields that have been touched
 +                       * in 'match->key'. We cannot simply memset
 +                       * 'match->mask', because padding bytes and fields not
 +                       * specified in 'match->key' should be left to 0.
 +                       * Instead, we use a stream of netlink attributes,
 +                       * copied from 'key' and set to 0xff.
 +                       * ovs_key_from_nlattrs() will take care of filling
 +                       * 'match->mask' appropriately.
 +                       */
 +                      newmask = kmemdup(nla_key,
 +                                        nla_total_size(nla_len(nla_key)),
 +                                        GFP_KERNEL);
 +                      if (!newmask)
 +                              return -ENOMEM;
  
 -              mask_set_nlattr(newmask, 0xff);
 +                      mask_set_nlattr(newmask, 0xff);
  
 -              /* The userspace does not send tunnel attributes that are 0,
 -               * but we should not wildcard them nonetheless.
 -               */
 -              if (match->key->tun_key.ipv4_dst)
 -                      SW_FLOW_KEY_MEMSET_FIELD(match, tun_key, 0xff, true);
 +                      /* The userspace does not send tunnel attributes that
 +                       * are 0, but we should not wildcard them nonetheless.
 +                       */
 +                      if (match->key->tun_key.ipv4_dst)
 +                              SW_FLOW_KEY_MEMSET_FIELD(match, tun_key,
 +                                                       0xff, true);
  
 -              mask = newmask;
 -      }
 +                      nla_mask = newmask;
 +              }
  
 -      if (mask) {
 -              err = parse_flow_mask_nlattrs(mask, a, &mask_attrs);
 +              err = parse_flow_mask_nlattrs(nla_mask, a, &mask_attrs, log);
                if (err)
                        goto free_newmask;
  
 +              /* Always match on tci. */
 +              SW_FLOW_KEY_PUT(match, eth.tci, htons(0xffff), true);
 +
                if (mask_attrs & 1 << OVS_KEY_ATTR_ENCAP) {
                        __be16 eth_type = 0;
                        __be16 tci = 0;
  
                        if (!encap_valid) {
 -                              OVS_NLERR("Encap mask attribute is set for non-VLAN frame.\n");
 +                              OVS_NLERR(log, "Encap mask attribute is set for non-VLAN frame.");
                                err = -EINVAL;
                                goto free_newmask;
                        }
                        if (eth_type == htons(0xffff)) {
                                mask_attrs &= ~(1 << OVS_KEY_ATTR_ETHERTYPE);
                                encap = a[OVS_KEY_ATTR_ENCAP];
 -                              err = parse_flow_mask_nlattrs(encap, a, &mask_attrs);
 +                              err = parse_flow_mask_nlattrs(encap, a,
 +                                                            &mask_attrs, log);
                                if (err)
                                        goto free_newmask;
                        } else {
 -                              OVS_NLERR("VLAN frames must have an exact match on the TPID (mask=%x).\n",
 -                                              ntohs(eth_type));
 +                              OVS_NLERR(log, "VLAN frames must have an exact match on the TPID (mask=%x).",
 +                                        ntohs(eth_type));
                                err = -EINVAL;
                                goto free_newmask;
                        }
                                tci = nla_get_be16(a[OVS_KEY_ATTR_VLAN]);
  
                        if (!(tci & htons(VLAN_TAG_PRESENT))) {
 -                              OVS_NLERR("VLAN tag present bit must have an exact match (tci_mask=%x).\n", ntohs(tci));
 +                              OVS_NLERR(log, "VLAN tag present bit must have an exact match (tci_mask=%x).",
 +                                        ntohs(tci));
                                err = -EINVAL;
                                goto free_newmask;
                        }
                }
  
 -              err = ovs_key_from_nlattrs(match, mask_attrs, a, true);
 +              err = ovs_key_from_nlattrs(match, mask_attrs, a, true, log);
                if (err)
                        goto free_newmask;
        }
  
 -      if (!match_validate(match, key_attrs, mask_attrs))
 +      if (!match_validate(match, key_attrs, mask_attrs, log))
                err = -EINVAL;
  
  free_newmask:
   * @key: Receives extracted in_port, priority, tun_key and skb_mark.
   * @attr: Netlink attribute holding nested %OVS_KEY_ATTR_* Netlink attribute
   * sequence.
 + * @log: Boolean to allow kernel error logging.  Normally true, but when
 + * probing for feature compatibility this should be passed in as false to
 + * suppress unnecessary error logging.
   *
   * This parses a series of Netlink attributes that form a flow key, which must
   * take the same form accepted by flow_from_nlattrs(), but only enough of it to
   */
  
  int ovs_nla_get_flow_metadata(const struct nlattr *attr,
 -                            struct sw_flow_key *key)
 +                            struct sw_flow_key *key,
 +                            bool log)
  {
        const struct nlattr *a[OVS_KEY_ATTR_MAX + 1];
        struct sw_flow_match match;
        u64 attrs = 0;
        int err;
  
 -      err = parse_flow_nlattrs(attr, a, &attrs);
 +      err = parse_flow_nlattrs(attr, a, &attrs, log);
        if (err)
                return -EINVAL;
  
  
        key->phy.in_port = DP_MAX_PORTS;
  
 -      return metadata_from_nlattrs(&match, &attrs, a, false);
 +      return metadata_from_nlattrs(&match, &attrs, a, false, log);
  }
  
  int ovs_nla_put_flow(const struct sw_flow_key *swkey,
                arp_key->arp_op = htons(output->ip.proto);
                ether_addr_copy(arp_key->arp_sha, output->ipv4.arp.sha);
                ether_addr_copy(arp_key->arp_tha, output->ipv4.arp.tha);
 +      } else if (eth_p_mpls(swkey->eth.type)) {
 +              struct ovs_key_mpls *mpls_key;
 +
 +              nla = nla_reserve(skb, OVS_KEY_ATTR_MPLS, sizeof(*mpls_key));
 +              if (!nla)
 +                      goto nla_put_failure;
 +              mpls_key = nla_data(nla);
 +              mpls_key->mpls_lse = output->mpls.top_lse;
        }
  
        if ((swkey->eth.type == htons(ETH_P_IP) ||
@@@ -1348,14 -1233,12 +1348,14 @@@ nla_put_failure
  
  #define MAX_ACTIONS_BUFSIZE   (32 * 1024)
  
 -struct sw_flow_actions *ovs_nla_alloc_flow_actions(int size)
 +static struct sw_flow_actions *nla_alloc_flow_actions(int size, bool log)
  {
        struct sw_flow_actions *sfa;
  
 -      if (size > MAX_ACTIONS_BUFSIZE)
 +      if (size > MAX_ACTIONS_BUFSIZE) {
 +              OVS_NLERR(log, "Flow action size %u bytes exceeds max", size);
                return ERR_PTR(-EINVAL);
 +      }
  
        sfa = kmalloc(sizeof(*sfa) + size, GFP_KERNEL);
        if (!sfa)
@@@ -1373,7 -1256,7 +1373,7 @@@ void ovs_nla_free_flow_actions(struct s
  }
  
  static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa,
 -                                     int attr_len)
 +                                     int attr_len, bool log)
  {
  
        struct sw_flow_actions *acts;
                new_acts_size = MAX_ACTIONS_BUFSIZE;
        }
  
 -      acts = ovs_nla_alloc_flow_actions(new_acts_size);
 +      acts = nla_alloc_flow_actions(new_acts_size, log);
        if (IS_ERR(acts))
                return (void *)acts;
  
  }
  
  static struct nlattr *__add_action(struct sw_flow_actions **sfa,
 -                                 int attrtype, void *data, int len)
 +                                 int attrtype, void *data, int len, bool log)
  {
        struct nlattr *a;
  
 -      a = reserve_sfa_size(sfa, nla_attr_size(len));
 +      a = reserve_sfa_size(sfa, nla_attr_size(len), log);
        if (IS_ERR(a))
                return a;
  
  }
  
  static int add_action(struct sw_flow_actions **sfa, int attrtype,
 -                    void *data, int len)
 +                    void *data, int len, bool log)
  {
        struct nlattr *a;
  
 -      a = __add_action(sfa, attrtype, data, len);
 -      if (IS_ERR(a))
 -              return PTR_ERR(a);
 +      a = __add_action(sfa, attrtype, data, len, log);
  
 -      return 0;
 +      return PTR_ERR_OR_ZERO(a);
  }
  
  static inline int add_nested_action_start(struct sw_flow_actions **sfa,
 -                                        int attrtype)
 +                                        int attrtype, bool log)
  {
        int used = (*sfa)->actions_len;
        int err;
  
 -      err = add_action(sfa, attrtype, NULL, 0);
 +      err = add_action(sfa, attrtype, NULL, 0, log);
        if (err)
                return err;
  
@@@ -1458,15 -1343,9 +1458,15 @@@ static inline void add_nested_action_en
        a->nla_len = sfa->actions_len - st_offset;
  }
  
 +static int __ovs_nla_copy_actions(const struct nlattr *attr,
 +                                const struct sw_flow_key *key,
 +                                int depth, struct sw_flow_actions **sfa,
 +                                __be16 eth_type, __be16 vlan_tci, bool log);
 +
  static int validate_and_copy_sample(const struct nlattr *attr,
                                    const struct sw_flow_key *key, int depth,
 -                                  struct sw_flow_actions **sfa)
 +                                  struct sw_flow_actions **sfa,
 +                                  __be16 eth_type, __be16 vlan_tci, bool log)
  {
        const struct nlattr *attrs[OVS_SAMPLE_ATTR_MAX + 1];
        const struct nlattr *probability, *actions;
                return -EINVAL;
  
        /* validation done, copy sample action. */
 -      start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SAMPLE);
 +      start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SAMPLE, log);
        if (start < 0)
                return start;
        err = add_action(sfa, OVS_SAMPLE_ATTR_PROBABILITY,
 -                       nla_data(probability), sizeof(u32));
 +                       nla_data(probability), sizeof(u32), log);
        if (err)
                return err;
 -      st_acts = add_nested_action_start(sfa, OVS_SAMPLE_ATTR_ACTIONS);
 +      st_acts = add_nested_action_start(sfa, OVS_SAMPLE_ATTR_ACTIONS, log);
        if (st_acts < 0)
                return st_acts;
  
 -      err = ovs_nla_copy_actions(actions, key, depth + 1, sfa);
 +      err = __ovs_nla_copy_actions(actions, key, depth + 1, sfa,
 +                                   eth_type, vlan_tci, log);
        if (err)
                return err;
  
        return 0;
  }
  
 -static int validate_tp_port(const struct sw_flow_key *flow_key)
 +static int validate_tp_port(const struct sw_flow_key *flow_key,
 +                          __be16 eth_type)
  {
 -      if ((flow_key->eth.type == htons(ETH_P_IP) ||
 -           flow_key->eth.type == htons(ETH_P_IPV6)) &&
 +      if ((eth_type == htons(ETH_P_IP) || eth_type == htons(ETH_P_IPV6)) &&
            (flow_key->tp.src || flow_key->tp.dst))
                return 0;
  
@@@ -1541,7 -1419,7 +1541,7 @@@ void ovs_match_init(struct sw_flow_matc
  }
  
  static int validate_and_copy_set_tun(const struct nlattr *attr,
 -                                   struct sw_flow_actions **sfa)
 +                                   struct sw_flow_actions **sfa, bool log)
  {
        struct sw_flow_match match;
        struct sw_flow_key key;
        int err, start;
  
        ovs_match_init(&match, &key, NULL);
 -      err = ipv4_tun_from_nlattr(nla_data(attr), &match, false);
 +      err = ipv4_tun_from_nlattr(nla_data(attr), &match, false, log);
        if (err)
                return err;
  
                key.tun_key.tun_flags |= crit_opt ? TUNNEL_CRIT_OPT : 0;
        };
  
 -      start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SET);
 +      start = add_nested_action_start(sfa, OVS_ACTION_ATTR_SET, log);
        if (start < 0)
                return start;
  
        a = __add_action(sfa, OVS_KEY_ATTR_TUNNEL_INFO, NULL,
 -                       sizeof(*tun_info) + key.tun_opts_len);
 +                       sizeof(*tun_info) + key.tun_opts_len, log);
        if (IS_ERR(a))
                return PTR_ERR(a);
  
  static int validate_set(const struct nlattr *a,
                        const struct sw_flow_key *flow_key,
                        struct sw_flow_actions **sfa,
 -                      bool *set_tun)
 +                      bool *set_tun, __be16 eth_type, bool log)
  {
        const struct nlattr *ovs_key = nla_data(a);
        int key_type = nla_type(ovs_key);
                break;
  
        case OVS_KEY_ATTR_TUNNEL:
 +              if (eth_p_mpls(eth_type))
 +                      return -EINVAL;
 +
                *set_tun = true;
 -              err = validate_and_copy_set_tun(a, sfa);
 +              err = validate_and_copy_set_tun(a, sfa, log);
                if (err)
                        return err;
                break;
  
        case OVS_KEY_ATTR_IPV4:
 -              if (flow_key->eth.type != htons(ETH_P_IP))
 +              if (eth_type != htons(ETH_P_IP))
                        return -EINVAL;
  
                if (!flow_key->ip.proto)
                break;
  
        case OVS_KEY_ATTR_IPV6:
 -              if (flow_key->eth.type != htons(ETH_P_IPV6))
 +              if (eth_type != htons(ETH_P_IPV6))
                        return -EINVAL;
  
                if (!flow_key->ip.proto)
                if (flow_key->ip.proto != IPPROTO_TCP)
                        return -EINVAL;
  
 -              return validate_tp_port(flow_key);
 +              return validate_tp_port(flow_key, eth_type);
  
        case OVS_KEY_ATTR_UDP:
                if (flow_key->ip.proto != IPPROTO_UDP)
                        return -EINVAL;
  
 -              return validate_tp_port(flow_key);
 +              return validate_tp_port(flow_key, eth_type);
 +
 +      case OVS_KEY_ATTR_MPLS:
 +              if (!eth_p_mpls(eth_type))
 +                      return -EINVAL;
 +              break;
  
        case OVS_KEY_ATTR_SCTP:
                if (flow_key->ip.proto != IPPROTO_SCTP)
                        return -EINVAL;
  
 -              return validate_tp_port(flow_key);
 +              return validate_tp_port(flow_key, eth_type);
  
        default:
                return -EINVAL;
@@@ -1716,7 -1586,6 +1716,7 @@@ static int validate_userspace(const str
        static const struct nla_policy userspace_policy[OVS_USERSPACE_ATTR_MAX + 1] = {
                [OVS_USERSPACE_ATTR_PID] = {.type = NLA_U32 },
                [OVS_USERSPACE_ATTR_USERDATA] = {.type = NLA_UNSPEC },
 +              [OVS_USERSPACE_ATTR_EGRESS_TUN_PORT] = {.type = NLA_U32 },
        };
        struct nlattr *a[OVS_USERSPACE_ATTR_MAX + 1];
        int error;
  }
  
  static int copy_action(const struct nlattr *from,
 -                     struct sw_flow_actions **sfa)
 +                     struct sw_flow_actions **sfa, bool log)
  {
        int totlen = NLA_ALIGN(from->nla_len);
        struct nlattr *to;
  
 -      to = reserve_sfa_size(sfa, from->nla_len);
 +      to = reserve_sfa_size(sfa, from->nla_len, log);
        if (IS_ERR(to))
                return PTR_ERR(to);
  
        return 0;
  }
  
 -int ovs_nla_copy_actions(const struct nlattr *attr,
 -                       const struct sw_flow_key *key,
 -                       int depth,
 -                       struct sw_flow_actions **sfa)
 +static int __ovs_nla_copy_actions(const struct nlattr *attr,
 +                                const struct sw_flow_key *key,
 +                                int depth, struct sw_flow_actions **sfa,
 +                                __be16 eth_type, __be16 vlan_tci, bool log)
  {
        const struct nlattr *a;
 +      bool out_tnl_port = false;
        int rem, err;
  
        if (depth >= SAMPLE_ACTION_DEPTH)
                        [OVS_ACTION_ATTR_OUTPUT] = sizeof(u32),
                        [OVS_ACTION_ATTR_RECIRC] = sizeof(u32),
                        [OVS_ACTION_ATTR_USERSPACE] = (u32)-1,
 +                      [OVS_ACTION_ATTR_PUSH_MPLS] = sizeof(struct ovs_action_push_mpls),
 +                      [OVS_ACTION_ATTR_POP_MPLS] = sizeof(__be16),
                        [OVS_ACTION_ATTR_PUSH_VLAN] = sizeof(struct ovs_action_push_vlan),
                        [OVS_ACTION_ATTR_POP_VLAN] = 0,
                        [OVS_ACTION_ATTR_SET] = (u32)-1,
                case OVS_ACTION_ATTR_OUTPUT:
                        if (nla_get_u32(a) >= DP_MAX_PORTS)
                                return -EINVAL;
 +                      out_tnl_port = false;
 +
                        break;
  
                case OVS_ACTION_ATTR_HASH: {
                }
  
                case OVS_ACTION_ATTR_POP_VLAN:
 +                      vlan_tci = htons(0);
                        break;
  
                case OVS_ACTION_ATTR_PUSH_VLAN:
                                return -EINVAL;
                        if (!(vlan->vlan_tci & htons(VLAN_TAG_PRESENT)))
                                return -EINVAL;
 +                      vlan_tci = vlan->vlan_tci;
                        break;
  
                case OVS_ACTION_ATTR_RECIRC:
                        break;
  
 +              case OVS_ACTION_ATTR_PUSH_MPLS: {
 +                      const struct ovs_action_push_mpls *mpls = nla_data(a);
 +
 +                      /* Networking stack do not allow simultaneous Tunnel
 +                       * and MPLS GSO.
 +                       */
 +                      if (out_tnl_port)
 +                              return -EINVAL;
 +
 +                      if (!eth_p_mpls(mpls->mpls_ethertype))
 +                              return -EINVAL;
 +                      /* Prohibit push MPLS other than to a white list
 +                       * for packets that have a known tag order.
 +                       */
 +                      if (vlan_tci & htons(VLAN_TAG_PRESENT) ||
 +                          (eth_type != htons(ETH_P_IP) &&
 +                           eth_type != htons(ETH_P_IPV6) &&
 +                           eth_type != htons(ETH_P_ARP) &&
 +                           eth_type != htons(ETH_P_RARP) &&
 +                           !eth_p_mpls(eth_type)))
 +                              return -EINVAL;
 +                      eth_type = mpls->mpls_ethertype;
 +                      break;
 +              }
 +
 +              case OVS_ACTION_ATTR_POP_MPLS:
 +                      if (vlan_tci & htons(VLAN_TAG_PRESENT) ||
 +                          !eth_p_mpls(eth_type))
 +                              return -EINVAL;
 +
 +                      /* Disallow subsequent L2.5+ set and mpls_pop actions
 +                       * as there is no check here to ensure that the new
 +                       * eth_type is valid and thus set actions could
 +                       * write off the end of the packet or otherwise
 +                       * corrupt it.
 +                       *
 +                       * Support for these actions is planned using packet
 +                       * recirculation.
 +                       */
 +                      eth_type = htons(0);
 +                      break;
 +
                case OVS_ACTION_ATTR_SET:
 -                      err = validate_set(a, key, sfa, &skip_copy);
 +                      err = validate_set(a, key, sfa,
 +                                         &out_tnl_port, eth_type, log);
                        if (err)
                                return err;
 +
 +                      skip_copy = out_tnl_port;
                        break;
  
                case OVS_ACTION_ATTR_SAMPLE:
 -                      err = validate_and_copy_sample(a, key, depth, sfa);
 +                      err = validate_and_copy_sample(a, key, depth, sfa,
 +                                                     eth_type, vlan_tci, log);
                        if (err)
                                return err;
                        skip_copy = true;
                        break;
  
                default:
 +                      OVS_NLERR(log, "Unknown Action type %d", type);
                        return -EINVAL;
                }
                if (!skip_copy) {
 -                      err = copy_action(a, sfa);
 +                      err = copy_action(a, sfa, log);
                        if (err)
                                return err;
                }
        return 0;
  }
  
 +int ovs_nla_copy_actions(const struct nlattr *attr,
 +                       const struct sw_flow_key *key,
 +                       struct sw_flow_actions **sfa, bool log)
 +{
 +      int err;
 +
 +      *sfa = nla_alloc_flow_actions(nla_len(attr), log);
 +      if (IS_ERR(*sfa))
 +              return PTR_ERR(*sfa);
 +
 +      err = __ovs_nla_copy_actions(attr, key, 0, sfa, key->eth.type,
 +                                   key->eth.tci, log);
 +      if (err)
 +              kfree(*sfa);
 +
 +      return err;
 +}
 +
  static int sample_action_to_attr(const struct nlattr *attr, struct sk_buff *skb)
  {
        const struct nlattr *a;
diff --combined net/sched/Kconfig
@@@ -22,8 -22,9 +22,9 @@@ menuconfig NET_SCHE
          This code is considered to be experimental.
  
          To administer these schedulers, you'll need the user-level utilities
-         from the package iproute2+tc at <ftp://ftp.tux.org/pub/net/ip-routing/>.
-         That package also contains some documentation; for more, check out
+         from the package iproute2+tc at
+         <https://www.kernel.org/pub/linux/utils/net/iproute2/>.  That package
+         also contains some documentation; for more, check out
          <http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2>.
  
          This Quality of Service (QoS) support will enable you to use
@@@ -336,7 -337,7 +337,7 @@@ config NET_SCH_PLU
          of virtual machines by allowing the generated network output to be rolled
          back if needed.
  
-         For more information, please refer to http://wiki.xensource.com/xenwiki/Remus
+         For more information, please refer to <http://wiki.xenproject.org/wiki/Remus>
  
          Say Y here if you are using this kernel for Xen dom0 and
          want to protect Xen guests with Remus.
@@@ -686,17 -687,6 +687,17 @@@ config NET_ACT_CSU
          To compile this code as a module, choose M here: the
          module will be called act_csum.
  
 +config NET_ACT_VLAN
 +        tristate "Vlan manipulation"
 +        depends on NET_CLS_ACT
 +        ---help---
 +        Say Y here to push or pop vlan headers.
 +
 +        If unsure, say N.
 +
 +        To compile this code as a module, choose M here: the
 +        module will be called act_vlan.
 +
  config NET_CLS_IND
        bool "Incoming device classification"
        depends on NET_CLS_U32 || NET_CLS_FW