]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
authorDavid S. Miller <davem@davemloft.net>
Wed, 5 Jun 2013 22:56:43 +0000 (15:56 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 5 Jun 2013 23:37:30 +0000 (16:37 -0700)
Merge 'net' bug fixes into 'net-next' as we have patches
that will build on top of them.

This merge commit includes a change from Emil Goode
(emilgoode@gmail.com) that fixes a warning that would
have been introduced by this merge.  Specifically it
fixes the pingv6_ops method ipv6_chk_addr() to add a
"const" to the "struct net_device *dev" argument and
likewise update the dummy_ipv6_chk_addr() declaration.

Signed-off-by: David S. Miller <davem@davemloft.net>
24 files changed:
1  2 
arch/arm/configs/omap2plus_defconfig
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/broadcom/tg3.h
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_hw.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/qlogic/qlge/qlge_main.c
drivers/net/ethernet/xilinx/xilinx_emaclite.c
drivers/net/phy/phy.c
drivers/net/team/team.c
include/linux/skbuff.h
include/net/ping.h
net/core/skbuff.c
net/ipv4/ip_tunnel.c
net/ipv4/route.c
net/ipv6/addrconf.c
net/ipv6/ping.c
net/ipv6/udp_offload.c
net/mac80211/iface.c
net/sched/sch_tbf.c
net/xfrm/xfrm_policy.c

index aa2100919ee51f1fb2f7123aff2d5c56cbe49489,abbe31937c65228e53dc2c97b4b2d4c14451ec38..769c0f039882c2d99661c41832b2738e82a1ccfd
@@@ -20,6 -20,7 +20,7 @@@ CONFIG_MODULE_FORCE_UNLOAD=
  CONFIG_MODVERSIONS=y
  CONFIG_MODULE_SRCVERSION_ALL=y
  # CONFIG_BLK_DEV_BSG is not set
+ CONFIG_ARCH_MULTI_V6=y
  CONFIG_ARCH_OMAP2PLUS=y
  CONFIG_OMAP_RESET_CLOCKS=y
  CONFIG_OMAP_MUX_DEBUG=y
@@@ -283,4 -284,3 +284,4 @@@ CONFIG_SOC_OMAP5=
  CONFIG_TI_DAVINCI_MDIO=y
  CONFIG_TI_DAVINCI_CPDMA=y
  CONFIG_TI_CPSW=y
 +CONFIG_AT803X_PHY=y
index 14b5acd8eafc172f2d72fc41aee2c6f1c24bf518,638e55435b04f474ff841698cc46cc09f6da1a6f..4e42bdd7c5222bb84422605641a86c425444aedc
@@@ -124,7 -124,7 +124,7 @@@ static void bnx2x_shrink_eth_fp(struct 
        int i, cos, old_eth_num = BNX2X_NUM_ETH_QUEUES(bp);
  
        /* Queue pointer cannot be re-set on an fp-basis, as moving pointer
 -       * backward along the array could cause memory to be overriden
 +       * backward along the array could cause memory to be overridden
         */
        for (cos = 1; cos < bp->max_cos; cos++) {
                for (i = 0; i < old_eth_num - delta; i++) {
@@@ -165,6 -165,7 +165,6 @@@ static u16 bnx2x_free_tx_pkt(struct bnx
        dma_unmap_single(&bp->pdev->dev, BD_UNMAP_ADDR(tx_start_bd),
                         BD_UNMAP_LEN(tx_start_bd), DMA_TO_DEVICE);
  
 -
        nbd = le16_to_cpu(tx_start_bd->nbd) - 1;
  #ifdef BNX2X_STOP_ON_ERROR
        if ((nbd - 1) > (MAX_SKB_FRAGS + 2)) {
@@@ -258,7 -259,7 +258,7 @@@ int bnx2x_tx_int(struct bnx2x *bp, stru
        smp_mb();
  
        if (unlikely(netif_tx_queue_stopped(txq))) {
 -              /* Taking tx_lock() is needed to prevent reenabling the queue
 +              /* Taking tx_lock() is needed to prevent re-enabling the queue
                 * while it's empty. This could have happen if rx_action() gets
                 * suspended in bnx2x_tx_int() after the condition before
                 * netif_tx_wake_queue(), while tx_action (bnx2x_start_xmit()):
@@@ -571,7 -572,7 +571,7 @@@ static int bnx2x_fill_frag_skb(struct b
                        return err;
                }
  
 -              /* Unmap the page as we r going to pass it to the stack */
 +              /* Unmap the page as we're going to pass it to the stack */
                dma_unmap_page(&bp->pdev->dev,
                               dma_unmap_addr(&old_rx_pg, mapping),
                               SGE_PAGES, DMA_FROM_DEVICE);
@@@ -732,6 -733,7 +732,6 @@@ static void bnx2x_tpa_stop(struct bnx2
                        dev_kfree_skb_any(skb);
                }
  
 -
                /* put new data in bin */
                rx_buf->data = new_data;
  
@@@ -897,6 -899,7 +897,6 @@@ int bnx2x_rx_int(struct bnx2x_fastpath 
                                                cqe_fp);
  
                                goto next_rx;
 -
                        }
                        queue = cqe->end_agg_cqe.queue_index;
                        tpa_info = &fp->tpa_info[queue];
@@@ -1001,6 -1004,7 +1001,6 @@@ reuse_rx
                                               le16_to_cpu(cqe_fp->vlan_tag));
                napi_gro_receive(&fp->napi, skb);
  
 -
  next_rx:
                rx_buf->data = NULL;
  
@@@ -1114,7 -1118,7 +1114,7 @@@ static void bnx2x_fill_report_data(stru
  
        memset(data, 0, sizeof(*data));
  
 -      /* Fill the report data: efective line speed */
 +      /* Fill the report data: effective line speed */
        data->line_speed = line_speed;
  
        /* Link is down */
@@@ -1157,7 -1161,7 +1157,7 @@@ void bnx2x_link_report(struct bnx2x *bp
   *
   * @bp:               driver handle
   *
 - * None atomic inmlementation.
 + * None atomic implementation.
   * Should be called under the phy_lock.
   */
  void __bnx2x_link_report(struct bnx2x *bp)
@@@ -1300,7 -1304,7 +1300,7 @@@ void bnx2x_init_rx_rings(struct bnx2x *
                   "mtu %d  rx_buf_size %d\n", bp->dev->mtu, fp->rx_buf_size);
  
                if (!fp->disable_tpa) {
 -                      /* Fill the per-aggregtion pool */
 +                      /* Fill the per-aggregation pool */
                        for (i = 0; i < MAX_AGG_QS(bp); i++) {
                                struct bnx2x_agg_info *tpa_info =
                                        &fp->tpa_info[i];
@@@ -1825,7 -1829,7 +1825,7 @@@ u16 bnx2x_select_queue(struct net_devic
        }
  
        /* select a non-FCoE queue */
 -      return __skb_tx_hash(dev, skb, BNX2X_NUM_ETH_QUEUES(bp));
 +      return __netdev_pick_tx(dev, skb) % BNX2X_NUM_ETH_QUEUES(bp);
  }
  
  void bnx2x_set_num_queues(struct bnx2x *bp)
   *
   * If the actual number of Tx queues (for each CoS) is less than 16 then there
   * will be the holes at the end of each group of 16 ETh L2 indices (0..15,
 - * 16..31,...) with indicies that are not coupled with any real Tx queue.
 + * 16..31,...) with indices that are not coupled with any real Tx queue.
   *
   * The proper configuration of skb->queue_mapping is handled by
   * bnx2x_select_queue() and __skb_tx_hash().
@@@ -1920,7 -1924,7 +1920,7 @@@ static void bnx2x_set_rx_buf_size(struc
                                  ETH_OVREHEAD +
                                  mtu +
                                  BNX2X_FW_RX_ALIGN_END;
 -              /* Note : rx_buf_size doesnt take into account NET_SKB_PAD */
 +              /* Note : rx_buf_size doesn't take into account NET_SKB_PAD */
                if (fp->rx_buf_size + NET_SKB_PAD <= PAGE_SIZE)
                        fp->rx_frag_size = fp->rx_buf_size + NET_SKB_PAD;
                else
@@@ -1933,7 -1937,7 +1933,7 @@@ static int bnx2x_init_rss_pf(struct bnx
        int i;
        u8 num_eth_queues = BNX2X_NUM_ETH_QUEUES(bp);
  
 -      /* Prepare the initial contents fo the indirection table if RSS is
 +      /* Prepare the initial contents for the indirection table if RSS is
         * enabled
         */
        for (i = 0; i < sizeof(bp->rss_conf_obj.ind_table); i++)
@@@ -2011,7 -2015,7 +2011,7 @@@ static int bnx2x_init_hw(struct bnx2x *
  
  /*
   * Cleans the object that have internal lists without sending
 - * ramrods. Should be run when interrutps are disabled.
 + * ramrods. Should be run when interrupts are disabled.
   */
  void bnx2x_squeeze_objects(struct bnx2x *bp)
  {
@@@ -2162,10 -2166,10 +2162,10 @@@ static int bnx2x_alloc_fw_stats_mem(str
        bp->fw_stats_data_mapping = bp->fw_stats_mapping +
                bp->fw_stats_req_sz;
  
 -      DP(BNX2X_MSG_SP, "statistics request base address set to %x %x",
 +      DP(BNX2X_MSG_SP, "statistics request base address set to %x %x\n",
           U64_HI(bp->fw_stats_req_mapping),
           U64_LO(bp->fw_stats_req_mapping));
 -      DP(BNX2X_MSG_SP, "statistics data base address set to %x %x",
 +      DP(BNX2X_MSG_SP, "statistics data base address set to %x %x\n",
           U64_HI(bp->fw_stats_data_mapping),
           U64_LO(bp->fw_stats_data_mapping));
        return 0;
@@@ -2179,8 -2183,6 +2179,8 @@@ alloc_mem_err
  /* send load request to mcp and analyze response */
  static int bnx2x_nic_load_request(struct bnx2x *bp, u32 *load_code)
  {
 +      u32 param;
 +
        /* init fw_seq */
        bp->fw_seq =
                (SHMEM_RD(bp, func_mb[BP_FW_MB_IDX(bp)].drv_mb_header) &
                 DRV_PULSE_SEQ_MASK);
        BNX2X_DEV_INFO("drv_pulse 0x%x\n", bp->fw_drv_pulse_wr_seq);
  
 +      param = DRV_MSG_CODE_LOAD_REQ_WITH_LFA;
 +
 +      if (IS_MF_SD(bp) && bnx2x_port_after_undi(bp))
 +              param |= DRV_MSG_CODE_LOAD_REQ_FORCE_LFA;
 +
        /* load request */
 -      (*load_code) = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ,
 -                                      DRV_MSG_CODE_LOAD_REQ_WITH_LFA);
 +      (*load_code) = bnx2x_fw_command(bp, DRV_MSG_CODE_LOAD_REQ, param);
  
        /* if mcp fails to respond we must abort */
        if (!(*load_code)) {
@@@ -2240,7 -2238,7 +2240,7 @@@ int bnx2x_nic_load_analyze_req(struct b
  
                /* abort nic load if version mismatch */
                if (my_fw != loaded_fw) {
 -                      BNX2X_ERR("bnx2x with FW %x was already loaded which mismatches my %x FW. aborting\n",
 +                      BNX2X_ERR("bnx2x with FW %x was already loaded which mismatches my %x FW. Aborting\n",
                                  loaded_fw, my_fw);
                        return -EBUSY;
                }
@@@ -2318,10 -2316,10 +2318,10 @@@ static void bnx2x_nic_load_afex_dcc(str
  static void bnx2x_bz_fp(struct bnx2x *bp, int index)
  {
        struct bnx2x_fastpath *fp = &bp->fp[index];
 -
        int cos;
        struct napi_struct orig_napi = fp->napi;
        struct bnx2x_agg_info *orig_tpa_info = fp->tpa_info;
 +
        /* bzero bnx2x_fastpath contents */
        if (fp->tpa_info)
                memset(fp->tpa_info, 0, ETH_MAX_AGGREGATION_QUEUES_E1H_E2 *
                        fp->txdata_ptr[cos] = &bp->bnx2x_txq[cos *
                                BNX2X_NUM_ETH_QUEUES(bp) + index];
  
 -      /*
 -       * set the tpa flag for each queue. The tpa flag determines the queue
 +      /* set the tpa flag for each queue. The tpa flag determines the queue
         * minimal size so it must be set prior to queue memory allocation
         */
        fp->disable_tpa = !(bp->flags & TPA_ENABLE_FLAG ||
@@@ -2430,6 -2429,7 +2430,6 @@@ int bnx2x_load_cnic(struct bnx2x *bp
        if (bp->state == BNX2X_STATE_OPEN)
                bnx2x_cnic_notify(bp, CNIC_CTL_START_CMD);
  
 -
        DP(NETIF_MSG_IFUP, "Ending successfully CNIC-related load\n");
  
        return 0;
@@@ -2472,7 -2472,6 +2472,7 @@@ int bnx2x_nic_load(struct bnx2x *bp, in
  
        bp->state = BNX2X_STATE_OPENING_WAIT4_LOAD;
  
 +      /* zero the structure w/o any lock, before SP handler is initialized */
        memset(&bp->last_reported_link, 0, sizeof(bp->last_reported_link));
        __set_bit(BNX2X_LINK_REPORT_LINK_DOWN,
                &bp->last_reported_link.link_report_flags);
        }
  
        /* configure multi cos mappings in kernel.
 -       * this configuration may be overriden by a multi class queue discipline
 -       * or by a dcbx negotiation result.
 +       * this configuration may be overridden by a multi class queue
 +       * discipline or by a dcbx negotiation result.
         */
        bnx2x_setup_tc(bp->dev, bp->max_cos);
  
        /* Start the Tx */
        switch (load_mode) {
        case LOAD_NORMAL:
 -              /* Tx queue should be only reenabled */
 +              /* Tx queue should be only re-enabled */
                netif_tx_wake_all_queues(bp->dev);
                break;
  
@@@ -2842,7 -2841,7 +2842,7 @@@ int bnx2x_nic_unload(struct bnx2x *bp, 
        }
  
        /* Nothing to do during unload if previous bnx2x_nic_load()
 -       * have not completed succesfully - all resourses are released.
 +       * have not completed successfully - all resources are released.
         *
         * we can get here only after unsuccessful ndo_* callback, during which
         * dev->IFF_UP flag is still on.
                /* Send the UNLOAD_REQUEST to the MCP */
                bnx2x_send_unload_req(bp, unload_mode);
  
 -              /*
 -               * Prevent transactions to host from the functions on the
 +              /* Prevent transactions to host from the functions on the
                 * engine that doesn't reset global blocks in case of global
 -               * attention once gloabl blocks are reset and gates are opened
 +               * attention once global blocks are reset and gates are opened
                 * (the engine which leader will perform the recovery
                 * last).
                 */
        }
  
        /*
 -       * At this stage no more interrupts will arrive so we may safly clean
 +       * At this stage no more interrupts will arrive so we may safely clean
         * the queueable objects here in case they failed to get cleaned so far.
         */
        if (IS_PF(bp))
                        bnx2x_set_reset_global(bp);
        }
  
 -
        /* The last driver must disable a "close the gate" if there is no
         * parity attention or "process kill" pending.
         */
@@@ -3191,11 -3192,11 +3191,11 @@@ static u32 bnx2x_xmit_type(struct bnx2
                rc |= XMIT_CSUM_TCP;
  
        if (skb_is_gso_v6(skb)) {
-               rc |= (XMIT_GSO_V6 | XMIT_CSUM_TCP | XMIT_CSUM_V6);
+               rc |= (XMIT_GSO_V6 | XMIT_CSUM_TCP);
                if (rc & XMIT_CSUM_ENC)
                        rc |= XMIT_GSO_ENC_V6;
        } else if (skb_is_gso(skb)) {
-               rc |= (XMIT_GSO_V4 | XMIT_CSUM_V4 | XMIT_CSUM_TCP);
+               rc |= (XMIT_GSO_V4 | XMIT_CSUM_TCP);
                if (rc & XMIT_CSUM_ENC)
                        rc |= XMIT_GSO_ENC_V4;
        }
@@@ -3482,19 -3483,18 +3482,18 @@@ static void bnx2x_update_pbds_gso_enc(s
  {
        u16 hlen_w = 0;
        u8 outerip_off, outerip_len = 0;
        /* from outer IP to transport */
        hlen_w = (skb_inner_transport_header(skb) -
                  skb_network_header(skb)) >> 1;
  
        /* transport len */
-       if (xmit_type & XMIT_CSUM_TCP)
-               hlen_w += inner_tcp_hdrlen(skb) >> 1;
-       else
-               hlen_w += sizeof(struct udphdr) >> 1;
+       hlen_w += inner_tcp_hdrlen(skb) >> 1;
  
        pbd2->fw_ip_hdr_to_payload_w = hlen_w;
  
-       if (xmit_type & XMIT_CSUM_ENC_V4) {
+       /* outer IP header info */
+       if (xmit_type & XMIT_CSUM_V4) {
                struct iphdr *iph = ip_hdr(skb);
                pbd2->fw_ip_csum_wo_len_flags_frag =
                        bswab16(csum_fold((~iph->check) -
@@@ -3586,7 -3586,7 +3585,7 @@@ netdev_tx_t bnx2x_start_xmit(struct sk_
        DP(NETIF_MSG_TX_QUEUED, "indices: txq %d, fp %d, txdata %d\n",
           txq_index, fp_index, txdata_index); */
  
 -      /* enable this debug print to view the tranmission details
 +      /* enable this debug print to view the transmission details
        DP(NETIF_MSG_TX_QUEUED,
           "transmitting packet cid %d fp index %d txdata_index %d tx_data ptr %p fp pointer %p\n",
           txdata->cid, fp_index, txdata_index, txdata, fp); */
                        bnx2x_set_pbd_gso_e2(skb, &pbd_e2_parsing_data,
                                             xmit_type);
                else
-                       bnx2x_set_pbd_gso(skb, pbd_e1x, tx_start_bd,
-                                         xmit_type);
+                       bnx2x_set_pbd_gso(skb, pbd_e1x, first_bd, xmit_type);
        }
  
        /* Set the PBD's parsing_data field if not zero
@@@ -3969,7 -3968,7 +3967,7 @@@ int bnx2x_setup_tc(struct net_device *d
        /* setup tc must be called under rtnl lock */
        ASSERT_RTNL();
  
 -      /* no traffic classes requested. aborting */
 +      /* no traffic classes requested. Aborting */
        if (!num_tc) {
                netdev_reset_tc(dev);
                return 0;
  
        /* requested to support too many traffic classes */
        if (num_tc > bp->max_cos) {
 -              BNX2X_ERR("support for too many traffic classes requested: %d. max supported is %d\n",
 +              BNX2X_ERR("support for too many traffic classes requested: %d. Max supported is %d\n",
                          num_tc, bp->max_cos);
                return -EINVAL;
        }
                   prio, bp->prio_to_cos[prio]);
        }
  
 -
 -      /* Use this configuration to diffrentiate tc0 from other COSes
 +      /* Use this configuration to differentiate tc0 from other COSes
           This can be used for ets or pfc, and save the effort of setting
           up a multio class queue disc or negotiating DCBX with a switch
        netdev_set_prio_tc_map(dev, 0, 0);
@@@ -4472,6 -4472,7 +4470,6 @@@ int bnx2x_alloc_mem_bp(struct bnx2x *bp
  alloc_err:
        bnx2x_free_mem_bp(bp);
        return -ENOMEM;
 -
  }
  
  int bnx2x_reload_if_running(struct net_device *dev)
@@@ -4513,6 -4514,7 +4511,6 @@@ int bnx2x_get_cur_phy_idx(struct bnx2x 
        }
  
        return sel_phy_idx;
 -
  }
  int bnx2x_get_link_cfg_idx(struct bnx2x *bp)
  {
@@@ -4600,7 -4602,6 +4598,7 @@@ int bnx2x_set_features(struct net_devic
  {
        struct bnx2x *bp = netdev_priv(dev);
        u32 flags = bp->flags;
 +      u32 changes;
        bool bnx2x_reload = false;
  
        if (features & NETIF_F_LRO)
                }
        }
  
 -      if (flags ^ bp->flags) {
 -              bp->flags = flags;
 +      changes = flags ^ bp->flags;
 +
 +      /* if GRO is changed while LRO is enabled, don't force a reload */
 +      if ((changes & GRO_ENABLE_FLAG) && (flags & TPA_ENABLE_FLAG))
 +              changes &= ~GRO_ENABLE_FLAG;
 +
 +      if (changes)
                bnx2x_reload = true;
 -      }
 +
 +      bp->flags = flags;
  
        if (bnx2x_reload) {
                if (bp->recovery_state == BNX2X_RECOVERY_DONE)
@@@ -4729,6 -4724,7 +4727,6 @@@ int bnx2x_resume(struct pci_dev *pdev
        return rc;
  }
  
 -
  void bnx2x_set_ctx_validation(struct bnx2x *bp, struct eth_context *cxt,
                              u32 cid)
  {
@@@ -4746,6 -4742,7 +4744,6 @@@ static void storm_memset_hc_timeout(str
                                    u8 fw_sb_id, u8 sb_index,
                                    u8 ticks)
  {
 -
        u32 addr = BAR_CSTRORM_INTMEM +
                   CSTORM_STATUS_BLOCK_DATA_TIMEOUT_OFFSET(fw_sb_id, sb_index);
        REG_WR8(bp, addr, ticks);
index 3cfae0e49207212e42e7c97be15fb5159fd8007a,0f493c8dc28b631039cf87ad266e7ffa19601e69..28a645fc68bf8852c6ba5f1260ced7dced0a3dfa
@@@ -965,6 -965,9 +965,6 @@@ static void tg3_ape_driver_state_change
  
                event = APE_EVENT_STATUS_STATE_UNLOAD;
                break;
 -      case RESET_KIND_SUSPEND:
 -              event = APE_EVENT_STATUS_STATE_SUSPEND;
 -              break;
        default:
                return;
        }
@@@ -1311,8 -1314,8 +1311,8 @@@ static int tg3_phy_toggle_auxctl_smdsp(
  
        if (err)
                return err;
 -      if (enable)
  
 +      if (enable)
                val |= MII_TG3_AUXCTL_ACTL_SMDSP_ENA;
        else
                val &= ~MII_TG3_AUXCTL_ACTL_SMDSP_ENA;
@@@ -1736,6 -1739,10 +1736,6 @@@ static void tg3_write_sig_pre_reset(str
                        break;
                }
        }
 -
 -      if (kind == RESET_KIND_INIT ||
 -          kind == RESET_KIND_SUSPEND)
 -              tg3_ape_driver_state_change(tp, kind);
  }
  
  /* tp->lock is held. */
@@@ -1757,6 -1764,9 +1757,6 @@@ static void tg3_write_sig_post_reset(st
                        break;
                }
        }
 -
 -      if (kind == RESET_KIND_SHUTDOWN)
 -              tg3_ape_driver_state_change(tp, kind);
  }
  
  /* tp->lock is held. */
@@@ -2310,46 -2320,6 +2310,46 @@@ static void tg3_phy_apply_otp(struct tg
        tg3_phy_toggle_auxctl_smdsp(tp, false);
  }
  
 +static void tg3_eee_pull_config(struct tg3 *tp, struct ethtool_eee *eee)
 +{
 +      u32 val;
 +      struct ethtool_eee *dest = &tp->eee;
 +
 +      if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
 +              return;
 +
 +      if (eee)
 +              dest = eee;
 +
 +      if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, TG3_CL45_D7_EEERES_STAT, &val))
 +              return;
 +
 +      /* Pull eee_active */
 +      if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T ||
 +          val == TG3_CL45_D7_EEERES_STAT_LP_100TX) {
 +              dest->eee_active = 1;
 +      } else
 +              dest->eee_active = 0;
 +
 +      /* Pull lp advertised settings */
 +      if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE, &val))
 +              return;
 +      dest->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val);
 +
 +      /* Pull advertised and eee_enabled settings */
 +      if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, &val))
 +              return;
 +      dest->eee_enabled = !!val;
 +      dest->advertised = mmd_eee_adv_to_ethtool_adv_t(val);
 +
 +      /* Pull tx_lpi_enabled */
 +      val = tr32(TG3_CPMU_EEE_MODE);
 +      dest->tx_lpi_enabled = !!(val & TG3_CPMU_EEEMD_LPI_IN_TX);
 +
 +      /* Pull lpi timer value */
 +      dest->tx_lpi_timer = tr32(TG3_CPMU_EEE_DBTMR1) & 0xffff;
 +}
 +
  static void tg3_phy_eee_adjust(struct tg3 *tp, bool current_link_up)
  {
        u32 val;
  
                tw32(TG3_CPMU_EEE_CTRL, eeectl);
  
 -              tg3_phy_cl45_read(tp, MDIO_MMD_AN,
 -                                TG3_CL45_D7_EEERES_STAT, &val);
 -
 -              if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T ||
 -                  val == TG3_CL45_D7_EEERES_STAT_LP_100TX)
 +              tg3_eee_pull_config(tp, NULL);
 +              if (tp->eee.eee_active)
                        tp->setlpicnt = 2;
        }
  
@@@ -4196,8 -4169,6 +4196,8 @@@ static int tg3_power_down_prepare(struc
  
        tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
  
 +      tg3_ape_driver_state_change(tp, RESET_KIND_SHUTDOWN);
 +
        return 0;
  }
  
@@@ -4298,16 -4269,6 +4298,16 @@@ static int tg3_phy_autoneg_cfg(struct t
                /* Advertise 1000-BaseT EEE ability */
                if (advertise & ADVERTISED_1000baseT_Full)
                        val |= MDIO_AN_EEE_ADV_1000T;
 +
 +              if (!tp->eee.eee_enabled) {
 +                      val = 0;
 +                      tp->eee.advertised = 0;
 +              } else {
 +                      tp->eee.advertised = advertise &
 +                                           (ADVERTISED_100baseT_Full |
 +                                            ADVERTISED_1000baseT_Full);
 +              }
 +
                err = tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val);
                if (err)
                        val = 0;
@@@ -4552,23 -4513,26 +4552,23 @@@ static int tg3_init_5401phy_dsp(struct 
  
  static bool tg3_phy_eee_config_ok(struct tg3 *tp)
  {
 -      u32 val;
 -      u32 tgtadv = 0;
 -      u32 advertising = tp->link_config.advertising;
 +      struct ethtool_eee eee;
  
        if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
                return true;
  
 -      if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, &val))
 -              return false;
 -
 -      val &= (MDIO_AN_EEE_ADV_100TX | MDIO_AN_EEE_ADV_1000T);
 -
 +      tg3_eee_pull_config(tp, &eee);
  
 -      if (advertising & ADVERTISED_100baseT_Full)
 -              tgtadv |= MDIO_AN_EEE_ADV_100TX;
 -      if (advertising & ADVERTISED_1000baseT_Full)
 -              tgtadv |= MDIO_AN_EEE_ADV_1000T;
 -
 -      if (val != tgtadv)
 -              return false;
 +      if (tp->eee.eee_enabled) {
 +              if (tp->eee.advertised != eee.advertised ||
 +                  tp->eee.tx_lpi_timer != eee.tx_lpi_timer ||
 +                  tp->eee.tx_lpi_enabled != eee.tx_lpi_enabled)
 +                      return false;
 +      } else {
 +              /* EEE is disabled but we're advertising */
 +              if (eee.advertised)
 +                      return false;
 +      }
  
        return true;
  }
@@@ -4669,42 -4633,6 +4669,42 @@@ static void tg3_clear_mac_status(struc
        udelay(40);
  }
  
 +static void tg3_setup_eee(struct tg3 *tp)
 +{
 +      u32 val;
 +
 +      val = TG3_CPMU_EEE_LNKIDL_PCIE_NL0 |
 +            TG3_CPMU_EEE_LNKIDL_UART_IDL;
 +      if (tg3_chip_rev_id(tp) == CHIPREV_ID_57765_A0)
 +              val |= TG3_CPMU_EEE_LNKIDL_APE_TX_MT;
 +
 +      tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL, val);
 +
 +      tw32_f(TG3_CPMU_EEE_CTRL,
 +             TG3_CPMU_EEE_CTRL_EXIT_20_1_US);
 +
 +      val = TG3_CPMU_EEEMD_ERLY_L1_XIT_DET |
 +            (tp->eee.tx_lpi_enabled ? TG3_CPMU_EEEMD_LPI_IN_TX : 0) |
 +            TG3_CPMU_EEEMD_LPI_IN_RX |
 +            TG3_CPMU_EEEMD_EEE_ENABLE;
 +
 +      if (tg3_asic_rev(tp) != ASIC_REV_5717)
 +              val |= TG3_CPMU_EEEMD_SND_IDX_DET_EN;
 +
 +      if (tg3_flag(tp, ENABLE_APE))
 +              val |= TG3_CPMU_EEEMD_APE_TX_DET_EN;
 +
 +      tw32_f(TG3_CPMU_EEE_MODE, tp->eee.eee_enabled ? val : 0);
 +
 +      tw32_f(TG3_CPMU_EEE_DBTMR1,
 +             TG3_CPMU_DBTMR1_PCIEXIT_2047US |
 +             (tp->eee.tx_lpi_timer & 0xffff));
 +
 +      tw32_f(TG3_CPMU_EEE_DBTMR2,
 +             TG3_CPMU_DBTMR2_APE_TX_2047US |
 +             TG3_CPMU_DBTMR2_TXIDXEQ_2047US);
 +}
 +
  static int tg3_setup_copper_phy(struct tg3 *tp, bool force_reset)
  {
        bool current_link_up;
                         */
                        if (!eee_config_ok &&
                            (tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) &&
 -                          !force_reset)
 +                          !force_reset) {
 +                              tg3_setup_eee(tp);
                                tg3_phy_reset(tp);
 +                      }
                } else {
                        if (!(bmcr & BMCR_ANENABLE) &&
                            tp->link_config.speed == current_speed &&
@@@ -6386,7 -6312,9 +6386,7 @@@ static void tg3_tx_recover(struct tg3 *
                    "Please report the problem to the driver maintainer "
                    "and include system chipset information.\n");
  
 -      spin_lock(&tp->lock);
        tg3_flag_set(tp, TX_RECOVERY_PENDING);
 -      spin_unlock(&tp->lock);
  }
  
  static inline u32 tg3_tx_avail(struct tg3_napi *tnapi)
@@@ -9238,9 -9166,11 +9238,9 @@@ static void __tg3_set_coalesce(struct t
  }
  
  /* tp->lock is held. */
 -static void tg3_rings_reset(struct tg3 *tp)
 +static void tg3_tx_rcbs_disable(struct tg3 *tp)
  {
 -      int i;
 -      u32 stblk, txrcb, rxrcb, limit;
 -      struct tg3_napi *tnapi = &tp->napi[0];
 +      u32 txrcb, limit;
  
        /* Disable all transmit rings but the first. */
        if (!tg3_flag(tp, 5705_PLUS))
             txrcb < limit; txrcb += TG3_BDINFO_SIZE)
                tg3_write_mem(tp, txrcb + TG3_BDINFO_MAXLEN_FLAGS,
                              BDINFO_FLAGS_DISABLED);
 +}
 +
 +/* tp->lock is held. */
 +static void tg3_tx_rcbs_init(struct tg3 *tp)
 +{
 +      int i = 0;
 +      u32 txrcb = NIC_SRAM_SEND_RCB;
 +
 +      if (tg3_flag(tp, ENABLE_TSS))
 +              i++;
 +
 +      for (; i < tp->irq_max; i++, txrcb += TG3_BDINFO_SIZE) {
 +              struct tg3_napi *tnapi = &tp->napi[i];
 +
 +              if (!tnapi->tx_ring)
 +                      continue;
 +
 +              tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping,
 +                             (TG3_TX_RING_SIZE << BDINFO_FLAGS_MAXLEN_SHIFT),
 +                             NIC_SRAM_TX_BUFFER_DESC);
 +      }
 +}
  
 +/* tp->lock is held. */
 +static void tg3_rx_ret_rcbs_disable(struct tg3 *tp)
 +{
 +      u32 rxrcb, limit;
  
        /* Disable all receive return rings but the first. */
        if (tg3_flag(tp, 5717_PLUS))
             rxrcb < limit; rxrcb += TG3_BDINFO_SIZE)
                tg3_write_mem(tp, rxrcb + TG3_BDINFO_MAXLEN_FLAGS,
                              BDINFO_FLAGS_DISABLED);
 +}
 +
 +/* tp->lock is held. */
 +static void tg3_rx_ret_rcbs_init(struct tg3 *tp)
 +{
 +      int i = 0;
 +      u32 rxrcb = NIC_SRAM_RCV_RET_RCB;
 +
 +      if (tg3_flag(tp, ENABLE_RSS))
 +              i++;
 +
 +      for (; i < tp->irq_max; i++, rxrcb += TG3_BDINFO_SIZE) {
 +              struct tg3_napi *tnapi = &tp->napi[i];
 +
 +              if (!tnapi->rx_rcb)
 +                      continue;
 +
 +              tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
 +                             (tp->rx_ret_ring_mask + 1) <<
 +                              BDINFO_FLAGS_MAXLEN_SHIFT, 0);
 +      }
 +}
 +
 +/* tp->lock is held. */
 +static void tg3_rings_reset(struct tg3 *tp)
 +{
 +      int i;
 +      u32 stblk;
 +      struct tg3_napi *tnapi = &tp->napi[0];
 +
 +      tg3_tx_rcbs_disable(tp);
 +
 +      tg3_rx_ret_rcbs_disable(tp);
  
        /* Disable interrupts */
        tw32_mailbox_f(tp->napi[0].int_mbox, 1);
                        tw32_tx_mbox(mbox + i * 8, 0);
        }
  
 -      txrcb = NIC_SRAM_SEND_RCB;
 -      rxrcb = NIC_SRAM_RCV_RET_RCB;
 -
        /* Clear status block in ram. */
        memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
  
        tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
             ((u64) tnapi->status_mapping & 0xffffffff));
  
 -      if (tnapi->tx_ring) {
 -              tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping,
 -                             (TG3_TX_RING_SIZE <<
 -                              BDINFO_FLAGS_MAXLEN_SHIFT),
 -                             NIC_SRAM_TX_BUFFER_DESC);
 -              txrcb += TG3_BDINFO_SIZE;
 -      }
 -
 -      if (tnapi->rx_rcb) {
 -              tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
 -                             (tp->rx_ret_ring_mask + 1) <<
 -                              BDINFO_FLAGS_MAXLEN_SHIFT, 0);
 -              rxrcb += TG3_BDINFO_SIZE;
 -      }
 -
        stblk = HOSTCC_STATBLCK_RING1;
  
        for (i = 1, tnapi++; i < tp->irq_cnt; i++, tnapi++) {
                u64 mapping = (u64)tnapi->status_mapping;
                tw32(stblk + TG3_64BIT_REG_HIGH, mapping >> 32);
                tw32(stblk + TG3_64BIT_REG_LOW, mapping & 0xffffffff);
 +              stblk += 8;
  
                /* Clear status block in ram. */
                memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
 -
 -              if (tnapi->tx_ring) {
 -                      tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping,
 -                                     (TG3_TX_RING_SIZE <<
 -                                      BDINFO_FLAGS_MAXLEN_SHIFT),
 -                                     NIC_SRAM_TX_BUFFER_DESC);
 -                      txrcb += TG3_BDINFO_SIZE;
 -              }
 -
 -              tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
 -                             ((tp->rx_ret_ring_mask + 1) <<
 -                              BDINFO_FLAGS_MAXLEN_SHIFT), 0);
 -
 -              stblk += 8;
 -              rxrcb += TG3_BDINFO_SIZE;
        }
 +
 +      tg3_tx_rcbs_init(tp);
 +      tg3_rx_ret_rcbs_init(tp);
  }
  
  static void tg3_setup_rxbd_thresholds(struct tg3 *tp)
@@@ -9568,6 -9468,14 +9568,14 @@@ static void tg3_rss_write_indir_tbl(str
        }
  }
  
+ static inline u32 tg3_lso_rd_dma_workaround_bit(struct tg3 *tp)
+ {
+       if (tg3_asic_rev(tp) == ASIC_REV_5719)
+               return TG3_LSO_RD_DMA_TX_LENGTH_WA_5719;
+       else
+               return TG3_LSO_RD_DMA_TX_LENGTH_WA_5720;
+ }
  /* tp->lock is held. */
  static int tg3_reset_hw(struct tg3 *tp, bool reset_phy)
  {
        if (tg3_flag(tp, INIT_COMPLETE))
                tg3_abort_hw(tp, 1);
  
 -      /* Enable MAC control of LPI */
 -      if (tp->phy_flags & TG3_PHYFLG_EEE_CAP) {
 -              val = TG3_CPMU_EEE_LNKIDL_PCIE_NL0 |
 -                    TG3_CPMU_EEE_LNKIDL_UART_IDL;
 -              if (tg3_chip_rev_id(tp) == CHIPREV_ID_57765_A0)
 -                      val |= TG3_CPMU_EEE_LNKIDL_APE_TX_MT;
 -
 -              tw32_f(TG3_CPMU_EEE_LNKIDL_CTRL, val);
 -
 -              tw32_f(TG3_CPMU_EEE_CTRL,
 -                     TG3_CPMU_EEE_CTRL_EXIT_20_1_US);
 -
 -              val = TG3_CPMU_EEEMD_ERLY_L1_XIT_DET |
 -                    TG3_CPMU_EEEMD_LPI_IN_TX |
 -                    TG3_CPMU_EEEMD_LPI_IN_RX |
 -                    TG3_CPMU_EEEMD_EEE_ENABLE;
 -
 -              if (tg3_asic_rev(tp) != ASIC_REV_5717)
 -                      val |= TG3_CPMU_EEEMD_SND_IDX_DET_EN;
 -
 -              if (tg3_flag(tp, ENABLE_APE))
 -                      val |= TG3_CPMU_EEEMD_APE_TX_DET_EN;
 -
 -              tw32_f(TG3_CPMU_EEE_MODE, val);
 -
 -              tw32_f(TG3_CPMU_EEE_DBTMR1,
 -                     TG3_CPMU_DBTMR1_PCIEXIT_2047US |
 -                     TG3_CPMU_DBTMR1_LNKIDLE_2047US);
 -
 -              tw32_f(TG3_CPMU_EEE_DBTMR2,
 -                     TG3_CPMU_DBTMR2_APE_TX_2047US |
 -                     TG3_CPMU_DBTMR2_TXIDXEQ_2047US);
 -      }
 -
        if ((tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) &&
            !(tp->phy_flags & TG3_PHYFLG_USER_CONFIGURED)) {
                tg3_phy_pull_config(tp);
 +              tg3_eee_pull_config(tp, NULL);
                tp->phy_flags |= TG3_PHYFLG_USER_CONFIGURED;
        }
  
 +      /* Enable MAC control of LPI */
 +      if (tp->phy_flags & TG3_PHYFLG_EEE_CAP)
 +              tg3_setup_eee(tp);
 +
        if (reset_phy)
                tg3_phy_reset(tp);
  
        tw32_f(RDMAC_MODE, rdmac_mode);
        udelay(40);
  
-       if (tg3_asic_rev(tp) == ASIC_REV_5719) {
+       if (tg3_asic_rev(tp) == ASIC_REV_5719 ||
+           tg3_asic_rev(tp) == ASIC_REV_5720) {
                for (i = 0; i < TG3_NUM_RDMA_CHANNELS; i++) {
                        if (tr32(TG3_RDMA_LENGTH + (i << 2)) > TG3_MAX_MTU(tp))
                                break;
                }
                if (i < TG3_NUM_RDMA_CHANNELS) {
                        val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL);
-                       val |= TG3_LSO_RD_DMA_TX_LENGTH_WA;
+                       val |= tg3_lso_rd_dma_workaround_bit(tp);
                        tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val);
-                       tg3_flag_set(tp, 5719_RDMA_BUG);
+                       tg3_flag_set(tp, 5719_5720_RDMA_BUG);
                }
        }
  
@@@ -10597,15 -10535,15 +10606,15 @@@ static void tg3_periodic_fetch_stats(st
        TG3_STAT_ADD32(&sp->tx_ucast_packets, MAC_TX_STATS_UCAST);
        TG3_STAT_ADD32(&sp->tx_mcast_packets, MAC_TX_STATS_MCAST);
        TG3_STAT_ADD32(&sp->tx_bcast_packets, MAC_TX_STATS_BCAST);
-       if (unlikely(tg3_flag(tp, 5719_RDMA_BUG) &&
+       if (unlikely(tg3_flag(tp, 5719_5720_RDMA_BUG) &&
                     (sp->tx_ucast_packets.low + sp->tx_mcast_packets.low +
                      sp->tx_bcast_packets.low) > TG3_NUM_RDMA_CHANNELS)) {
                u32 val;
  
                val = tr32(TG3_LSO_RD_DMA_CRPTEN_CTRL);
-               val &= ~TG3_LSO_RD_DMA_TX_LENGTH_WA;
+               val &= ~tg3_lso_rd_dma_workaround_bit(tp);
                tw32(TG3_LSO_RD_DMA_CRPTEN_CTRL, val);
-               tg3_flag_clear(tp, 5719_RDMA_BUG);
+               tg3_flag_clear(tp, 5719_5720_RDMA_BUG);
        }
  
        TG3_STAT_ADD32(&sp->rx_octets, MAC_RX_STATS_OCTETS);
@@@ -11242,7 -11180,7 +11251,7 @@@ static int tg3_start(struct tg3 *tp, bo
         */
        err = tg3_alloc_consistent(tp);
        if (err)
 -              goto err_out1;
 +              goto out_ints_fini;
  
        tg3_napi_init(tp);
  
                                tnapi = &tp->napi[i];
                                free_irq(tnapi->irq_vec, tnapi);
                        }
 -                      goto err_out2;
 +                      goto out_napi_fini;
                }
        }
  
        tg3_full_lock(tp, 0);
  
 +      if (init)
 +              tg3_ape_driver_state_change(tp, RESET_KIND_INIT);
 +
        err = tg3_init_hw(tp, reset_phy);
        if (err) {
                tg3_halt(tp, RESET_KIND_SHUTDOWN, 1);
        tg3_full_unlock(tp);
  
        if (err)
 -              goto err_out3;
 +              goto out_free_irq;
  
        if (test_irq && tg3_flag(tp, USING_MSI)) {
                err = tg3_test_msi(tp);
                        tg3_free_rings(tp);
                        tg3_full_unlock(tp);
  
 -                      goto err_out2;
 +                      goto out_napi_fini;
                }
  
                if (!tg3_flag(tp, 57765_PLUS) && tg3_flag(tp, USING_MSI)) {
  
        return 0;
  
 -err_out3:
 +out_free_irq:
        for (i = tp->irq_cnt - 1; i >= 0; i--) {
                struct tg3_napi *tnapi = &tp->napi[i];
                free_irq(tnapi->irq_vec, tnapi);
        }
  
 -err_out2:
 +out_napi_fini:
        tg3_napi_disable(tp);
        tg3_napi_fini(tp);
        tg3_free_consistent(tp);
  
 -err_out1:
 +out_ints_fini:
        tg3_ints_fini(tp);
  
        return err;
@@@ -13381,13 -13316,11 +13390,13 @@@ static void tg3_self_test(struct net_de
        struct tg3 *tp = netdev_priv(dev);
        bool doextlpbk = etest->flags & ETH_TEST_FL_EXTERNAL_LB;
  
 -      if ((tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) &&
 -          tg3_power_up(tp)) {
 -              etest->flags |= ETH_TEST_FL_FAILED;
 -              memset(data, 1, sizeof(u64) * TG3_NUM_TEST);
 -              return;
 +      if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
 +              if (tg3_power_up(tp)) {
 +                      etest->flags |= ETH_TEST_FL_FAILED;
 +                      memset(data, 1, sizeof(u64) * TG3_NUM_TEST);
 +                      return;
 +              }
 +              tg3_ape_driver_state_change(tp, RESET_KIND_INIT);
        }
  
        memset(data, 0, sizeof(u64) * TG3_NUM_TEST);
@@@ -13678,57 -13611,6 +13687,57 @@@ static int tg3_set_coalesce(struct net_
        return 0;
  }
  
 +static int tg3_set_eee(struct net_device *dev, struct ethtool_eee *edata)
 +{
 +      struct tg3 *tp = netdev_priv(dev);
 +
 +      if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) {
 +              netdev_warn(tp->dev, "Board does not support EEE!\n");
 +              return -EOPNOTSUPP;
 +      }
 +
 +      if (edata->advertised != tp->eee.advertised) {
 +              netdev_warn(tp->dev,
 +                          "Direct manipulation of EEE advertisement is not supported\n");
 +              return -EINVAL;
 +      }
 +
 +      if (edata->tx_lpi_timer > TG3_CPMU_DBTMR1_LNKIDLE_MAX) {
 +              netdev_warn(tp->dev,
 +                          "Maximal Tx Lpi timer supported is %#x(u)\n",
 +                          TG3_CPMU_DBTMR1_LNKIDLE_MAX);
 +              return -EINVAL;
 +      }
 +
 +      tp->eee = *edata;
 +
 +      tp->phy_flags |= TG3_PHYFLG_USER_CONFIGURED;
 +      tg3_warn_mgmt_link_flap(tp);
 +
 +      if (netif_running(tp->dev)) {
 +              tg3_full_lock(tp, 0);
 +              tg3_setup_eee(tp);
 +              tg3_phy_reset(tp);
 +              tg3_full_unlock(tp);
 +      }
 +
 +      return 0;
 +}
 +
 +static int tg3_get_eee(struct net_device *dev, struct ethtool_eee *edata)
 +{
 +      struct tg3 *tp = netdev_priv(dev);
 +
 +      if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP)) {
 +              netdev_warn(tp->dev,
 +                          "Board does not support EEE!\n");
 +              return -EOPNOTSUPP;
 +      }
 +
 +      *edata = tp->eee;
 +      return 0;
 +}
 +
  static const struct ethtool_ops tg3_ethtool_ops = {
        .get_settings           = tg3_get_settings,
        .set_settings           = tg3_set_settings,
        .get_channels           = tg3_get_channels,
        .set_channels           = tg3_set_channels,
        .get_ts_info            = tg3_get_ts_info,
 +      .get_eee                = tg3_get_eee,
 +      .set_eee                = tg3_set_eee,
  };
  
  static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev,
@@@ -15112,18 -14992,9 +15121,18 @@@ static int tg3_phy_probe(struct tg3 *tp
             (tg3_asic_rev(tp) == ASIC_REV_5717 &&
              tg3_chip_rev_id(tp) != CHIPREV_ID_5717_A0) ||
             (tg3_asic_rev(tp) == ASIC_REV_57765 &&
 -            tg3_chip_rev_id(tp) != CHIPREV_ID_57765_A0)))
 +            tg3_chip_rev_id(tp) != CHIPREV_ID_57765_A0))) {
                tp->phy_flags |= TG3_PHYFLG_EEE_CAP;
  
 +              tp->eee.supported = SUPPORTED_100baseT_Full |
 +                                  SUPPORTED_1000baseT_Full;
 +              tp->eee.advertised = ADVERTISED_100baseT_Full |
 +                                   ADVERTISED_1000baseT_Full;
 +              tp->eee.eee_enabled = 1;
 +              tp->eee.tx_lpi_enabled = 1;
 +              tp->eee.tx_lpi_timer = TG3_CPMU_DBTMR1_LNKIDLE_2047US;
 +      }
 +
        tg3_phy_init_link_config(tp);
  
        if (!(tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN) &&
@@@ -17195,7 -17066,7 +17204,7 @@@ static int tg3_init_one(struct pci_dev 
  {
        struct net_device *dev;
        struct tg3 *tp;
 -      int i, err, pm_cap;
 +      int i, err;
        u32 sndmbx, rcvmbx, intmbx;
        char str[40];
        u64 dma_mask, persist_dma_mask;
  
        pci_set_master(pdev);
  
 -      /* Find power-management capability. */
 -      pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM);
 -      if (pm_cap == 0) {
 -              dev_err(&pdev->dev,
 -                      "Cannot find Power Management capability, aborting\n");
 -              err = -EIO;
 -              goto err_out_free_res;
 -      }
 -
 -      err = pci_set_power_state(pdev, PCI_D0);
 -      if (err) {
 -              dev_err(&pdev->dev, "Transition to D0 failed, aborting\n");
 -              goto err_out_free_res;
 -      }
 -
        dev = alloc_etherdev_mq(sizeof(*tp), TG3_IRQ_MAX_VECS);
        if (!dev) {
                err = -ENOMEM;
 -              goto err_out_power_down;
 +              goto err_out_free_res;
        }
  
        SET_NETDEV_DEV(dev, &pdev->dev);
        tp = netdev_priv(dev);
        tp->pdev = pdev;
        tp->dev = dev;
 -      tp->pm_cap = pm_cap;
 +      tp->pm_cap = pdev->pm_cap;
        tp->rx_mode = TG3_DEF_RX_MODE;
        tp->tx_mode = TG3_DEF_TX_MODE;
        tp->irq_sync = 1;
@@@ -17566,6 -17452,9 +17575,6 @@@ err_out_iounmap
  err_out_free_dev:
        free_netdev(dev);
  
 -err_out_power_down:
 -      pci_set_power_state(pdev, PCI_D3hot);
 -
  err_out_free_res:
        pci_release_regions(pdev);
  
@@@ -17675,8 -17564,6 +17684,8 @@@ static int tg3_resume(struct device *de
  
        tg3_full_lock(tp, 0);
  
 +      tg3_ape_driver_state_change(tp, RESET_KIND_INIT);
 +
        tg3_flag_set(tp, INIT_COMPLETE);
        err = tg3_restart_hw(tp,
                             !(tp->phy_flags & TG3_PHYFLG_KEEP_LINK_ON_PWRDN));
@@@ -17811,7 -17698,6 +17820,7 @@@ static void tg3_io_resume(struct pci_de
                goto done;
  
        tg3_full_lock(tp, 0);
 +      tg3_ape_driver_state_change(tp, RESET_KIND_INIT);
        tg3_flag_set(tp, INIT_COMPLETE);
        err = tg3_restart_hw(tp, true);
        if (err) {
@@@ -17849,4 -17735,15 +17858,4 @@@ static struct pci_driver tg3_driver = 
        .driver.pm      = &tg3_pm_ops,
  };
  
 -static int __init tg3_init(void)
 -{
 -      return pci_register_driver(&tg3_driver);
 -}
 -
 -static void __exit tg3_cleanup(void)
 -{
 -      pci_unregister_driver(&tg3_driver);
 -}
 -
 -module_init(tg3_init);
 -module_exit(tg3_cleanup);
 +module_pci_driver(tg3_driver);
index 2530c20dd8235ae091fdb12d7c0a2cf43e04abc5,ff6e30eeae354e11895ae3e77bef4644050dd730..cd63d1189aae9fdfbcceb5615d76b8d6d74704d2
  #define TG3_CPMU_EEE_DBTMR1           0x000036b4
  #define  TG3_CPMU_DBTMR1_PCIEXIT_2047US        0x07ff0000
  #define  TG3_CPMU_DBTMR1_LNKIDLE_2047US        0x000007ff
 +#define  TG3_CPMU_DBTMR1_LNKIDLE_MAX   0x0000ffff
  #define TG3_CPMU_EEE_DBTMR2           0x000036b8
  #define  TG3_CPMU_DBTMR2_APE_TX_2047US         0x07ff0000
  #define  TG3_CPMU_DBTMR2_TXIDXEQ_2047US        0x000007ff
  #define TG3_LSO_RD_DMA_CRPTEN_CTRL    0x00004910
  #define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_BD_4K  0x00030000
  #define TG3_LSO_RD_DMA_CRPTEN_CTRL_BLEN_LSO_4K         0x000c0000
- #define TG3_LSO_RD_DMA_TX_LENGTH_WA    0x02000000
+ #define TG3_LSO_RD_DMA_TX_LENGTH_WA_5719       0x02000000
+ #define TG3_LSO_RD_DMA_TX_LENGTH_WA_5720       0x00200000
  /* 0x4914 --> 0x4be0 unused */
  
  #define TG3_NUM_RDMA_CHANNELS         4
@@@ -3060,7 -3060,7 +3061,7 @@@ enum TG3_FLAGS 
        TG3_FLAG_APE_HAS_NCSI,
        TG3_FLAG_TX_TSTAMP_EN,
        TG3_FLAG_4K_FIFO_LIMIT,
-       TG3_FLAG_5719_RDMA_BUG,
+       TG3_FLAG_5719_5720_RDMA_BUG,
        TG3_FLAG_RESET_TASK_PENDING,
        TG3_FLAG_PTP_CAPABLE,
        TG3_FLAG_5705_PLUS,
@@@ -3372,7 -3372,6 +3373,7 @@@ struct tg3 
        unsigned int                    irq_cnt;
  
        struct ethtool_coalesce         coal;
 +      struct ethtool_eee              eee;
  
        /* firmware info */
        const char                      *fw_needed;
index fcc30a2d831b8dbdbd9a7cecff2e815a6d97abd2,0a510684e46857a66b8c969b63ea728b8ec446b9..c827b1b6b1ceb81c5d10bdc2db6fcea3192701a3
@@@ -262,6 -262,7 +262,7 @@@ struct be_rx_compl_info 
        u8 ipv6;
        u8 vtm;
        u8 pkt_type;
+       u8 ip_frag;
  };
  
  struct be_rx_obj {
@@@ -332,9 -333,6 +333,9 @@@ enum vf_state 
  #define BE_VF_UC_PMAC_COUNT           2
  #define BE_FLAGS_QNQ_ASYNC_EVT_RCVD           (1 << 11)
  
 +/* Ethtool set_dump flags */
 +#define LANCER_INITIATE_FW_DUMP                       0x1
 +
  struct phy_info {
        u8 transceiver;
        u8 autoneg;
@@@ -400,7 -398,6 +401,7 @@@ struct be_adapter 
        u32 cmd_privileges;
        /* Ethtool knobs and info */
        char fw_ver[FW_VER_LEN];
 +      char fw_on_flash[FW_VER_LEN];
        int if_handle;          /* Used to configure filtering */
        u32 *pmac_id;           /* MAC addr handle used by BE card */
        u32 beacon_state;       /* for set_phys_id */
index 4d0ec3649a632dcb9e6fcf67eb638823f281b094,1db2df61b8af65d5b0ca32534b8b6a96e9a2c794..6e6e0a117ee2fe16061ae8e0b77a51aaacd3336b
@@@ -562,7 -562,7 +562,7 @@@ int lancer_test_and_set_rdy_state(struc
  
        resource_error = lancer_provisioning_error(adapter);
        if (resource_error)
-               return -1;
+               return -EAGAIN;
  
        status = lancer_wait_ready(adapter);
        if (!status) {
         * when PF provisions resources.
         */
        resource_error = lancer_provisioning_error(adapter);
-       if (status == -1 && !resource_error)
-               adapter->eeh_error = true;
+       if (resource_error)
+               status = -EAGAIN;
  
        return status;
  }
        return status;
  }
  
 +static int lancer_wait_idle(struct be_adapter *adapter)
 +{
 +#define SLIPORT_IDLE_TIMEOUT 30
 +      u32 reg_val;
 +      int status = 0, i;
 +
 +      for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) {
 +              reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET);
 +              if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0)
 +                      break;
 +
 +              ssleep(1);
 +      }
 +
 +      if (i == SLIPORT_IDLE_TIMEOUT)
 +              status = -1;
 +
 +      return status;
 +}
 +
 +int lancer_physdev_ctrl(struct be_adapter *adapter, u32 mask)
 +{
 +      int status = 0;
 +
 +      status = lancer_wait_idle(adapter);
 +      if (status)
 +              return status;
 +
 +      iowrite32(mask, adapter->db + PHYSDEV_CONTROL_OFFSET);
 +
 +      return status;
 +}
 +
 +/* Routine to check whether dump image is present or not */
 +bool dump_present(struct be_adapter *adapter)
 +{
 +      u32 sliport_status = 0;
 +
 +      sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
 +      return !!(sliport_status & SLIPORT_STATUS_DIP_MASK);
 +}
 +
 +int lancer_initiate_dump(struct be_adapter *adapter)
 +{
 +      int status;
 +
 +      /* give firmware reset and diagnostic dump */
 +      status = lancer_physdev_ctrl(adapter, PHYSDEV_CONTROL_FW_RESET_MASK |
 +                                   PHYSDEV_CONTROL_DD_MASK);
 +      if (status < 0) {
 +              dev_err(&adapter->pdev->dev, "Firmware reset failed\n");
 +              return status;
 +      }
 +
 +      status = lancer_wait_idle(adapter);
 +      if (status)
 +              return status;
 +
 +      if (!dump_present(adapter)) {
 +              dev_err(&adapter->pdev->dev, "Dump image not present\n");
 +              return -1;
 +      }
 +
 +      return 0;
 +}
 +
  /* Uses sync mcc */
  int be_cmd_enable_vf(struct be_adapter *adapter, u8 domain)
  {
index 0311d9bfe8585742ff339e4a9c5098351b78e34f,8780183c6d1c3aa3168e55d59c51c3f63e545267..3e2162121601e79481428c4d7ca02c3523dc0e33
  #define PHYSDEV_CONTROL_OFFSET                0x414
  
  #define SLIPORT_STATUS_ERR_MASK               0x80000000
 +#define SLIPORT_STATUS_DIP_MASK               0x02000000
  #define SLIPORT_STATUS_RN_MASK                0x01000000
  #define SLIPORT_STATUS_RDY_MASK               0x00800000
  #define SLI_PORT_CONTROL_IP_MASK      0x08000000
  #define PHYSDEV_CONTROL_FW_RESET_MASK 0x00000002
 +#define PHYSDEV_CONTROL_DD_MASK               0x00000004
  #define PHYSDEV_CONTROL_INP_MASK      0x40000000
  
  #define SLIPORT_ERROR_NO_RESOURCE1    0x2
@@@ -358,7 -356,7 +358,7 @@@ struct amap_eth_rx_compl_v0 
        u8 ip_version;          /* dword 1 */
        u8 macdst[6];           /* dword 1 */
        u8 vtp;                 /* dword 1 */
-       u8 rsvd0;               /* dword 1 */
+       u8 ip_frag;             /* dword 1 */
        u8 fragndx[10];         /* dword 1 */
        u8 ct[2];               /* dword 1 */
        u8 sw;                  /* dword 1 */
index 5d9044e4afe23c3236405ac55c3ff7a3b32f1260,8bc1b21b1c790b44cffc347d7fe365f22f3a7ee2..9aef457dacbb9d99a38d514530528cc4bf71bd95
@@@ -834,39 -834,32 +834,39 @@@ static int be_vlan_tag_tx_chk(struct be
        return vlan_tx_tag_present(skb) || adapter->pvid || adapter->qnq_vid;
  }
  
 -static int be_ipv6_tx_stall_chk(struct be_adapter *adapter, struct sk_buff *skb)
 +static int be_ipv6_tx_stall_chk(struct be_adapter *adapter,
 +                              struct sk_buff *skb)
  {
 -      return BE3_chip(adapter) &&
 -              be_ipv6_exthdr_check(skb);
 +      return BE3_chip(adapter) && be_ipv6_exthdr_check(skb);
  }
  
 -static netdev_tx_t be_xmit(struct sk_buff *skb,
 -                      struct net_device *netdev)
 +static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter,
 +                                         struct sk_buff *skb,
 +                                         bool *skip_hw_vlan)
  {
 -      struct be_adapter *adapter = netdev_priv(netdev);
 -      struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)];
 -      struct be_queue_info *txq = &txo->q;
 -      struct iphdr *ip = NULL;
 -      u32 wrb_cnt = 0, copied = 0;
 -      u32 start = txq->head, eth_hdr_len;
 -      bool dummy_wrb, stopped = false;
 -      bool skip_hw_vlan = false;
        struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
 +      unsigned int eth_hdr_len;
 +      struct iphdr *ip;
  
 -      eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ?
 -              VLAN_ETH_HLEN : ETH_HLEN;
 +      /* Lancer ASIC has a bug wherein packets that are 32 bytes or less
 +       * may cause a transmit stall on that port. So the work-around is to
 +       * pad such packets to a 36-byte length.
 +       */
 +      if (unlikely(lancer_chip(adapter) && skb->len <= 32)) {
 +              if (skb_padto(skb, 36))
 +                      goto tx_drop;
 +              skb->len = 36;
 +      }
  
        /* For padded packets, BE HW modifies tot_len field in IP header
         * incorrecly when VLAN tag is inserted by HW.
 +       * For padded packets, Lancer computes incorrect checksum.
         */
 -      if (skb->len <= 60 && vlan_tx_tag_present(skb) && is_ipv4_pkt(skb)) {
 +      eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ?
 +                                              VLAN_ETH_HLEN : ETH_HLEN;
 +      if (skb->len <= 60 &&
 +          (lancer_chip(adapter) || vlan_tx_tag_present(skb)) &&
 +          is_ipv4_pkt(skb)) {
                ip = (struct iphdr *)ip_hdr(skb);
                pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len));
        }
         */
        if ((adapter->function_mode & UMC_ENABLED) &&
            veh->h_vlan_proto == htons(ETH_P_8021Q))
 -                      skip_hw_vlan = true;
 +                      *skip_hw_vlan = true;
  
        /* HW has a bug wherein it will calculate CSUM for VLAN
         * pkts even though it is disabled.
         * Manually insert VLAN in pkt.
         */
        if (skb->ip_summed != CHECKSUM_PARTIAL &&
 -                      vlan_tx_tag_present(skb)) {
 -              skb = be_insert_vlan_in_pkt(adapter, skb, &skip_hw_vlan);
 +          vlan_tx_tag_present(skb)) {
 +              skb = be_insert_vlan_in_pkt(adapter, skb, skip_hw_vlan);
                if (unlikely(!skb))
                        goto tx_drop;
        }
         * skip HW tagging is not enabled by FW.
         */
        if (unlikely(be_ipv6_tx_stall_chk(adapter, skb) &&
 -                   (adapter->pvid || adapter->qnq_vid) &&
 -                   !qnq_async_evt_rcvd(adapter)))
 +          (adapter->pvid || adapter->qnq_vid) &&
 +          !qnq_async_evt_rcvd(adapter)))
                goto tx_drop;
  
        /* Manual VLAN tag insertion to prevent:
         */
        if (be_ipv6_tx_stall_chk(adapter, skb) &&
            be_vlan_tag_tx_chk(adapter, skb)) {
 -              skb = be_insert_vlan_in_pkt(adapter, skb, &skip_hw_vlan);
 +              skb = be_insert_vlan_in_pkt(adapter, skb, skip_hw_vlan);
                if (unlikely(!skb))
                        goto tx_drop;
        }
  
 +      return skb;
 +tx_drop:
 +      dev_kfree_skb_any(skb);
 +      return NULL;
 +}
 +
 +static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev)
 +{
 +      struct be_adapter *adapter = netdev_priv(netdev);
 +      struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)];
 +      struct be_queue_info *txq = &txo->q;
 +      bool dummy_wrb, stopped = false;
 +      u32 wrb_cnt = 0, copied = 0;
 +      bool skip_hw_vlan = false;
 +      u32 start = txq->head;
 +
 +      skb = be_xmit_workarounds(adapter, skb, &skip_hw_vlan);
 +      if (!skb)
 +              return NETDEV_TX_OK;
 +
        wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb);
  
        copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb,
                txq->head = start;
                dev_kfree_skb_any(skb);
        }
 -tx_drop:
        return NETDEV_TX_OK;
  }
  
@@@ -1625,6 -1599,8 +1625,8 @@@ static void be_parse_rx_compl_v0(struc
                                               compl);
        }
        rxcp->port = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, port, compl);
+       rxcp->ip_frag = AMAP_GET_BITS(struct amap_eth_rx_compl_v0,
+                                     ip_frag, compl);
  }
  
  static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
        else
                be_parse_rx_compl_v0(compl, rxcp);
  
+       if (rxcp->ip_frag)
+               rxcp->l4_csum = 0;
        if (rxcp->vlanf) {
                /* vlanf could be wrongly set in some cards.
                 * ignore if vtm is not set */
@@@ -2194,7 -2173,7 +2199,7 @@@ static irqreturn_t be_msix(int irq, voi
  
  static inline bool do_gro(struct be_rx_compl_info *rxcp)
  {
-       return (rxcp->tcpf && !rxcp->err) ? true : false;
+       return (rxcp->tcpf && !rxcp->err && rxcp->l4_csum) ? true : false;
  }
  
  static int be_process_rx(struct be_rx_obj *rxo, struct napi_struct *napi,
@@@ -3205,7 -3184,7 +3210,7 @@@ static int be_setup(struct be_adapter *
        if (status)
                goto err;
  
 -      be_cmd_get_fw_ver(adapter, adapter->fw_ver, NULL);
 +      be_cmd_get_fw_ver(adapter, adapter->fw_ver, adapter->fw_on_flash);
  
        if (adapter->vlans_added)
                be_vid_config(adapter);
@@@ -3551,6 -3530,40 +3556,6 @@@ static int be_flash_skyhawk(struct be_a
        return 0;
  }
  
 -static int lancer_wait_idle(struct be_adapter *adapter)
 -{
 -#define SLIPORT_IDLE_TIMEOUT 30
 -      u32 reg_val;
 -      int status = 0, i;
 -
 -      for (i = 0; i < SLIPORT_IDLE_TIMEOUT; i++) {
 -              reg_val = ioread32(adapter->db + PHYSDEV_CONTROL_OFFSET);
 -              if ((reg_val & PHYSDEV_CONTROL_INP_MASK) == 0)
 -                      break;
 -
 -              ssleep(1);
 -      }
 -
 -      if (i == SLIPORT_IDLE_TIMEOUT)
 -              status = -1;
 -
 -      return status;
 -}
 -
 -static int lancer_fw_reset(struct be_adapter *adapter)
 -{
 -      int status = 0;
 -
 -      status = lancer_wait_idle(adapter);
 -      if (status)
 -              return status;
 -
 -      iowrite32(PHYSDEV_CONTROL_FW_RESET_MASK, adapter->db +
 -                PHYSDEV_CONTROL_OFFSET);
 -
 -      return status;
 -}
 -
  static int lancer_fw_download(struct be_adapter *adapter,
                                const struct firmware *fw)
  {
        }
  
        if (change_status == LANCER_FW_RESET_NEEDED) {
 -              status = lancer_fw_reset(adapter);
 +              status = lancer_physdev_ctrl(adapter,
 +                                           PHYSDEV_CONTROL_FW_RESET_MASK);
                if (status) {
                        dev_err(&adapter->pdev->dev,
                                "Adapter busy for FW reset.\n"
@@@ -3764,10 -3776,6 +3769,10 @@@ int be_load_fw(struct be_adapter *adapt
        else
                status = be_fw_download(adapter, fw);
  
 +      if (!status)
 +              be_cmd_get_fw_ver(adapter, adapter->fw_ver,
 +                                adapter->fw_on_flash);
 +
  fw_exit:
        release_firmware(fw);
        return status;
@@@ -4090,6 -4098,7 +4095,7 @@@ static int be_get_initial_config(struc
  
  static int lancer_recover_func(struct be_adapter *adapter)
  {
+       struct device *dev = &adapter->pdev->dev;
        int status;
  
        status = lancer_test_and_set_rdy_state(adapter);
  
        be_clear(adapter);
  
-       adapter->hw_error = false;
-       adapter->fw_timeout = false;
+       be_clear_all_error(adapter);
  
        status = be_setup(adapter);
        if (status)
                        goto err;
        }
  
-       dev_err(&adapter->pdev->dev,
-               "Adapter SLIPORT recovery succeeded\n");
+       dev_err(dev, "Error recovery successful\n");
        return 0;
  err:
-       if (adapter->eeh_error)
-               dev_err(&adapter->pdev->dev,
-                       "Adapter SLIPORT recovery failed\n");
+       if (status == -EAGAIN)
+               dev_err(dev, "Waiting for resource provisioning\n");
+       else
+               dev_err(dev, "Error recovery failed\n");
  
        return status;
  }
@@@ -4129,28 -4137,27 +4134,27 @@@ static void be_func_recovery_task(struc
  {
        struct be_adapter *adapter =
                container_of(work, struct be_adapter,  func_recovery_work.work);
-       int status;
+       int status = 0;
  
        be_detect_error(adapter);
  
        if (adapter->hw_error && lancer_chip(adapter)) {
  
-               if (adapter->eeh_error)
-                       goto out;
                rtnl_lock();
                netif_device_detach(adapter->netdev);
                rtnl_unlock();
  
                status = lancer_recover_func(adapter);
                if (!status)
                        netif_device_attach(adapter->netdev);
        }
  
- out:
-       schedule_delayed_work(&adapter->func_recovery_work,
-                             msecs_to_jiffies(1000));
+       /* In Lancer, for all errors other than provisioning error (-EAGAIN),
+        * no need to attempt further recovery.
+        */
+       if (!status || status == -EAGAIN)
+               schedule_delayed_work(&adapter->func_recovery_work,
+                                     msecs_to_jiffies(1000));
  }
  
  static void be_worker(struct work_struct *work)
@@@ -4433,20 -4440,19 +4437,19 @@@ static pci_ers_result_t be_eeh_err_dete
  
        dev_err(&adapter->pdev->dev, "EEH error detected\n");
  
-       adapter->eeh_error = true;
-       cancel_delayed_work_sync(&adapter->func_recovery_work);
+       if (!adapter->eeh_error) {
+               adapter->eeh_error = true;
  
-       rtnl_lock();
-       netif_device_detach(netdev);
-       rtnl_unlock();
+               cancel_delayed_work_sync(&adapter->func_recovery_work);
  
-       if (netif_running(netdev)) {
                rtnl_lock();
-               be_close(netdev);
+               netif_device_detach(netdev);
+               if (netif_running(netdev))
+                       be_close(netdev);
                rtnl_unlock();
+               be_clear(adapter);
        }
-       be_clear(adapter);
  
        if (state == pci_channel_io_perm_failure)
                return PCI_ERS_RESULT_DISCONNECT;
@@@ -4471,7 -4477,6 +4474,6 @@@ static pci_ers_result_t be_eeh_reset(st
        int status;
  
        dev_info(&adapter->pdev->dev, "EEH reset\n");
-       be_clear_all_error(adapter);
  
        status = pci_enable_device(pdev);
        if (status)
                return PCI_ERS_RESULT_DISCONNECT;
  
        pci_cleanup_aer_uncorrect_error_status(pdev);
+       be_clear_all_error(adapter);
        return PCI_ERS_RESULT_RECOVERED;
  }
  
index 9b0c6472bf043c8453c907837f6d41303700a33c,a667015be22ada3a3bb85628620584e4fb1982e3..c42c42a0cc573745da7843557b32680476a4ae34
@@@ -53,6 -53,7 +53,6 @@@
  #include <linux/of_device.h>
  #include <linux/of_gpio.h>
  #include <linux/of_net.h>
 -#include <linux/pinctrl/consumer.h>
  #include <linux/regulator/consumer.h>
  
  #include <asm/cacheflush.h>
@@@ -242,7 -243,7 +242,7 @@@ static void *swap_buffer(void *bufaddr
        int i;
        unsigned int *buf = bufaddr;
  
 -      for (i = 0; i < (len + 3) / 4; i++, buf++)
 +      for (i = 0; i < DIV_ROUND_UP(len, 4); i++, buf++)
                *buf = cpu_to_be32(*buf);
  
        return bufaddr;
@@@ -1037,6 -1038,18 +1037,18 @@@ static void fec_get_mac(struct net_devi
                iap = &tmpaddr[0];
        }
  
+       /*
+        * 5) random mac address
+        */
+       if (!is_valid_ether_addr(iap)) {
+               /* Report it and use a random ethernet address instead */
+               netdev_err(ndev, "Invalid MAC address: %pM\n", iap);
+               eth_hw_addr_random(ndev);
+               netdev_info(ndev, "Using random MAC address: %pM\n",
+                           ndev->dev_addr);
+               return;
+       }
        memcpy(ndev->dev_addr, iap, ETH_ALEN);
  
        /* Adjust MAC if using macaddr */
@@@ -1840,6 -1853,8 +1852,6 @@@ fec_probe(struct platform_device *pdev
        struct resource *r;
        const struct of_device_id *of_id;
        static int dev_id;
 -      struct pinctrl *pinctrl;
 -      struct regulator *reg_phy;
  
        of_id = of_match_device(fec_dt_ids, &pdev->dev);
        if (of_id)
                fep->phy_interface = ret;
        }
  
 -      pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
 -      if (IS_ERR(pinctrl)) {
 -              ret = PTR_ERR(pinctrl);
 -              goto failed_pin;
 -      }
 -
        fep->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
        if (IS_ERR(fep->clk_ipg)) {
                ret = PTR_ERR(fep->clk_ipg);
        clk_prepare_enable(fep->clk_enet_out);
        clk_prepare_enable(fep->clk_ptp);
  
 -      reg_phy = devm_regulator_get(&pdev->dev, "phy");
 -      if (!IS_ERR(reg_phy)) {
 -              ret = regulator_enable(reg_phy);
 +      fep->reg_phy = devm_regulator_get(&pdev->dev, "phy");
 +      if (!IS_ERR(fep->reg_phy)) {
 +              ret = regulator_enable(fep->reg_phy);
                if (ret) {
                        dev_err(&pdev->dev,
                                "Failed to enable phy regulator: %d\n", ret);
                        goto failed_regulator;
                }
 +      } else {
 +              fep->reg_phy = NULL;
        }
  
        fec_reset_phy(pdev);
  failed_register:
        fec_enet_mii_remove(fep);
  failed_mii_init:
 -failed_init:
 +failed_irq:
        for (i = 0; i < FEC_IRQ_NUM; i++) {
                irq = platform_get_irq(pdev, i);
                if (irq > 0)
                        free_irq(irq, ndev);
        }
 -failed_irq:
 +failed_init:
 +      if (fep->reg_phy)
 +              regulator_disable(fep->reg_phy);
  failed_regulator:
        clk_disable_unprepare(fep->clk_ahb);
        clk_disable_unprepare(fep->clk_ipg);
        clk_disable_unprepare(fep->clk_enet_out);
        clk_disable_unprepare(fep->clk_ptp);
 -failed_pin:
  failed_clk:
  failed_ioremap:
        free_netdev(ndev);
@@@ -2009,21 -2027,21 +2021,21 @@@ fec_drv_remove(struct platform_device *
        unregister_netdev(ndev);
        fec_enet_mii_remove(fep);
        del_timer_sync(&fep->time_keep);
 +      for (i = 0; i < FEC_IRQ_NUM; i++) {
 +              int irq = platform_get_irq(pdev, i);
 +              if (irq > 0)
 +                      free_irq(irq, ndev);
 +      }
 +      if (fep->reg_phy)
 +              regulator_disable(fep->reg_phy);
        clk_disable_unprepare(fep->clk_ptp);
        if (fep->ptp_clock)
                ptp_clock_unregister(fep->ptp_clock);
        clk_disable_unprepare(fep->clk_enet_out);
        clk_disable_unprepare(fep->clk_ahb);
        clk_disable_unprepare(fep->clk_ipg);
 -      for (i = 0; i < FEC_IRQ_NUM; i++) {
 -              int irq = platform_get_irq(pdev, i);
 -              if (irq > 0)
 -                      free_irq(irq, ndev);
 -      }
        free_netdev(ndev);
  
 -      platform_set_drvdata(pdev, NULL);
 -
        return 0;
  }
  
@@@ -2042,9 -2060,6 +2054,9 @@@ fec_suspend(struct device *dev
        clk_disable_unprepare(fep->clk_ahb);
        clk_disable_unprepare(fep->clk_ipg);
  
 +      if (fep->reg_phy)
 +              regulator_disable(fep->reg_phy);
 +
        return 0;
  }
  
@@@ -2053,13 -2068,6 +2065,13 @@@ fec_resume(struct device *dev
  {
        struct net_device *ndev = dev_get_drvdata(dev);
        struct fec_enet_private *fep = netdev_priv(ndev);
 +      int ret;
 +
 +      if (fep->reg_phy) {
 +              ret = regulator_enable(fep->reg_phy);
 +              if (ret)
 +                      return ret;
 +      }
  
        clk_prepare_enable(fep->clk_enet_out);
        clk_prepare_enable(fep->clk_ahb);
index e04d471acb10d8a8e9fba7b55ef703753eae6c96,f87cc216045b5feb5e20dbc2f4df3fe2190eba14..2553cf4503b9f83996bb72bd291fb756558644f9
@@@ -4717,6 -4717,7 +4717,7 @@@ static int qlge_probe(struct pci_dev *p
                dev_err(&pdev->dev, "net device registration failed.\n");
                ql_release_all(pdev);
                pci_disable_device(pdev);
+               free_netdev(ndev);
                return err;
        }
        /* Start up the timer to trigger EEH if
@@@ -4945,4 -4946,15 +4946,4 @@@ static struct pci_driver qlge_driver = 
        .err_handler = &qlge_err_handler
  };
  
 -static int __init qlge_init_module(void)
 -{
 -      return pci_register_driver(&qlge_driver);
 -}
 -
 -static void __exit qlge_exit(void)
 -{
 -      pci_unregister_driver(&qlge_driver);
 -}
 -
 -module_init(qlge_init_module);
 -module_exit(qlge_exit);
 +module_pci_driver(qlge_driver);
index c4d8aeffb4ba5f7275712f04854cb7c10bd12a1b,b7268b3dae777a1fc29b5aed36f19ec96df462aa..1cd131bde680bea02152fa14146bda981d3dd0e5
@@@ -2,9 -2,9 +2,9 @@@
   * Xilinx EmacLite Linux driver for the Xilinx Ethernet MAC Lite device.
   *
   * This is a new flat driver which is based on the original emac_lite
 - * driver from John Williams <john.williams@petalogix.com>.
 + * driver from John Williams <john.williams@xilinx.com>.
   *
 - * 2007-2009 (c) Xilinx, Inc.
 + * 2007 - 2013 (c) Xilinx, Inc.
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published by the
@@@ -159,32 -159,34 +159,32 @@@ static void xemaclite_enable_interrupts
        u32 reg_data;
  
        /* Enable the Tx interrupts for the first Buffer */
 -      reg_data = in_be32(drvdata->base_addr + XEL_TSR_OFFSET);
 -      out_be32(drvdata->base_addr + XEL_TSR_OFFSET,
 -               reg_data | XEL_TSR_XMIT_IE_MASK);
 +      reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET);
 +      __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
 +                   drvdata->base_addr + XEL_TSR_OFFSET);
  
        /* Enable the Tx interrupts for the second Buffer if
         * configured in HW */
        if (drvdata->tx_ping_pong != 0) {
 -              reg_data = in_be32(drvdata->base_addr +
 +              reg_data = __raw_readl(drvdata->base_addr +
                                   XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
 -              out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
 -                       XEL_TSR_OFFSET,
 -                       reg_data | XEL_TSR_XMIT_IE_MASK);
 +              __raw_writel(reg_data | XEL_TSR_XMIT_IE_MASK,
 +                           drvdata->base_addr + XEL_BUFFER_OFFSET +
 +                           XEL_TSR_OFFSET);
        }
  
        /* Enable the Rx interrupts for the first buffer */
 -      out_be32(drvdata->base_addr + XEL_RSR_OFFSET,
 -               XEL_RSR_RECV_IE_MASK);
 +      __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr + XEL_RSR_OFFSET);
  
        /* Enable the Rx interrupts for the second Buffer if
         * configured in HW */
        if (drvdata->rx_ping_pong != 0) {
 -              out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
 -                       XEL_RSR_OFFSET,
 -                       XEL_RSR_RECV_IE_MASK);
 +              __raw_writel(XEL_RSR_RECV_IE_MASK, drvdata->base_addr +
 +                           XEL_BUFFER_OFFSET + XEL_RSR_OFFSET);
        }
  
        /* Enable the Global Interrupt Enable */
 -      out_be32(drvdata->base_addr + XEL_GIER_OFFSET, XEL_GIER_GIE_MASK);
 +      __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
  }
  
  /**
@@@ -199,37 -201,37 +199,37 @@@ static void xemaclite_disable_interrupt
        u32 reg_data;
  
        /* Disable the Global Interrupt Enable */
 -      out_be32(drvdata->base_addr + XEL_GIER_OFFSET, XEL_GIER_GIE_MASK);
 +      __raw_writel(XEL_GIER_GIE_MASK, drvdata->base_addr + XEL_GIER_OFFSET);
  
        /* Disable the Tx interrupts for the first buffer */
 -      reg_data = in_be32(drvdata->base_addr + XEL_TSR_OFFSET);
 -      out_be32(drvdata->base_addr + XEL_TSR_OFFSET,
 -               reg_data & (~XEL_TSR_XMIT_IE_MASK));
 +      reg_data = __raw_readl(drvdata->base_addr + XEL_TSR_OFFSET);
 +      __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
 +                   drvdata->base_addr + XEL_TSR_OFFSET);
  
        /* Disable the Tx interrupts for the second Buffer
         * if configured in HW */
        if (drvdata->tx_ping_pong != 0) {
 -              reg_data = in_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
 +              reg_data = __raw_readl(drvdata->base_addr + XEL_BUFFER_OFFSET +
                                   XEL_TSR_OFFSET);
 -              out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
 -                       XEL_TSR_OFFSET,
 -                       reg_data & (~XEL_TSR_XMIT_IE_MASK));
 +              __raw_writel(reg_data & (~XEL_TSR_XMIT_IE_MASK),
 +                           drvdata->base_addr + XEL_BUFFER_OFFSET +
 +                           XEL_TSR_OFFSET);
        }
  
        /* Disable the Rx interrupts for the first buffer */
 -      reg_data = in_be32(drvdata->base_addr + XEL_RSR_OFFSET);
 -      out_be32(drvdata->base_addr + XEL_RSR_OFFSET,
 -               reg_data & (~XEL_RSR_RECV_IE_MASK));
 +      reg_data = __raw_readl(drvdata->base_addr + XEL_RSR_OFFSET);
 +      __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
 +                   drvdata->base_addr + XEL_RSR_OFFSET);
  
        /* Disable the Rx interrupts for the second buffer
         * if configured in HW */
        if (drvdata->rx_ping_pong != 0) {
  
 -              reg_data = in_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
 +              reg_data = __raw_readl(drvdata->base_addr + XEL_BUFFER_OFFSET +
                                   XEL_RSR_OFFSET);
 -              out_be32(drvdata->base_addr + XEL_BUFFER_OFFSET +
 -                       XEL_RSR_OFFSET,
 -                       reg_data & (~XEL_RSR_RECV_IE_MASK));
 +              __raw_writel(reg_data & (~XEL_RSR_RECV_IE_MASK),
 +                           drvdata->base_addr + XEL_BUFFER_OFFSET +
 +                           XEL_RSR_OFFSET);
        }
  }
  
@@@ -349,7 -351,7 +349,7 @@@ static int xemaclite_send_data(struct n
                byte_count = ETH_FRAME_LEN;
  
        /* Check if the expected buffer is available */
 -      reg_data = in_be32(addr + XEL_TSR_OFFSET);
 +      reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
        if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
             XEL_TSR_XMIT_ACTIVE_MASK)) == 0) {
  
  
                addr = (void __iomem __force *)((u32 __force)addr ^
                                                 XEL_BUFFER_OFFSET);
 -              reg_data = in_be32(addr + XEL_TSR_OFFSET);
 +              reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
  
                if ((reg_data & (XEL_TSR_XMIT_BUSY_MASK |
                     XEL_TSR_XMIT_ACTIVE_MASK)) != 0)
        /* Write the frame to the buffer */
        xemaclite_aligned_write(data, (u32 __force *) addr, byte_count);
  
 -      out_be32(addr + XEL_TPLR_OFFSET, (byte_count & XEL_TPLR_LENGTH_MASK));
 +      __raw_writel((byte_count & XEL_TPLR_LENGTH_MASK),
 +                   addr + XEL_TPLR_OFFSET);
  
        /* Update the Tx Status Register to indicate that there is a
         * frame to send. Set the XEL_TSR_XMIT_ACTIVE_MASK flag which
         * is used by the interrupt handler to check whether a frame
         * has been transmitted */
 -      reg_data = in_be32(addr + XEL_TSR_OFFSET);
 +      reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
        reg_data |= (XEL_TSR_XMIT_BUSY_MASK | XEL_TSR_XMIT_ACTIVE_MASK);
 -      out_be32(addr + XEL_TSR_OFFSET, reg_data);
 +      __raw_writel(reg_data, addr + XEL_TSR_OFFSET);
  
        return 0;
  }
@@@ -407,7 -408,7 +407,7 @@@ static u16 xemaclite_recv_data(struct n
        addr = (drvdata->base_addr + drvdata->next_rx_buf_to_use);
  
        /* Verify which buffer has valid data */
 -      reg_data = in_be32(addr + XEL_RSR_OFFSET);
 +      reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
  
        if ((reg_data & XEL_RSR_RECV_DONE_MASK) == XEL_RSR_RECV_DONE_MASK) {
                if (drvdata->rx_ping_pong != 0)
                        return 0;       /* No data was available */
  
                /* Verify that buffer has valid data */
 -              reg_data = in_be32(addr + XEL_RSR_OFFSET);
 +              reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
                if ((reg_data & XEL_RSR_RECV_DONE_MASK) !=
                     XEL_RSR_RECV_DONE_MASK)
                        return 0;       /* No data was available */
        }
  
        /* Get the protocol type of the ethernet frame that arrived */
 -      proto_type = ((ntohl(in_be32(addr + XEL_HEADER_OFFSET +
 +      proto_type = ((ntohl(__raw_readl(addr + XEL_HEADER_OFFSET +
                        XEL_RXBUFF_OFFSET)) >> XEL_HEADER_SHIFT) &
                        XEL_RPLR_LENGTH_MASK);
  
        if (proto_type > (ETH_FRAME_LEN + ETH_FCS_LEN)) {
  
                if (proto_type == ETH_P_IP) {
 -                      length = ((ntohl(in_be32(addr +
 +                      length = ((ntohl(__raw_readl(addr +
                                        XEL_HEADER_IP_LENGTH_OFFSET +
                                        XEL_RXBUFF_OFFSET)) >>
                                        XEL_HEADER_SHIFT) &
                                data, length);
  
        /* Acknowledge the frame */
 -      reg_data = in_be32(addr + XEL_RSR_OFFSET);
 +      reg_data = __raw_readl(addr + XEL_RSR_OFFSET);
        reg_data &= ~XEL_RSR_RECV_DONE_MASK;
 -      out_be32(addr + XEL_RSR_OFFSET, reg_data);
 +      __raw_writel(reg_data, addr + XEL_RSR_OFFSET);
  
        return length;
  }
@@@ -491,14 -492,14 +491,14 @@@ static void xemaclite_update_address(st
  
        xemaclite_aligned_write(address_ptr, (u32 __force *) addr, ETH_ALEN);
  
 -      out_be32(addr + XEL_TPLR_OFFSET, ETH_ALEN);
 +      __raw_writel(ETH_ALEN, addr + XEL_TPLR_OFFSET);
  
        /* Update the MAC address in the EmacLite */
 -      reg_data = in_be32(addr + XEL_TSR_OFFSET);
 -      out_be32(addr + XEL_TSR_OFFSET, reg_data | XEL_TSR_PROG_MAC_ADDR);
 +      reg_data = __raw_readl(addr + XEL_TSR_OFFSET);
 +      __raw_writel(reg_data | XEL_TSR_PROG_MAC_ADDR, addr + XEL_TSR_OFFSET);
  
        /* Wait for EmacLite to finish with the MAC address update */
 -      while ((in_be32(addr + XEL_TSR_OFFSET) &
 +      while ((__raw_readl(addr + XEL_TSR_OFFSET) &
                XEL_TSR_PROG_MAC_ADDR) != 0)
                ;
  }
@@@ -668,32 -669,31 +668,32 @@@ static irqreturn_t xemaclite_interrupt(
        u32 tx_status;
  
        /* Check if there is Rx Data available */
 -      if ((in_be32(base_addr + XEL_RSR_OFFSET) & XEL_RSR_RECV_DONE_MASK) ||
 -                      (in_be32(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET)
 +      if ((__raw_readl(base_addr + XEL_RSR_OFFSET) &
 +                       XEL_RSR_RECV_DONE_MASK) ||
 +          (__raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_RSR_OFFSET)
                         & XEL_RSR_RECV_DONE_MASK))
  
                xemaclite_rx_handler(dev);
  
        /* Check if the Transmission for the first buffer is completed */
 -      tx_status = in_be32(base_addr + XEL_TSR_OFFSET);
 +      tx_status = __raw_readl(base_addr + XEL_TSR_OFFSET);
        if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
                (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
  
                tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
 -              out_be32(base_addr + XEL_TSR_OFFSET, tx_status);
 +              __raw_writel(tx_status, base_addr + XEL_TSR_OFFSET);
  
                tx_complete = true;
        }
  
        /* Check if the Transmission for the second buffer is completed */
 -      tx_status = in_be32(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
 +      tx_status = __raw_readl(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
        if (((tx_status & XEL_TSR_XMIT_BUSY_MASK) == 0) &&
                (tx_status & XEL_TSR_XMIT_ACTIVE_MASK) != 0) {
  
                tx_status &= ~XEL_TSR_XMIT_ACTIVE_MASK;
 -              out_be32(base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET,
 -                       tx_status);
 +              __raw_writel(tx_status, base_addr + XEL_BUFFER_OFFSET +
 +                           XEL_TSR_OFFSET);
  
                tx_complete = true;
        }
@@@ -726,7 -726,7 +726,7 @@@ static int xemaclite_mdio_wait(struct n
        /* wait for the MDIO interface to not be busy or timeout
           after some time.
        */
 -      while (in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET) &
 +      while (__raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET) &
                        XEL_MDIOCTRL_MDIOSTS_MASK) {
                if (end - jiffies <= 0) {
                        WARN_ON(1);
@@@ -762,17 -762,17 +762,17 @@@ static int xemaclite_mdio_read(struct m
         * MDIO Address register. Set the Status bit in the MDIO Control
         * register to start a MDIO read transaction.
         */
 -      ctrl_reg = in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET);
 -      out_be32(lp->base_addr + XEL_MDIOADDR_OFFSET,
 -               XEL_MDIOADDR_OP_MASK |
 -               ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg));
 -      out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET,
 -               ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK);
 +      ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
 +      __raw_writel(XEL_MDIOADDR_OP_MASK |
 +                   ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
 +                   lp->base_addr + XEL_MDIOADDR_OFFSET);
 +      __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
 +                   lp->base_addr + XEL_MDIOCTRL_OFFSET);
  
        if (xemaclite_mdio_wait(lp))
                return -ETIMEDOUT;
  
 -      rc = in_be32(lp->base_addr + XEL_MDIORD_OFFSET);
 +      rc = __raw_readl(lp->base_addr + XEL_MDIORD_OFFSET);
  
        dev_dbg(&lp->ndev->dev,
                "xemaclite_mdio_read(phy_id=%i, reg=%x) == %x\n",
@@@ -809,13 -809,13 +809,13 @@@ static int xemaclite_mdio_write(struct 
         * Data register. Finally, set the Status bit in the MDIO Control
         * register to start a MDIO write transaction.
         */
 -      ctrl_reg = in_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET);
 -      out_be32(lp->base_addr + XEL_MDIOADDR_OFFSET,
 -               ~XEL_MDIOADDR_OP_MASK &
 -               ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg));
 -      out_be32(lp->base_addr + XEL_MDIOWR_OFFSET, val);
 -      out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET,
 -               ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK);
 +      ctrl_reg = __raw_readl(lp->base_addr + XEL_MDIOCTRL_OFFSET);
 +      __raw_writel(~XEL_MDIOADDR_OP_MASK &
 +                   ((phy_id << XEL_MDIOADDR_PHYADR_SHIFT) | reg),
 +                   lp->base_addr + XEL_MDIOADDR_OFFSET);
 +      __raw_writel(val, lp->base_addr + XEL_MDIOWR_OFFSET);
 +      __raw_writel(ctrl_reg | XEL_MDIOCTRL_MDIOSTS_MASK,
 +                   lp->base_addr + XEL_MDIOCTRL_OFFSET);
  
        return 0;
  }
@@@ -848,39 -848,24 +848,39 @@@ static int xemaclite_mdio_setup(struct 
        int rc;
        struct resource res;
        struct device_node *np = of_get_parent(lp->phy_node);
 +      struct device_node *npp;
  
        /* Don't register the MDIO bus if the phy_node or its parent node
         * can't be found.
         */
 -      if (!np)
 +      if (!np) {
 +              dev_err(dev, "Failed to register mdio bus.\n");
                return -ENODEV;
 +      }
 +      npp = of_get_parent(np);
 +
 +      of_address_to_resource(npp, 0, &res);
 +      if (lp->ndev->mem_start != res.start) {
 +              struct phy_device *phydev;
 +              phydev = of_phy_find_device(lp->phy_node);
 +              if (!phydev)
 +                      dev_info(dev,
 +                               "MDIO of the phy is not registered yet\n");
 +              return 0;
 +      }
  
        /* Enable the MDIO bus by asserting the enable bit in MDIO Control
         * register.
         */
 -      out_be32(lp->base_addr + XEL_MDIOCTRL_OFFSET,
 -               XEL_MDIOCTRL_MDIOEN_MASK);
 +      __raw_writel(XEL_MDIOCTRL_MDIOEN_MASK,
 +                   lp->base_addr + XEL_MDIOCTRL_OFFSET);
  
        bus = mdiobus_alloc();
 -      if (!bus)
 +      if (!bus) {
 +              dev_err(dev, "Failed to allocate mdiobus\n");
                return -ENOMEM;
 +      }
  
 -      of_address_to_resource(np, 0, &res);
        snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx",
                 (unsigned long long)res.start);
        bus->priv = lp;
        lp->mii_bus = bus;
  
        rc = of_mdiobus_register(bus, np);
 -      if (rc)
 +      if (rc) {
 +              dev_err(dev, "Failed to register mdio bus.\n");
                goto err_register;
 +      }
  
        return 0;
  
@@@ -913,7 -896,7 +913,7 @@@ err_register
   * There's nothing in the Emaclite device to be configured when the link
   * state changes. We just print the status.
   */
 -void xemaclite_adjust_link(struct net_device *ndev)
 +static void xemaclite_adjust_link(struct net_device *ndev)
  {
        struct net_local *lp = netdev_priv(ndev);
        struct phy_device *phy = lp->phy_dev;
@@@ -963,7 -946,8 +963,8 @@@ static int xemaclite_open(struct net_de
                phy_write(lp->phy_dev, MII_CTRL1000, 0);
  
                /* Advertise only 10 and 100mbps full/half duplex speeds */
-               phy_write(lp->phy_dev, MII_ADVERTISE, ADVERTISE_ALL);
+               phy_write(lp->phy_dev, MII_ADVERTISE, ADVERTISE_ALL |
+                         ADVERTISE_CSMA);
  
                /* Restart auto negotiation */
                bmcr = phy_read(lp->phy_dev, MII_BMCR);
@@@ -1074,14 -1058,13 +1075,14 @@@ static int xemaclite_send(struct sk_buf
   * This function un maps the IO region of the Emaclite device and frees the net
   * device.
   */
 -static void xemaclite_remove_ndev(struct net_device *ndev)
 +static void xemaclite_remove_ndev(struct net_device *ndev,
 +                                struct platform_device *pdev)
  {
        if (ndev) {
                struct net_local *lp = netdev_priv(ndev);
  
                if (lp->base_addr)
 -                      iounmap((void __iomem __force *) (lp->base_addr));
 +                      devm_iounmap(&pdev->dev, lp->base_addr);
                free_netdev(ndev);
        }
  }
@@@ -1127,7 -1110,8 +1128,7 @@@ static struct net_device_ops xemaclite_
   */
  static int xemaclite_of_probe(struct platform_device *ofdev)
  {
 -      struct resource r_irq; /* Interrupt resources */
 -      struct resource r_mem; /* IO mem resources */
 +      struct resource *res;
        struct net_device *ndev = NULL;
        struct net_local *lp = NULL;
        struct device *dev = &ofdev->dev;
  
        dev_info(dev, "Device Tree Probing\n");
  
 -      /* Get iospace for the device */
 -      rc = of_address_to_resource(ofdev->dev.of_node, 0, &r_mem);
 -      if (rc) {
 -              dev_err(dev, "invalid address\n");
 -              return rc;
 -      }
 -
 -      /* Get IRQ for the device */
 -      rc = of_irq_to_resource(ofdev->dev.of_node, 0, &r_irq);
 -      if (!rc) {
 -              dev_err(dev, "no IRQ found\n");
 -              return rc;
 -      }
 -
        /* Create an ethernet device instance */
        ndev = alloc_etherdev(sizeof(struct net_local));
        if (!ndev)
        dev_set_drvdata(dev, ndev);
        SET_NETDEV_DEV(ndev, &ofdev->dev);
  
 -      ndev->irq = r_irq.start;
 -      ndev->mem_start = r_mem.start;
 -      ndev->mem_end = r_mem.end;
 -
        lp = netdev_priv(ndev);
        lp->ndev = ndev;
  
 -      if (!request_mem_region(ndev->mem_start,
 -                              ndev->mem_end - ndev->mem_start + 1,
 -                              DRIVER_NAME)) {
 -              dev_err(dev, "Couldn't lock memory region at %p\n",
 -                      (void *)ndev->mem_start);
 -              rc = -EBUSY;
 -              goto error2;
 +      /* Get IRQ for the device */
 +      res = platform_get_resource(ofdev, IORESOURCE_IRQ, 0);
 +      if (!res) {
 +              dev_err(dev, "no IRQ found\n");
 +              goto error;
        }
  
 -      /* Get the virtual base address for the device */
 -      lp->base_addr = ioremap(r_mem.start, resource_size(&r_mem));
 -      if (NULL == lp->base_addr) {
 -              dev_err(dev, "EmacLite: Could not allocate iomem\n");
 -              rc = -EIO;
 -              goto error1;
 -      }
 +      ndev->irq = res->start;
 +
 +      res = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
 +      lp->base_addr = devm_request_and_ioremap(&ofdev->dev, res);
 +      if (!lp->base_addr)
 +              goto error;
 +
 +      ndev->mem_start = res->start;
 +      ndev->mem_end = res->end;
  
        spin_lock_init(&lp->reset_lock);
        lp->next_tx_buf_to_use = 0x0;
                dev_warn(dev, "No MAC address found\n");
  
        /* Clear the Tx CSR's in case this is a restart */
 -      out_be32(lp->base_addr + XEL_TSR_OFFSET, 0);
 -      out_be32(lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET, 0);
 +      __raw_writel(0, lp->base_addr + XEL_TSR_OFFSET);
 +      __raw_writel(0, lp->base_addr + XEL_BUFFER_OFFSET + XEL_TSR_OFFSET);
  
        /* Set the MAC address in the EmacLite device */
        xemaclite_update_address(lp, ndev->dev_addr);
        if (rc) {
                dev_err(dev,
                        "Cannot register network device, aborting\n");
 -              goto error1;
 +              goto error;
        }
  
        dev_info(dev,
                 (unsigned int __force)lp->base_addr, ndev->irq);
        return 0;
  
 -error1:
 -      release_mem_region(ndev->mem_start, resource_size(&r_mem));
 -
 -error2:
 -      xemaclite_remove_ndev(ndev);
 +error:
 +      xemaclite_remove_ndev(ndev, ofdev);
        return rc;
  }
  
@@@ -1246,7 -1251,9 +1247,7 @@@ static int xemaclite_of_remove(struct p
                of_node_put(lp->phy_node);
        lp->phy_node = NULL;
  
 -      release_mem_region(ndev->mem_start, ndev->mem_end-ndev->mem_start + 1);
 -
 -      xemaclite_remove_ndev(ndev);
 +      xemaclite_remove_ndev(ndev, of_dev);
        dev_set_drvdata(dev, NULL);
  
        return 0;
diff --combined drivers/net/phy/phy.c
index b2a94e436ed8f20a1812aca51f4acdfd2d7da93e,38f0b312ff85e339bc742c8472ef244bb9c50a40..10d058ab4f7969b50a0f8b378ac360e263b2104e
@@@ -294,8 -294,7 +294,8 @@@ int phy_ethtool_gset(struct phy_device 
        cmd->duplex = phydev->duplex;
        cmd->port = PORT_MII;
        cmd->phy_address = phydev->addr;
 -      cmd->transceiver = XCVR_EXTERNAL;
 +      cmd->transceiver = phy_is_internal(phydev) ?
 +              XCVR_INTERNAL : XCVR_EXTERNAL;
        cmd->autoneg = phydev->autoneg;
  
        return 0;
@@@ -420,6 -419,8 +420,6 @@@ out_unlock
  EXPORT_SYMBOL(phy_start_aneg);
  
  
 -static void phy_change(struct work_struct *work);
 -
  /**
   * phy_start_machine - start PHY state machine tracking
   * @phydev: the phy_device struct
@@@ -564,6 -565,8 +564,6 @@@ int phy_start_interrupts(struct phy_dev
  {
        int err = 0;
  
 -      INIT_WORK(&phydev->phy_queue, phy_change);
 -
        atomic_set(&phydev->irq_disable, 0);
        if (request_irq(phydev->irq, phy_interrupt,
                                IRQF_SHARED,
@@@ -620,7 -623,7 +620,7 @@@ EXPORT_SYMBOL(phy_stop_interrupts)
   * phy_change - Scheduled by the phy_interrupt/timer to handle PHY changes
   * @work: work_struct that describes the work to be done
   */
 -static void phy_change(struct work_struct *work)
 +void phy_change(struct work_struct *work)
  {
        int err;
        struct phy_device *phydev =
@@@ -679,7 -682,7 +679,7 @@@ void phy_stop(struct phy_device *phydev
        if (PHY_HALTED == phydev->state)
                goto out_unlock;
  
 -      if (phydev->irq != PHY_POLL) {
 +      if (phy_interrupt_is_valid(phydev)) {
                /* Disable PHY Interrupts */
                phy_config_interrupt(phydev, PHY_INTERRUPT_DISABLED);
  
@@@ -825,9 -828,8 +825,9 @@@ void phy_state_machine(struct work_stru
                        break;
                case PHY_RUNNING:
                        /* Only register a CHANGE if we are
 -                       * polling */
 -                      if (PHY_POLL == phydev->irq)
 +                       * polling or ignoring interrupts
 +                       */
 +                      if (!phy_interrupt_is_valid(phydev))
                                phydev->state = PHY_CHANGELINK;
                        break;
                case PHY_CHANGELINK:
  
                        phydev->adjust_link(phydev->attached_dev);
  
 -                      if (PHY_POLL != phydev->irq)
 +                      if (phy_interrupt_is_valid(phydev))
                                err = phy_config_interrupt(phydev,
                                                PHY_INTERRUPT_ENABLED);
                        break;
        schedule_delayed_work(&phydev->state_queue, PHY_STATE_TIME * HZ);
  }
  
 +void phy_mac_interrupt(struct phy_device *phydev, int new_link)
 +{
 +      cancel_work_sync(&phydev->phy_queue);
 +      phydev->link = new_link;
 +      schedule_work(&phydev->phy_queue);
 +}
 +EXPORT_SYMBOL(phy_mac_interrupt);
 +
  static inline void mmd_phy_indirect(struct mii_bus *bus, int prtad, int devad,
                                    int addr)
  {
@@@ -1050,7 -1044,7 +1050,7 @@@ int phy_init_eee(struct phy_device *phy
                adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv);
                lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp);
                idx = phy_find_setting(phydev->speed, phydev->duplex);
-               if ((lp & adv & settings[idx].setting))
+               if (!(lp & adv & settings[idx].setting))
                        goto eee_exit;
  
                if (clk_stop_enable) {
diff --combined drivers/net/team/team.c
index 9273f48a512bbf97c2df63bdb6d8a3dc08d07a5e,d016a76ad44b40add050d83a7ba7335c304a63c1..04e9adb748c537ba6d4d370f0bb4327526578a79
@@@ -2374,7 -2374,8 +2374,8 @@@ static int team_nl_send_port_list_get(s
        bool incomplete;
        int i;
  
-       port = list_first_entry(&team->port_list, struct team_port, list);
+       port = list_first_entry_or_null(&team->port_list,
+                                       struct team_port, list);
  
  start_again:
        err = __send_and_alloc_skb(&skb, team, portid, send_func);
                err = team_nl_fill_one_port_get(skb, one_port);
                if (err)
                        goto errout;
-       } else {
-               list_for_each_entry(port, &team->port_list, list) {
+       } else if (port) {
+               list_for_each_entry_from(port, &team->port_list, list) {
                        err = team_nl_fill_one_port_get(skb, port);
                        if (err) {
                                if (err == -EMSGSIZE) {
@@@ -2647,7 -2648,7 +2648,7 @@@ static void team_port_change_check(stru
  static int team_device_event(struct notifier_block *unused,
                             unsigned long event, void *ptr)
  {
 -      struct net_device *dev = (struct net_device *) ptr;
 +      struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct team_port *port;
  
        port = team_port_get_rtnl(dev);
diff --combined include/linux/skbuff.h
index b9997907a0f1f2f82123e90e98cb4c8f3b0a2ef6,9c676eae396867fbcc656bc9466fe19459f31b2f..9995834d2cb6b4050c607250870abda56858843b
@@@ -319,8 -319,6 +319,8 @@@ enum 
        SKB_GSO_GRE = 1 << 6,
  
        SKB_GSO_UDP_TUNNEL = 1 << 7,
 +
 +      SKB_GSO_MPLS = 1 << 8,
  };
  
  #if BITS_PER_LONG > 32
@@@ -391,7 -389,6 +391,7 @@@ typedef unsigned char *sk_buff_data_t
   *    @dropcount: total number of sk_receive_queue overflows
   *    @vlan_proto: vlan encapsulation protocol
   *    @vlan_tci: vlan tag control information
 + *    @inner_protocol: Protocol (encapsulation)
   *    @inner_transport_header: Inner transport layer header (encapsulation)
   *    @inner_network_header: Network layer header (encapsulation)
   *    @inner_mac_header: Link layer header (encapsulation)
@@@ -512,13 -509,12 +512,13 @@@ struct sk_buff 
                __u32           reserved_tailroom;
        };
  
 -      sk_buff_data_t          inner_transport_header;
 -      sk_buff_data_t          inner_network_header;
 -      sk_buff_data_t          inner_mac_header;
 -      sk_buff_data_t          transport_header;
 -      sk_buff_data_t          network_header;
 -      sk_buff_data_t          mac_header;
 +      __be16                  inner_protocol;
 +      __u16                   inner_transport_header;
 +      __u16                   inner_network_header;
 +      __u16                   inner_mac_header;
 +      __u16                   transport_header;
 +      __u16                   network_header;
 +      __u16                   mac_header;
        /* These elements must be at the end, see alloc_skb() for details.  */
        sk_buff_data_t          tail;
        sk_buff_data_t          end;
@@@ -1391,11 -1387,6 +1391,11 @@@ static inline void skb_set_tail_pointer
        skb_reset_tail_pointer(skb);
        skb->tail += offset;
  }
 +
 +static inline unsigned long skb_tail_offset(const struct sk_buff *skb)
 +{
 +      return skb->tail;
 +}
  #else /* NET_SKBUFF_DATA_USES_OFFSET */
  static inline unsigned char *skb_tail_pointer(const struct sk_buff *skb)
  {
@@@ -1412,10 -1403,6 +1412,10 @@@ static inline void skb_set_tail_pointer
        skb->tail = skb->data + offset;
  }
  
 +static inline unsigned long skb_tail_offset(const struct sk_buff *skb)
 +{
 +      return skb->tail - skb->head;
 +}
  #endif /* NET_SKBUFF_DATA_USES_OFFSET */
  
  /*
@@@ -1540,6 -1527,7 +1540,6 @@@ static inline void skb_reset_mac_len(st
        skb->mac_len = skb->network_header - skb->mac_header;
  }
  
 -#ifdef NET_SKBUFF_DATA_USES_OFFSET
  static inline unsigned char *skb_inner_transport_header(const struct sk_buff
                                                        *skb)
  {
@@@ -1593,7 -1581,7 +1593,7 @@@ static inline void skb_set_inner_mac_he
  }
  static inline bool skb_transport_header_was_set(const struct sk_buff *skb)
  {
 -      return skb->transport_header != ~0U;
 +      return skb->transport_header != (typeof(skb->transport_header))~0U;
  }
  
  static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
@@@ -1636,7 -1624,7 +1636,7 @@@ static inline unsigned char *skb_mac_he
  
  static inline int skb_mac_header_was_set(const struct sk_buff *skb)
  {
 -      return skb->mac_header != ~0U;
 +      return skb->mac_header != (typeof(skb->mac_header))~0U;
  }
  
  static inline void skb_reset_mac_header(struct sk_buff *skb)
@@@ -1650,6 -1638,112 +1650,6 @@@ static inline void skb_set_mac_header(s
        skb->mac_header += offset;
  }
  
 -#else /* NET_SKBUFF_DATA_USES_OFFSET */
 -static inline unsigned char *skb_inner_transport_header(const struct sk_buff
 -                                                      *skb)
 -{
 -      return skb->inner_transport_header;
 -}
 -
 -static inline void skb_reset_inner_transport_header(struct sk_buff *skb)
 -{
 -      skb->inner_transport_header = skb->data;
 -}
 -
 -static inline void skb_set_inner_transport_header(struct sk_buff *skb,
 -                                                 const int offset)
 -{
 -      skb->inner_transport_header = skb->data + offset;
 -}
 -
 -static inline unsigned char *skb_inner_network_header(const struct sk_buff *skb)
 -{
 -      return skb->inner_network_header;
 -}
 -
 -static inline void skb_reset_inner_network_header(struct sk_buff *skb)
 -{
 -      skb->inner_network_header = skb->data;
 -}
 -
 -static inline void skb_set_inner_network_header(struct sk_buff *skb,
 -                                              const int offset)
 -{
 -      skb->inner_network_header = skb->data + offset;
 -}
 -
 -static inline unsigned char *skb_inner_mac_header(const struct sk_buff *skb)
 -{
 -      return skb->inner_mac_header;
 -}
 -
 -static inline void skb_reset_inner_mac_header(struct sk_buff *skb)
 -{
 -      skb->inner_mac_header = skb->data;
 -}
 -
 -static inline void skb_set_inner_mac_header(struct sk_buff *skb,
 -                                              const int offset)
 -{
 -      skb->inner_mac_header = skb->data + offset;
 -}
 -static inline bool skb_transport_header_was_set(const struct sk_buff *skb)
 -{
 -      return skb->transport_header != NULL;
 -}
 -
 -static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
 -{
 -      return skb->transport_header;
 -}
 -
 -static inline void skb_reset_transport_header(struct sk_buff *skb)
 -{
 -      skb->transport_header = skb->data;
 -}
 -
 -static inline void skb_set_transport_header(struct sk_buff *skb,
 -                                          const int offset)
 -{
 -      skb->transport_header = skb->data + offset;
 -}
 -
 -static inline unsigned char *skb_network_header(const struct sk_buff *skb)
 -{
 -      return skb->network_header;
 -}
 -
 -static inline void skb_reset_network_header(struct sk_buff *skb)
 -{
 -      skb->network_header = skb->data;
 -}
 -
 -static inline void skb_set_network_header(struct sk_buff *skb, const int offset)
 -{
 -      skb->network_header = skb->data + offset;
 -}
 -
 -static inline unsigned char *skb_mac_header(const struct sk_buff *skb)
 -{
 -      return skb->mac_header;
 -}
 -
 -static inline int skb_mac_header_was_set(const struct sk_buff *skb)
 -{
 -      return skb->mac_header != NULL;
 -}
 -
 -static inline void skb_reset_mac_header(struct sk_buff *skb)
 -{
 -      skb->mac_header = skb->data;
 -}
 -
 -static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
 -{
 -      skb->mac_header = skb->data + offset;
 -}
 -#endif /* NET_SKBUFF_DATA_USES_OFFSET */
 -
  static inline void skb_probe_transport_header(struct sk_buff *skb,
                                              const int offset_hint)
  {
@@@ -2758,6 -2852,21 +2758,21 @@@ static inline int skb_tnl_header_len(co
                SKB_GSO_CB(inner_skb)->mac_offset;
  }
  
+ static inline int gso_pskb_expand_head(struct sk_buff *skb, int extra)
+ {
+       int new_headroom, headroom;
+       int ret;
+       headroom = skb_headroom(skb);
+       ret = pskb_expand_head(skb, extra, 0, GFP_ATOMIC);
+       if (ret)
+               return ret;
+       new_headroom = skb_headroom(skb);
+       SKB_GSO_CB(skb)->mac_offset += (new_headroom - headroom);
+       return 0;
+ }
  static inline bool skb_is_gso(const struct sk_buff *skb)
  {
        return skb_shinfo(skb)->gso_size;
diff --combined include/net/ping.h
index db04802f1673573a919e79db08984274031dbaf3,682b5ae9af5165dcc71b4f366c81db7a4df20c01..5db0224b73ac47b1513ffb9361e48aa0167bb24d
@@@ -13,7 -13,6 +13,7 @@@
  #ifndef _PING_H
  #define _PING_H
  
 +#include <net/icmp.h>
  #include <net/netns/hash.h>
  
  /* PING_HTABLE_SIZE must be power of 2 */
   */
  #define GID_T_MAX (((gid_t)~0U) >> 1)
  
-                            struct net_device *dev, int strict);
 +/* Compatibility glue so we can support IPv6 when it's compiled as a module */
 +struct pingv6_ops {
 +      int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len);
 +      int (*ip6_datagram_recv_ctl)(struct sock *sk, struct msghdr *msg,
 +                                   struct sk_buff *skb);
 +      int (*icmpv6_err_convert)(u8 type, u8 code, int *err);
 +      void (*ipv6_icmp_error)(struct sock *sk, struct sk_buff *skb, int err,
 +                              __be16 port, u32 info, u8 *payload);
 +      int (*ipv6_chk_addr)(struct net *net, const struct in6_addr *addr,
++                           const struct net_device *dev, int strict);
 +};
 +
  struct ping_table {
        struct hlist_nulls_head hash[PING_HTABLE_SIZE];
        rwlock_t                lock;
  struct ping_iter_state {
        struct seq_net_private  p;
        int                     bucket;
 +      sa_family_t             family;
  };
  
  extern struct proto ping_prot;
 +extern struct ping_table ping_table;
 +#if IS_ENABLED(CONFIG_IPV6)
 +extern struct pingv6_ops pingv6_ops;
 +#endif
 +
 +struct pingfakehdr {
 +      struct icmphdr icmph;
 +      struct iovec *iov;
 +      sa_family_t family;
 +      __wsum wcheck;
 +};
 +
 +int  ping_get_port(struct sock *sk, unsigned short ident);
 +void ping_hash(struct sock *sk);
 +void ping_unhash(struct sock *sk);
  
 +int  ping_init_sock(struct sock *sk);
 +void ping_close(struct sock *sk, long timeout);
 +int  ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len);
 +void ping_err(struct sk_buff *skb, int offset, u32 info);
 +int  ping_getfrag(void *from, char *to, int offset, int fraglen, int odd,
 +                struct sk_buff *);
  
 -extern void ping_rcv(struct sk_buff *);
 -extern void ping_err(struct sk_buff *, u32 info);
 +int  ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 +                size_t len, int noblock, int flags, int *addr_len);
 +int  ping_common_sendmsg(int family, struct msghdr *msg, size_t len,
 +                       void *user_icmph, size_t icmph_len);
 +int  ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 +                   size_t len);
 +int  ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 +                   size_t len);
 +int  ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
 +void ping_rcv(struct sk_buff *skb);
  
  #ifdef CONFIG_PROC_FS
 +struct ping_seq_afinfo {
 +      char                            *name;
 +      sa_family_t                     family;
 +      const struct file_operations    *seq_fops;
 +      const struct seq_operations     seq_ops;
 +};
 +
 +extern const struct file_operations ping_seq_fops;
 +
 +void *ping_seq_start(struct seq_file *seq, loff_t *pos, sa_family_t family);
 +void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos);
 +void ping_seq_stop(struct seq_file *seq, void *v);
 +int ping_proc_register(struct net *net, struct ping_seq_afinfo *afinfo);
 +void ping_proc_unregister(struct net *net, struct ping_seq_afinfo *afinfo);
 +
  extern int __init ping_proc_init(void);
  extern void ping_proc_exit(void);
  #endif
  
  void __init ping_init(void);
 -
 +int  __init pingv6_init(void);
 +void pingv6_exit(void);
  
  #endif /* _PING_H */
diff --combined net/core/skbuff.c
index 6b1b52c5593bef956a8ddf0584b7dce7d9b262eb,cfd777bd6bd0cea8023cfe32e431488727982225..73f57a0e15234a99a3dc64094ff56b28200de57d
@@@ -195,11 -195,13 +195,11 @@@ struct sk_buff *__alloc_skb_head(gfp_t 
         * the tail pointer in struct sk_buff!
         */
        memset(skb, 0, offsetof(struct sk_buff, tail));
-       skb->data = NULL;
+       skb->head = NULL;
        skb->truesize = sizeof(struct sk_buff);
        atomic_set(&skb->users, 1);
  
 -#ifdef NET_SKBUFF_DATA_USES_OFFSET
 -      skb->mac_header = ~0U;
 -#endif
 +      skb->mac_header = (typeof(skb->mac_header))~0U;
  out:
        return skb;
  }
@@@ -273,8 -275,10 +273,8 @@@ struct sk_buff *__alloc_skb(unsigned in
        skb->data = data;
        skb_reset_tail_pointer(skb);
        skb->end = skb->tail + size;
 -#ifdef NET_SKBUFF_DATA_USES_OFFSET
 -      skb->mac_header = ~0U;
 -      skb->transport_header = ~0U;
 -#endif
 +      skb->mac_header = (typeof(skb->mac_header))~0U;
 +      skb->transport_header = (typeof(skb->transport_header))~0U;
  
        /* make sure we initialize shinfo sequentially */
        shinfo = skb_shinfo(skb);
@@@ -340,8 -344,10 +340,8 @@@ struct sk_buff *build_skb(void *data, u
        skb->data = data;
        skb_reset_tail_pointer(skb);
        skb->end = skb->tail + size;
 -#ifdef NET_SKBUFF_DATA_USES_OFFSET
 -      skb->mac_header = ~0U;
 -      skb->transport_header = ~0U;
 -#endif
 +      skb->mac_header = (typeof(skb->mac_header))~0U;
 +      skb->transport_header = (typeof(skb->transport_header))~0U;
  
        /* make sure we initialize shinfo sequentially */
        shinfo = skb_shinfo(skb);
@@@ -605,7 -611,7 +605,7 @@@ static void skb_release_head_state(stru
  static void skb_release_all(struct sk_buff *skb)
  {
        skb_release_head_state(skb);
-       if (likely(skb->data))
+       if (likely(skb->head))
                skb_release_data(skb);
  }
  
@@@ -2847,7 -2853,7 +2847,7 @@@ struct sk_buff *skb_segment(struct sk_b
                                                 doffset + tnl_hlen);
  
                if (fskb != skb_shinfo(skb)->frag_list)
 -                      continue;
 +                      goto perform_csum_check;
  
                if (!sg) {
                        nskb->ip_summed = CHECKSUM_NONE;
@@@ -2911,7 -2917,6 +2911,7 @@@ skip_fraglist
                nskb->len += nskb->data_len;
                nskb->truesize += nskb->data_len;
  
 +perform_csum_check:
                if (!csum) {
                        nskb->csum = skb_checksum(nskb, doffset,
                                                  nskb->len - doffset, 0);
diff --combined net/ipv4/ip_tunnel.c
index b89095c1518f50d28e58e099fb9011d0d5c260ae,be2f8da0ae8ebc4b94a257dd50914db14212a451..7c79cf8ad449c5a91235704f9a9d82ab4e6bc769
@@@ -487,7 -487,7 +487,7 @@@ drop
  EXPORT_SYMBOL_GPL(ip_tunnel_rcv);
  
  void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
 -                  const struct iphdr *tnl_params)
 +                  const struct iphdr *tnl_params, const u8 protocol)
  {
        struct ip_tunnel *tunnel = netdev_priv(dev);
        const struct iphdr *inner_iph;
  
        inner_iph = (const struct iphdr *)skb_inner_network_header(skb);
  
+       memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
        dst = tnl_params->daddr;
        if (dst == 0) {
                /* NBMA tunnel */
  
        skb_dst_drop(skb);
        skb_dst_set(skb, &rt->dst);
-       memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
  
        /* Push down and install the IP header. */
        skb_push(skb, sizeof(struct iphdr));
        iph->version    =       4;
        iph->ihl        =       sizeof(struct iphdr) >> 2;
        iph->frag_off   =       df;
 -      iph->protocol   =       tnl_params->protocol;
 +      iph->protocol   =       protocol;
        iph->tos        =       ip_tunnel_ecn_encap(tos, inner_iph, skb);
        iph->daddr      =       fl4.daddr;
        iph->saddr      =       fl4.saddr;
diff --combined net/ipv4/route.c
index 403e283028690a173b112f1600ef2ecf1b2f1550,d35bbf0cf4045d04f67d30e31f15c5271058dd5a..198ea596f2d9a783f9d19bbd6be5924f81afb4c6
@@@ -594,25 -594,11 +594,25 @@@ static inline u32 fnhe_hashfun(__be32 d
        return hval & (FNHE_HASH_SIZE - 1);
  }
  
 +static void fill_route_from_fnhe(struct rtable *rt, struct fib_nh_exception *fnhe)
 +{
 +      rt->rt_pmtu = fnhe->fnhe_pmtu;
 +      rt->dst.expires = fnhe->fnhe_expires;
 +
 +      if (fnhe->fnhe_gw) {
 +              rt->rt_flags |= RTCF_REDIRECTED;
 +              rt->rt_gateway = fnhe->fnhe_gw;
 +              rt->rt_uses_gateway = 1;
 +      }
 +}
 +
  static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw,
                                  u32 pmtu, unsigned long expires)
  {
        struct fnhe_hash_bucket *hash;
        struct fib_nh_exception *fnhe;
 +      struct rtable *rt;
 +      unsigned int i;
        int depth;
        u32 hval = fnhe_hashfun(daddr);
  
                        fnhe->fnhe_gw = gw;
                if (pmtu) {
                        fnhe->fnhe_pmtu = pmtu;
 -                      fnhe->fnhe_expires = expires;
 +                      fnhe->fnhe_expires = max(1UL, expires);
                }
 +              /* Update all cached dsts too */
 +              rt = rcu_dereference(fnhe->fnhe_rth);
 +              if (rt)
 +                      fill_route_from_fnhe(rt, fnhe);
        } else {
                if (depth > FNHE_RECLAIM_DEPTH)
                        fnhe = fnhe_oldest(hash);
                        fnhe->fnhe_next = hash->chain;
                        rcu_assign_pointer(hash->chain, fnhe);
                }
 +              fnhe->fnhe_genid = fnhe_genid(dev_net(nh->nh_dev));
                fnhe->fnhe_daddr = daddr;
                fnhe->fnhe_gw = gw;
                fnhe->fnhe_pmtu = pmtu;
                fnhe->fnhe_expires = expires;
 +
 +              /* Exception created; mark the cached routes for the nexthop
 +               * stale, so anyone caching it rechecks if this exception
 +               * applies to them.
 +               */
 +              for_each_possible_cpu(i) {
 +                      struct rtable __rcu **prt;
 +                      prt = per_cpu_ptr(nh->nh_pcpu_rth_output, i);
 +                      rt = rcu_dereference(*prt);
 +                      if (rt)
 +                              rt->dst.obsolete = DST_OBSOLETE_KILL;
 +              }
        }
  
        fnhe->fnhe_stamp = jiffies;
@@@ -768,10 -737,15 +768,15 @@@ static void ip_do_redirect(struct dst_e
  {
        struct rtable *rt;
        struct flowi4 fl4;
+       const struct iphdr *iph = (const struct iphdr *) skb->data;
+       int oif = skb->dev->ifindex;
+       u8 tos = RT_TOS(iph->tos);
+       u8 prot = iph->protocol;
+       u32 mark = skb->mark;
  
        rt = (struct rtable *) dst;
  
-       ip_rt_build_flow_key(&fl4, sk, skb);
+       __build_flow_key(&fl4, sk, iph, oif, tos, prot, mark, 0);
        __ip_do_redirect(rt, skb, &fl4, true);
  }
  
@@@ -948,9 -922,12 +953,9 @@@ static void __ip_rt_update_pmtu(struct 
        if (mtu < ip_rt_min_pmtu)
                mtu = ip_rt_min_pmtu;
  
 -      if (!rt->rt_pmtu) {
 -              dst->obsolete = DST_OBSOLETE_KILL;
 -      } else {
 -              rt->rt_pmtu = mtu;
 -              dst->expires = max(1UL, jiffies + ip_rt_mtu_expires);
 -      }
 +      if (rt->rt_pmtu == mtu &&
 +          time_before(jiffies, dst->expires - ip_rt_mtu_expires / 2))
 +              return;
  
        rcu_read_lock();
        if (fib_lookup(dev_net(dst->dev), fl4, &res) == 0) {
@@@ -1091,11 -1068,11 +1096,11 @@@ static struct dst_entry *ipv4_dst_check
         * DST_OBSOLETE_FORCE_CHK which forces validation calls down
         * into this function always.
         *
 -       * When a PMTU/redirect information update invalidates a
 -       * route, this is indicated by setting obsolete to
 -       * DST_OBSOLETE_KILL.
 +       * When a PMTU/redirect information update invalidates a route,
 +       * this is indicated by setting obsolete to DST_OBSOLETE_KILL or
 +       * DST_OBSOLETE_DEAD by dst_free().
         */
 -      if (dst->obsolete == DST_OBSOLETE_KILL || rt_is_expired(rt))
 +      if (dst->obsolete != DST_OBSOLETE_FORCE_CHK || rt_is_expired(rt))
                return NULL;
        return dst;
  }
@@@ -1237,17 -1214,26 +1242,17 @@@ static bool rt_bind_exception(struct rt
        spin_lock_bh(&fnhe_lock);
  
        if (daddr == fnhe->fnhe_daddr) {
 +              int genid = fnhe_genid(dev_net(rt->dst.dev));
                struct rtable *orig = rcu_dereference(fnhe->fnhe_rth);
 -              if (orig && rt_is_expired(orig)) {
 +
 +              if (fnhe->fnhe_genid != genid) {
 +                      fnhe->fnhe_genid = genid;
                        fnhe->fnhe_gw = 0;
                        fnhe->fnhe_pmtu = 0;
                        fnhe->fnhe_expires = 0;
                }
 -              if (fnhe->fnhe_pmtu) {
 -                      unsigned long expires = fnhe->fnhe_expires;
 -                      unsigned long diff = expires - jiffies;
 -
 -                      if (time_before(jiffies, expires)) {
 -                              rt->rt_pmtu = fnhe->fnhe_pmtu;
 -                              dst_set_expires(&rt->dst, diff);
 -                      }
 -              }
 -              if (fnhe->fnhe_gw) {
 -                      rt->rt_flags |= RTCF_REDIRECTED;
 -                      rt->rt_gateway = fnhe->fnhe_gw;
 -                      rt->rt_uses_gateway = 1;
 -              } else if (!rt->rt_gateway)
 +              fill_route_from_fnhe(rt, fnhe);
 +              if (!rt->rt_gateway)
                        rt->rt_gateway = daddr;
  
                rcu_assign_pointer(fnhe->fnhe_rth, rt);
@@@ -2447,11 -2433,8 +2452,11 @@@ static int ipv4_sysctl_rtcache_flush(ct
                                        void __user *buffer,
                                        size_t *lenp, loff_t *ppos)
  {
 +      struct net *net = (struct net *)__ctl->extra1;
 +
        if (write) {
 -              rt_cache_flush((struct net *)__ctl->extra1);
 +              rt_cache_flush(net);
 +              fnhe_genid_bump(net);
                return 0;
        }
  
@@@ -2626,7 -2609,6 +2631,7 @@@ static __net_initdata struct pernet_ope
  static __net_init int rt_genid_init(struct net *net)
  {
        atomic_set(&net->rt_genid, 0);
 +      atomic_set(&net->fnhe_genid, 0);
        get_random_bytes(&net->ipv4.dev_addr_genid,
                         sizeof(net->ipv4.dev_addr_genid));
        return 0;
diff --combined net/ipv6/addrconf.c
index 7b34f06af344838de37e3af4bbd9117995113045,1bbf744c2cc35e7953b9580db08a357f4e829a04..21010fddb203cc768901625cf6c17e1cb0f7c654
@@@ -1126,7 -1126,8 +1126,7 @@@ retry
  
        ift = !max_addresses ||
              ipv6_count_addresses(idev) < max_addresses ?
 -              ipv6_add_addr(idev, &addr, tmp_plen,
 -                            ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK,
 +              ipv6_add_addr(idev, &addr, tmp_plen, ipv6_addr_scope(&addr),
                              addr_flags) : NULL;
        if (IS_ERR_OR_NULL(ift)) {
                in6_ifa_put(ifp);
@@@ -1486,7 -1487,7 +1486,7 @@@ static int ipv6_count_addresses(struct 
  }
  
  int ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
-                 struct net_device *dev, int strict)
+                 const struct net_device *dev, int strict)
  {
        struct inet6_ifaddr *ifp;
        unsigned int hash = inet6_addr_hash(addr);
@@@ -2401,7 -2402,6 +2401,7 @@@ err_exit
   *    Manual configuration of address on an interface
   */
  static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *pfx,
 +                        const struct in6_addr *peer_pfx,
                          unsigned int plen, __u8 ifa_flags, __u32 prefered_lft,
                          __u32 valid_lft)
  {
                ifp->valid_lft = valid_lft;
                ifp->prefered_lft = prefered_lft;
                ifp->tstamp = jiffies;
 +              if (peer_pfx)
 +                      ifp->peer_addr = *peer_pfx;
                spin_unlock_bh(&ifp->lock);
  
                addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev,
@@@ -2528,7 -2526,7 +2528,7 @@@ int addrconf_add_ifaddr(struct net *net
                return -EFAULT;
  
        rtnl_lock();
 -      err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr,
 +      err = inet6_addr_add(net, ireq.ifr6_ifindex, &ireq.ifr6_addr, NULL,
                             ireq.ifr6_prefixlen, IFA_F_PERMANENT,
                             INFINITY_LIFE_TIME, INFINITY_LIFE_TIME);
        rtnl_unlock();
@@@ -2660,8 -2658,10 +2660,10 @@@ static void init_loopback(struct net_de
                        sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
  
                        /* Failure cases are ignored */
-                       if (!IS_ERR(sp_rt))
+                       if (!IS_ERR(sp_rt)) {
+                               sp_ifa->rt = sp_rt;
                                ip6_ins_rt(sp_rt);
+                       }
                }
                read_unlock_bh(&idev->lock);
        }
@@@ -2826,9 -2826,9 +2828,9 @@@ static void addrconf_ip6_tnl_config(str
  }
  
  static int addrconf_notify(struct notifier_block *this, unsigned long event,
 -                         void *data)
 +                         void *ptr)
  {
 -      struct net_device *dev = (struct net_device *) data;
 +      struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct inet6_dev *idev = __in6_dev_get(dev);
        int run_pending = 0;
        int err;
@@@ -3612,20 -3612,18 +3614,20 @@@ restart
        rcu_read_unlock_bh();
  }
  
 -static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local)
 +static struct in6_addr *extract_addr(struct nlattr *addr, struct nlattr *local,
 +                                   struct in6_addr **peer_pfx)
  {
        struct in6_addr *pfx = NULL;
  
 +      *peer_pfx = NULL;
 +
        if (addr)
                pfx = nla_data(addr);
  
        if (local) {
                if (pfx && nla_memcmp(local, pfx, sizeof(*pfx)))
 -                      pfx = NULL;
 -              else
 -                      pfx = nla_data(local);
 +                      *peer_pfx = pfx;
 +              pfx = nla_data(local);
        }
  
        return pfx;
@@@ -3643,7 -3641,7 +3645,7 @@@ inet6_rtm_deladdr(struct sk_buff *skb, 
        struct net *net = sock_net(skb->sk);
        struct ifaddrmsg *ifm;
        struct nlattr *tb[IFA_MAX+1];
 -      struct in6_addr *pfx;
 +      struct in6_addr *pfx, *peer_pfx;
        int err;
  
        err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFA_MAX, ifa_ipv6_policy);
                return err;
  
        ifm = nlmsg_data(nlh);
 -      pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
 +      pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx);
        if (pfx == NULL)
                return -EINVAL;
  
@@@ -3709,7 -3707,7 +3711,7 @@@ inet6_rtm_newaddr(struct sk_buff *skb, 
        struct net *net = sock_net(skb->sk);
        struct ifaddrmsg *ifm;
        struct nlattr *tb[IFA_MAX+1];
 -      struct in6_addr *pfx;
 +      struct in6_addr *pfx, *peer_pfx;
        struct inet6_ifaddr *ifa;
        struct net_device *dev;
        u32 valid_lft = INFINITY_LIFE_TIME, preferred_lft = INFINITY_LIFE_TIME;
                return err;
  
        ifm = nlmsg_data(nlh);
 -      pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
 +      pfx = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer_pfx);
        if (pfx == NULL)
                return -EINVAL;
  
                 * It would be best to check for !NLM_F_CREATE here but
                 * userspace alreay relies on not having to provide this.
                 */
 -              return inet6_addr_add(net, ifm->ifa_index, pfx,
 +              return inet6_addr_add(net, ifm->ifa_index, pfx, peer_pfx,
                                      ifm->ifa_prefixlen, ifa_flags,
                                      preferred_lft, valid_lft);
        }
@@@ -3806,7 -3804,6 +3808,7 @@@ static inline int rt_scope(int ifa_scop
  static inline int inet6_ifaddr_msgsize(void)
  {
        return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
 +             + nla_total_size(16) /* IFA_LOCAL */
               + nla_total_size(16) /* IFA_ADDRESS */
               + nla_total_size(sizeof(struct ifa_cacheinfo));
  }
@@@ -3845,22 -3842,13 +3847,22 @@@ static int inet6_fill_ifaddr(struct sk_
                valid = INFINITY_LIFE_TIME;
        }
  
 -      if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0 ||
 -          put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0) {
 -              nlmsg_cancel(skb, nlh);
 -              return -EMSGSIZE;
 -      }
 +      if (!ipv6_addr_any(&ifa->peer_addr)) {
 +              if (nla_put(skb, IFA_LOCAL, 16, &ifa->addr) < 0 ||
 +                  nla_put(skb, IFA_ADDRESS, 16, &ifa->peer_addr) < 0)
 +                      goto error;
 +      } else
 +              if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0)
 +                      goto error;
 +
 +      if (put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0)
 +              goto error;
  
        return nlmsg_end(skb, nlh);
 +
 +error:
 +      nlmsg_cancel(skb, nlh);
 +      return -EMSGSIZE;
  }
  
  static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
@@@ -4060,7 -4048,7 +4062,7 @@@ static int inet6_rtm_getaddr(struct sk_
        struct net *net = sock_net(in_skb->sk);
        struct ifaddrmsg *ifm;
        struct nlattr *tb[IFA_MAX+1];
 -      struct in6_addr *addr = NULL;
 +      struct in6_addr *addr = NULL, *peer;
        struct net_device *dev = NULL;
        struct inet6_ifaddr *ifa;
        struct sk_buff *skb;
        if (err < 0)
                goto errout;
  
 -      addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL]);
 +      addr = extract_addr(tb[IFA_ADDRESS], tb[IFA_LOCAL], &peer);
        if (addr == NULL) {
                err = -EINVAL;
                goto errout;
@@@ -4578,26 -4566,11 +4580,26 @@@ static void __ipv6_ifa_notify(int event
                        ip6_ins_rt(ifp->rt);
                if (ifp->idev->cnf.forwarding)
                        addrconf_join_anycast(ifp);
 +              if (!ipv6_addr_any(&ifp->peer_addr))
 +                      addrconf_prefix_route(&ifp->peer_addr, 128,
 +                                            ifp->idev->dev, 0, 0);
                break;
        case RTM_DELADDR:
                if (ifp->idev->cnf.forwarding)
                        addrconf_leave_anycast(ifp);
                addrconf_leave_solict(ifp->idev, &ifp->addr);
 +              if (!ipv6_addr_any(&ifp->peer_addr)) {
 +                      struct rt6_info *rt;
 +                      struct net_device *dev = ifp->idev->dev;
 +
 +                      rt = rt6_lookup(dev_net(dev), &ifp->peer_addr, NULL,
 +                                      dev->ifindex, 1);
 +                      if (rt) {
 +                              dst_hold(&rt->dst);
 +                              if (ip6_del_rt(rt))
 +                                      dst_free(&rt->dst);
 +                      }
 +              }
                dst_hold(&ifp->rt->dst);
  
                if (ip6_del_rt(ifp->rt))
@@@ -4645,16 -4618,13 +4647,16 @@@ int addrconf_sysctl_forward(ctl_table *
  
  static void dev_disable_change(struct inet6_dev *idev)
  {
 +      struct netdev_notifier_info info;
 +
        if (!idev || !idev->dev)
                return;
  
 +      netdev_notifier_info_init(&info, idev->dev);
        if (idev->cnf.disable_ipv6)
 -              addrconf_notify(NULL, NETDEV_DOWN, idev->dev);
 +              addrconf_notify(NULL, NETDEV_DOWN, &info);
        else
 -              addrconf_notify(NULL, NETDEV_UP, idev->dev);
 +              addrconf_notify(NULL, NETDEV_UP, &info);
  }
  
  static void addrconf_disable_change(struct net *net, __s32 newf)
diff --combined net/ipv6/ping.c
index 62ac5f2e0aaf232708a4753abcb0e9adb3a8f602,0000000000000000000000000000000000000000..a43110385918975136f46e93e15f217e49fa7365
mode 100644,000000..100644
--- /dev/null
@@@ -1,272 -1,0 +1,272 @@@
-                       struct net_device *dev, int strict)
 +/*
 + * INET               An implementation of the TCP/IP protocol suite for the LINUX
 + *            operating system.  INET is implemented using the  BSD Socket
 + *            interface as the means of communication with the user level.
 + *
 + *            "Ping" sockets
 + *
 + *            This program is free software; you can redistribute it and/or
 + *            modify it under the terms of the GNU General Public License
 + *            as published by the Free Software Foundation; either version
 + *            2 of the License, or (at your option) any later version.
 + *
 + * Based on ipv4/ping.c code.
 + *
 + * Authors:   Lorenzo Colitti (IPv6 support)
 + *            Vasiliy Kulikov / Openwall (IPv4 implementation, for Linux 2.6),
 + *            Pavel Kankovsky (IPv4 implementation, for Linux 2.4.32)
 + *
 + */
 +
 +#include <net/addrconf.h>
 +#include <net/ipv6.h>
 +#include <net/ip6_route.h>
 +#include <net/protocol.h>
 +#include <net/udp.h>
 +#include <net/transp_v6.h>
 +#include <net/ping.h>
 +
 +struct proto pingv6_prot = {
 +      .name =         "PINGv6",
 +      .owner =        THIS_MODULE,
 +      .init =         ping_init_sock,
 +      .close =        ping_close,
 +      .connect =      ip6_datagram_connect,
 +      .disconnect =   udp_disconnect,
 +      .setsockopt =   ipv6_setsockopt,
 +      .getsockopt =   ipv6_getsockopt,
 +      .sendmsg =      ping_v6_sendmsg,
 +      .recvmsg =      ping_recvmsg,
 +      .bind =         ping_bind,
 +      .backlog_rcv =  ping_queue_rcv_skb,
 +      .hash =         ping_hash,
 +      .unhash =       ping_unhash,
 +      .get_port =     ping_get_port,
 +      .obj_size =     sizeof(struct raw6_sock),
 +};
 +EXPORT_SYMBOL_GPL(pingv6_prot);
 +
 +static struct inet_protosw pingv6_protosw = {
 +      .type =      SOCK_DGRAM,
 +      .protocol =  IPPROTO_ICMPV6,
 +      .prot =      &pingv6_prot,
 +      .ops =       &inet6_dgram_ops,
 +      .no_check =  UDP_CSUM_DEFAULT,
 +      .flags =     INET_PROTOSW_REUSE,
 +};
 +
 +
 +/* Compatibility glue so we can support IPv6 when it's compiled as a module */
 +int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len)
 +{
 +      return -EAFNOSUPPORT;
 +}
 +int dummy_ip6_datagram_recv_ctl(struct sock *sk, struct msghdr *msg,
 +                               struct sk_buff *skb)
 +{
 +      return -EAFNOSUPPORT;
 +}
 +int dummy_icmpv6_err_convert(u8 type, u8 code, int *err)
 +{
 +      return -EAFNOSUPPORT;
 +}
 +void dummy_ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
 +                          __be16 port, u32 info, u8 *payload) {}
 +int dummy_ipv6_chk_addr(struct net *net, const struct in6_addr *addr,
++                      const struct net_device *dev, int strict)
 +{
 +      return 0;
 +}
 +
 +int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 +                  size_t len)
 +{
 +      struct inet_sock *inet = inet_sk(sk);
 +      struct ipv6_pinfo *np = inet6_sk(sk);
 +      struct icmp6hdr user_icmph;
 +      int addr_type;
 +      struct in6_addr *daddr;
 +      int iif = 0;
 +      struct flowi6 fl6;
 +      int err;
 +      int hlimit;
 +      struct dst_entry *dst;
 +      struct rt6_info *rt;
 +      struct pingfakehdr pfh;
 +
 +      pr_debug("ping_v6_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num);
 +
 +      err = ping_common_sendmsg(AF_INET6, msg, len, &user_icmph,
 +                                sizeof(user_icmph));
 +      if (err)
 +              return err;
 +
 +      if (msg->msg_name) {
 +              struct sockaddr_in6 *u = (struct sockaddr_in6 *) msg->msg_name;
 +              if (msg->msg_namelen < sizeof(struct sockaddr_in6) ||
 +                  u->sin6_family != AF_INET6) {
 +                      return -EINVAL;
 +              }
 +              if (sk->sk_bound_dev_if &&
 +                  sk->sk_bound_dev_if != u->sin6_scope_id) {
 +                      return -EINVAL;
 +              }
 +              daddr = &(u->sin6_addr);
 +              iif = u->sin6_scope_id;
 +      } else {
 +              if (sk->sk_state != TCP_ESTABLISHED)
 +                      return -EDESTADDRREQ;
 +              daddr = &np->daddr;
 +      }
 +
 +      if (!iif)
 +              iif = sk->sk_bound_dev_if;
 +
 +      addr_type = ipv6_addr_type(daddr);
 +      if (__ipv6_addr_needs_scope_id(addr_type) && !iif)
 +              return -EINVAL;
 +      if (addr_type & IPV6_ADDR_MAPPED)
 +              return -EINVAL;
 +
 +      /* TODO: use ip6_datagram_send_ctl to get options from cmsg */
 +
 +      memset(&fl6, 0, sizeof(fl6));
 +
 +      fl6.flowi6_proto = IPPROTO_ICMPV6;
 +      fl6.saddr = np->saddr;
 +      fl6.daddr = *daddr;
 +      fl6.fl6_icmp_type = user_icmph.icmp6_type;
 +      fl6.fl6_icmp_code = user_icmph.icmp6_code;
 +      security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
 +
 +      if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
 +              fl6.flowi6_oif = np->mcast_oif;
 +      else if (!fl6.flowi6_oif)
 +              fl6.flowi6_oif = np->ucast_oif;
 +
 +      dst = ip6_sk_dst_lookup_flow(sk, &fl6,  daddr, 1);
 +      if (IS_ERR(dst))
 +              return PTR_ERR(dst);
 +      rt = (struct rt6_info *) dst;
 +
 +      np = inet6_sk(sk);
 +      if (!np)
 +              return -EBADF;
 +
 +      if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
 +              fl6.flowi6_oif = np->mcast_oif;
 +      else if (!fl6.flowi6_oif)
 +              fl6.flowi6_oif = np->ucast_oif;
 +
 +      pfh.icmph.type = user_icmph.icmp6_type;
 +      pfh.icmph.code = user_icmph.icmp6_code;
 +      pfh.icmph.checksum = 0;
 +      pfh.icmph.un.echo.id = inet->inet_sport;
 +      pfh.icmph.un.echo.sequence = user_icmph.icmp6_sequence;
 +      pfh.iov = msg->msg_iov;
 +      pfh.wcheck = 0;
 +      pfh.family = AF_INET6;
 +
 +      if (ipv6_addr_is_multicast(&fl6.daddr))
 +              hlimit = np->mcast_hops;
 +      else
 +              hlimit = np->hop_limit;
 +      if (hlimit < 0)
 +              hlimit = ip6_dst_hoplimit(dst);
 +
 +      err = ip6_append_data(sk, ping_getfrag, &pfh, len,
 +                            0, hlimit,
 +                            np->tclass, NULL, &fl6, rt,
 +                            MSG_DONTWAIT, np->dontfrag);
 +
 +      if (err) {
 +              ICMP6_INC_STATS_BH(sock_net(sk), rt->rt6i_idev,
 +                                 ICMP6_MIB_OUTERRORS);
 +              ip6_flush_pending_frames(sk);
 +      } else {
 +              err = icmpv6_push_pending_frames(sk, &fl6,
 +                                               (struct icmp6hdr *) &pfh.icmph,
 +                                               len);
 +      }
 +
 +      return err;
 +}
 +
 +#ifdef CONFIG_PROC_FS
 +static void *ping_v6_seq_start(struct seq_file *seq, loff_t *pos)
 +{
 +      return ping_seq_start(seq, pos, AF_INET6);
 +}
 +
 +int ping_v6_seq_show(struct seq_file *seq, void *v)
 +{
 +      if (v == SEQ_START_TOKEN) {
 +              seq_puts(seq, IPV6_SEQ_DGRAM_HEADER);
 +      } else {
 +              int bucket = ((struct ping_iter_state *) seq->private)->bucket;
 +              struct inet_sock *inet = inet_sk(v);
 +              __u16 srcp = ntohs(inet->inet_sport);
 +              __u16 destp = ntohs(inet->inet_dport);
 +              ip6_dgram_sock_seq_show(seq, v, srcp, destp, bucket);
 +      }
 +      return 0;
 +}
 +
 +static struct ping_seq_afinfo ping_v6_seq_afinfo = {
 +      .name           = "icmp6",
 +      .family         = AF_INET6,
 +      .seq_fops       = &ping_seq_fops,
 +      .seq_ops        = {
 +              .start          = ping_v6_seq_start,
 +              .show           = ping_v6_seq_show,
 +              .next           = ping_seq_next,
 +              .stop           = ping_seq_stop,
 +      },
 +};
 +
 +static int __net_init ping_v6_proc_init_net(struct net *net)
 +{
 +      return ping_proc_register(net, &ping_v6_seq_afinfo);
 +}
 +
 +static void __net_init ping_v6_proc_exit_net(struct net *net)
 +{
 +      return ping_proc_unregister(net, &ping_v6_seq_afinfo);
 +}
 +
 +static struct pernet_operations ping_v6_net_ops = {
 +      .init = ping_v6_proc_init_net,
 +      .exit = ping_v6_proc_exit_net,
 +};
 +#endif
 +
 +int __init pingv6_init(void)
 +{
 +#ifdef CONFIG_PROC_FS
 +      int ret = register_pernet_subsys(&ping_v6_net_ops);
 +      if (ret)
 +              return ret;
 +#endif
 +      pingv6_ops.ipv6_recv_error = ipv6_recv_error;
 +      pingv6_ops.ip6_datagram_recv_ctl = ip6_datagram_recv_ctl;
 +      pingv6_ops.icmpv6_err_convert = icmpv6_err_convert;
 +      pingv6_ops.ipv6_icmp_error = ipv6_icmp_error;
 +      pingv6_ops.ipv6_chk_addr = ipv6_chk_addr;
 +      return inet6_register_protosw(&pingv6_protosw);
 +}
 +
 +/* This never gets called because it's not possible to unload the ipv6 module,
 + * but just in case.
 + */
 +void pingv6_exit(void)
 +{
 +      pingv6_ops.ipv6_recv_error = dummy_ipv6_recv_error;
 +      pingv6_ops.ip6_datagram_recv_ctl = dummy_ip6_datagram_recv_ctl;
 +      pingv6_ops.icmpv6_err_convert = dummy_icmpv6_err_convert;
 +      pingv6_ops.ipv6_icmp_error = dummy_ipv6_icmp_error;
 +      pingv6_ops.ipv6_chk_addr = dummy_ipv6_chk_addr;
 +#ifdef CONFIG_PROC_FS
 +      unregister_pernet_subsys(&ping_v6_net_ops);
 +#endif
 +      inet6_unregister_protosw(&pingv6_protosw);
 +}
diff --combined net/ipv6/udp_offload.c
index 76d401a93c7a3a0946e4623cee09598f26e12eed,d3cfaf9c7a0858d8bb1e9fd60c412c3b03cbf3e3..5d1b8d7ac9931c7d0cbe35c06318d08659a5af7b
@@@ -46,11 -46,12 +46,12 @@@ static struct sk_buff *udp6_ufo_fragmen
        unsigned int mss;
        unsigned int unfrag_ip6hlen, unfrag_len;
        struct frag_hdr *fptr;
-       u8 *mac_start, *prevhdr;
+       u8 *packet_start, *prevhdr;
        u8 nexthdr;
        u8 frag_hdr_sz = sizeof(struct frag_hdr);
        int offset;
        __wsum csum;
+       int tnl_hlen;
  
        mss = skb_shinfo(skb)->gso_size;
        if (unlikely(skb->len <= mss))
@@@ -63,8 -64,7 +64,8 @@@
                if (unlikely(type & ~(SKB_GSO_UDP |
                                      SKB_GSO_DODGY |
                                      SKB_GSO_UDP_TUNNEL |
 -                                    SKB_GSO_GRE) ||
 +                                    SKB_GSO_GRE |
 +                                    SKB_GSO_MPLS) ||
                             !(type & (SKB_GSO_UDP))))
                        goto out;
  
        skb->ip_summed = CHECKSUM_NONE;
  
        /* Check if there is enough headroom to insert fragment header. */
-       if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) &&
-           pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC))
-               goto out;
+       tnl_hlen = skb_tnl_header_len(skb);
+       if (skb_headroom(skb) < (tnl_hlen + frag_hdr_sz)) {
+               if (gso_pskb_expand_head(skb, tnl_hlen + frag_hdr_sz))
+                       goto out;
+       }
  
        /* Find the unfragmentable header and shift it left by frag_hdr_sz
         * bytes to insert fragment header.
        unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
        nexthdr = *prevhdr;
        *prevhdr = NEXTHDR_FRAGMENT;
-       unfrag_len = skb_network_header(skb) - skb_mac_header(skb) +
-                    unfrag_ip6hlen;
-       mac_start = skb_mac_header(skb);
-       memmove(mac_start-frag_hdr_sz, mac_start, unfrag_len);
+       unfrag_len = (skb_network_header(skb) - skb_mac_header(skb)) +
+                    unfrag_ip6hlen + tnl_hlen;
+       packet_start = (u8 *) skb->head + SKB_GSO_CB(skb)->mac_offset;
+       memmove(packet_start-frag_hdr_sz, packet_start, unfrag_len);
  
+       SKB_GSO_CB(skb)->mac_offset -= frag_hdr_sz;
        skb->mac_header -= frag_hdr_sz;
        skb->network_header -= frag_hdr_sz;
  
diff --combined net/mac80211/iface.c
index d2c3fd178dbe16cf396f3f9b62368e1ee9f4c633,98d20c0f6fed8829c1881e16b274c2bf97c589c4..7c3ba8628d4e6aefe6ce98747dada70bbc04ab55
@@@ -159,9 -159,10 +159,10 @@@ static int ieee80211_change_mtu(struct 
        return 0;
  }
  
- static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr)
+ static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr)
  {
-       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_sub_if_data *iter;
        u64 new, mask, tmp;
        u8 *m;
        int ret = 0;
  
  
        mutex_lock(&local->iflist_mtx);
-       list_for_each_entry(sdata, &local->interfaces, list) {
-               if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+       list_for_each_entry(iter, &local->interfaces, list) {
+               if (iter == sdata)
+                       continue;
+               if (iter->vif.type == NL80211_IFTYPE_MONITOR)
                        continue;
  
-               m = sdata->vif.addr;
+               m = iter->vif.addr;
                tmp =   ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
                        ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
                        ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
@@@ -209,7 -213,7 +213,7 @@@ static int ieee80211_change_mac(struct 
        if (ieee80211_sdata_running(sdata))
                return -EBUSY;
  
-       ret = ieee80211_verify_mac(sdata->local, sa->sa_data);
+       ret = ieee80211_verify_mac(sdata, sa->sa_data);
        if (ret)
                return ret;
  
@@@ -474,6 -478,9 +478,9 @@@ int ieee80211_do_open(struct wireless_d
                        master->control_port_protocol;
                sdata->control_port_no_encrypt =
                        master->control_port_no_encrypt;
+               sdata->vif.cab_queue = master->vif.cab_queue;
+               memcpy(sdata->vif.hw_queue, master->vif.hw_queue,
+                      sizeof(sdata->vif.hw_queue));
                break;
                }
        case NL80211_IFTYPE_AP:
  
        ieee80211_recalc_ps(local, -1);
  
-       if (dev) {
+       if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
+           sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
+               /* XXX: for AP_VLAN, actually track AP queues */
+               netif_tx_start_all_queues(dev);
+       } else if (dev) {
                unsigned long flags;
                int n_acs = IEEE80211_NUM_ACS;
                int ac;
@@@ -1479,7 -1490,17 +1490,17 @@@ static void ieee80211_assign_perm_addr(
                        break;
                }
  
+               /*
+                * Pick address of existing interface in case user changed
+                * MAC address manually, default to perm_addr.
+                */
                m = local->hw.wiphy->perm_addr;
+               list_for_each_entry(sdata, &local->interfaces, list) {
+                       if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
+                               continue;
+                       m = sdata->vif.addr;
+                       break;
+               }
                start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) |
                        ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
                        ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
@@@ -1696,6 -1717,15 +1717,15 @@@ void ieee80211_remove_interfaces(struc
  
        ASSERT_RTNL();
  
+       /*
+        * Close all AP_VLAN interfaces first, as otherwise they
+        * might be closed while the AP interface they belong to
+        * is closed, causing unregister_netdevice_many() to crash.
+        */
+       list_for_each_entry(sdata, &local->interfaces, list)
+               if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+                       dev_close(sdata->dev);
        mutex_lock(&local->iflist_mtx);
        list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
                list_del(&sdata->list);
  }
  
  static int netdev_notify(struct notifier_block *nb,
 -                       unsigned long state,
 -                       void *ndev)
 +                       unsigned long state, void *ptr)
  {
 -      struct net_device *dev = ndev;
 +      struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct ieee80211_sub_if_data *sdata;
  
        if (state != NETDEV_CHANGENAME)
diff --combined net/sched/sch_tbf.c
index 38008b0980d9f90d89a84ac217b3a03d44e80442,e478d316602b1b9ca94100369e878f0a315a72cd..1aaf1b6e51a2be238bc47797597ed3bcb76de4b1
@@@ -116,57 -116,14 +116,57 @@@ struct tbf_sched_data 
        struct qdisc_watchdog watchdog; /* Watchdog timer */
  };
  
 +
 +/* GSO packet is too big, segment it so that tbf can transmit
 + * each segment in time
 + */
 +static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch)
 +{
 +      struct tbf_sched_data *q = qdisc_priv(sch);
 +      struct sk_buff *segs, *nskb;
 +      netdev_features_t features = netif_skb_features(skb);
 +      int ret, nb;
 +
 +      segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
 +
 +      if (IS_ERR_OR_NULL(segs))
 +              return qdisc_reshape_fail(skb, sch);
 +
 +      nb = 0;
 +      while (segs) {
 +              nskb = segs->next;
 +              segs->next = NULL;
 +              if (likely(segs->len <= q->max_size)) {
 +                      qdisc_skb_cb(segs)->pkt_len = segs->len;
 +                      ret = qdisc_enqueue(segs, q->qdisc);
 +              } else {
 +                      ret = qdisc_reshape_fail(skb, sch);
 +              }
 +              if (ret != NET_XMIT_SUCCESS) {
 +                      if (net_xmit_drop_count(ret))
 +                              sch->qstats.drops++;
 +              } else {
 +                      nb++;
 +              }
 +              segs = nskb;
 +      }
 +      sch->q.qlen += nb;
 +      if (nb > 1)
 +              qdisc_tree_decrease_qlen(sch, 1 - nb);
 +      consume_skb(skb);
 +      return nb > 0 ? NET_XMIT_SUCCESS : NET_XMIT_DROP;
 +}
 +
  static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch)
  {
        struct tbf_sched_data *q = qdisc_priv(sch);
        int ret;
  
 -      if (qdisc_pkt_len(skb) > q->max_size)
 +      if (qdisc_pkt_len(skb) > q->max_size) {
 +              if (skb_is_gso(skb))
 +                      return tbf_segment(skb, sch);
                return qdisc_reshape_fail(skb, sch);
 -
 +      }
        ret = qdisc_enqueue(skb, q->qdisc);
        if (ret != NET_XMIT_SUCCESS) {
                if (net_xmit_drop_count(ret))
@@@ -341,9 -298,9 +341,9 @@@ static int tbf_change(struct Qdisc *sch
        q->tokens = q->buffer;
        q->ptokens = q->mtu;
  
-       psched_ratecfg_precompute(&q->rate, rtab->rate.rate);
+       psched_ratecfg_precompute(&q->rate, &rtab->rate);
        if (ptab) {
-               psched_ratecfg_precompute(&q->peak, ptab->rate.rate);
+               psched_ratecfg_precompute(&q->peak, &ptab->rate);
                q->peak_present = true;
        } else {
                q->peak_present = false;
@@@ -393,9 -350,9 +393,9 @@@ static int tbf_dump(struct Qdisc *sch, 
                goto nla_put_failure;
  
        opt.limit = q->limit;
-       opt.rate.rate = psched_ratecfg_getrate(&q->rate);
+       psched_ratecfg_getrate(&opt.rate, &q->rate);
        if (q->peak_present)
-               opt.peakrate.rate = psched_ratecfg_getrate(&q->peak);
+               psched_ratecfg_getrate(&opt.peakrate, &q->peak);
        else
                memset(&opt.peakrate, 0, sizeof(opt.peakrate));
        opt.mtu = PSCHED_NS2TICKS(q->mtu);
diff --combined net/xfrm/xfrm_policy.c
index 536ccc95de89ff6aad96ea07a2e3fcf0498f342d,ea970b8002a20a614a5bc9fe89afa3c39b131180..e52cab3591dd78c373274bb64420f87383775e8c
@@@ -2557,11 -2557,12 +2557,12 @@@ static void __xfrm_garbage_collect(stru
        }
  }
  
static void xfrm_garbage_collect(struct net *net)
+ void xfrm_garbage_collect(struct net *net)
  {
        flow_cache_flush();
        __xfrm_garbage_collect(net);
  }
+ EXPORT_SYMBOL(xfrm_garbage_collect);
  
  static void xfrm_garbage_collect_deferred(struct net *net)
  {
@@@ -2784,7 -2785,7 +2785,7 @@@ static void __net_init xfrm_dst_ops_ini
  
  static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
  {
 -      struct net_device *dev = ptr;
 +      struct net_device *dev = netdev_notifier_info_to_dev(ptr);
  
        switch (event) {
        case NETDEV_DOWN: