Merge branch 'master' of ra.kernel.org:/pub/scm/linux/kernel/git/davem/net
David S. Miller [Mon, 24 Oct 2011 22:18:09 +0000 (18:18 -0400)]
21 files changed:
1  2 
MAINTAINERS
arch/mips/Kconfig
drivers/net/bonding/bond_main.c
drivers/net/can/mscan/mscan.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/jme.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ppp/pptp.c
include/linux/skbuff.h
kernel/sys.c
net/batman-adv/translation-table.c
net/bridge/br_if.c
net/bridge/br_private.h
net/core/dev.c
net/core/fib_rules.c
net/ipv4/route.c
net/ipv4/tcp_minisocks.c

diff --cc MAINTAINERS
@@@ -2468,10 -2460,10 +2468,10 @@@ S:   Supporte
  F:    drivers/infiniband/hw/ehca/
  
  EHEA (IBM pSeries eHEA 10Gb ethernet adapter) DRIVER
- M:    Breno Leitao <leitao@linux.vnet.ibm.com>
+ M:    Thadeu Lima de Souza Cascardo <cascardo@linux.vnet.ibm.com>
  L:    netdev@vger.kernel.org
  S:    Maintained
 -F:    drivers/net/ehea/
 +F:    drivers/net/ethernet/ibm/ehea/
  
  EMBEDDED LINUX
  M:    Paul Gortmaker <paul.gortmaker@windriver.com>
Simple merge
Simple merge
Simple merge
index 2f92487,0000000..627a580
mode 100644,000000..100644
--- /dev/null
@@@ -1,2069 -1,0 +1,2075 @@@
 +/* bnx2x.h: Broadcom Everest network driver.
 + *
 + * Copyright (c) 2007-2011 Broadcom Corporation
 + *
 + * 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.
 + *
 + * Maintained by: Eilon Greenstein <eilong@broadcom.com>
 + * Written by: Eliezer Tamir
 + * Based on code from Michael Chan's bnx2 driver
 + */
 +
 +#ifndef BNX2X_H
 +#define BNX2X_H
 +#include <linux/netdevice.h>
 +#include <linux/dma-mapping.h>
 +#include <linux/types.h>
 +
 +/* compilation time flags */
 +
 +/* define this to make the driver freeze on error to allow getting debug info
 + * (you will need to reboot afterwards) */
 +/* #define BNX2X_STOP_ON_ERROR */
 +
 +#define DRV_MODULE_VERSION      "1.70.00-0"
 +#define DRV_MODULE_RELDATE      "2011/06/13"
 +#define BNX2X_BC_VER            0x040200
 +
 +#if defined(CONFIG_DCB)
 +#define BCM_DCBNL
 +#endif
 +#if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
 +#define BCM_CNIC 1
 +#include "../cnic_if.h"
 +#endif
 +
 +#ifdef BCM_CNIC
 +#define BNX2X_MIN_MSIX_VEC_CNT 3
 +#define BNX2X_MSIX_VEC_FP_START 2
 +#else
 +#define BNX2X_MIN_MSIX_VEC_CNT 2
 +#define BNX2X_MSIX_VEC_FP_START 1
 +#endif
 +
 +#include <linux/mdio.h>
 +
 +#include "bnx2x_reg.h"
 +#include "bnx2x_fw_defs.h"
 +#include "bnx2x_hsi.h"
 +#include "bnx2x_link.h"
 +#include "bnx2x_sp.h"
 +#include "bnx2x_dcb.h"
 +#include "bnx2x_stats.h"
 +
 +/* error/debug prints */
 +
 +#define DRV_MODULE_NAME               "bnx2x"
 +
 +/* for messages that are currently off */
 +#define BNX2X_MSG_OFF                 0
 +#define BNX2X_MSG_MCP                 0x010000 /* was: NETIF_MSG_HW */
 +#define BNX2X_MSG_STATS                       0x020000 /* was: NETIF_MSG_TIMER */
 +#define BNX2X_MSG_NVM                 0x040000 /* was: NETIF_MSG_HW */
 +#define BNX2X_MSG_DMAE                        0x080000 /* was: NETIF_MSG_HW */
 +#define BNX2X_MSG_SP                  0x100000 /* was: NETIF_MSG_INTR */
 +#define BNX2X_MSG_FP                  0x200000 /* was: NETIF_MSG_INTR */
 +
 +/* regular debug print */
 +#define DP(__mask, fmt, ...)                                  \
 +do {                                                          \
 +      if (bp->msg_enable & (__mask))                          \
 +              pr_notice("[%s:%d(%s)]" fmt,                    \
 +                        __func__, __LINE__,                   \
 +                        bp->dev ? (bp->dev->name) : "?",      \
 +                        ##__VA_ARGS__);                       \
 +} while (0)
 +
 +#define DP_CONT(__mask, fmt, ...)                             \
 +do {                                                          \
 +      if (bp->msg_enable & (__mask))                          \
 +              pr_cont(fmt, ##__VA_ARGS__);                    \
 +} while (0)
 +
 +/* errors debug print */
 +#define BNX2X_DBG_ERR(fmt, ...)                                       \
 +do {                                                          \
 +      if (netif_msg_probe(bp))                                \
 +              pr_err("[%s:%d(%s)]" fmt,                       \
 +                     __func__, __LINE__,                      \
 +                     bp->dev ? (bp->dev->name) : "?",         \
 +                     ##__VA_ARGS__);                          \
 +} while (0)
 +
 +/* for errors (never masked) */
 +#define BNX2X_ERR(fmt, ...)                                   \
 +do {                                                          \
 +      pr_err("[%s:%d(%s)]" fmt,                               \
 +             __func__, __LINE__,                              \
 +             bp->dev ? (bp->dev->name) : "?",                 \
 +             ##__VA_ARGS__);                                  \
 +} while (0)
 +
 +#define BNX2X_ERROR(fmt, ...)                                 \
 +      pr_err("[%s:%d]" fmt, __func__, __LINE__, ##__VA_ARGS__)
 +
 +
 +/* before we have a dev->name use dev_info() */
 +#define BNX2X_DEV_INFO(fmt, ...)                               \
 +do {                                                           \
 +      if (netif_msg_probe(bp))                                 \
 +              dev_info(&bp->pdev->dev, fmt, ##__VA_ARGS__);    \
 +} while (0)
 +
 +#ifdef BNX2X_STOP_ON_ERROR
 +void bnx2x_int_disable(struct bnx2x *bp);
 +#define bnx2x_panic()                         \
 +do {                                          \
 +      bp->panic = 1;                          \
 +      BNX2X_ERR("driver assert\n");           \
 +      bnx2x_int_disable(bp);                  \
 +      bnx2x_panic_dump(bp);                   \
 +} while (0)
 +#else
 +#define bnx2x_panic()                         \
 +do {                                          \
 +      bp->panic = 1;                          \
 +      BNX2X_ERR("driver assert\n");           \
 +      bnx2x_panic_dump(bp);                   \
 +} while (0)
 +#endif
 +
 +#define bnx2x_mc_addr(ha)      ((ha)->addr)
 +#define bnx2x_uc_addr(ha)      ((ha)->addr)
 +
 +#define U64_LO(x)                     (u32)(((u64)(x)) & 0xffffffff)
 +#define U64_HI(x)                     (u32)(((u64)(x)) >> 32)
 +#define HILO_U64(hi, lo)              ((((u64)(hi)) << 32) + (lo))
 +
 +
 +#define REG_ADDR(bp, offset)          ((bp->regview) + (offset))
 +
 +#define REG_RD(bp, offset)            readl(REG_ADDR(bp, offset))
 +#define REG_RD8(bp, offset)           readb(REG_ADDR(bp, offset))
 +#define REG_RD16(bp, offset)          readw(REG_ADDR(bp, offset))
 +
 +#define REG_WR(bp, offset, val)               writel((u32)val, REG_ADDR(bp, offset))
 +#define REG_WR8(bp, offset, val)      writeb((u8)val, REG_ADDR(bp, offset))
 +#define REG_WR16(bp, offset, val)     writew((u16)val, REG_ADDR(bp, offset))
 +
 +#define REG_RD_IND(bp, offset)                bnx2x_reg_rd_ind(bp, offset)
 +#define REG_WR_IND(bp, offset, val)   bnx2x_reg_wr_ind(bp, offset, val)
 +
 +#define REG_RD_DMAE(bp, offset, valp, len32) \
 +      do { \
 +              bnx2x_read_dmae(bp, offset, len32);\
 +              memcpy(valp, bnx2x_sp(bp, wb_data[0]), (len32) * 4); \
 +      } while (0)
 +
 +#define REG_WR_DMAE(bp, offset, valp, len32) \
 +      do { \
 +              memcpy(bnx2x_sp(bp, wb_data[0]), valp, (len32) * 4); \
 +              bnx2x_write_dmae(bp, bnx2x_sp_mapping(bp, wb_data), \
 +                               offset, len32); \
 +      } while (0)
 +
 +#define REG_WR_DMAE_LEN(bp, offset, valp, len32) \
 +      REG_WR_DMAE(bp, offset, valp, len32)
 +
 +#define VIRT_WR_DMAE_LEN(bp, data, addr, len32, le32_swap) \
 +      do { \
 +              memcpy(GUNZIP_BUF(bp), data, (len32) * 4); \
 +              bnx2x_write_big_buf_wb(bp, addr, len32); \
 +      } while (0)
 +
 +#define SHMEM_ADDR(bp, field)         (bp->common.shmem_base + \
 +                                       offsetof(struct shmem_region, field))
 +#define SHMEM_RD(bp, field)           REG_RD(bp, SHMEM_ADDR(bp, field))
 +#define SHMEM_WR(bp, field, val)      REG_WR(bp, SHMEM_ADDR(bp, field), val)
 +
 +#define SHMEM2_ADDR(bp, field)                (bp->common.shmem2_base + \
 +                                       offsetof(struct shmem2_region, field))
 +#define SHMEM2_RD(bp, field)          REG_RD(bp, SHMEM2_ADDR(bp, field))
 +#define SHMEM2_WR(bp, field, val)     REG_WR(bp, SHMEM2_ADDR(bp, field), val)
 +#define MF_CFG_ADDR(bp, field)                (bp->common.mf_cfg_base + \
 +                                       offsetof(struct mf_cfg, field))
 +#define MF2_CFG_ADDR(bp, field)               (bp->common.mf2_cfg_base + \
 +                                       offsetof(struct mf2_cfg, field))
 +
 +#define MF_CFG_RD(bp, field)          REG_RD(bp, MF_CFG_ADDR(bp, field))
 +#define MF_CFG_WR(bp, field, val)     REG_WR(bp,\
 +                                             MF_CFG_ADDR(bp, field), (val))
 +#define MF2_CFG_RD(bp, field)         REG_RD(bp, MF2_CFG_ADDR(bp, field))
 +
 +#define SHMEM2_HAS(bp, field)         ((bp)->common.shmem2_base &&    \
 +                                       (SHMEM2_RD((bp), size) >       \
 +                                       offsetof(struct shmem2_region, field)))
 +
 +#define EMAC_RD(bp, reg)              REG_RD(bp, emac_base + reg)
 +#define EMAC_WR(bp, reg, val)         REG_WR(bp, emac_base + reg, val)
 +
 +/* SP SB indices */
 +
 +/* General SP events - stats query, cfc delete, etc  */
 +#define HC_SP_INDEX_ETH_DEF_CONS              3
 +
 +/* EQ completions */
 +#define HC_SP_INDEX_EQ_CONS                   7
 +
 +/* FCoE L2 connection completions */
 +#define HC_SP_INDEX_ETH_FCOE_TX_CQ_CONS               6
 +#define HC_SP_INDEX_ETH_FCOE_RX_CQ_CONS               4
 +/* iSCSI L2 */
 +#define HC_SP_INDEX_ETH_ISCSI_CQ_CONS         5
 +#define HC_SP_INDEX_ETH_ISCSI_RX_CQ_CONS      1
 +
 +/* Special clients parameters */
 +
 +/* SB indices */
 +/* FCoE L2 */
 +#define BNX2X_FCOE_L2_RX_INDEX \
 +      (&bp->def_status_blk->sp_sb.\
 +      index_values[HC_SP_INDEX_ETH_FCOE_RX_CQ_CONS])
 +
 +#define BNX2X_FCOE_L2_TX_INDEX \
 +      (&bp->def_status_blk->sp_sb.\
 +      index_values[HC_SP_INDEX_ETH_FCOE_TX_CQ_CONS])
 +
 +/**
 + *  CIDs and CLIDs:
 + *  CLIDs below is a CLID for func 0, then the CLID for other
 + *  functions will be calculated by the formula:
 + *
 + *  FUNC_N_CLID_X = N * NUM_SPECIAL_CLIENTS + FUNC_0_CLID_X
 + *
 + */
- /* iSCSI L2 */
- #define BNX2X_ISCSI_ETH_CL_ID_IDX     1
- #define BNX2X_ISCSI_ETH_CID           49
- /* FCoE L2 */
- #define BNX2X_FCOE_ETH_CL_ID_IDX      2
- #define BNX2X_FCOE_ETH_CID            50
++enum {
++      BNX2X_ISCSI_ETH_CL_ID_IDX,
++      BNX2X_FCOE_ETH_CL_ID_IDX,
++      BNX2X_MAX_CNIC_ETH_CL_ID_IDX,
++};
++
++#define BNX2X_CNIC_START_ETH_CID      48
++enum {
++      /* iSCSI L2 */
++      BNX2X_ISCSI_ETH_CID = BNX2X_CNIC_START_ETH_CID,
++      /* FCoE L2 */
++      BNX2X_FCOE_ETH_CID,
++};
 +
 +/** Additional rings budgeting */
 +#ifdef BCM_CNIC
 +#define CNIC_PRESENT                  1
 +#define FCOE_PRESENT                  1
 +#else
 +#define CNIC_PRESENT                  0
 +#define FCOE_PRESENT                  0
 +#endif /* BCM_CNIC */
 +#define NON_ETH_CONTEXT_USE   (FCOE_PRESENT)
 +
 +#define AEU_IN_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR \
 +      AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR
 +
 +#define SM_RX_ID                      0
 +#define SM_TX_ID                      1
 +
 +/* defines for multiple tx priority indices */
 +#define FIRST_TX_ONLY_COS_INDEX               1
 +#define FIRST_TX_COS_INDEX            0
 +
 +/* defines for decodeing the fastpath index and the cos index out of the
 + * transmission queue index
 + */
 +#define MAX_TXQS_PER_COS      FP_SB_MAX_E1x
 +
 +#define TXQ_TO_FP(txq_index)  ((txq_index) % MAX_TXQS_PER_COS)
 +#define TXQ_TO_COS(txq_index) ((txq_index) / MAX_TXQS_PER_COS)
 +
 +/* rules for calculating the cids of tx-only connections */
 +#define CID_TO_FP(cid)                ((cid) % MAX_TXQS_PER_COS)
 +#define CID_COS_TO_TX_ONLY_CID(cid, cos)      (cid + cos * MAX_TXQS_PER_COS)
 +
 +/* fp index inside class of service range */
 +#define FP_COS_TO_TXQ(fp, cos)    ((fp)->index + cos * MAX_TXQS_PER_COS)
 +
 +/*
 + * 0..15 eth cos0
 + * 16..31 eth cos1 if applicable
 + * 32..47 eth cos2 If applicable
 + * fcoe queue follows eth queues (16, 32, 48 depending on cos)
 + */
 +#define MAX_ETH_TXQ_IDX(bp)   (MAX_TXQS_PER_COS * (bp)->max_cos)
 +#define FCOE_TXQ_IDX(bp)      (MAX_ETH_TXQ_IDX(bp))
 +
 +/* fast path */
 +struct sw_rx_bd {
 +      struct sk_buff  *skb;
 +      DEFINE_DMA_UNMAP_ADDR(mapping);
 +};
 +
 +struct sw_tx_bd {
 +      struct sk_buff  *skb;
 +      u16             first_bd;
 +      u8              flags;
 +/* Set on the first BD descriptor when there is a split BD */
 +#define BNX2X_TSO_SPLIT_BD            (1<<0)
 +};
 +
 +struct sw_rx_page {
 +      struct page     *page;
 +      DEFINE_DMA_UNMAP_ADDR(mapping);
 +};
 +
 +union db_prod {
 +      struct doorbell_set_prod data;
 +      u32             raw;
 +};
 +
 +/* dropless fc FW/HW related params */
 +#define BRB_SIZE(bp)          (CHIP_IS_E3(bp) ? 1024 : 512)
 +#define MAX_AGG_QS(bp)                (CHIP_IS_E1(bp) ? \
 +                                      ETH_MAX_AGGREGATION_QUEUES_E1 :\
 +                                      ETH_MAX_AGGREGATION_QUEUES_E1H_E2)
 +#define FW_DROP_LEVEL(bp)     (3 + MAX_SPQ_PENDING + MAX_AGG_QS(bp))
 +#define FW_PREFETCH_CNT               16
 +#define DROPLESS_FC_HEADROOM  100
 +
 +/* MC hsi */
 +#define BCM_PAGE_SHIFT                12
 +#define BCM_PAGE_SIZE         (1 << BCM_PAGE_SHIFT)
 +#define BCM_PAGE_MASK         (~(BCM_PAGE_SIZE - 1))
 +#define BCM_PAGE_ALIGN(addr)  (((addr) + BCM_PAGE_SIZE - 1) & BCM_PAGE_MASK)
 +
 +#define PAGES_PER_SGE_SHIFT   0
 +#define PAGES_PER_SGE         (1 << PAGES_PER_SGE_SHIFT)
 +#define SGE_PAGE_SIZE         PAGE_SIZE
 +#define SGE_PAGE_SHIFT                PAGE_SHIFT
 +#define SGE_PAGE_ALIGN(addr)  PAGE_ALIGN((typeof(PAGE_SIZE))(addr))
 +
 +/* SGE ring related macros */
 +#define NUM_RX_SGE_PAGES      2
 +#define RX_SGE_CNT            (BCM_PAGE_SIZE / sizeof(struct eth_rx_sge))
 +#define NEXT_PAGE_SGE_DESC_CNT        2
 +#define MAX_RX_SGE_CNT                (RX_SGE_CNT - NEXT_PAGE_SGE_DESC_CNT)
 +/* RX_SGE_CNT is promised to be a power of 2 */
 +#define RX_SGE_MASK           (RX_SGE_CNT - 1)
 +#define NUM_RX_SGE            (RX_SGE_CNT * NUM_RX_SGE_PAGES)
 +#define MAX_RX_SGE            (NUM_RX_SGE - 1)
 +#define NEXT_SGE_IDX(x)               ((((x) & RX_SGE_MASK) == \
 +                                (MAX_RX_SGE_CNT - 1)) ? \
 +                                      (x) + 1 + NEXT_PAGE_SGE_DESC_CNT : \
 +                                      (x) + 1)
 +#define RX_SGE(x)             ((x) & MAX_RX_SGE)
 +
 +/*
 + * Number of required  SGEs is the sum of two:
 + * 1. Number of possible opened aggregations (next packet for
 + *    these aggregations will probably consume SGE immidiatelly)
 + * 2. Rest of BRB blocks divided by 2 (block will consume new SGE only
 + *    after placement on BD for new TPA aggregation)
 + *
 + * Takes into account NEXT_PAGE_SGE_DESC_CNT "next" elements on each page
 + */
 +#define NUM_SGE_REQ           (MAX_AGG_QS(bp) + \
 +                                      (BRB_SIZE(bp) - MAX_AGG_QS(bp)) / 2)
 +#define NUM_SGE_PG_REQ                ((NUM_SGE_REQ + MAX_RX_SGE_CNT - 1) / \
 +                                              MAX_RX_SGE_CNT)
 +#define SGE_TH_LO(bp)         (NUM_SGE_REQ + \
 +                               NUM_SGE_PG_REQ * NEXT_PAGE_SGE_DESC_CNT)
 +#define SGE_TH_HI(bp)         (SGE_TH_LO(bp) + DROPLESS_FC_HEADROOM)
 +
 +/* Manipulate a bit vector defined as an array of u64 */
 +
 +/* Number of bits in one sge_mask array element */
 +#define BIT_VEC64_ELEM_SZ             64
 +#define BIT_VEC64_ELEM_SHIFT          6
 +#define BIT_VEC64_ELEM_MASK           ((u64)BIT_VEC64_ELEM_SZ - 1)
 +
 +
 +#define __BIT_VEC64_SET_BIT(el, bit) \
 +      do { \
 +              el = ((el) | ((u64)0x1 << (bit))); \
 +      } while (0)
 +
 +#define __BIT_VEC64_CLEAR_BIT(el, bit) \
 +      do { \
 +              el = ((el) & (~((u64)0x1 << (bit)))); \
 +      } while (0)
 +
 +
 +#define BIT_VEC64_SET_BIT(vec64, idx) \
 +      __BIT_VEC64_SET_BIT((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT], \
 +                         (idx) & BIT_VEC64_ELEM_MASK)
 +
 +#define BIT_VEC64_CLEAR_BIT(vec64, idx) \
 +      __BIT_VEC64_CLEAR_BIT((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT], \
 +                           (idx) & BIT_VEC64_ELEM_MASK)
 +
 +#define BIT_VEC64_TEST_BIT(vec64, idx) \
 +      (((vec64)[(idx) >> BIT_VEC64_ELEM_SHIFT] >> \
 +      ((idx) & BIT_VEC64_ELEM_MASK)) & 0x1)
 +
 +/* Creates a bitmask of all ones in less significant bits.
 +   idx - index of the most significant bit in the created mask */
 +#define BIT_VEC64_ONES_MASK(idx) \
 +              (((u64)0x1 << (((idx) & BIT_VEC64_ELEM_MASK) + 1)) - 1)
 +#define BIT_VEC64_ELEM_ONE_MASK       ((u64)(~0))
 +
 +/*******************************************************/
 +
 +
 +
 +/* Number of u64 elements in SGE mask array */
 +#define RX_SGE_MASK_LEN                       ((NUM_RX_SGE_PAGES * RX_SGE_CNT) / \
 +                                       BIT_VEC64_ELEM_SZ)
 +#define RX_SGE_MASK_LEN_MASK          (RX_SGE_MASK_LEN - 1)
 +#define NEXT_SGE_MASK_ELEM(el)                (((el) + 1) & RX_SGE_MASK_LEN_MASK)
 +
 +union host_hc_status_block {
 +      /* pointer to fp status block e1x */
 +      struct host_hc_status_block_e1x *e1x_sb;
 +      /* pointer to fp status block e2 */
 +      struct host_hc_status_block_e2  *e2_sb;
 +};
 +
 +struct bnx2x_agg_info {
 +      /*
 +       * First aggregation buffer is an skb, the following - are pages.
 +       * We will preallocate the skbs for each aggregation when
 +       * we open the interface and will replace the BD at the consumer
 +       * with this one when we receive the TPA_START CQE in order to
 +       * keep the Rx BD ring consistent.
 +       */
 +      struct sw_rx_bd         first_buf;
 +      u8                      tpa_state;
 +#define BNX2X_TPA_START                       1
 +#define BNX2X_TPA_STOP                        2
 +#define BNX2X_TPA_ERROR                       3
 +      u8                      placement_offset;
 +      u16                     parsing_flags;
 +      u16                     vlan_tag;
 +      u16                     len_on_bd;
 +};
 +
 +#define Q_STATS_OFFSET32(stat_name) \
 +                      (offsetof(struct bnx2x_eth_q_stats, stat_name) / 4)
 +
 +struct bnx2x_fp_txdata {
 +
 +      struct sw_tx_bd         *tx_buf_ring;
 +
 +      union eth_tx_bd_types   *tx_desc_ring;
 +      dma_addr_t              tx_desc_mapping;
 +
 +      u32                     cid;
 +
 +      union db_prod           tx_db;
 +
 +      u16                     tx_pkt_prod;
 +      u16                     tx_pkt_cons;
 +      u16                     tx_bd_prod;
 +      u16                     tx_bd_cons;
 +
 +      unsigned long           tx_pkt;
 +
 +      __le16                  *tx_cons_sb;
 +
 +      int                     txq_index;
 +};
 +
 +struct bnx2x_fastpath {
 +      struct bnx2x            *bp; /* parent */
 +
 +#define BNX2X_NAPI_WEIGHT       128
 +      struct napi_struct      napi;
 +      union host_hc_status_block      status_blk;
 +      /* chip independed shortcuts into sb structure */
 +      __le16                  *sb_index_values;
 +      __le16                  *sb_running_index;
 +      /* chip independed shortcut into rx_prods_offset memory */
 +      u32                     ustorm_rx_prods_offset;
 +
 +      u32                     rx_buf_size;
 +
 +      dma_addr_t              status_blk_mapping;
 +
 +      u8                      max_cos; /* actual number of active tx coses */
 +      struct bnx2x_fp_txdata  txdata[BNX2X_MULTI_TX_COS];
 +
 +      struct sw_rx_bd         *rx_buf_ring;   /* BDs mappings ring */
 +      struct sw_rx_page       *rx_page_ring;  /* SGE pages mappings ring */
 +
 +      struct eth_rx_bd        *rx_desc_ring;
 +      dma_addr_t              rx_desc_mapping;
 +
 +      union eth_rx_cqe        *rx_comp_ring;
 +      dma_addr_t              rx_comp_mapping;
 +
 +      /* SGE ring */
 +      struct eth_rx_sge       *rx_sge_ring;
 +      dma_addr_t              rx_sge_mapping;
 +
 +      u64                     sge_mask[RX_SGE_MASK_LEN];
 +
 +      u32                     cid;
 +
 +      __le16                  fp_hc_idx;
 +
 +      u8                      index;          /* number in fp array */
 +      u8                      cl_id;          /* eth client id */
 +      u8                      cl_qzone_id;
 +      u8                      fw_sb_id;       /* status block number in FW */
 +      u8                      igu_sb_id;      /* status block number in HW */
 +
 +      u16                     rx_bd_prod;
 +      u16                     rx_bd_cons;
 +      u16                     rx_comp_prod;
 +      u16                     rx_comp_cons;
 +      u16                     rx_sge_prod;
 +      /* The last maximal completed SGE */
 +      u16                     last_max_sge;
 +      __le16                  *rx_cons_sb;
 +      unsigned long           rx_pkt,
 +                              rx_calls;
 +
 +      /* TPA related */
 +      struct bnx2x_agg_info   tpa_info[ETH_MAX_AGGREGATION_QUEUES_E1H_E2];
 +      u8                      disable_tpa;
 +#ifdef BNX2X_STOP_ON_ERROR
 +      u64                     tpa_queue_used;
 +#endif
 +
 +      struct tstorm_per_queue_stats old_tclient;
 +      struct ustorm_per_queue_stats old_uclient;
 +      struct xstorm_per_queue_stats old_xclient;
 +      struct bnx2x_eth_q_stats eth_q_stats;
 +
 +      /* The size is calculated using the following:
 +           sizeof name field from netdev structure +
 +           4 ('-Xx-' string) +
 +           4 (for the digits and to make it DWORD aligned) */
 +#define FP_NAME_SIZE          (sizeof(((struct net_device *)0)->name) + 8)
 +      char                    name[FP_NAME_SIZE];
 +
 +      /* MACs object */
 +      struct bnx2x_vlan_mac_obj mac_obj;
 +
 +      /* Queue State object */
 +      struct bnx2x_queue_sp_obj q_obj;
 +
 +};
 +
 +#define bnx2x_fp(bp, nr, var)         (bp->fp[nr].var)
 +
 +/* Use 2500 as a mini-jumbo MTU for FCoE */
 +#define BNX2X_FCOE_MINI_JUMBO_MTU     2500
 +
 +/* FCoE L2 `fastpath' entry is right after the eth entries */
 +#define FCOE_IDX                      BNX2X_NUM_ETH_QUEUES(bp)
 +#define bnx2x_fcoe_fp(bp)             (&bp->fp[FCOE_IDX])
 +#define bnx2x_fcoe(bp, var)           (bnx2x_fcoe_fp(bp)->var)
 +#define bnx2x_fcoe_tx(bp, var)                (bnx2x_fcoe_fp(bp)-> \
 +                                              txdata[FIRST_TX_COS_INDEX].var)
 +
 +
 +#define IS_ETH_FP(fp)                 (fp->index < \
 +                                       BNX2X_NUM_ETH_QUEUES(fp->bp))
 +#ifdef BCM_CNIC
 +#define IS_FCOE_FP(fp)                        (fp->index == FCOE_IDX)
 +#define IS_FCOE_IDX(idx)              ((idx) == FCOE_IDX)
 +#else
 +#define IS_FCOE_FP(fp)                false
 +#define IS_FCOE_IDX(idx)      false
 +#endif
 +
 +
 +/* MC hsi */
 +#define MAX_FETCH_BD          13      /* HW max BDs per packet */
 +#define RX_COPY_THRESH                92
 +
 +#define NUM_TX_RINGS          16
 +#define TX_DESC_CNT           (BCM_PAGE_SIZE / sizeof(union eth_tx_bd_types))
 +#define NEXT_PAGE_TX_DESC_CNT 1
 +#define MAX_TX_DESC_CNT               (TX_DESC_CNT - NEXT_PAGE_TX_DESC_CNT)
 +#define NUM_TX_BD             (TX_DESC_CNT * NUM_TX_RINGS)
 +#define MAX_TX_BD             (NUM_TX_BD - 1)
 +#define MAX_TX_AVAIL          (MAX_TX_DESC_CNT * NUM_TX_RINGS - 2)
 +#define NEXT_TX_IDX(x)                ((((x) & MAX_TX_DESC_CNT) == \
 +                                (MAX_TX_DESC_CNT - 1)) ? \
 +                                      (x) + 1 + NEXT_PAGE_TX_DESC_CNT : \
 +                                      (x) + 1)
 +#define TX_BD(x)              ((x) & MAX_TX_BD)
 +#define TX_BD_POFF(x)         ((x) & MAX_TX_DESC_CNT)
 +
 +/* The RX BD ring is special, each bd is 8 bytes but the last one is 16 */
 +#define NUM_RX_RINGS          8
 +#define RX_DESC_CNT           (BCM_PAGE_SIZE / sizeof(struct eth_rx_bd))
 +#define NEXT_PAGE_RX_DESC_CNT 2
 +#define MAX_RX_DESC_CNT               (RX_DESC_CNT - NEXT_PAGE_RX_DESC_CNT)
 +#define RX_DESC_MASK          (RX_DESC_CNT - 1)
 +#define NUM_RX_BD             (RX_DESC_CNT * NUM_RX_RINGS)
 +#define MAX_RX_BD             (NUM_RX_BD - 1)
 +#define MAX_RX_AVAIL          (MAX_RX_DESC_CNT * NUM_RX_RINGS - 2)
 +
 +/* dropless fc calculations for BDs
 + *
 + * Number of BDs should as number of buffers in BRB:
 + * Low threshold takes into account NEXT_PAGE_RX_DESC_CNT
 + * "next" elements on each page
 + */
 +#define NUM_BD_REQ            BRB_SIZE(bp)
 +#define NUM_BD_PG_REQ         ((NUM_BD_REQ + MAX_RX_DESC_CNT - 1) / \
 +                                            MAX_RX_DESC_CNT)
 +#define BD_TH_LO(bp)          (NUM_BD_REQ + \
 +                               NUM_BD_PG_REQ * NEXT_PAGE_RX_DESC_CNT + \
 +                               FW_DROP_LEVEL(bp))
 +#define BD_TH_HI(bp)          (BD_TH_LO(bp) + DROPLESS_FC_HEADROOM)
 +
 +#define MIN_RX_AVAIL          ((bp)->dropless_fc ? BD_TH_HI(bp) + 128 : 128)
 +
 +#define MIN_RX_SIZE_TPA_HW    (CHIP_IS_E1(bp) ? \
 +                                      ETH_MIN_RX_CQES_WITH_TPA_E1 : \
 +                                      ETH_MIN_RX_CQES_WITH_TPA_E1H_E2)
 +#define MIN_RX_SIZE_NONTPA_HW   ETH_MIN_RX_CQES_WITHOUT_TPA
 +#define MIN_RX_SIZE_TPA               (max_t(u32, MIN_RX_SIZE_TPA_HW, MIN_RX_AVAIL))
 +#define MIN_RX_SIZE_NONTPA    (max_t(u32, MIN_RX_SIZE_NONTPA_HW,\
 +                                                              MIN_RX_AVAIL))
 +
 +#define NEXT_RX_IDX(x)                ((((x) & RX_DESC_MASK) == \
 +                                (MAX_RX_DESC_CNT - 1)) ? \
 +                                      (x) + 1 + NEXT_PAGE_RX_DESC_CNT : \
 +                                      (x) + 1)
 +#define RX_BD(x)              ((x) & MAX_RX_BD)
 +
 +/*
 + * As long as CQE is X times bigger than BD entry we have to allocate X times
 + * more pages for CQ ring in order to keep it balanced with BD ring
 + */
 +#define CQE_BD_REL    (sizeof(union eth_rx_cqe) / sizeof(struct eth_rx_bd))
 +#define NUM_RCQ_RINGS         (NUM_RX_RINGS * CQE_BD_REL)
 +#define RCQ_DESC_CNT          (BCM_PAGE_SIZE / sizeof(union eth_rx_cqe))
 +#define NEXT_PAGE_RCQ_DESC_CNT        1
 +#define MAX_RCQ_DESC_CNT      (RCQ_DESC_CNT - NEXT_PAGE_RCQ_DESC_CNT)
 +#define NUM_RCQ_BD            (RCQ_DESC_CNT * NUM_RCQ_RINGS)
 +#define MAX_RCQ_BD            (NUM_RCQ_BD - 1)
 +#define MAX_RCQ_AVAIL         (MAX_RCQ_DESC_CNT * NUM_RCQ_RINGS - 2)
 +#define NEXT_RCQ_IDX(x)               ((((x) & MAX_RCQ_DESC_CNT) == \
 +                                (MAX_RCQ_DESC_CNT - 1)) ? \
 +                                      (x) + 1 + NEXT_PAGE_RCQ_DESC_CNT : \
 +                                      (x) + 1)
 +#define RCQ_BD(x)             ((x) & MAX_RCQ_BD)
 +
 +/* dropless fc calculations for RCQs
 + *
 + * Number of RCQs should be as number of buffers in BRB:
 + * Low threshold takes into account NEXT_PAGE_RCQ_DESC_CNT
 + * "next" elements on each page
 + */
 +#define NUM_RCQ_REQ           BRB_SIZE(bp)
 +#define NUM_RCQ_PG_REQ                ((NUM_BD_REQ + MAX_RCQ_DESC_CNT - 1) / \
 +                                            MAX_RCQ_DESC_CNT)
 +#define RCQ_TH_LO(bp)         (NUM_RCQ_REQ + \
 +                               NUM_RCQ_PG_REQ * NEXT_PAGE_RCQ_DESC_CNT + \
 +                               FW_DROP_LEVEL(bp))
 +#define RCQ_TH_HI(bp)         (RCQ_TH_LO(bp) + DROPLESS_FC_HEADROOM)
 +
 +
 +/* This is needed for determining of last_max */
 +#define SUB_S16(a, b)         (s16)((s16)(a) - (s16)(b))
 +#define SUB_S32(a, b)         (s32)((s32)(a) - (s32)(b))
 +
 +
 +#define BNX2X_SWCID_SHIFT     17
 +#define BNX2X_SWCID_MASK      ((0x1 << BNX2X_SWCID_SHIFT) - 1)
 +
 +/* used on a CID received from the HW */
 +#define SW_CID(x)                     (le32_to_cpu(x) & BNX2X_SWCID_MASK)
 +#define CQE_CMD(x)                    (le32_to_cpu(x) >> \
 +                                      COMMON_RAMROD_ETH_RX_CQE_CMD_ID_SHIFT)
 +
 +#define BD_UNMAP_ADDR(bd)             HILO_U64(le32_to_cpu((bd)->addr_hi), \
 +                                               le32_to_cpu((bd)->addr_lo))
 +#define BD_UNMAP_LEN(bd)              (le16_to_cpu((bd)->nbytes))
 +
 +#define BNX2X_DB_MIN_SHIFT            3       /* 8 bytes */
 +#define BNX2X_DB_SHIFT                        7       /* 128 bytes*/
 +#if (BNX2X_DB_SHIFT < BNX2X_DB_MIN_SHIFT)
 +#error "Min DB doorbell stride is 8"
 +#endif
 +#define DPM_TRIGER_TYPE                       0x40
 +#define DOORBELL(bp, cid, val) \
 +      do { \
 +              writel((u32)(val), bp->doorbells + (bp->db_size * (cid)) + \
 +                     DPM_TRIGER_TYPE); \
 +      } while (0)
 +
 +
 +/* TX CSUM helpers */
 +#define SKB_CS_OFF(skb)               (offsetof(struct tcphdr, check) - \
 +                               skb->csum_offset)
 +#define SKB_CS(skb)           (*(u16 *)(skb_transport_header(skb) + \
 +                                        skb->csum_offset))
 +
 +#define pbd_tcp_flags(skb)    (ntohl(tcp_flag_word(tcp_hdr(skb)))>>16 & 0xff)
 +
 +#define XMIT_PLAIN                    0
 +#define XMIT_CSUM_V4                  0x1
 +#define XMIT_CSUM_V6                  0x2
 +#define XMIT_CSUM_TCP                 0x4
 +#define XMIT_GSO_V4                   0x8
 +#define XMIT_GSO_V6                   0x10
 +
 +#define XMIT_CSUM                     (XMIT_CSUM_V4 | XMIT_CSUM_V6)
 +#define XMIT_GSO                      (XMIT_GSO_V4 | XMIT_GSO_V6)
 +
 +
 +/* stuff added to make the code fit 80Col */
 +#define CQE_TYPE(cqe_fp_flags)         ((cqe_fp_flags) & ETH_FAST_PATH_RX_CQE_TYPE)
 +#define CQE_TYPE_START(cqe_type) ((cqe_type) == RX_ETH_CQE_TYPE_ETH_START_AGG)
 +#define CQE_TYPE_STOP(cqe_type)  ((cqe_type) == RX_ETH_CQE_TYPE_ETH_STOP_AGG)
 +#define CQE_TYPE_SLOW(cqe_type)  ((cqe_type) == RX_ETH_CQE_TYPE_ETH_RAMROD)
 +#define CQE_TYPE_FAST(cqe_type)  ((cqe_type) == RX_ETH_CQE_TYPE_ETH_FASTPATH)
 +
 +#define ETH_RX_ERROR_FALGS            ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG
 +
 +#define BNX2X_IP_CSUM_ERR(cqe) \
 +                      (!((cqe)->fast_path_cqe.status_flags & \
 +                         ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG) && \
 +                       ((cqe)->fast_path_cqe.type_error_flags & \
 +                        ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG))
 +
 +#define BNX2X_L4_CSUM_ERR(cqe) \
 +                      (!((cqe)->fast_path_cqe.status_flags & \
 +                         ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG) && \
 +                       ((cqe)->fast_path_cqe.type_error_flags & \
 +                        ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG))
 +
 +#define BNX2X_RX_CSUM_OK(cqe) \
 +                      (!(BNX2X_L4_CSUM_ERR(cqe) || BNX2X_IP_CSUM_ERR(cqe)))
 +
 +#define BNX2X_PRS_FLAG_OVERETH_IPV4(flags) \
 +                              (((le16_to_cpu(flags) & \
 +                                 PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) >> \
 +                                PARSING_FLAGS_OVER_ETHERNET_PROTOCOL_SHIFT) \
 +                               == PRS_FLAG_OVERETH_IPV4)
 +#define BNX2X_RX_SUM_FIX(cqe) \
 +      BNX2X_PRS_FLAG_OVERETH_IPV4(cqe->fast_path_cqe.pars_flags.flags)
 +
 +
 +#define FP_USB_FUNC_OFF       \
 +                      offsetof(struct cstorm_status_block_u, func)
 +#define FP_CSB_FUNC_OFF       \
 +                      offsetof(struct cstorm_status_block_c, func)
 +
 +#define HC_INDEX_ETH_RX_CQ_CONS               1
 +
 +#define HC_INDEX_OOO_TX_CQ_CONS               4
 +
 +#define HC_INDEX_ETH_TX_CQ_CONS_COS0  5
 +
 +#define HC_INDEX_ETH_TX_CQ_CONS_COS1  6
 +
 +#define HC_INDEX_ETH_TX_CQ_CONS_COS2  7
 +
 +#define HC_INDEX_ETH_FIRST_TX_CQ_CONS HC_INDEX_ETH_TX_CQ_CONS_COS0
 +
 +#define BNX2X_RX_SB_INDEX \
 +      (&fp->sb_index_values[HC_INDEX_ETH_RX_CQ_CONS])
 +
 +#define BNX2X_TX_SB_INDEX_BASE BNX2X_TX_SB_INDEX_COS0
 +
 +#define BNX2X_TX_SB_INDEX_COS0 \
 +      (&fp->sb_index_values[HC_INDEX_ETH_TX_CQ_CONS_COS0])
 +
 +/* end of fast path */
 +
 +/* common */
 +
 +struct bnx2x_common {
 +
 +      u32                     chip_id;
 +/* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */
 +#define CHIP_ID(bp)                   (bp->common.chip_id & 0xfffffff0)
 +
 +#define CHIP_NUM(bp)                  (bp->common.chip_id >> 16)
 +#define CHIP_NUM_57710                        0x164e
 +#define CHIP_NUM_57711                        0x164f
 +#define CHIP_NUM_57711E                       0x1650
 +#define CHIP_NUM_57712                        0x1662
 +#define CHIP_NUM_57712_MF             0x1663
 +#define CHIP_NUM_57713                        0x1651
 +#define CHIP_NUM_57713E                       0x1652
 +#define CHIP_NUM_57800                        0x168a
 +#define CHIP_NUM_57800_MF             0x16a5
 +#define CHIP_NUM_57810                        0x168e
 +#define CHIP_NUM_57810_MF             0x16ae
 +#define CHIP_NUM_57840                        0x168d
 +#define CHIP_NUM_57840_MF             0x16ab
 +#define CHIP_IS_E1(bp)                        (CHIP_NUM(bp) == CHIP_NUM_57710)
 +#define CHIP_IS_57711(bp)             (CHIP_NUM(bp) == CHIP_NUM_57711)
 +#define CHIP_IS_57711E(bp)            (CHIP_NUM(bp) == CHIP_NUM_57711E)
 +#define CHIP_IS_57712(bp)             (CHIP_NUM(bp) == CHIP_NUM_57712)
 +#define CHIP_IS_57712_MF(bp)          (CHIP_NUM(bp) == CHIP_NUM_57712_MF)
 +#define CHIP_IS_57800(bp)             (CHIP_NUM(bp) == CHIP_NUM_57800)
 +#define CHIP_IS_57800_MF(bp)          (CHIP_NUM(bp) == CHIP_NUM_57800_MF)
 +#define CHIP_IS_57810(bp)             (CHIP_NUM(bp) == CHIP_NUM_57810)
 +#define CHIP_IS_57810_MF(bp)          (CHIP_NUM(bp) == CHIP_NUM_57810_MF)
 +#define CHIP_IS_57840(bp)             (CHIP_NUM(bp) == CHIP_NUM_57840)
 +#define CHIP_IS_57840_MF(bp)          (CHIP_NUM(bp) == CHIP_NUM_57840_MF)
 +#define CHIP_IS_E1H(bp)                       (CHIP_IS_57711(bp) || \
 +                                       CHIP_IS_57711E(bp))
 +#define CHIP_IS_E2(bp)                        (CHIP_IS_57712(bp) || \
 +                                       CHIP_IS_57712_MF(bp))
 +#define CHIP_IS_E3(bp)                        (CHIP_IS_57800(bp) || \
 +                                       CHIP_IS_57800_MF(bp) || \
 +                                       CHIP_IS_57810(bp) || \
 +                                       CHIP_IS_57810_MF(bp) || \
 +                                       CHIP_IS_57840(bp) || \
 +                                       CHIP_IS_57840_MF(bp))
 +#define CHIP_IS_E1x(bp)                       (CHIP_IS_E1((bp)) || CHIP_IS_E1H((bp)))
 +#define USES_WARPCORE(bp)             (CHIP_IS_E3(bp))
 +#define IS_E1H_OFFSET                 (!CHIP_IS_E1(bp))
 +
 +#define CHIP_REV_SHIFT                        12
 +#define CHIP_REV_MASK                 (0xF << CHIP_REV_SHIFT)
 +#define CHIP_REV_VAL(bp)              (bp->common.chip_id & CHIP_REV_MASK)
 +#define CHIP_REV_Ax                   (0x0 << CHIP_REV_SHIFT)
 +#define CHIP_REV_Bx                   (0x1 << CHIP_REV_SHIFT)
 +/* assume maximum 5 revisions */
 +#define CHIP_REV_IS_SLOW(bp)          (CHIP_REV_VAL(bp) > 0x00005000)
 +/* Emul versions are A=>0xe, B=>0xc, C=>0xa, D=>8, E=>6 */
 +#define CHIP_REV_IS_EMUL(bp)          ((CHIP_REV_IS_SLOW(bp)) && \
 +                                       !(CHIP_REV_VAL(bp) & 0x00001000))
 +/* FPGA versions are A=>0xf, B=>0xd, C=>0xb, D=>9, E=>7 */
 +#define CHIP_REV_IS_FPGA(bp)          ((CHIP_REV_IS_SLOW(bp)) && \
 +                                       (CHIP_REV_VAL(bp) & 0x00001000))
 +
 +#define CHIP_TIME(bp)                 ((CHIP_REV_IS_EMUL(bp)) ? 2000 : \
 +                                      ((CHIP_REV_IS_FPGA(bp)) ? 200 : 1))
 +
 +#define CHIP_METAL(bp)                        (bp->common.chip_id & 0x00000ff0)
 +#define CHIP_BOND_ID(bp)              (bp->common.chip_id & 0x0000000f)
 +#define CHIP_REV_SIM(bp)              (((CHIP_REV_MASK - CHIP_REV_VAL(bp)) >>\
 +                                         (CHIP_REV_SHIFT + 1)) \
 +                                              << CHIP_REV_SHIFT)
 +#define CHIP_REV(bp)                  (CHIP_REV_IS_SLOW(bp) ? \
 +                                              CHIP_REV_SIM(bp) :\
 +                                              CHIP_REV_VAL(bp))
 +#define CHIP_IS_E3B0(bp)              (CHIP_IS_E3(bp) && \
 +                                       (CHIP_REV(bp) == CHIP_REV_Bx))
 +#define CHIP_IS_E3A0(bp)              (CHIP_IS_E3(bp) && \
 +                                       (CHIP_REV(bp) == CHIP_REV_Ax))
 +
 +      int                     flash_size;
 +#define BNX2X_NVRAM_1MB_SIZE                  0x20000 /* 1M bit in bytes */
 +#define BNX2X_NVRAM_TIMEOUT_COUNT             30000
 +#define BNX2X_NVRAM_PAGE_SIZE                 256
 +
 +      u32                     shmem_base;
 +      u32                     shmem2_base;
 +      u32                     mf_cfg_base;
 +      u32                     mf2_cfg_base;
 +
 +      u32                     hw_config;
 +
 +      u32                     bc_ver;
 +
 +      u8                      int_block;
 +#define INT_BLOCK_HC                  0
 +#define INT_BLOCK_IGU                 1
 +#define INT_BLOCK_MODE_NORMAL         0
 +#define INT_BLOCK_MODE_BW_COMP                2
 +#define CHIP_INT_MODE_IS_NBC(bp)              \
 +                      (!CHIP_IS_E1x(bp) &&    \
 +                      !((bp)->common.int_block & INT_BLOCK_MODE_BW_COMP))
 +#define CHIP_INT_MODE_IS_BC(bp) (!CHIP_INT_MODE_IS_NBC(bp))
 +
 +      u8                      chip_port_mode;
 +#define CHIP_4_PORT_MODE                      0x0
 +#define CHIP_2_PORT_MODE                      0x1
 +#define CHIP_PORT_MODE_NONE                   0x2
 +#define CHIP_MODE(bp)                 (bp->common.chip_port_mode)
 +#define CHIP_MODE_IS_4_PORT(bp) (CHIP_MODE(bp) == CHIP_4_PORT_MODE)
 +};
 +
 +/* IGU MSIX STATISTICS on 57712: 64 for VFs; 4 for PFs; 4 for Attentions */
 +#define BNX2X_IGU_STAS_MSG_VF_CNT 64
 +#define BNX2X_IGU_STAS_MSG_PF_CNT 4
 +
 +/* end of common */
 +
 +/* port */
 +
 +struct bnx2x_port {
 +      u32                     pmf;
 +
 +      u32                     link_config[LINK_CONFIG_SIZE];
 +
 +      u32                     supported[LINK_CONFIG_SIZE];
 +/* link settings - missing defines */
 +#define SUPPORTED_2500baseX_Full      (1 << 15)
 +
 +      u32                     advertising[LINK_CONFIG_SIZE];
 +/* link settings - missing defines */
 +#define ADVERTISED_2500baseX_Full     (1 << 15)
 +
 +      u32                     phy_addr;
 +
 +      /* used to synchronize phy accesses */
 +      struct mutex            phy_mutex;
 +      int                     need_hw_lock;
 +
 +      u32                     port_stx;
 +
 +      struct nig_stats        old_nig_stats;
 +};
 +
 +/* end of port */
 +
 +#define STATS_OFFSET32(stat_name) \
 +                      (offsetof(struct bnx2x_eth_stats, stat_name) / 4)
 +
 +/* slow path */
 +
 +/* slow path work-queue */
 +extern struct workqueue_struct *bnx2x_wq;
 +
 +#define BNX2X_MAX_NUM_OF_VFS  64
 +#define BNX2X_VF_ID_INVALID   0xFF
 +
 +/*
 + * The total number of L2 queues, MSIX vectors and HW contexts (CIDs) is
 + * control by the number of fast-path status blocks supported by the
 + * device (HW/FW). Each fast-path status block (FP-SB) aka non-default
 + * status block represents an independent interrupts context that can
 + * serve a regular L2 networking queue. However special L2 queues such
 + * as the FCoE queue do not require a FP-SB and other components like
 + * the CNIC may consume FP-SB reducing the number of possible L2 queues
 + *
 + * If the maximum number of FP-SB available is X then:
 + * a. If CNIC is supported it consumes 1 FP-SB thus the max number of
 + *    regular L2 queues is Y=X-1
 + * b. in MF mode the actual number of L2 queues is Y= (X-1/MF_factor)
 + * c. If the FCoE L2 queue is supported the actual number of L2 queues
 + *    is Y+1
 + * d. The number of irqs (MSIX vectors) is either Y+1 (one extra for
 + *    slow-path interrupts) or Y+2 if CNIC is supported (one additional
 + *    FP interrupt context for the CNIC).
 + * e. The number of HW context (CID count) is always X or X+1 if FCoE
 + *    L2 queue is supported. the cid for the FCoE L2 queue is always X.
 + */
 +
 +/* fast-path interrupt contexts E1x */
 +#define FP_SB_MAX_E1x         16
 +/* fast-path interrupt contexts E2 */
 +#define FP_SB_MAX_E2          HC_SB_MAX_SB_E2
 +
 +union cdu_context {
 +      struct eth_context eth;
 +      char pad[1024];
 +};
 +
 +/* CDU host DB constants */
 +#define CDU_ILT_PAGE_SZ_HW    3
 +#define CDU_ILT_PAGE_SZ               (8192 << CDU_ILT_PAGE_SZ_HW) /* 64K */
 +#define ILT_PAGE_CIDS         (CDU_ILT_PAGE_SZ / sizeof(union cdu_context))
 +
 +#ifdef BCM_CNIC
 +#define CNIC_ISCSI_CID_MAX    256
 +#define CNIC_FCOE_CID_MAX     2048
 +#define CNIC_CID_MAX          (CNIC_ISCSI_CID_MAX + CNIC_FCOE_CID_MAX)
 +#define CNIC_ILT_LINES                DIV_ROUND_UP(CNIC_CID_MAX, ILT_PAGE_CIDS)
 +#endif
 +
 +#define QM_ILT_PAGE_SZ_HW     0
 +#define QM_ILT_PAGE_SZ                (4096 << QM_ILT_PAGE_SZ_HW) /* 4K */
 +#define QM_CID_ROUND          1024
 +
 +#ifdef BCM_CNIC
 +/* TM (timers) host DB constants */
 +#define TM_ILT_PAGE_SZ_HW     0
 +#define TM_ILT_PAGE_SZ                (4096 << TM_ILT_PAGE_SZ_HW) /* 4K */
 +/* #define TM_CONN_NUM                (CNIC_STARTING_CID+CNIC_ISCSI_CXT_MAX) */
 +#define TM_CONN_NUM           1024
 +#define TM_ILT_SZ             (8 * TM_CONN_NUM)
 +#define TM_ILT_LINES          DIV_ROUND_UP(TM_ILT_SZ, TM_ILT_PAGE_SZ)
 +
 +/* SRC (Searcher) host DB constants */
 +#define SRC_ILT_PAGE_SZ_HW    0
 +#define SRC_ILT_PAGE_SZ               (4096 << SRC_ILT_PAGE_SZ_HW) /* 4K */
 +#define SRC_HASH_BITS         10
 +#define SRC_CONN_NUM          (1 << SRC_HASH_BITS) /* 1024 */
 +#define SRC_ILT_SZ            (sizeof(struct src_ent) * SRC_CONN_NUM)
 +#define SRC_T2_SZ             SRC_ILT_SZ
 +#define SRC_ILT_LINES         DIV_ROUND_UP(SRC_ILT_SZ, SRC_ILT_PAGE_SZ)
 +
 +#endif
 +
 +#define MAX_DMAE_C            8
 +
 +/* DMA memory not used in fastpath */
 +struct bnx2x_slowpath {
 +      union {
 +              struct mac_configuration_cmd            e1x;
 +              struct eth_classify_rules_ramrod_data   e2;
 +      } mac_rdata;
 +
 +
 +      union {
 +              struct tstorm_eth_mac_filter_config     e1x;
 +              struct eth_filter_rules_ramrod_data     e2;
 +      } rx_mode_rdata;
 +
 +      union {
 +              struct mac_configuration_cmd            e1;
 +              struct eth_multicast_rules_ramrod_data  e2;
 +      } mcast_rdata;
 +
 +      struct eth_rss_update_ramrod_data       rss_rdata;
 +
 +      /* Queue State related ramrods are always sent under rtnl_lock */
 +      union {
 +              struct client_init_ramrod_data  init_data;
 +              struct client_update_ramrod_data update_data;
 +      } q_rdata;
 +
 +      union {
 +              struct function_start_data      func_start;
 +              /* pfc configuration for DCBX ramrod */
 +              struct flow_control_configuration pfc_config;
 +      } func_rdata;
 +
 +      /* used by dmae command executer */
 +      struct dmae_command             dmae[MAX_DMAE_C];
 +
 +      u32                             stats_comp;
 +      union mac_stats                 mac_stats;
 +      struct nig_stats                nig_stats;
 +      struct host_port_stats          port_stats;
 +      struct host_func_stats          func_stats;
 +      struct host_func_stats          func_stats_base;
 +
 +      u32                             wb_comp;
 +      u32                             wb_data[4];
 +};
 +
 +#define bnx2x_sp(bp, var)             (&bp->slowpath->var)
 +#define bnx2x_sp_mapping(bp, var) \
 +              (bp->slowpath_mapping + offsetof(struct bnx2x_slowpath, var))
 +
 +
 +/* attn group wiring */
 +#define MAX_DYNAMIC_ATTN_GRPS         8
 +
 +struct attn_route {
 +      u32 sig[5];
 +};
 +
 +struct iro {
 +      u32 base;
 +      u16 m1;
 +      u16 m2;
 +      u16 m3;
 +      u16 size;
 +};
 +
 +struct hw_context {
 +      union cdu_context *vcxt;
 +      dma_addr_t cxt_mapping;
 +      size_t size;
 +};
 +
 +/* forward */
 +struct bnx2x_ilt;
 +
 +
 +enum bnx2x_recovery_state {
 +      BNX2X_RECOVERY_DONE,
 +      BNX2X_RECOVERY_INIT,
 +      BNX2X_RECOVERY_WAIT,
 +      BNX2X_RECOVERY_FAILED
 +};
 +
 +/*
 + * Event queue (EQ or event ring) MC hsi
 + * NUM_EQ_PAGES and EQ_DESC_CNT_PAGE must be power of 2
 + */
 +#define NUM_EQ_PAGES          1
 +#define EQ_DESC_CNT_PAGE      (BCM_PAGE_SIZE / sizeof(union event_ring_elem))
 +#define EQ_DESC_MAX_PAGE      (EQ_DESC_CNT_PAGE - 1)
 +#define NUM_EQ_DESC           (EQ_DESC_CNT_PAGE * NUM_EQ_PAGES)
 +#define EQ_DESC_MASK          (NUM_EQ_DESC - 1)
 +#define MAX_EQ_AVAIL          (EQ_DESC_MAX_PAGE * NUM_EQ_PAGES - 2)
 +
 +/* depends on EQ_DESC_CNT_PAGE being a power of 2 */
 +#define NEXT_EQ_IDX(x)                ((((x) & EQ_DESC_MAX_PAGE) == \
 +                                (EQ_DESC_MAX_PAGE - 1)) ? (x) + 2 : (x) + 1)
 +
 +/* depends on the above and on NUM_EQ_PAGES being a power of 2 */
 +#define EQ_DESC(x)            ((x) & EQ_DESC_MASK)
 +
 +#define BNX2X_EQ_INDEX \
 +      (&bp->def_status_blk->sp_sb.\
 +      index_values[HC_SP_INDEX_EQ_CONS])
 +
 +/* This is a data that will be used to create a link report message.
 + * We will keep the data used for the last link report in order
 + * to prevent reporting the same link parameters twice.
 + */
 +struct bnx2x_link_report_data {
 +      u16 line_speed;                 /* Effective line speed */
 +      unsigned long link_report_flags;/* BNX2X_LINK_REPORT_XXX flags */
 +};
 +
 +enum {
 +      BNX2X_LINK_REPORT_FD,           /* Full DUPLEX */
 +      BNX2X_LINK_REPORT_LINK_DOWN,
 +      BNX2X_LINK_REPORT_RX_FC_ON,
 +      BNX2X_LINK_REPORT_TX_FC_ON,
 +};
 +
 +enum {
 +      BNX2X_PORT_QUERY_IDX,
 +      BNX2X_PF_QUERY_IDX,
 +      BNX2X_FIRST_QUEUE_QUERY_IDX,
 +};
 +
 +struct bnx2x_fw_stats_req {
 +      struct stats_query_header hdr;
 +      struct stats_query_entry query[STATS_QUERY_CMD_COUNT];
 +};
 +
 +struct bnx2x_fw_stats_data {
 +      struct stats_counter    storm_counters;
 +      struct per_port_stats   port;
 +      struct per_pf_stats     pf;
 +      struct per_queue_stats  queue_stats[1];
 +};
 +
 +/* Public slow path states */
 +enum {
 +      BNX2X_SP_RTNL_SETUP_TC,
 +      BNX2X_SP_RTNL_TX_TIMEOUT,
 +};
 +
 +
 +struct bnx2x {
 +      /* Fields used in the tx and intr/napi performance paths
 +       * are grouped together in the beginning of the structure
 +       */
 +      struct bnx2x_fastpath   *fp;
 +      void __iomem            *regview;
 +      void __iomem            *doorbells;
 +      u16                     db_size;
 +
 +      u8                      pf_num; /* absolute PF number */
 +      u8                      pfid;   /* per-path PF number */
 +      int                     base_fw_ndsb; /**/
 +#define BP_PATH(bp)                   (CHIP_IS_E1x(bp) ? 0 : (bp->pf_num & 1))
 +#define BP_PORT(bp)                   (bp->pfid & 1)
 +#define BP_FUNC(bp)                   (bp->pfid)
 +#define BP_ABS_FUNC(bp)                       (bp->pf_num)
 +#define BP_VN(bp)                     ((bp)->pfid >> 1)
 +#define BP_MAX_VN_NUM(bp)             (CHIP_MODE_IS_4_PORT(bp) ? 2 : 4)
 +#define BP_L_ID(bp)                   (BP_VN(bp) << 2)
 +#define BP_FW_MB_IDX_VN(bp, vn)               (BP_PORT(bp) +\
 +        (vn) * ((CHIP_IS_E1x(bp) || (CHIP_MODE_IS_4_PORT(bp))) ? 2  : 1))
 +#define BP_FW_MB_IDX(bp)              BP_FW_MB_IDX_VN(bp, BP_VN(bp))
 +
 +      struct net_device       *dev;
 +      struct pci_dev          *pdev;
 +
 +      const struct iro        *iro_arr;
 +#define IRO (bp->iro_arr)
 +
 +      enum bnx2x_recovery_state recovery_state;
 +      int                     is_leader;
 +      struct msix_entry       *msix_table;
 +
 +      int                     tx_ring_size;
 +
 +/* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
 +#define ETH_OVREHEAD          (ETH_HLEN + 8 + 8)
 +#define ETH_MIN_PACKET_SIZE           60
 +#define ETH_MAX_PACKET_SIZE           1500
 +#define ETH_MAX_JUMBO_PACKET_SIZE     9600
 +
 +      /* Max supported alignment is 256 (8 shift) */
 +#define BNX2X_RX_ALIGN_SHIFT          ((L1_CACHE_SHIFT < 8) ? \
 +                                       L1_CACHE_SHIFT : 8)
 +      /* FW use 2 Cache lines Alignment for start packet and size  */
 +#define BNX2X_FW_RX_ALIGN             (2 << BNX2X_RX_ALIGN_SHIFT)
 +#define BNX2X_PXP_DRAM_ALIGN          (BNX2X_RX_ALIGN_SHIFT - 5)
 +
 +      struct host_sp_status_block *def_status_blk;
 +#define DEF_SB_IGU_ID                 16
 +#define DEF_SB_ID                     HC_SP_SB_ID
 +      __le16                  def_idx;
 +      __le16                  def_att_idx;
 +      u32                     attn_state;
 +      struct attn_route       attn_group[MAX_DYNAMIC_ATTN_GRPS];
 +
 +      /* slow path ring */
 +      struct eth_spe          *spq;
 +      dma_addr_t              spq_mapping;
 +      u16                     spq_prod_idx;
 +      struct eth_spe          *spq_prod_bd;
 +      struct eth_spe          *spq_last_bd;
 +      __le16                  *dsb_sp_prod;
 +      atomic_t                cq_spq_left; /* ETH_XXX ramrods credit */
 +      /* used to synchronize spq accesses */
 +      spinlock_t              spq_lock;
 +
 +      /* event queue */
 +      union event_ring_elem   *eq_ring;
 +      dma_addr_t              eq_mapping;
 +      u16                     eq_prod;
 +      u16                     eq_cons;
 +      __le16                  *eq_cons_sb;
 +      atomic_t                eq_spq_left; /* COMMON_XXX ramrods credit */
 +
 +
 +
 +      /* Counter for marking that there is a STAT_QUERY ramrod pending */
 +      u16                     stats_pending;
 +      /*  Counter for completed statistics ramrods */
 +      u16                     stats_comp;
 +
 +      /* End of fields used in the performance code paths */
 +
 +      int                     panic;
 +      int                     msg_enable;
 +
 +      u32                     flags;
 +#define PCIX_FLAG                     (1 << 0)
 +#define PCI_32BIT_FLAG                        (1 << 1)
 +#define ONE_PORT_FLAG                 (1 << 2)
 +#define NO_WOL_FLAG                   (1 << 3)
 +#define USING_DAC_FLAG                        (1 << 4)
 +#define USING_MSIX_FLAG                       (1 << 5)
 +#define USING_MSI_FLAG                        (1 << 6)
 +#define DISABLE_MSI_FLAG              (1 << 7)
 +#define TPA_ENABLE_FLAG                       (1 << 8)
 +#define NO_MCP_FLAG                   (1 << 9)
 +
 +#define BP_NOMCP(bp)                  (bp->flags & NO_MCP_FLAG)
 +#define MF_FUNC_DIS                   (1 << 11)
 +#define OWN_CNIC_IRQ                  (1 << 12)
 +#define NO_ISCSI_OOO_FLAG             (1 << 13)
 +#define NO_ISCSI_FLAG                 (1 << 14)
 +#define NO_FCOE_FLAG                  (1 << 15)
 +
 +#define NO_ISCSI(bp)          ((bp)->flags & NO_ISCSI_FLAG)
 +#define NO_ISCSI_OOO(bp)      ((bp)->flags & NO_ISCSI_OOO_FLAG)
 +#define NO_FCOE(bp)           ((bp)->flags & NO_FCOE_FLAG)
 +
 +      int                     pm_cap;
 +      int                     mrrs;
 +
 +      struct delayed_work     sp_task;
 +      struct delayed_work     sp_rtnl_task;
 +
 +      struct delayed_work     period_task;
 +      struct timer_list       timer;
 +      int                     current_interval;
 +
 +      u16                     fw_seq;
 +      u16                     fw_drv_pulse_wr_seq;
 +      u32                     func_stx;
 +
 +      struct link_params      link_params;
 +      struct link_vars        link_vars;
 +      u32                     link_cnt;
 +      struct bnx2x_link_report_data last_reported_link;
 +
 +      struct mdio_if_info     mdio;
 +
 +      struct bnx2x_common     common;
 +      struct bnx2x_port       port;
 +
 +      struct cmng_struct_per_port cmng;
 +      u32                     vn_weight_sum;
 +      u32                     mf_config[E1HVN_MAX];
 +      u32                     mf2_config[E2_FUNC_MAX];
 +      u32                     path_has_ovlan; /* E3 */
 +      u16                     mf_ov;
 +      u8                      mf_mode;
 +#define IS_MF(bp)             (bp->mf_mode != 0)
 +#define IS_MF_SI(bp)          (bp->mf_mode == MULTI_FUNCTION_SI)
 +#define IS_MF_SD(bp)          (bp->mf_mode == MULTI_FUNCTION_SD)
 +
 +      u8                      wol;
 +
 +      int                     rx_ring_size;
 +
 +      u16                     tx_quick_cons_trip_int;
 +      u16                     tx_quick_cons_trip;
 +      u16                     tx_ticks_int;
 +      u16                     tx_ticks;
 +
 +      u16                     rx_quick_cons_trip_int;
 +      u16                     rx_quick_cons_trip;
 +      u16                     rx_ticks_int;
 +      u16                     rx_ticks;
 +/* Maximal coalescing timeout in us */
 +#define BNX2X_MAX_COALESCE_TOUT               (0xf0*12)
 +
 +      u32                     lin_cnt;
 +
 +      u16                     state;
 +#define BNX2X_STATE_CLOSED            0
 +#define BNX2X_STATE_OPENING_WAIT4_LOAD        0x1000
 +#define BNX2X_STATE_OPENING_WAIT4_PORT        0x2000
 +#define BNX2X_STATE_OPEN              0x3000
 +#define BNX2X_STATE_CLOSING_WAIT4_HALT        0x4000
 +#define BNX2X_STATE_CLOSING_WAIT4_DELETE 0x5000
 +
 +#define BNX2X_STATE_DIAG              0xe000
 +#define BNX2X_STATE_ERROR             0xf000
 +
 +      int                     multi_mode;
 +#define BNX2X_MAX_PRIORITY            8
 +#define BNX2X_MAX_ENTRIES_PER_PRI     16
 +#define BNX2X_MAX_COS                 3
 +#define BNX2X_MAX_TX_COS              2
 +      int                     num_queues;
 +      int                     disable_tpa;
 +
 +      u32                     rx_mode;
 +#define BNX2X_RX_MODE_NONE            0
 +#define BNX2X_RX_MODE_NORMAL          1
 +#define BNX2X_RX_MODE_ALLMULTI                2
 +#define BNX2X_RX_MODE_PROMISC         3
 +#define BNX2X_MAX_MULTICAST           64
 +
 +      u8                      igu_dsb_id;
 +      u8                      igu_base_sb;
 +      u8                      igu_sb_cnt;
 +      dma_addr_t              def_status_blk_mapping;
 +
 +      struct bnx2x_slowpath   *slowpath;
 +      dma_addr_t              slowpath_mapping;
 +
 +      /* Total number of FW statistics requests */
 +      u8                      fw_stats_num;
 +
 +      /*
 +       * This is a memory buffer that will contain both statistics
 +       * ramrod request and data.
 +       */
 +      void                    *fw_stats;
 +      dma_addr_t              fw_stats_mapping;
 +
 +      /*
 +       * FW statistics request shortcut (points at the
 +       * beginning of fw_stats buffer).
 +       */
 +      struct bnx2x_fw_stats_req       *fw_stats_req;
 +      dma_addr_t                      fw_stats_req_mapping;
 +      int                             fw_stats_req_sz;
 +
 +      /*
 +       * FW statistics data shortcut (points at the begining of
 +       * fw_stats buffer + fw_stats_req_sz).
 +       */
 +      struct bnx2x_fw_stats_data      *fw_stats_data;
 +      dma_addr_t                      fw_stats_data_mapping;
 +      int                             fw_stats_data_sz;
 +
 +      struct hw_context       context;
 +
 +      struct bnx2x_ilt        *ilt;
 +#define BP_ILT(bp)            ((bp)->ilt)
 +#define ILT_MAX_LINES         256
 +/*
 + * Maximum supported number of RSS queues: number of IGU SBs minus one that goes
 + * to CNIC.
 + */
 +#define BNX2X_MAX_RSS_COUNT(bp)       ((bp)->igu_sb_cnt - CNIC_PRESENT)
 +
 +/*
 + * Maximum CID count that might be required by the bnx2x:
 + * Max Tss * Max_Tx_Multi_Cos + CNIC L2 Clients (FCoE and iSCSI related)
 + */
 +#define BNX2X_L2_CID_COUNT(bp)        (MAX_TXQS_PER_COS * BNX2X_MULTI_TX_COS +\
 +                                      NON_ETH_CONTEXT_USE + CNIC_PRESENT)
 +#define L2_ILT_LINES(bp)      (DIV_ROUND_UP(BNX2X_L2_CID_COUNT(bp),\
 +                                      ILT_PAGE_CIDS))
 +#define BNX2X_DB_SIZE(bp)     (BNX2X_L2_CID_COUNT(bp) * (1 << BNX2X_DB_SHIFT))
 +
 +      int                     qm_cid_count;
 +
 +      int                     dropless_fc;
 +
 +#ifdef BCM_CNIC
 +      u32                     cnic_flags;
 +#define BNX2X_CNIC_FLAG_MAC_SET               1
 +      void                    *t2;
 +      dma_addr_t              t2_mapping;
 +      struct cnic_ops __rcu   *cnic_ops;
 +      void                    *cnic_data;
 +      u32                     cnic_tag;
 +      struct cnic_eth_dev     cnic_eth_dev;
 +      union host_hc_status_block cnic_sb;
 +      dma_addr_t              cnic_sb_mapping;
 +      struct eth_spe          *cnic_kwq;
 +      struct eth_spe          *cnic_kwq_prod;
 +      struct eth_spe          *cnic_kwq_cons;
 +      struct eth_spe          *cnic_kwq_last;
 +      u16                     cnic_kwq_pending;
 +      u16                     cnic_spq_pending;
 +      u8                      fip_mac[ETH_ALEN];
 +      struct mutex            cnic_mutex;
 +      struct bnx2x_vlan_mac_obj iscsi_l2_mac_obj;
 +
 +      /* Start index of the "special" (CNIC related) L2 cleints */
 +      u8                              cnic_base_cl_id;
 +#endif
 +
 +      int                     dmae_ready;
 +      /* used to synchronize dmae accesses */
 +      spinlock_t              dmae_lock;
 +
 +      /* used to protect the FW mail box */
 +      struct mutex            fw_mb_mutex;
 +
 +      /* used to synchronize stats collecting */
 +      int                     stats_state;
 +
 +      /* used for synchronization of concurrent threads statistics handling */
 +      spinlock_t              stats_lock;
 +
 +      /* used by dmae command loader */
 +      struct dmae_command     stats_dmae;
 +      int                     executer_idx;
 +
 +      u16                     stats_counter;
 +      struct bnx2x_eth_stats  eth_stats;
 +
 +      struct z_stream_s       *strm;
 +      void                    *gunzip_buf;
 +      dma_addr_t              gunzip_mapping;
 +      int                     gunzip_outlen;
 +#define FW_BUF_SIZE                   0x8000
 +#define GUNZIP_BUF(bp)                        (bp->gunzip_buf)
 +#define GUNZIP_PHYS(bp)                       (bp->gunzip_mapping)
 +#define GUNZIP_OUTLEN(bp)             (bp->gunzip_outlen)
 +
 +      struct raw_op           *init_ops;
 +      /* Init blocks offsets inside init_ops */
 +      u16                     *init_ops_offsets;
 +      /* Data blob - has 32 bit granularity */
 +      u32                     *init_data;
 +      u32                     init_mode_flags;
 +#define INIT_MODE_FLAGS(bp)   (bp->init_mode_flags)
 +      /* Zipped PRAM blobs - raw data */
 +      const u8                *tsem_int_table_data;
 +      const u8                *tsem_pram_data;
 +      const u8                *usem_int_table_data;
 +      const u8                *usem_pram_data;
 +      const u8                *xsem_int_table_data;
 +      const u8                *xsem_pram_data;
 +      const u8                *csem_int_table_data;
 +      const u8                *csem_pram_data;
 +#define INIT_OPS(bp)                  (bp->init_ops)
 +#define INIT_OPS_OFFSETS(bp)          (bp->init_ops_offsets)
 +#define INIT_DATA(bp)                 (bp->init_data)
 +#define INIT_TSEM_INT_TABLE_DATA(bp)  (bp->tsem_int_table_data)
 +#define INIT_TSEM_PRAM_DATA(bp)               (bp->tsem_pram_data)
 +#define INIT_USEM_INT_TABLE_DATA(bp)  (bp->usem_int_table_data)
 +#define INIT_USEM_PRAM_DATA(bp)               (bp->usem_pram_data)
 +#define INIT_XSEM_INT_TABLE_DATA(bp)  (bp->xsem_int_table_data)
 +#define INIT_XSEM_PRAM_DATA(bp)               (bp->xsem_pram_data)
 +#define INIT_CSEM_INT_TABLE_DATA(bp)  (bp->csem_int_table_data)
 +#define INIT_CSEM_PRAM_DATA(bp)               (bp->csem_pram_data)
 +
 +#define PHY_FW_VER_LEN                        20
 +      char                    fw_ver[32];
 +      const struct firmware   *firmware;
 +
 +      /* DCB support on/off */
 +      u16 dcb_state;
 +#define BNX2X_DCB_STATE_OFF                   0
 +#define BNX2X_DCB_STATE_ON                    1
 +
 +      /* DCBX engine mode */
 +      int dcbx_enabled;
 +#define BNX2X_DCBX_ENABLED_OFF                        0
 +#define BNX2X_DCBX_ENABLED_ON_NEG_OFF         1
 +#define BNX2X_DCBX_ENABLED_ON_NEG_ON          2
 +#define BNX2X_DCBX_ENABLED_INVALID            (-1)
 +
 +      bool dcbx_mode_uset;
 +
 +      struct bnx2x_config_dcbx_params         dcbx_config_params;
 +      struct bnx2x_dcbx_port_params           dcbx_port_params;
 +      int                                     dcb_version;
 +
 +      /* CAM credit pools */
 +      struct bnx2x_credit_pool_obj            macs_pool;
 +
 +      /* RX_MODE object */
 +      struct bnx2x_rx_mode_obj                rx_mode_obj;
 +
 +      /* MCAST object */
 +      struct bnx2x_mcast_obj                  mcast_obj;
 +
 +      /* RSS configuration object */
 +      struct bnx2x_rss_config_obj             rss_conf_obj;
 +
 +      /* Function State controlling object */
 +      struct bnx2x_func_sp_obj                func_obj;
 +
 +      unsigned long                           sp_state;
 +
 +      /* operation indication for the sp_rtnl task */
 +      unsigned long                           sp_rtnl_state;
 +
 +      /* DCBX Negotation results */
 +      struct dcbx_features                    dcbx_local_feat;
 +      u32                                     dcbx_error;
 +
 +#ifdef BCM_DCBNL
 +      struct dcbx_features                    dcbx_remote_feat;
 +      u32                                     dcbx_remote_flags;
 +#endif
 +      u32                                     pending_max;
 +
 +      /* multiple tx classes of service */
 +      u8                                      max_cos;
 +
 +      /* priority to cos mapping */
 +      u8                                      prio_to_cos[8];
 +};
 +
 +/* Tx queues may be less or equal to Rx queues */
 +extern int num_queues;
 +#define BNX2X_NUM_QUEUES(bp)  (bp->num_queues)
 +#define BNX2X_NUM_ETH_QUEUES(bp) (BNX2X_NUM_QUEUES(bp) - NON_ETH_CONTEXT_USE)
 +#define BNX2X_NUM_RX_QUEUES(bp)       BNX2X_NUM_QUEUES(bp)
 +
 +#define is_multi(bp)          (BNX2X_NUM_QUEUES(bp) > 1)
 +
 +#define BNX2X_MAX_QUEUES(bp)  BNX2X_MAX_RSS_COUNT(bp)
 +/* #define is_eth_multi(bp)   (BNX2X_NUM_ETH_QUEUES(bp) > 1) */
 +
 +#define RSS_IPV4_CAP_MASK                                             \
 +      TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY
 +
 +#define RSS_IPV4_TCP_CAP_MASK                                         \
 +      TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY
 +
 +#define RSS_IPV6_CAP_MASK                                             \
 +      TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY
 +
 +#define RSS_IPV6_TCP_CAP_MASK                                         \
 +      TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY
 +
 +/* func init flags */
 +#define FUNC_FLG_RSS          0x0001
 +#define FUNC_FLG_STATS                0x0002
 +/* removed  FUNC_FLG_UNMATCHED        0x0004 */
 +#define FUNC_FLG_TPA          0x0008
 +#define FUNC_FLG_SPQ          0x0010
 +#define FUNC_FLG_LEADING      0x0020  /* PF only */
 +
 +
 +struct bnx2x_func_init_params {
 +      /* dma */
 +      dma_addr_t      fw_stat_map;    /* valid iff FUNC_FLG_STATS */
 +      dma_addr_t      spq_map;        /* valid iff FUNC_FLG_SPQ */
 +
 +      u16             func_flgs;
 +      u16             func_id;        /* abs fid */
 +      u16             pf_id;
 +      u16             spq_prod;       /* valid iff FUNC_FLG_SPQ */
 +};
 +
 +#define for_each_eth_queue(bp, var) \
 +      for ((var) = 0; (var) < BNX2X_NUM_ETH_QUEUES(bp); (var)++)
 +
 +#define for_each_nondefault_eth_queue(bp, var) \
 +      for ((var) = 1; (var) < BNX2X_NUM_ETH_QUEUES(bp); (var)++)
 +
 +#define for_each_queue(bp, var) \
 +      for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
 +              if (skip_queue(bp, var))        \
 +                      continue;               \
 +              else
 +
 +/* Skip forwarding FP */
 +#define for_each_rx_queue(bp, var) \
 +      for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
 +              if (skip_rx_queue(bp, var))     \
 +                      continue;               \
 +              else
 +
 +/* Skip OOO FP */
 +#define for_each_tx_queue(bp, var) \
 +      for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
 +              if (skip_tx_queue(bp, var))     \
 +                      continue;               \
 +              else
 +
 +#define for_each_nondefault_queue(bp, var) \
 +      for ((var) = 1; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
 +              if (skip_queue(bp, var))        \
 +                      continue;               \
 +              else
 +
 +#define for_each_cos_in_tx_queue(fp, var) \
 +      for ((var) = 0; (var) < (fp)->max_cos; (var)++)
 +
 +/* skip rx queue
 + * if FCOE l2 support is disabled and this is the fcoe L2 queue
 + */
 +#define skip_rx_queue(bp, idx)        (NO_FCOE(bp) && IS_FCOE_IDX(idx))
 +
 +/* skip tx queue
 + * if FCOE l2 support is disabled and this is the fcoe L2 queue
 + */
 +#define skip_tx_queue(bp, idx)        (NO_FCOE(bp) && IS_FCOE_IDX(idx))
 +
 +#define skip_queue(bp, idx)   (NO_FCOE(bp) && IS_FCOE_IDX(idx))
 +
 +
 +
 +
 +/**
 + * bnx2x_set_mac_one - configure a single MAC address
 + *
 + * @bp:                       driver handle
 + * @mac:              MAC to configure
 + * @obj:              MAC object handle
 + * @set:              if 'true' add a new MAC, otherwise - delete
 + * @mac_type:         the type of the MAC to configure (e.g. ETH, UC list)
 + * @ramrod_flags:     RAMROD_XXX flags (e.g. RAMROD_CONT, RAMROD_COMP_WAIT)
 + *
 + * Configures one MAC according to provided parameters or continues the
 + * execution of previously scheduled commands if RAMROD_CONT is set in
 + * ramrod_flags.
 + *
 + * Returns zero if operation has successfully completed, a positive value if the
 + * operation has been successfully scheduled and a negative - if a requested
 + * operations has failed.
 + */
 +int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,
 +                    struct bnx2x_vlan_mac_obj *obj, bool set,
 +                    int mac_type, unsigned long *ramrod_flags);
 +/**
 + * Deletes all MACs configured for the specific MAC object.
 + *
 + * @param bp Function driver instance
 + * @param mac_obj MAC object to cleanup
 + *
 + * @return zero if all MACs were cleaned
 + */
 +
 +/**
 + * bnx2x_del_all_macs - delete all MACs configured for the specific MAC object
 + *
 + * @bp:                       driver handle
 + * @mac_obj:          MAC object handle
 + * @mac_type:         type of the MACs to clear (BNX2X_XXX_MAC)
 + * @wait_for_comp:    if 'true' block until completion
 + *
 + * Deletes all MACs of the specific type (e.g. ETH, UC list).
 + *
 + * Returns zero if operation has successfully completed, a positive value if the
 + * operation has been successfully scheduled and a negative - if a requested
 + * operations has failed.
 + */
 +int bnx2x_del_all_macs(struct bnx2x *bp,
 +                     struct bnx2x_vlan_mac_obj *mac_obj,
 +                     int mac_type, bool wait_for_comp);
 +
 +/* Init Function API  */
 +void bnx2x_func_init(struct bnx2x *bp, struct bnx2x_func_init_params *p);
 +int bnx2x_get_gpio(struct bnx2x *bp, int gpio_num, u8 port);
 +int bnx2x_set_gpio(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
 +int bnx2x_set_mult_gpio(struct bnx2x *bp, u8 pins, u32 mode);
 +int bnx2x_set_gpio_int(struct bnx2x *bp, int gpio_num, u32 mode, u8 port);
 +void bnx2x_read_mf_cfg(struct bnx2x *bp);
 +
 +
 +/* dmae */
 +void bnx2x_read_dmae(struct bnx2x *bp, u32 src_addr, u32 len32);
 +void bnx2x_write_dmae(struct bnx2x *bp, dma_addr_t dma_addr, u32 dst_addr,
 +                    u32 len32);
 +void bnx2x_post_dmae(struct bnx2x *bp, struct dmae_command *dmae, int idx);
 +u32 bnx2x_dmae_opcode_add_comp(u32 opcode, u8 comp_type);
 +u32 bnx2x_dmae_opcode_clr_src_reset(u32 opcode);
 +u32 bnx2x_dmae_opcode(struct bnx2x *bp, u8 src_type, u8 dst_type,
 +                    bool with_comp, u8 comp_type);
 +
 +
 +void bnx2x_calc_fc_adv(struct bnx2x *bp);
 +int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
 +                u32 data_hi, u32 data_lo, int cmd_type);
 +void bnx2x_update_coalesce(struct bnx2x *bp);
 +int bnx2x_get_cur_phy_idx(struct bnx2x *bp);
 +
 +static inline u32 reg_poll(struct bnx2x *bp, u32 reg, u32 expected, int ms,
 +                         int wait)
 +{
 +      u32 val;
 +
 +      do {
 +              val = REG_RD(bp, reg);
 +              if (val == expected)
 +                      break;
 +              ms -= wait;
 +              msleep(wait);
 +
 +      } while (ms > 0);
 +
 +      return val;
 +}
 +
 +#define BNX2X_ILT_ZALLOC(x, y, size) \
 +      do { \
 +              x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
 +              if (x) \
 +                      memset(x, 0, size); \
 +      } while (0)
 +
 +#define BNX2X_ILT_FREE(x, y, size) \
 +      do { \
 +              if (x) { \
 +                      dma_free_coherent(&bp->pdev->dev, size, x, y); \
 +                      x = NULL; \
 +                      y = 0; \
 +              } \
 +      } while (0)
 +
 +#define ILOG2(x)      (ilog2((x)))
 +
 +#define ILT_NUM_PAGE_ENTRIES  (3072)
 +/* In 57710/11 we use whole table since we have 8 func
 + * In 57712 we have only 4 func, but use same size per func, then only half of
 + * the table in use
 + */
 +#define ILT_PER_FUNC          (ILT_NUM_PAGE_ENTRIES/8)
 +
 +#define FUNC_ILT_BASE(func)   (func * ILT_PER_FUNC)
 +/*
 + * the phys address is shifted right 12 bits and has an added
 + * 1=valid bit added to the 53rd bit
 + * then since this is a wide register(TM)
 + * we split it into two 32 bit writes
 + */
 +#define ONCHIP_ADDR1(x)               ((u32)(((u64)x >> 12) & 0xFFFFFFFF))
 +#define ONCHIP_ADDR2(x)               ((u32)((1 << 20) | ((u64)x >> 44)))
 +
 +/* load/unload mode */
 +#define LOAD_NORMAL                   0
 +#define LOAD_OPEN                     1
 +#define LOAD_DIAG                     2
 +#define UNLOAD_NORMAL                 0
 +#define UNLOAD_CLOSE                  1
 +#define UNLOAD_RECOVERY                       2
 +
 +
 +/* DMAE command defines */
 +#define DMAE_TIMEOUT                  -1
 +#define DMAE_PCI_ERROR                        -2      /* E2 and onward */
 +#define DMAE_NOT_RDY                  -3
 +#define DMAE_PCI_ERR_FLAG             0x80000000
 +
 +#define DMAE_SRC_PCI                  0
 +#define DMAE_SRC_GRC                  1
 +
 +#define DMAE_DST_NONE                 0
 +#define DMAE_DST_PCI                  1
 +#define DMAE_DST_GRC                  2
 +
 +#define DMAE_COMP_PCI                 0
 +#define DMAE_COMP_GRC                 1
 +
 +/* E2 and onward - PCI error handling in the completion */
 +
 +#define DMAE_COMP_REGULAR             0
 +#define DMAE_COM_SET_ERR              1
 +
 +#define DMAE_CMD_SRC_PCI              (DMAE_SRC_PCI << \
 +                                              DMAE_COMMAND_SRC_SHIFT)
 +#define DMAE_CMD_SRC_GRC              (DMAE_SRC_GRC << \
 +                                              DMAE_COMMAND_SRC_SHIFT)
 +
 +#define DMAE_CMD_DST_PCI              (DMAE_DST_PCI << \
 +                                              DMAE_COMMAND_DST_SHIFT)
 +#define DMAE_CMD_DST_GRC              (DMAE_DST_GRC << \
 +                                              DMAE_COMMAND_DST_SHIFT)
 +
 +#define DMAE_CMD_C_DST_PCI            (DMAE_COMP_PCI << \
 +                                              DMAE_COMMAND_C_DST_SHIFT)
 +#define DMAE_CMD_C_DST_GRC            (DMAE_COMP_GRC << \
 +                                              DMAE_COMMAND_C_DST_SHIFT)
 +
 +#define DMAE_CMD_C_ENABLE             DMAE_COMMAND_C_TYPE_ENABLE
 +
 +#define DMAE_CMD_ENDIANITY_NO_SWAP    (0 << DMAE_COMMAND_ENDIANITY_SHIFT)
 +#define DMAE_CMD_ENDIANITY_B_SWAP     (1 << DMAE_COMMAND_ENDIANITY_SHIFT)
 +#define DMAE_CMD_ENDIANITY_DW_SWAP    (2 << DMAE_COMMAND_ENDIANITY_SHIFT)
 +#define DMAE_CMD_ENDIANITY_B_DW_SWAP  (3 << DMAE_COMMAND_ENDIANITY_SHIFT)
 +
 +#define DMAE_CMD_PORT_0                       0
 +#define DMAE_CMD_PORT_1                       DMAE_COMMAND_PORT
 +
 +#define DMAE_CMD_SRC_RESET            DMAE_COMMAND_SRC_RESET
 +#define DMAE_CMD_DST_RESET            DMAE_COMMAND_DST_RESET
 +#define DMAE_CMD_E1HVN_SHIFT          DMAE_COMMAND_E1HVN_SHIFT
 +
 +#define DMAE_SRC_PF                   0
 +#define DMAE_SRC_VF                   1
 +
 +#define DMAE_DST_PF                   0
 +#define DMAE_DST_VF                   1
 +
 +#define DMAE_C_SRC                    0
 +#define DMAE_C_DST                    1
 +
 +#define DMAE_LEN32_RD_MAX             0x80
 +#define DMAE_LEN32_WR_MAX(bp)         (CHIP_IS_E1(bp) ? 0x400 : 0x2000)
 +
 +#define DMAE_COMP_VAL                 0x60d0d0ae /* E2 and on - upper bit
 +                                                      indicates eror */
 +
 +#define MAX_DMAE_C_PER_PORT           8
 +#define INIT_DMAE_C(bp)                       (BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \
 +                                       BP_VN(bp))
 +#define PMF_DMAE_C(bp)                        (BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \
 +                                       E1HVN_MAX)
 +
 +/* PCIE link and speed */
 +#define PCICFG_LINK_WIDTH             0x1f00000
 +#define PCICFG_LINK_WIDTH_SHIFT               20
 +#define PCICFG_LINK_SPEED             0xf0000
 +#define PCICFG_LINK_SPEED_SHIFT               16
 +
 +
 +#define BNX2X_NUM_TESTS                       7
 +
 +#define BNX2X_PHY_LOOPBACK            0
 +#define BNX2X_MAC_LOOPBACK            1
 +#define BNX2X_PHY_LOOPBACK_FAILED     1
 +#define BNX2X_MAC_LOOPBACK_FAILED     2
 +#define BNX2X_LOOPBACK_FAILED         (BNX2X_MAC_LOOPBACK_FAILED | \
 +                                       BNX2X_PHY_LOOPBACK_FAILED)
 +
 +
 +#define STROM_ASSERT_ARRAY_SIZE               50
 +
 +
 +/* must be used on a CID before placing it on a HW ring */
 +#define HW_CID(bp, x)                 ((BP_PORT(bp) << 23) | \
 +                                       (BP_VN(bp) << BNX2X_SWCID_SHIFT) | \
 +                                       (x))
 +
 +#define SP_DESC_CNT           (BCM_PAGE_SIZE / sizeof(struct eth_spe))
 +#define MAX_SP_DESC_CNT                       (SP_DESC_CNT - 1)
 +
 +
 +#define BNX2X_BTR                     4
 +#define MAX_SPQ_PENDING                       8
 +
 +/* CMNG constants, as derived from system spec calculations */
 +/* default MIN rate in case VNIC min rate is configured to zero - 100Mbps */
 +#define DEF_MIN_RATE                                  100
 +/* resolution of the rate shaping timer - 400 usec */
 +#define RS_PERIODIC_TIMEOUT_USEC                      400
 +/* number of bytes in single QM arbitration cycle -
 + * coefficient for calculating the fairness timer */
 +#define QM_ARB_BYTES                                  160000
 +/* resolution of Min algorithm 1:100 */
 +#define MIN_RES                                               100
 +/* how many bytes above threshold for the minimal credit of Min algorithm*/
 +#define MIN_ABOVE_THRESH                              32768
 +/* Fairness algorithm integration time coefficient -
 + * for calculating the actual Tfair */
 +#define T_FAIR_COEF   ((MIN_ABOVE_THRESH +  QM_ARB_BYTES) * 8 * MIN_RES)
 +/* Memory of fairness algorithm . 2 cycles */
 +#define FAIR_MEM                                      2
 +
 +
 +#define ATTN_NIG_FOR_FUNC             (1L << 8)
 +#define ATTN_SW_TIMER_4_FUNC          (1L << 9)
 +#define GPIO_2_FUNC                   (1L << 10)
 +#define GPIO_3_FUNC                   (1L << 11)
 +#define GPIO_4_FUNC                   (1L << 12)
 +#define ATTN_GENERAL_ATTN_1           (1L << 13)
 +#define ATTN_GENERAL_ATTN_2           (1L << 14)
 +#define ATTN_GENERAL_ATTN_3           (1L << 15)
 +#define ATTN_GENERAL_ATTN_4           (1L << 13)
 +#define ATTN_GENERAL_ATTN_5           (1L << 14)
 +#define ATTN_GENERAL_ATTN_6           (1L << 15)
 +
 +#define ATTN_HARD_WIRED_MASK          0xff00
 +#define ATTENTION_ID                  4
 +
 +
 +/* stuff added to make the code fit 80Col */
 +
 +#define BNX2X_PMF_LINK_ASSERT \
 +      GENERAL_ATTEN_OFFSET(LINK_SYNC_ATTENTION_BIT_FUNC_0 + BP_FUNC(bp))
 +
 +#define BNX2X_MC_ASSERT_BITS \
 +      (GENERAL_ATTEN_OFFSET(TSTORM_FATAL_ASSERT_ATTENTION_BIT) | \
 +       GENERAL_ATTEN_OFFSET(USTORM_FATAL_ASSERT_ATTENTION_BIT) | \
 +       GENERAL_ATTEN_OFFSET(CSTORM_FATAL_ASSERT_ATTENTION_BIT) | \
 +       GENERAL_ATTEN_OFFSET(XSTORM_FATAL_ASSERT_ATTENTION_BIT))
 +
 +#define BNX2X_MCP_ASSERT \
 +      GENERAL_ATTEN_OFFSET(MCP_FATAL_ASSERT_ATTENTION_BIT)
 +
 +#define BNX2X_GRC_TIMEOUT     GENERAL_ATTEN_OFFSET(LATCHED_ATTN_TIMEOUT_GRC)
 +#define BNX2X_GRC_RSV         (GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCR) | \
 +                               GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCT) | \
 +                               GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCN) | \
 +                               GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCU) | \
 +                               GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RBCP) | \
 +                               GENERAL_ATTEN_OFFSET(LATCHED_ATTN_RSVD_GRC))
 +
 +#define HW_INTERRUT_ASSERT_SET_0 \
 +                              (AEU_INPUTS_ATTN_BITS_TSDM_HW_INTERRUPT | \
 +                               AEU_INPUTS_ATTN_BITS_TCM_HW_INTERRUPT | \
 +                               AEU_INPUTS_ATTN_BITS_TSEMI_HW_INTERRUPT | \
 +                               AEU_INPUTS_ATTN_BITS_PBCLIENT_HW_INTERRUPT)
 +#define HW_PRTY_ASSERT_SET_0  (AEU_INPUTS_ATTN_BITS_BRB_PARITY_ERROR | \
 +                               AEU_INPUTS_ATTN_BITS_PARSER_PARITY_ERROR | \
 +                               AEU_INPUTS_ATTN_BITS_TSDM_PARITY_ERROR | \
 +                               AEU_INPUTS_ATTN_BITS_SEARCHER_PARITY_ERROR |\
 +                               AEU_INPUTS_ATTN_BITS_TSEMI_PARITY_ERROR |\
 +                               AEU_INPUTS_ATTN_BITS_TCM_PARITY_ERROR |\
 +                               AEU_INPUTS_ATTN_BITS_PBCLIENT_PARITY_ERROR)
 +#define HW_INTERRUT_ASSERT_SET_1 \
 +                              (AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT | \
 +                               AEU_INPUTS_ATTN_BITS_TIMERS_HW_INTERRUPT | \
 +                               AEU_INPUTS_ATTN_BITS_XSDM_HW_INTERRUPT | \
 +                               AEU_INPUTS_ATTN_BITS_XCM_HW_INTERRUPT | \
 +                               AEU_INPUTS_ATTN_BITS_XSEMI_HW_INTERRUPT | \
 +                               AEU_INPUTS_ATTN_BITS_USDM_HW_INTERRUPT | \
 +                               AEU_INPUTS_ATTN_BITS_UCM_HW_INTERRUPT | \
 +                               AEU_INPUTS_ATTN_BITS_USEMI_HW_INTERRUPT | \
 +                               AEU_INPUTS_ATTN_BITS_UPB_HW_INTERRUPT | \
 +                               AEU_INPUTS_ATTN_BITS_CSDM_HW_INTERRUPT | \
 +                               AEU_INPUTS_ATTN_BITS_CCM_HW_INTERRUPT)
 +#define HW_PRTY_ASSERT_SET_1  (AEU_INPUTS_ATTN_BITS_PBF_PARITY_ERROR |\
 +                               AEU_INPUTS_ATTN_BITS_QM_PARITY_ERROR | \
 +                               AEU_INPUTS_ATTN_BITS_TIMERS_PARITY_ERROR |\
 +                               AEU_INPUTS_ATTN_BITS_XSDM_PARITY_ERROR | \
 +                               AEU_INPUTS_ATTN_BITS_XCM_PARITY_ERROR |\
 +                               AEU_INPUTS_ATTN_BITS_XSEMI_PARITY_ERROR | \
 +                               AEU_INPUTS_ATTN_BITS_DOORBELLQ_PARITY_ERROR |\
 +                               AEU_INPUTS_ATTN_BITS_NIG_PARITY_ERROR |\
 +                           AEU_INPUTS_ATTN_BITS_VAUX_PCI_CORE_PARITY_ERROR |\
 +                               AEU_INPUTS_ATTN_BITS_DEBUG_PARITY_ERROR | \
 +                               AEU_INPUTS_ATTN_BITS_USDM_PARITY_ERROR | \
 +                               AEU_INPUTS_ATTN_BITS_UCM_PARITY_ERROR |\
 +                               AEU_INPUTS_ATTN_BITS_USEMI_PARITY_ERROR | \
 +                               AEU_INPUTS_ATTN_BITS_UPB_PARITY_ERROR | \
 +                               AEU_INPUTS_ATTN_BITS_CSDM_PARITY_ERROR |\
 +                               AEU_INPUTS_ATTN_BITS_CCM_PARITY_ERROR)
 +#define HW_INTERRUT_ASSERT_SET_2 \
 +                              (AEU_INPUTS_ATTN_BITS_CSEMI_HW_INTERRUPT | \
 +                               AEU_INPUTS_ATTN_BITS_CDU_HW_INTERRUPT | \
 +                               AEU_INPUTS_ATTN_BITS_DMAE_HW_INTERRUPT | \
 +                      AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_HW_INTERRUPT |\
 +                               AEU_INPUTS_ATTN_BITS_MISC_HW_INTERRUPT)
 +#define HW_PRTY_ASSERT_SET_2  (AEU_INPUTS_ATTN_BITS_CSEMI_PARITY_ERROR | \
 +                               AEU_INPUTS_ATTN_BITS_PXP_PARITY_ERROR | \
 +                      AEU_INPUTS_ATTN_BITS_PXPPCICLOCKCLIENT_PARITY_ERROR |\
 +                               AEU_INPUTS_ATTN_BITS_CFC_PARITY_ERROR | \
 +                               AEU_INPUTS_ATTN_BITS_CDU_PARITY_ERROR | \
 +                               AEU_INPUTS_ATTN_BITS_DMAE_PARITY_ERROR |\
 +                               AEU_INPUTS_ATTN_BITS_IGU_PARITY_ERROR | \
 +                               AEU_INPUTS_ATTN_BITS_MISC_PARITY_ERROR)
 +
 +#define HW_PRTY_ASSERT_SET_3 (AEU_INPUTS_ATTN_BITS_MCP_LATCHED_ROM_PARITY | \
 +              AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_RX_PARITY | \
 +              AEU_INPUTS_ATTN_BITS_MCP_LATCHED_UMP_TX_PARITY | \
 +              AEU_INPUTS_ATTN_BITS_MCP_LATCHED_SCPAD_PARITY)
 +
 +#define HW_PRTY_ASSERT_SET_4 (AEU_INPUTS_ATTN_BITS_PGLUE_PARITY_ERROR | \
 +                            AEU_INPUTS_ATTN_BITS_ATC_PARITY_ERROR)
 +
 +#define RSS_FLAGS(bp) \
 +              (TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_CAPABILITY | \
 +               TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV4_TCP_CAPABILITY | \
 +               TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_CAPABILITY | \
 +               TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_IPV6_TCP_CAPABILITY | \
 +               (bp->multi_mode << \
 +                TSTORM_ETH_FUNCTION_COMMON_CONFIG_RSS_MODE_SHIFT))
 +#define MULTI_MASK                    0x7f
 +
 +
 +#define DEF_USB_FUNC_OFF      offsetof(struct cstorm_def_status_block_u, func)
 +#define DEF_CSB_FUNC_OFF      offsetof(struct cstorm_def_status_block_c, func)
 +#define DEF_XSB_FUNC_OFF      offsetof(struct xstorm_def_status_block, func)
 +#define DEF_TSB_FUNC_OFF      offsetof(struct tstorm_def_status_block, func)
 +
 +#define DEF_USB_IGU_INDEX_OFF \
 +                      offsetof(struct cstorm_def_status_block_u, igu_index)
 +#define DEF_CSB_IGU_INDEX_OFF \
 +                      offsetof(struct cstorm_def_status_block_c, igu_index)
 +#define DEF_XSB_IGU_INDEX_OFF \
 +                      offsetof(struct xstorm_def_status_block, igu_index)
 +#define DEF_TSB_IGU_INDEX_OFF \
 +                      offsetof(struct tstorm_def_status_block, igu_index)
 +
 +#define DEF_USB_SEGMENT_OFF \
 +                      offsetof(struct cstorm_def_status_block_u, segment)
 +#define DEF_CSB_SEGMENT_OFF \
 +                      offsetof(struct cstorm_def_status_block_c, segment)
 +#define DEF_XSB_SEGMENT_OFF \
 +                      offsetof(struct xstorm_def_status_block, segment)
 +#define DEF_TSB_SEGMENT_OFF \
 +                      offsetof(struct tstorm_def_status_block, segment)
 +
 +#define BNX2X_SP_DSB_INDEX \
 +              (&bp->def_status_blk->sp_sb.\
 +                                      index_values[HC_SP_INDEX_ETH_DEF_CONS])
 +
 +#define SET_FLAG(value, mask, flag) \
 +      do {\
 +              (value) &= ~(mask);\
 +              (value) |= ((flag) << (mask##_SHIFT));\
 +      } while (0)
 +
 +#define GET_FLAG(value, mask) \
 +      (((value) & (mask)) >> (mask##_SHIFT))
 +
 +#define GET_FIELD(value, fname) \
 +      (((value) & (fname##_MASK)) >> (fname##_SHIFT))
 +
 +#define CAM_IS_INVALID(x) \
 +      (GET_FLAG(x.flags, \
 +      MAC_CONFIGURATION_ENTRY_ACTION_TYPE) == \
 +      (T_ETH_MAC_COMMAND_INVALIDATE))
 +
 +/* Number of u32 elements in MC hash array */
 +#define MC_HASH_SIZE                  8
 +#define MC_HASH_OFFSET(bp, i)         (BAR_TSTRORM_INTMEM + \
 +      TSTORM_APPROXIMATE_MATCH_MULTICAST_FILTERING_OFFSET(BP_FUNC(bp)) + i*4)
 +
 +
 +#ifndef PXP2_REG_PXP2_INT_STS
 +#define PXP2_REG_PXP2_INT_STS         PXP2_REG_PXP2_INT_STS_0
 +#endif
 +
 +#ifndef ETH_MAX_RX_CLIENTS_E2
 +#define ETH_MAX_RX_CLIENTS_E2         ETH_MAX_RX_CLIENTS_E1H
 +#endif
 +
 +#define BNX2X_VPD_LEN                 128
 +#define VENDOR_ID_LEN                 4
 +
 +/* Congestion management fairness mode */
 +#define CMNG_FNS_NONE         0
 +#define CMNG_FNS_MINMAX               1
 +
 +#define HC_SEG_ACCESS_DEF             0   /*Driver decision 0-3*/
 +#define HC_SEG_ACCESS_ATTN            4
 +#define HC_SEG_ACCESS_NORM            0   /*Driver decision 0-1*/
 +
 +static const u32 dmae_reg_go_c[] = {
 +      DMAE_REG_GO_C0, DMAE_REG_GO_C1, DMAE_REG_GO_C2, DMAE_REG_GO_C3,
 +      DMAE_REG_GO_C4, DMAE_REG_GO_C5, DMAE_REG_GO_C6, DMAE_REG_GO_C7,
 +      DMAE_REG_GO_C8, DMAE_REG_GO_C9, DMAE_REG_GO_C10, DMAE_REG_GO_C11,
 +      DMAE_REG_GO_C12, DMAE_REG_GO_C13, DMAE_REG_GO_C14, DMAE_REG_GO_C15
 +};
 +
 +void bnx2x_set_ethtool_ops(struct net_device *netdev);
 +void bnx2x_notify_link_changed(struct bnx2x *bp);
 +#endif /* bnx2x.h */
index 5b1f9b5,0000000..283d663
mode 100644,000000..100644
--- /dev/null
@@@ -1,1491 -1,0 +1,1491 @@@
 +/* bnx2x_cmn.h: Broadcom Everest network driver.
 + *
 + * Copyright (c) 2007-2011 Broadcom Corporation
 + *
 + * 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.
 + *
 + * Maintained by: Eilon Greenstein <eilong@broadcom.com>
 + * Written by: Eliezer Tamir
 + * Based on code from Michael Chan's bnx2 driver
 + * UDP CSUM errata workaround by Arik Gendelman
 + * Slowpath and fastpath rework by Vladislav Zolotarov
 + * Statistics and Link management by Yitchak Gertner
 + *
 + */
 +#ifndef BNX2X_CMN_H
 +#define BNX2X_CMN_H
 +
 +#include <linux/types.h>
 +#include <linux/pci.h>
 +#include <linux/netdevice.h>
 +
 +
 +#include "bnx2x.h"
 +
 +/* This is used as a replacement for an MCP if it's not present */
 +extern int load_count[2][3]; /* per-path: 0-common, 1-port0, 2-port1 */
 +
 +extern int num_queues;
 +
 +/************************ Macros ********************************/
 +#define BNX2X_PCI_FREE(x, y, size) \
 +      do { \
 +              if (x) { \
 +                      dma_free_coherent(&bp->pdev->dev, size, (void *)x, y); \
 +                      x = NULL; \
 +                      y = 0; \
 +              } \
 +      } while (0)
 +
 +#define BNX2X_FREE(x) \
 +      do { \
 +              if (x) { \
 +                      kfree((void *)x); \
 +                      x = NULL; \
 +              } \
 +      } while (0)
 +
 +#define BNX2X_PCI_ALLOC(x, y, size) \
 +      do { \
 +              x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
 +              if (x == NULL) \
 +                      goto alloc_mem_err; \
 +              memset((void *)x, 0, size); \
 +      } while (0)
 +
 +#define BNX2X_ALLOC(x, size) \
 +      do { \
 +              x = kzalloc(size, GFP_KERNEL); \
 +              if (x == NULL) \
 +                      goto alloc_mem_err; \
 +      } while (0)
 +
 +/*********************** Interfaces ****************************
 + *  Functions that need to be implemented by each driver version
 + */
 +/* Init */
 +
 +/**
 + * bnx2x_send_unload_req - request unload mode from the MCP.
 + *
 + * @bp:                       driver handle
 + * @unload_mode:      requested function's unload mode
 + *
 + * Return unload mode returned by the MCP: COMMON, PORT or FUNC.
 + */
 +u32 bnx2x_send_unload_req(struct bnx2x *bp, int unload_mode);
 +
 +/**
 + * bnx2x_send_unload_done - send UNLOAD_DONE command to the MCP.
 + *
 + * @bp:               driver handle
 + */
 +void bnx2x_send_unload_done(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_config_rss_pf - configure RSS parameters.
 + *
 + * @bp:                       driver handle
 + * @ind_table:                indirection table to configure
 + * @config_hash:      re-configure RSS hash keys configuration
 + */
 +int bnx2x_config_rss_pf(struct bnx2x *bp, u8 *ind_table, bool config_hash);
 +
 +/**
 + * bnx2x__init_func_obj - init function object
 + *
 + * @bp:                       driver handle
 + *
 + * Initializes the Function Object with the appropriate
 + * parameters which include a function slow path driver
 + * interface.
 + */
 +void bnx2x__init_func_obj(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_setup_queue - setup eth queue.
 + *
 + * @bp:               driver handle
 + * @fp:               pointer to the fastpath structure
 + * @leading:  boolean
 + *
 + */
 +int bnx2x_setup_queue(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 +                     bool leading);
 +
 +/**
 + * bnx2x_setup_leading - bring up a leading eth queue.
 + *
 + * @bp:               driver handle
 + */
 +int bnx2x_setup_leading(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_fw_command - send the MCP a request
 + *
 + * @bp:               driver handle
 + * @command:  request
 + * @param:    request's parameter
 + *
 + * block until there is a reply
 + */
 +u32 bnx2x_fw_command(struct bnx2x *bp, u32 command, u32 param);
 +
 +/**
 + * bnx2x_initial_phy_init - initialize link parameters structure variables.
 + *
 + * @bp:               driver handle
 + * @load_mode:        current mode
 + */
 +u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode);
 +
 +/**
 + * bnx2x_link_set - configure hw according to link parameters structure.
 + *
 + * @bp:               driver handle
 + */
 +void bnx2x_link_set(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_link_test - query link status.
 + *
 + * @bp:               driver handle
 + * @is_serdes:        bool
 + *
 + * Returns 0 if link is UP.
 + */
 +u8 bnx2x_link_test(struct bnx2x *bp, u8 is_serdes);
 +
 +/**
 + * bnx2x_drv_pulse - write driver pulse to shmem
 + *
 + * @bp:               driver handle
 + *
 + * writes the value in bp->fw_drv_pulse_wr_seq to drv_pulse mbox
 + * in the shmem.
 + */
 +void bnx2x_drv_pulse(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_igu_ack_sb - update IGU with current SB value
 + *
 + * @bp:               driver handle
 + * @igu_sb_id:        SB id
 + * @segment:  SB segment
 + * @index:    SB index
 + * @op:               SB operation
 + * @update:   is HW update required
 + */
 +void bnx2x_igu_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 segment,
 +                    u16 index, u8 op, u8 update);
 +
 +/* Disable transactions from chip to host */
 +void bnx2x_pf_disable(struct bnx2x *bp);
 +
 +/**
 + * bnx2x__link_status_update - handles link status change.
 + *
 + * @bp:               driver handle
 + */
 +void bnx2x__link_status_update(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_link_report - report link status to upper layer.
 + *
 + * @bp:               driver handle
 + */
 +void bnx2x_link_report(struct bnx2x *bp);
 +
 +/* None-atomic version of bnx2x_link_report() */
 +void __bnx2x_link_report(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_get_mf_speed - calculate MF speed.
 + *
 + * @bp:               driver handle
 + *
 + * Takes into account current linespeed and MF configuration.
 + */
 +u16 bnx2x_get_mf_speed(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_msix_sp_int - MSI-X slowpath interrupt handler
 + *
 + * @irq:              irq number
 + * @dev_instance:     private instance
 + */
 +irqreturn_t bnx2x_msix_sp_int(int irq, void *dev_instance);
 +
 +/**
 + * bnx2x_interrupt - non MSI-X interrupt handler
 + *
 + * @irq:              irq number
 + * @dev_instance:     private instance
 + */
 +irqreturn_t bnx2x_interrupt(int irq, void *dev_instance);
 +#ifdef BCM_CNIC
 +
 +/**
 + * bnx2x_cnic_notify - send command to cnic driver
 + *
 + * @bp:               driver handle
 + * @cmd:      command
 + */
 +int bnx2x_cnic_notify(struct bnx2x *bp, int cmd);
 +
 +/**
 + * bnx2x_setup_cnic_irq_info - provides cnic with IRQ information
 + *
 + * @bp:               driver handle
 + */
 +void bnx2x_setup_cnic_irq_info(struct bnx2x *bp);
 +#endif
 +
 +/**
 + * bnx2x_int_enable - enable HW interrupts.
 + *
 + * @bp:               driver handle
 + */
 +void bnx2x_int_enable(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_int_disable_sync - disable interrupts.
 + *
 + * @bp:               driver handle
 + * @disable_hw:       true, disable HW interrupts.
 + *
 + * This function ensures that there are no
 + * ISRs or SP DPCs (sp_task) are running after it returns.
 + */
 +void bnx2x_int_disable_sync(struct bnx2x *bp, int disable_hw);
 +
 +/**
 + * bnx2x_nic_init - init driver internals.
 + *
 + * @bp:               driver handle
 + * @load_code:        COMMON, PORT or FUNCTION
 + *
 + * Initializes:
 + *  - rings
 + *  - status blocks
 + *  - etc.
 + */
 +void bnx2x_nic_init(struct bnx2x *bp, u32 load_code);
 +
 +/**
 + * bnx2x_alloc_mem - allocate driver's memory.
 + *
 + * @bp:               driver handle
 + */
 +int bnx2x_alloc_mem(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_free_mem - release driver's memory.
 + *
 + * @bp:               driver handle
 + */
 +void bnx2x_free_mem(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_set_num_queues - set number of queues according to mode.
 + *
 + * @bp:               driver handle
 + */
 +void bnx2x_set_num_queues(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_chip_cleanup - cleanup chip internals.
 + *
 + * @bp:                       driver handle
 + * @unload_mode:      COMMON, PORT, FUNCTION
 + *
 + * - Cleanup MAC configuration.
 + * - Closes clients.
 + * - etc.
 + */
 +void bnx2x_chip_cleanup(struct bnx2x *bp, int unload_mode);
 +
 +/**
 + * bnx2x_acquire_hw_lock - acquire HW lock.
 + *
 + * @bp:               driver handle
 + * @resource: resource bit which was locked
 + */
 +int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource);
 +
 +/**
 + * bnx2x_release_hw_lock - release HW lock.
 + *
 + * @bp:               driver handle
 + * @resource: resource bit which was locked
 + */
 +int bnx2x_release_hw_lock(struct bnx2x *bp, u32 resource);
 +
 +/**
 + * bnx2x_release_leader_lock - release recovery leader lock
 + *
 + * @bp:               driver handle
 + */
 +int bnx2x_release_leader_lock(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_set_eth_mac - configure eth MAC address in the HW
 + *
 + * @bp:               driver handle
 + * @set:      set or clear
 + *
 + * Configures according to the value in netdev->dev_addr.
 + */
 +int bnx2x_set_eth_mac(struct bnx2x *bp, bool set);
 +
 +/**
 + * bnx2x_set_rx_mode - set MAC filtering configurations.
 + *
 + * @dev:      netdevice
 + *
 + * called with netif_tx_lock from dev_mcast.c
 + * If bp->state is OPEN, should be called with
 + * netif_addr_lock_bh()
 + */
 +void bnx2x_set_rx_mode(struct net_device *dev);
 +
 +/**
 + * bnx2x_set_storm_rx_mode - configure MAC filtering rules in a FW.
 + *
 + * @bp:               driver handle
 + *
 + * If bp->state is OPEN, should be called with
 + * netif_addr_lock_bh().
 + */
 +void bnx2x_set_storm_rx_mode(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_set_q_rx_mode - configures rx_mode for a single queue.
 + *
 + * @bp:                       driver handle
 + * @cl_id:            client id
 + * @rx_mode_flags:    rx mode configuration
 + * @rx_accept_flags:  rx accept configuration
 + * @tx_accept_flags:  tx accept configuration (tx switch)
 + * @ramrod_flags:     ramrod configuration
 + */
 +void bnx2x_set_q_rx_mode(struct bnx2x *bp, u8 cl_id,
 +                       unsigned long rx_mode_flags,
 +                       unsigned long rx_accept_flags,
 +                       unsigned long tx_accept_flags,
 +                       unsigned long ramrod_flags);
 +
 +/* Parity errors related */
 +void bnx2x_inc_load_cnt(struct bnx2x *bp);
 +u32 bnx2x_dec_load_cnt(struct bnx2x *bp);
 +bool bnx2x_chk_parity_attn(struct bnx2x *bp, bool *global, bool print);
 +bool bnx2x_reset_is_done(struct bnx2x *bp, int engine);
 +void bnx2x_set_reset_in_progress(struct bnx2x *bp);
 +void bnx2x_set_reset_global(struct bnx2x *bp);
 +void bnx2x_disable_close_the_gate(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_sp_event - handle ramrods completion.
 + *
 + * @fp:               fastpath handle for the event
 + * @rr_cqe:   eth_rx_cqe
 + */
 +void bnx2x_sp_event(struct bnx2x_fastpath *fp, union eth_rx_cqe *rr_cqe);
 +
 +/**
 + * bnx2x_ilt_set_info - prepare ILT configurations.
 + *
 + * @bp:               driver handle
 + */
 +void bnx2x_ilt_set_info(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_dcbx_init - initialize dcbx protocol.
 + *
 + * @bp:               driver handle
 + */
 +void bnx2x_dcbx_init(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_set_power_state - set power state to the requested value.
 + *
 + * @bp:               driver handle
 + * @state:    required state D0 or D3hot
 + *
 + * Currently only D0 and D3hot are supported.
 + */
 +int bnx2x_set_power_state(struct bnx2x *bp, pci_power_t state);
 +
 +/**
 + * bnx2x_update_max_mf_config - update MAX part of MF configuration in HW.
 + *
 + * @bp:               driver handle
 + * @value:    new value
 + */
 +void bnx2x_update_max_mf_config(struct bnx2x *bp, u32 value);
 +/* Error handling */
 +void bnx2x_panic_dump(struct bnx2x *bp);
 +
 +void bnx2x_fw_dump_lvl(struct bnx2x *bp, const char *lvl);
 +
 +/* dev_close main block */
 +int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode);
 +
 +/* dev_open main block */
 +int bnx2x_nic_load(struct bnx2x *bp, int load_mode);
 +
 +/* hard_xmit callback */
 +netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev);
 +
 +/* setup_tc callback */
 +int bnx2x_setup_tc(struct net_device *dev, u8 num_tc);
 +
 +/* select_queue callback */
 +u16 bnx2x_select_queue(struct net_device *dev, struct sk_buff *skb);
 +
 +/* reload helper */
 +int bnx2x_reload_if_running(struct net_device *dev);
 +
 +int bnx2x_change_mac_addr(struct net_device *dev, void *p);
 +
 +/* NAPI poll Rx part */
 +int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget);
 +
 +void bnx2x_update_rx_prod(struct bnx2x *bp, struct bnx2x_fastpath *fp,
 +                      u16 bd_prod, u16 rx_comp_prod, u16 rx_sge_prod);
 +
 +/* NAPI poll Tx part */
 +int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata);
 +
 +/* suspend/resume callbacks */
 +int bnx2x_suspend(struct pci_dev *pdev, pm_message_t state);
 +int bnx2x_resume(struct pci_dev *pdev);
 +
 +/* Release IRQ vectors */
 +void bnx2x_free_irq(struct bnx2x *bp);
 +
 +void bnx2x_free_fp_mem(struct bnx2x *bp);
 +int bnx2x_alloc_fp_mem(struct bnx2x *bp);
 +void bnx2x_init_rx_rings(struct bnx2x *bp);
 +void bnx2x_free_skbs(struct bnx2x *bp);
 +void bnx2x_netif_stop(struct bnx2x *bp, int disable_hw);
 +void bnx2x_netif_start(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_enable_msix - set msix configuration.
 + *
 + * @bp:               driver handle
 + *
 + * fills msix_table, requests vectors, updates num_queues
 + * according to number of available vectors.
 + */
 +int bnx2x_enable_msix(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_enable_msi - request msi mode from OS, updated internals accordingly
 + *
 + * @bp:               driver handle
 + */
 +int bnx2x_enable_msi(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_poll - NAPI callback
 + *
 + * @napi:     napi structure
 + * @budget:
 + *
 + */
 +int bnx2x_poll(struct napi_struct *napi, int budget);
 +
 +/**
 + * bnx2x_alloc_mem_bp - allocate memories outsize main driver structure
 + *
 + * @bp:               driver handle
 + */
 +int __devinit bnx2x_alloc_mem_bp(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_free_mem_bp - release memories outsize main driver structure
 + *
 + * @bp:               driver handle
 + */
 +void bnx2x_free_mem_bp(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_change_mtu - change mtu netdev callback
 + *
 + * @dev:      net device
 + * @new_mtu:  requested mtu
 + *
 + */
 +int bnx2x_change_mtu(struct net_device *dev, int new_mtu);
 +
 +#if defined(NETDEV_FCOE_WWNN) && defined(BCM_CNIC)
 +/**
 + * bnx2x_fcoe_get_wwn - return the requested WWN value for this port
 + *
 + * @dev:      net_device
 + * @wwn:      output buffer
 + * @type:     WWN type: NETDEV_FCOE_WWNN (node) or NETDEV_FCOE_WWPN (port)
 + *
 + */
 +int bnx2x_fcoe_get_wwn(struct net_device *dev, u64 *wwn, int type);
 +#endif
 +u32 bnx2x_fix_features(struct net_device *dev, u32 features);
 +int bnx2x_set_features(struct net_device *dev, u32 features);
 +
 +/**
 + * bnx2x_tx_timeout - tx timeout netdev callback
 + *
 + * @dev:      net device
 + */
 +void bnx2x_tx_timeout(struct net_device *dev);
 +
 +/*********************** Inlines **********************************/
 +/*********************** Fast path ********************************/
 +static inline void bnx2x_update_fpsb_idx(struct bnx2x_fastpath *fp)
 +{
 +      barrier(); /* status block is written to by the chip */
 +      fp->fp_hc_idx = fp->sb_running_index[SM_RX_ID];
 +}
 +
 +static inline void bnx2x_update_rx_prod_gen(struct bnx2x *bp,
 +                      struct bnx2x_fastpath *fp, u16 bd_prod,
 +                      u16 rx_comp_prod, u16 rx_sge_prod, u32 start)
 +{
 +      struct ustorm_eth_rx_producers rx_prods = {0};
 +      u32 i;
 +
 +      /* Update producers */
 +      rx_prods.bd_prod = bd_prod;
 +      rx_prods.cqe_prod = rx_comp_prod;
 +      rx_prods.sge_prod = rx_sge_prod;
 +
 +      /*
 +       * Make sure that the BD and SGE data is updated before updating the
 +       * producers since FW might read the BD/SGE right after the producer
 +       * is updated.
 +       * This is only applicable for weak-ordered memory model archs such
 +       * as IA-64. The following barrier is also mandatory since FW will
 +       * assumes BDs must have buffers.
 +       */
 +      wmb();
 +
 +      for (i = 0; i < sizeof(rx_prods)/4; i++)
 +              REG_WR(bp, start + i*4, ((u32 *)&rx_prods)[i]);
 +
 +      mmiowb(); /* keep prod updates ordered */
 +
 +      DP(NETIF_MSG_RX_STATUS,
 +         "queue[%d]:  wrote  bd_prod %u  cqe_prod %u  sge_prod %u\n",
 +         fp->index, bd_prod, rx_comp_prod, rx_sge_prod);
 +}
 +
 +static inline void bnx2x_igu_ack_sb_gen(struct bnx2x *bp, u8 igu_sb_id,
 +                                      u8 segment, u16 index, u8 op,
 +                                      u8 update, u32 igu_addr)
 +{
 +      struct igu_regular cmd_data = {0};
 +
 +      cmd_data.sb_id_and_flags =
 +                      ((index << IGU_REGULAR_SB_INDEX_SHIFT) |
 +                       (segment << IGU_REGULAR_SEGMENT_ACCESS_SHIFT) |
 +                       (update << IGU_REGULAR_BUPDATE_SHIFT) |
 +                       (op << IGU_REGULAR_ENABLE_INT_SHIFT));
 +
 +      DP(NETIF_MSG_HW, "write 0x%08x to IGU addr 0x%x\n",
 +         cmd_data.sb_id_and_flags, igu_addr);
 +      REG_WR(bp, igu_addr, cmd_data.sb_id_and_flags);
 +
 +      /* Make sure that ACK is written */
 +      mmiowb();
 +      barrier();
 +}
 +
 +static inline void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func,
 +                                        u8 idu_sb_id, bool is_Pf)
 +{
 +      u32 data, ctl, cnt = 100;
 +      u32 igu_addr_data = IGU_REG_COMMAND_REG_32LSB_DATA;
 +      u32 igu_addr_ctl = IGU_REG_COMMAND_REG_CTRL;
 +      u32 igu_addr_ack = IGU_REG_CSTORM_TYPE_0_SB_CLEANUP + (idu_sb_id/32)*4;
 +      u32 sb_bit =  1 << (idu_sb_id%32);
 +      u32 func_encode = func |
 +                      ((is_Pf == true ? 1 : 0) << IGU_FID_ENCODE_IS_PF_SHIFT);
 +      u32 addr_encode = IGU_CMD_E2_PROD_UPD_BASE + idu_sb_id;
 +
 +      /* Not supported in BC mode */
 +      if (CHIP_INT_MODE_IS_BC(bp))
 +              return;
 +
 +      data = (IGU_USE_REGISTER_cstorm_type_0_sb_cleanup
 +                      << IGU_REGULAR_CLEANUP_TYPE_SHIFT)      |
 +              IGU_REGULAR_CLEANUP_SET                         |
 +              IGU_REGULAR_BCLEANUP;
 +
 +      ctl = addr_encode << IGU_CTRL_REG_ADDRESS_SHIFT         |
 +            func_encode << IGU_CTRL_REG_FID_SHIFT             |
 +            IGU_CTRL_CMD_TYPE_WR << IGU_CTRL_REG_TYPE_SHIFT;
 +
 +      DP(NETIF_MSG_HW, "write 0x%08x to IGU(via GRC) addr 0x%x\n",
 +                       data, igu_addr_data);
 +      REG_WR(bp, igu_addr_data, data);
 +      mmiowb();
 +      barrier();
 +      DP(NETIF_MSG_HW, "write 0x%08x to IGU(via GRC) addr 0x%x\n",
 +                        ctl, igu_addr_ctl);
 +      REG_WR(bp, igu_addr_ctl, ctl);
 +      mmiowb();
 +      barrier();
 +
 +      /* wait for clean up to finish */
 +      while (!(REG_RD(bp, igu_addr_ack) & sb_bit) && --cnt)
 +              msleep(20);
 +
 +
 +      if (!(REG_RD(bp, igu_addr_ack) & sb_bit)) {
 +              DP(NETIF_MSG_HW, "Unable to finish IGU cleanup: "
 +                        "idu_sb_id %d offset %d bit %d (cnt %d)\n",
 +                        idu_sb_id, idu_sb_id/32, idu_sb_id%32, cnt);
 +      }
 +}
 +
 +static inline void bnx2x_hc_ack_sb(struct bnx2x *bp, u8 sb_id,
 +                                 u8 storm, u16 index, u8 op, u8 update)
 +{
 +      u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp)*32 +
 +                     COMMAND_REG_INT_ACK);
 +      struct igu_ack_register igu_ack;
 +
 +      igu_ack.status_block_index = index;
 +      igu_ack.sb_id_and_flags =
 +                      ((sb_id << IGU_ACK_REGISTER_STATUS_BLOCK_ID_SHIFT) |
 +                       (storm << IGU_ACK_REGISTER_STORM_ID_SHIFT) |
 +                       (update << IGU_ACK_REGISTER_UPDATE_INDEX_SHIFT) |
 +                       (op << IGU_ACK_REGISTER_INTERRUPT_MODE_SHIFT));
 +
 +      DP(BNX2X_MSG_OFF, "write 0x%08x to HC addr 0x%x\n",
 +         (*(u32 *)&igu_ack), hc_addr);
 +      REG_WR(bp, hc_addr, (*(u32 *)&igu_ack));
 +
 +      /* Make sure that ACK is written */
 +      mmiowb();
 +      barrier();
 +}
 +
 +static inline void bnx2x_ack_sb(struct bnx2x *bp, u8 igu_sb_id, u8 storm,
 +                              u16 index, u8 op, u8 update)
 +{
 +      if (bp->common.int_block == INT_BLOCK_HC)
 +              bnx2x_hc_ack_sb(bp, igu_sb_id, storm, index, op, update);
 +      else {
 +              u8 segment;
 +
 +              if (CHIP_INT_MODE_IS_BC(bp))
 +                      segment = storm;
 +              else if (igu_sb_id != bp->igu_dsb_id)
 +                      segment = IGU_SEG_ACCESS_DEF;
 +              else if (storm == ATTENTION_ID)
 +                      segment = IGU_SEG_ACCESS_ATTN;
 +              else
 +                      segment = IGU_SEG_ACCESS_DEF;
 +              bnx2x_igu_ack_sb(bp, igu_sb_id, segment, index, op, update);
 +      }
 +}
 +
 +static inline u16 bnx2x_hc_ack_int(struct bnx2x *bp)
 +{
 +      u32 hc_addr = (HC_REG_COMMAND_REG + BP_PORT(bp)*32 +
 +                     COMMAND_REG_SIMD_MASK);
 +      u32 result = REG_RD(bp, hc_addr);
 +
 +      DP(BNX2X_MSG_OFF, "read 0x%08x from HC addr 0x%x\n",
 +         result, hc_addr);
 +
 +      barrier();
 +      return result;
 +}
 +
 +static inline u16 bnx2x_igu_ack_int(struct bnx2x *bp)
 +{
 +      u32 igu_addr = (BAR_IGU_INTMEM + IGU_REG_SISR_MDPC_WMASK_LSB_UPPER*8);
 +      u32 result = REG_RD(bp, igu_addr);
 +
 +      DP(NETIF_MSG_HW, "read 0x%08x from IGU addr 0x%x\n",
 +         result, igu_addr);
 +
 +      barrier();
 +      return result;
 +}
 +
 +static inline u16 bnx2x_ack_int(struct bnx2x *bp)
 +{
 +      barrier();
 +      if (bp->common.int_block == INT_BLOCK_HC)
 +              return bnx2x_hc_ack_int(bp);
 +      else
 +              return bnx2x_igu_ack_int(bp);
 +}
 +
 +static inline int bnx2x_has_tx_work_unload(struct bnx2x_fp_txdata *txdata)
 +{
 +      /* Tell compiler that consumer and producer can change */
 +      barrier();
 +      return txdata->tx_pkt_prod != txdata->tx_pkt_cons;
 +}
 +
 +static inline u16 bnx2x_tx_avail(struct bnx2x *bp,
 +                               struct bnx2x_fp_txdata *txdata)
 +{
 +      s16 used;
 +      u16 prod;
 +      u16 cons;
 +
 +      prod = txdata->tx_bd_prod;
 +      cons = txdata->tx_bd_cons;
 +
 +      /* NUM_TX_RINGS = number of "next-page" entries
 +         It will be used as a threshold */
 +      used = SUB_S16(prod, cons) + (s16)NUM_TX_RINGS;
 +
 +#ifdef BNX2X_STOP_ON_ERROR
 +      WARN_ON(used < 0);
 +      WARN_ON(used > bp->tx_ring_size);
 +      WARN_ON((bp->tx_ring_size - used) > MAX_TX_AVAIL);
 +#endif
 +
 +      return (s16)(bp->tx_ring_size) - used;
 +}
 +
 +static inline int bnx2x_tx_queue_has_work(struct bnx2x_fp_txdata *txdata)
 +{
 +      u16 hw_cons;
 +
 +      /* Tell compiler that status block fields can change */
 +      barrier();
 +      hw_cons = le16_to_cpu(*txdata->tx_cons_sb);
 +      return hw_cons != txdata->tx_pkt_cons;
 +}
 +
 +static inline bool bnx2x_has_tx_work(struct bnx2x_fastpath *fp)
 +{
 +      u8 cos;
 +      for_each_cos_in_tx_queue(fp, cos)
 +              if (bnx2x_tx_queue_has_work(&fp->txdata[cos]))
 +                      return true;
 +      return false;
 +}
 +
 +static inline int bnx2x_has_rx_work(struct bnx2x_fastpath *fp)
 +{
 +      u16 rx_cons_sb;
 +
 +      /* Tell compiler that status block fields can change */
 +      barrier();
 +      rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb);
 +      if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT)
 +              rx_cons_sb++;
 +      return (fp->rx_comp_cons != rx_cons_sb);
 +}
 +
 +/**
 + * bnx2x_tx_disable - disables tx from stack point of view
 + *
 + * @bp:               driver handle
 + */
 +static inline void bnx2x_tx_disable(struct bnx2x *bp)
 +{
 +      netif_tx_disable(bp->dev);
 +      netif_carrier_off(bp->dev);
 +}
 +
 +static inline void bnx2x_free_rx_sge(struct bnx2x *bp,
 +                                   struct bnx2x_fastpath *fp, u16 index)
 +{
 +      struct sw_rx_page *sw_buf = &fp->rx_page_ring[index];
 +      struct page *page = sw_buf->page;
 +      struct eth_rx_sge *sge = &fp->rx_sge_ring[index];
 +
 +      /* Skip "next page" elements */
 +      if (!page)
 +              return;
 +
 +      dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(sw_buf, mapping),
 +                     SGE_PAGE_SIZE*PAGES_PER_SGE, DMA_FROM_DEVICE);
 +      __free_pages(page, PAGES_PER_SGE_SHIFT);
 +
 +      sw_buf->page = NULL;
 +      sge->addr_hi = 0;
 +      sge->addr_lo = 0;
 +}
 +
 +static inline void bnx2x_add_all_napi(struct bnx2x *bp)
 +{
 +      int i;
 +
 +      /* Add NAPI objects */
 +      for_each_rx_queue(bp, i)
 +              netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
 +                             bnx2x_poll, BNX2X_NAPI_WEIGHT);
 +}
 +
 +static inline void bnx2x_del_all_napi(struct bnx2x *bp)
 +{
 +      int i;
 +
 +      for_each_rx_queue(bp, i)
 +              netif_napi_del(&bnx2x_fp(bp, i, napi));
 +}
 +
 +static inline void bnx2x_disable_msi(struct bnx2x *bp)
 +{
 +      if (bp->flags & USING_MSIX_FLAG) {
 +              pci_disable_msix(bp->pdev);
 +              bp->flags &= ~USING_MSIX_FLAG;
 +      } else if (bp->flags & USING_MSI_FLAG) {
 +              pci_disable_msi(bp->pdev);
 +              bp->flags &= ~USING_MSI_FLAG;
 +      }
 +}
 +
 +static inline int bnx2x_calc_num_queues(struct bnx2x *bp)
 +{
 +      return  num_queues ?
 +               min_t(int, num_queues, BNX2X_MAX_QUEUES(bp)) :
 +               min_t(int, num_online_cpus(), BNX2X_MAX_QUEUES(bp));
 +}
 +
 +static inline void bnx2x_clear_sge_mask_next_elems(struct bnx2x_fastpath *fp)
 +{
 +      int i, j;
 +
 +      for (i = 1; i <= NUM_RX_SGE_PAGES; i++) {
 +              int idx = RX_SGE_CNT * i - 1;
 +
 +              for (j = 0; j < 2; j++) {
 +                      BIT_VEC64_CLEAR_BIT(fp->sge_mask, idx);
 +                      idx--;
 +              }
 +      }
 +}
 +
 +static inline void bnx2x_init_sge_ring_bit_mask(struct bnx2x_fastpath *fp)
 +{
 +      /* Set the mask to all 1-s: it's faster to compare to 0 than to 0xf-s */
 +      memset(fp->sge_mask, 0xff,
 +             (NUM_RX_SGE >> BIT_VEC64_ELEM_SHIFT)*sizeof(u64));
 +
 +      /* Clear the two last indices in the page to 1:
 +         these are the indices that correspond to the "next" element,
 +         hence will never be indicated and should be removed from
 +         the calculations. */
 +      bnx2x_clear_sge_mask_next_elems(fp);
 +}
 +
 +static inline int bnx2x_alloc_rx_sge(struct bnx2x *bp,
 +                                   struct bnx2x_fastpath *fp, u16 index)
 +{
 +      struct page *page = alloc_pages(GFP_ATOMIC, PAGES_PER_SGE_SHIFT);
 +      struct sw_rx_page *sw_buf = &fp->rx_page_ring[index];
 +      struct eth_rx_sge *sge = &fp->rx_sge_ring[index];
 +      dma_addr_t mapping;
 +
 +      if (unlikely(page == NULL))
 +              return -ENOMEM;
 +
 +      mapping = dma_map_page(&bp->pdev->dev, page, 0,
 +                             SGE_PAGE_SIZE*PAGES_PER_SGE, DMA_FROM_DEVICE);
 +      if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
 +              __free_pages(page, PAGES_PER_SGE_SHIFT);
 +              return -ENOMEM;
 +      }
 +
 +      sw_buf->page = page;
 +      dma_unmap_addr_set(sw_buf, mapping, mapping);
 +
 +      sge->addr_hi = cpu_to_le32(U64_HI(mapping));
 +      sge->addr_lo = cpu_to_le32(U64_LO(mapping));
 +
 +      return 0;
 +}
 +
 +static inline int bnx2x_alloc_rx_skb(struct bnx2x *bp,
 +                                   struct bnx2x_fastpath *fp, u16 index)
 +{
 +      struct sk_buff *skb;
 +      struct sw_rx_bd *rx_buf = &fp->rx_buf_ring[index];
 +      struct eth_rx_bd *rx_bd = &fp->rx_desc_ring[index];
 +      dma_addr_t mapping;
 +
 +      skb = netdev_alloc_skb(bp->dev, fp->rx_buf_size);
 +      if (unlikely(skb == NULL))
 +              return -ENOMEM;
 +
 +      mapping = dma_map_single(&bp->pdev->dev, skb->data, fp->rx_buf_size,
 +                               DMA_FROM_DEVICE);
 +      if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
 +              dev_kfree_skb_any(skb);
 +              return -ENOMEM;
 +      }
 +
 +      rx_buf->skb = skb;
 +      dma_unmap_addr_set(rx_buf, mapping, mapping);
 +
 +      rx_bd->addr_hi = cpu_to_le32(U64_HI(mapping));
 +      rx_bd->addr_lo = cpu_to_le32(U64_LO(mapping));
 +
 +      return 0;
 +}
 +
 +/* note that we are not allocating a new skb,
 + * we are just moving one from cons to prod
 + * we are not creating a new mapping,
 + * so there is no need to check for dma_mapping_error().
 + */
 +static inline void bnx2x_reuse_rx_skb(struct bnx2x_fastpath *fp,
 +                                    u16 cons, u16 prod)
 +{
 +      struct sw_rx_bd *cons_rx_buf = &fp->rx_buf_ring[cons];
 +      struct sw_rx_bd *prod_rx_buf = &fp->rx_buf_ring[prod];
 +      struct eth_rx_bd *cons_bd = &fp->rx_desc_ring[cons];
 +      struct eth_rx_bd *prod_bd = &fp->rx_desc_ring[prod];
 +
 +      dma_unmap_addr_set(prod_rx_buf, mapping,
 +                         dma_unmap_addr(cons_rx_buf, mapping));
 +      prod_rx_buf->skb = cons_rx_buf->skb;
 +      *prod_bd = *cons_bd;
 +}
 +
 +/************************* Init ******************************************/
 +
 +/**
 + * bnx2x_func_start - init function
 + *
 + * @bp:               driver handle
 + *
 + * Must be called before sending CLIENT_SETUP for the first client.
 + */
 +static inline int bnx2x_func_start(struct bnx2x *bp)
 +{
 +      struct bnx2x_func_state_params func_params = {0};
 +      struct bnx2x_func_start_params *start_params =
 +              &func_params.params.start;
 +
 +      /* Prepare parameters for function state transitions */
 +      __set_bit(RAMROD_COMP_WAIT, &func_params.ramrod_flags);
 +
 +      func_params.f_obj = &bp->func_obj;
 +      func_params.cmd = BNX2X_F_CMD_START;
 +
 +      /* Function parameters */
 +      start_params->mf_mode = bp->mf_mode;
 +      start_params->sd_vlan_tag = bp->mf_ov;
 +      if (CHIP_IS_E1x(bp))
 +              start_params->network_cos_mode = OVERRIDE_COS;
 +      else
 +              start_params->network_cos_mode = STATIC_COS;
 +
 +      return bnx2x_func_state_change(bp, &func_params);
 +}
 +
 +
 +/**
 + * bnx2x_set_fw_mac_addr - fill in a MAC address in FW format
 + *
 + * @fw_hi:    pointer to upper part
 + * @fw_mid:   pointer to middle part
 + * @fw_lo:    pointer to lower part
 + * @mac:      pointer to MAC address
 + */
 +static inline void bnx2x_set_fw_mac_addr(u16 *fw_hi, u16 *fw_mid, u16 *fw_lo,
 +                                       u8 *mac)
 +{
 +      ((u8 *)fw_hi)[0]  = mac[1];
 +      ((u8 *)fw_hi)[1]  = mac[0];
 +      ((u8 *)fw_mid)[0] = mac[3];
 +      ((u8 *)fw_mid)[1] = mac[2];
 +      ((u8 *)fw_lo)[0]  = mac[5];
 +      ((u8 *)fw_lo)[1]  = mac[4];
 +}
 +
 +static inline void bnx2x_free_rx_sge_range(struct bnx2x *bp,
 +                                         struct bnx2x_fastpath *fp, int last)
 +{
 +      int i;
 +
 +      if (fp->disable_tpa)
 +              return;
 +
 +      for (i = 0; i < last; i++)
 +              bnx2x_free_rx_sge(bp, fp, i);
 +}
 +
 +static inline void bnx2x_free_tpa_pool(struct bnx2x *bp,
 +                                     struct bnx2x_fastpath *fp, int last)
 +{
 +      int i;
 +
 +      for (i = 0; i < last; i++) {
 +              struct bnx2x_agg_info *tpa_info = &fp->tpa_info[i];
 +              struct sw_rx_bd *first_buf = &tpa_info->first_buf;
 +              struct sk_buff *skb = first_buf->skb;
 +
 +              if (skb == NULL) {
 +                      DP(NETIF_MSG_IFDOWN, "tpa bin %d empty on free\n", i);
 +                      continue;
 +              }
 +              if (tpa_info->tpa_state == BNX2X_TPA_START)
 +                      dma_unmap_single(&bp->pdev->dev,
 +                                       dma_unmap_addr(first_buf, mapping),
 +                                       fp->rx_buf_size, DMA_FROM_DEVICE);
 +              dev_kfree_skb(skb);
 +              first_buf->skb = NULL;
 +      }
 +}
 +
 +static inline void bnx2x_init_tx_ring_one(struct bnx2x_fp_txdata *txdata)
 +{
 +      int i;
 +
 +      for (i = 1; i <= NUM_TX_RINGS; i++) {
 +              struct eth_tx_next_bd *tx_next_bd =
 +                      &txdata->tx_desc_ring[TX_DESC_CNT * i - 1].next_bd;
 +
 +              tx_next_bd->addr_hi =
 +                      cpu_to_le32(U64_HI(txdata->tx_desc_mapping +
 +                                  BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
 +              tx_next_bd->addr_lo =
 +                      cpu_to_le32(U64_LO(txdata->tx_desc_mapping +
 +                                  BCM_PAGE_SIZE*(i % NUM_TX_RINGS)));
 +      }
 +
 +      SET_FLAG(txdata->tx_db.data.header.header, DOORBELL_HDR_DB_TYPE, 1);
 +      txdata->tx_db.data.zero_fill1 = 0;
 +      txdata->tx_db.data.prod = 0;
 +
 +      txdata->tx_pkt_prod = 0;
 +      txdata->tx_pkt_cons = 0;
 +      txdata->tx_bd_prod = 0;
 +      txdata->tx_bd_cons = 0;
 +      txdata->tx_pkt = 0;
 +}
 +
 +static inline void bnx2x_init_tx_rings(struct bnx2x *bp)
 +{
 +      int i;
 +      u8 cos;
 +
 +      for_each_tx_queue(bp, i)
 +              for_each_cos_in_tx_queue(&bp->fp[i], cos)
 +                      bnx2x_init_tx_ring_one(&bp->fp[i].txdata[cos]);
 +}
 +
 +static inline void bnx2x_set_next_page_rx_bd(struct bnx2x_fastpath *fp)
 +{
 +      int i;
 +
 +      for (i = 1; i <= NUM_RX_RINGS; i++) {
 +              struct eth_rx_bd *rx_bd;
 +
 +              rx_bd = &fp->rx_desc_ring[RX_DESC_CNT * i - 2];
 +              rx_bd->addr_hi =
 +                      cpu_to_le32(U64_HI(fp->rx_desc_mapping +
 +                                  BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
 +              rx_bd->addr_lo =
 +                      cpu_to_le32(U64_LO(fp->rx_desc_mapping +
 +                                  BCM_PAGE_SIZE*(i % NUM_RX_RINGS)));
 +      }
 +}
 +
 +static inline void bnx2x_set_next_page_sgl(struct bnx2x_fastpath *fp)
 +{
 +      int i;
 +
 +      for (i = 1; i <= NUM_RX_SGE_PAGES; i++) {
 +              struct eth_rx_sge *sge;
 +
 +              sge = &fp->rx_sge_ring[RX_SGE_CNT * i - 2];
 +              sge->addr_hi =
 +                      cpu_to_le32(U64_HI(fp->rx_sge_mapping +
 +                      BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES)));
 +
 +              sge->addr_lo =
 +                      cpu_to_le32(U64_LO(fp->rx_sge_mapping +
 +                      BCM_PAGE_SIZE*(i % NUM_RX_SGE_PAGES)));
 +      }
 +}
 +
 +static inline void bnx2x_set_next_page_rx_cq(struct bnx2x_fastpath *fp)
 +{
 +      int i;
 +      for (i = 1; i <= NUM_RCQ_RINGS; i++) {
 +              struct eth_rx_cqe_next_page *nextpg;
 +
 +              nextpg = (struct eth_rx_cqe_next_page *)
 +                      &fp->rx_comp_ring[RCQ_DESC_CNT * i - 1];
 +              nextpg->addr_hi =
 +                      cpu_to_le32(U64_HI(fp->rx_comp_mapping +
 +                                 BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
 +              nextpg->addr_lo =
 +                      cpu_to_le32(U64_LO(fp->rx_comp_mapping +
 +                                 BCM_PAGE_SIZE*(i % NUM_RCQ_RINGS)));
 +      }
 +}
 +
 +/* Returns the number of actually allocated BDs */
 +static inline int bnx2x_alloc_rx_bds(struct bnx2x_fastpath *fp,
 +                                    int rx_ring_size)
 +{
 +      struct bnx2x *bp = fp->bp;
 +      u16 ring_prod, cqe_ring_prod;
 +      int i;
 +
 +      fp->rx_comp_cons = 0;
 +      cqe_ring_prod = ring_prod = 0;
 +
 +      /* This routine is called only during fo init so
 +       * fp->eth_q_stats.rx_skb_alloc_failed = 0
 +       */
 +      for (i = 0; i < rx_ring_size; i++) {
 +              if (bnx2x_alloc_rx_skb(bp, fp, ring_prod) < 0) {
 +                      fp->eth_q_stats.rx_skb_alloc_failed++;
 +                      continue;
 +              }
 +              ring_prod = NEXT_RX_IDX(ring_prod);
 +              cqe_ring_prod = NEXT_RCQ_IDX(cqe_ring_prod);
 +              WARN_ON(ring_prod <= (i - fp->eth_q_stats.rx_skb_alloc_failed));
 +      }
 +
 +      if (fp->eth_q_stats.rx_skb_alloc_failed)
 +              BNX2X_ERR("was only able to allocate "
 +                        "%d rx skbs on queue[%d]\n",
 +                        (i - fp->eth_q_stats.rx_skb_alloc_failed), fp->index);
 +
 +      fp->rx_bd_prod = ring_prod;
 +      /* Limit the CQE producer by the CQE ring size */
 +      fp->rx_comp_prod = min_t(u16, NUM_RCQ_RINGS*RCQ_DESC_CNT,
 +                             cqe_ring_prod);
 +      fp->rx_pkt = fp->rx_calls = 0;
 +
 +      return i - fp->eth_q_stats.rx_skb_alloc_failed;
 +}
 +
 +/* Statistics ID are global per chip/path, while Client IDs for E1x are per
 + * port.
 + */
 +static inline u8 bnx2x_stats_id(struct bnx2x_fastpath *fp)
 +{
 +      if (!CHIP_IS_E1x(fp->bp))
 +              return fp->cl_id;
 +      else
 +              return fp->cl_id + BP_PORT(fp->bp) * FP_SB_MAX_E1x;
 +}
 +
 +static inline void bnx2x_init_vlan_mac_fp_objs(struct bnx2x_fastpath *fp,
 +                                             bnx2x_obj_type obj_type)
 +{
 +      struct bnx2x *bp = fp->bp;
 +
 +      /* Configure classification DBs */
 +      bnx2x_init_mac_obj(bp, &fp->mac_obj, fp->cl_id, fp->cid,
 +                         BP_FUNC(bp), bnx2x_sp(bp, mac_rdata),
 +                         bnx2x_sp_mapping(bp, mac_rdata),
 +                         BNX2X_FILTER_MAC_PENDING,
 +                         &bp->sp_state, obj_type,
 +                         &bp->macs_pool);
 +}
 +
 +/**
 + * bnx2x_get_path_func_num - get number of active functions
 + *
 + * @bp:               driver handle
 + *
 + * Calculates the number of active (not hidden) functions on the
 + * current path.
 + */
 +static inline u8 bnx2x_get_path_func_num(struct bnx2x *bp)
 +{
 +      u8 func_num = 0, i;
 +
 +      /* 57710 has only one function per-port */
 +      if (CHIP_IS_E1(bp))
 +              return 1;
 +
 +      /* Calculate a number of functions enabled on the current
 +       * PATH/PORT.
 +       */
 +      if (CHIP_REV_IS_SLOW(bp)) {
 +              if (IS_MF(bp))
 +                      func_num = 4;
 +              else
 +                      func_num = 2;
 +      } else {
 +              for (i = 0; i < E1H_FUNC_MAX / 2; i++) {
 +                      u32 func_config =
 +                              MF_CFG_RD(bp,
 +                                        func_mf_config[BP_PORT(bp) + 2 * i].
 +                                        config);
 +                      func_num +=
 +                              ((func_config & FUNC_MF_CFG_FUNC_HIDE) ? 0 : 1);
 +              }
 +      }
 +
 +      WARN_ON(!func_num);
 +
 +      return func_num;
 +}
 +
 +static inline void bnx2x_init_bp_objs(struct bnx2x *bp)
 +{
 +      /* RX_MODE controlling object */
 +      bnx2x_init_rx_mode_obj(bp, &bp->rx_mode_obj);
 +
 +      /* multicast configuration controlling object */
 +      bnx2x_init_mcast_obj(bp, &bp->mcast_obj, bp->fp->cl_id, bp->fp->cid,
 +                           BP_FUNC(bp), BP_FUNC(bp),
 +                           bnx2x_sp(bp, mcast_rdata),
 +                           bnx2x_sp_mapping(bp, mcast_rdata),
 +                           BNX2X_FILTER_MCAST_PENDING, &bp->sp_state,
 +                           BNX2X_OBJ_TYPE_RX);
 +
 +      /* Setup CAM credit pools */
 +      bnx2x_init_mac_credit_pool(bp, &bp->macs_pool, BP_FUNC(bp),
 +                                 bnx2x_get_path_func_num(bp));
 +
 +      /* RSS configuration object */
 +      bnx2x_init_rss_config_obj(bp, &bp->rss_conf_obj, bp->fp->cl_id,
 +                                bp->fp->cid, BP_FUNC(bp), BP_FUNC(bp),
 +                                bnx2x_sp(bp, rss_rdata),
 +                                bnx2x_sp_mapping(bp, rss_rdata),
 +                                BNX2X_FILTER_RSS_CONF_PENDING, &bp->sp_state,
 +                                BNX2X_OBJ_TYPE_RX);
 +}
 +
 +static inline u8 bnx2x_fp_qzone_id(struct bnx2x_fastpath *fp)
 +{
 +      if (CHIP_IS_E1x(fp->bp))
 +              return fp->cl_id + BP_PORT(fp->bp) * ETH_MAX_RX_CLIENTS_E1H;
 +      else
 +              return fp->cl_id;
 +}
 +
 +static inline u32 bnx2x_rx_ustorm_prods_offset(struct bnx2x_fastpath *fp)
 +{
 +      struct bnx2x *bp = fp->bp;
 +
 +      if (!CHIP_IS_E1x(bp))
 +              return USTORM_RX_PRODS_E2_OFFSET(fp->cl_qzone_id);
 +      else
 +              return USTORM_RX_PRODS_E1X_OFFSET(BP_PORT(bp), fp->cl_id);
 +}
 +
 +static inline void bnx2x_init_txdata(struct bnx2x *bp,
 +      struct bnx2x_fp_txdata *txdata, u32 cid, int txq_index,
 +      __le16 *tx_cons_sb)
 +{
 +      txdata->cid = cid;
 +      txdata->txq_index = txq_index;
 +      txdata->tx_cons_sb = tx_cons_sb;
 +
 +      DP(BNX2X_MSG_SP, "created tx data cid %d, txq %d\n",
 +         txdata->cid, txdata->txq_index);
 +}
 +
 +#ifdef BCM_CNIC
 +static inline u8 bnx2x_cnic_eth_cl_id(struct bnx2x *bp, u8 cl_idx)
 +{
 +      return bp->cnic_base_cl_id + cl_idx +
-               (bp->pf_num >> 1) * NON_ETH_CONTEXT_USE;
++              (bp->pf_num >> 1) * BNX2X_MAX_CNIC_ETH_CL_ID_IDX;
 +}
 +
 +static inline u8 bnx2x_cnic_fw_sb_id(struct bnx2x *bp)
 +{
 +
 +      /* the 'first' id is allocated for the cnic */
 +      return bp->base_fw_ndsb;
 +}
 +
 +static inline u8 bnx2x_cnic_igu_sb_id(struct bnx2x *bp)
 +{
 +      return bp->igu_base_sb;
 +}
 +
 +
 +static inline void bnx2x_init_fcoe_fp(struct bnx2x *bp)
 +{
 +      struct bnx2x_fastpath *fp = bnx2x_fcoe_fp(bp);
 +      unsigned long q_type = 0;
 +
 +      bnx2x_fcoe(bp, cl_id) = bnx2x_cnic_eth_cl_id(bp,
 +                                                   BNX2X_FCOE_ETH_CL_ID_IDX);
 +      /** Current BNX2X_FCOE_ETH_CID deffinition implies not more than
 +       *  16 ETH clients per function when CNIC is enabled!
 +       *
 +       *  Fix it ASAP!!!
 +       */
 +      bnx2x_fcoe(bp, cid) = BNX2X_FCOE_ETH_CID;
 +      bnx2x_fcoe(bp, fw_sb_id) = DEF_SB_ID;
 +      bnx2x_fcoe(bp, igu_sb_id) = bp->igu_dsb_id;
 +      bnx2x_fcoe(bp, rx_cons_sb) = BNX2X_FCOE_L2_RX_INDEX;
 +
 +      bnx2x_init_txdata(bp, &bnx2x_fcoe(bp, txdata[0]),
 +                        fp->cid, FCOE_TXQ_IDX(bp), BNX2X_FCOE_L2_TX_INDEX);
 +
 +      DP(BNX2X_MSG_SP, "created fcoe tx data (fp index %d)\n", fp->index);
 +
 +      /* qZone id equals to FW (per path) client id */
 +      bnx2x_fcoe(bp, cl_qzone_id) = bnx2x_fp_qzone_id(fp);
 +      /* init shortcut */
 +      bnx2x_fcoe(bp, ustorm_rx_prods_offset) =
 +              bnx2x_rx_ustorm_prods_offset(fp);
 +
 +      /* Configure Queue State object */
 +      __set_bit(BNX2X_Q_TYPE_HAS_RX, &q_type);
 +      __set_bit(BNX2X_Q_TYPE_HAS_TX, &q_type);
 +
 +      /* No multi-CoS for FCoE L2 client */
 +      BUG_ON(fp->max_cos != 1);
 +
 +      bnx2x_init_queue_obj(bp, &fp->q_obj, fp->cl_id, &fp->cid, 1,
 +                           BP_FUNC(bp), bnx2x_sp(bp, q_rdata),
 +                           bnx2x_sp_mapping(bp, q_rdata), q_type);
 +
 +      DP(NETIF_MSG_IFUP, "queue[%d]: bnx2x_init_sb(%p,%p) cl_id %d fw_sb %d "
 +                         "igu_sb %d\n",
 +         fp->index, bp, fp->status_blk.e2_sb, fp->cl_id, fp->fw_sb_id,
 +         fp->igu_sb_id);
 +}
 +#endif
 +
 +static inline int bnx2x_clean_tx_queue(struct bnx2x *bp,
 +                                     struct bnx2x_fp_txdata *txdata)
 +{
 +      int cnt = 1000;
 +
 +      while (bnx2x_has_tx_work_unload(txdata)) {
 +              if (!cnt) {
 +                      BNX2X_ERR("timeout waiting for queue[%d]: "
 +                               "txdata->tx_pkt_prod(%d) != txdata->tx_pkt_cons(%d)\n",
 +                                txdata->txq_index, txdata->tx_pkt_prod,
 +                                txdata->tx_pkt_cons);
 +#ifdef BNX2X_STOP_ON_ERROR
 +                      bnx2x_panic();
 +                      return -EBUSY;
 +#else
 +                      break;
 +#endif
 +              }
 +              cnt--;
 +              usleep_range(1000, 1000);
 +      }
 +
 +      return 0;
 +}
 +
 +int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
 +
 +static inline void __storm_memset_struct(struct bnx2x *bp,
 +                                       u32 addr, size_t size, u32 *data)
 +{
 +      int i;
 +      for (i = 0; i < size/4; i++)
 +              REG_WR(bp, addr + (i * 4), data[i]);
 +}
 +
 +static inline void storm_memset_func_cfg(struct bnx2x *bp,
 +                              struct tstorm_eth_function_common_config *tcfg,
 +                              u16 abs_fid)
 +{
 +      size_t size = sizeof(struct tstorm_eth_function_common_config);
 +
 +      u32 addr = BAR_TSTRORM_INTMEM +
 +                      TSTORM_FUNCTION_COMMON_CONFIG_OFFSET(abs_fid);
 +
 +      __storm_memset_struct(bp, addr, size, (u32 *)tcfg);
 +}
 +
 +static inline void storm_memset_cmng(struct bnx2x *bp,
 +                              struct cmng_struct_per_port *cmng,
 +                              u8 port)
 +{
 +      size_t size = sizeof(struct cmng_struct_per_port);
 +
 +      u32 addr = BAR_XSTRORM_INTMEM +
 +                      XSTORM_CMNG_PER_PORT_VARS_OFFSET(port);
 +
 +      __storm_memset_struct(bp, addr, size, (u32 *)cmng);
 +}
 +
 +/**
 + * bnx2x_wait_sp_comp - wait for the outstanding SP commands.
 + *
 + * @bp:               driver handle
 + * @mask:     bits that need to be cleared
 + */
 +static inline bool bnx2x_wait_sp_comp(struct bnx2x *bp, unsigned long mask)
 +{
 +      int tout = 5000; /* Wait for 5 secs tops */
 +
 +      while (tout--) {
 +              smp_mb();
 +              netif_addr_lock_bh(bp->dev);
 +              if (!(bp->sp_state & mask)) {
 +                      netif_addr_unlock_bh(bp->dev);
 +                      return true;
 +              }
 +              netif_addr_unlock_bh(bp->dev);
 +
 +              usleep_range(1000, 1000);
 +      }
 +
 +      smp_mb();
 +
 +      netif_addr_lock_bh(bp->dev);
 +      if (bp->sp_state & mask) {
 +              BNX2X_ERR("Filtering completion timed out. sp_state 0x%lx, "
 +                        "mask 0x%lx\n", bp->sp_state, mask);
 +              netif_addr_unlock_bh(bp->dev);
 +              return false;
 +      }
 +      netif_addr_unlock_bh(bp->dev);
 +
 +      return true;
 +}
 +
 +/**
 + * bnx2x_set_ctx_validation - set CDU context validation values
 + *
 + * @bp:               driver handle
 + * @cxt:      context of the connection on the host memory
 + * @cid:      SW CID of the connection to be configured
 + */
 +void bnx2x_set_ctx_validation(struct bnx2x *bp, struct eth_context *cxt,
 +                            u32 cid);
 +
 +void bnx2x_update_coalesce_sb_index(struct bnx2x *bp, u8 fw_sb_id,
 +                                  u8 sb_index, u8 disable, u16 usec);
 +void bnx2x_acquire_phy_lock(struct bnx2x *bp);
 +void bnx2x_release_phy_lock(struct bnx2x *bp);
 +
 +/**
 + * bnx2x_extract_max_cfg - extract MAX BW part from MF configuration.
 + *
 + * @bp:               driver handle
 + * @mf_cfg:   MF configuration
 + *
 + */
 +static inline u16 bnx2x_extract_max_cfg(struct bnx2x *bp, u32 mf_cfg)
 +{
 +      u16 max_cfg = (mf_cfg & FUNC_MF_CFG_MAX_BW_MASK) >>
 +                            FUNC_MF_CFG_MAX_BW_SHIFT;
 +      if (!max_cfg) {
 +              DP(NETIF_MSG_LINK,
 +                 "Max BW configured to 0 - using 100 instead\n");
 +              max_cfg = 100;
 +      }
 +      return max_cfg;
 +}
 +
 +#endif /* BNX2X_CMN_H */
index b89027c,0000000..b865e9f
mode 100644,000000..100644
--- /dev/null
@@@ -1,15951 -1,0 +1,15951 @@@
 +/*
 + * tg3.c: Broadcom Tigon3 ethernet driver.
 + *
 + * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
 + * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
 + * Copyright (C) 2004 Sun Microsystems Inc.
 + * Copyright (C) 2005-2011 Broadcom Corporation.
 + *
 + * Firmware is:
 + *    Derived from proprietary unpublished source code,
 + *    Copyright (C) 2000-2003 Broadcom Corporation.
 + *
 + *    Permission is hereby granted for the distribution of this firmware
 + *    data in hexadecimal or equivalent format, provided this copyright
 + *    notice is accompanying it.
 + */
 +
 +
 +#include <linux/module.h>
 +#include <linux/moduleparam.h>
 +#include <linux/stringify.h>
 +#include <linux/kernel.h>
 +#include <linux/types.h>
 +#include <linux/compiler.h>
 +#include <linux/slab.h>
 +#include <linux/delay.h>
 +#include <linux/in.h>
 +#include <linux/init.h>
 +#include <linux/interrupt.h>
 +#include <linux/ioport.h>
 +#include <linux/pci.h>
 +#include <linux/netdevice.h>
 +#include <linux/etherdevice.h>
 +#include <linux/skbuff.h>
 +#include <linux/ethtool.h>
 +#include <linux/mdio.h>
 +#include <linux/mii.h>
 +#include <linux/phy.h>
 +#include <linux/brcmphy.h>
 +#include <linux/if_vlan.h>
 +#include <linux/ip.h>
 +#include <linux/tcp.h>
 +#include <linux/workqueue.h>
 +#include <linux/prefetch.h>
 +#include <linux/dma-mapping.h>
 +#include <linux/firmware.h>
 +
 +#include <net/checksum.h>
 +#include <net/ip.h>
 +
 +#include <asm/system.h>
 +#include <linux/io.h>
 +#include <asm/byteorder.h>
 +#include <linux/uaccess.h>
 +
 +#ifdef CONFIG_SPARC
 +#include <asm/idprom.h>
 +#include <asm/prom.h>
 +#endif
 +
 +#define BAR_0 0
 +#define BAR_2 2
 +
 +#include "tg3.h"
 +
 +/* Functions & macros to verify TG3_FLAGS types */
 +
 +static inline int _tg3_flag(enum TG3_FLAGS flag, unsigned long *bits)
 +{
 +      return test_bit(flag, bits);
 +}
 +
 +static inline void _tg3_flag_set(enum TG3_FLAGS flag, unsigned long *bits)
 +{
 +      set_bit(flag, bits);
 +}
 +
 +static inline void _tg3_flag_clear(enum TG3_FLAGS flag, unsigned long *bits)
 +{
 +      clear_bit(flag, bits);
 +}
 +
 +#define tg3_flag(tp, flag)                            \
 +      _tg3_flag(TG3_FLAG_##flag, (tp)->tg3_flags)
 +#define tg3_flag_set(tp, flag)                                \
 +      _tg3_flag_set(TG3_FLAG_##flag, (tp)->tg3_flags)
 +#define tg3_flag_clear(tp, flag)                      \
 +      _tg3_flag_clear(TG3_FLAG_##flag, (tp)->tg3_flags)
 +
 +#define DRV_MODULE_NAME               "tg3"
 +#define TG3_MAJ_NUM                   3
 +#define TG3_MIN_NUM                   120
 +#define DRV_MODULE_VERSION    \
 +      __stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
 +#define DRV_MODULE_RELDATE    "August 18, 2011"
 +
 +#define RESET_KIND_SHUTDOWN   0
 +#define RESET_KIND_INIT               1
 +#define RESET_KIND_SUSPEND    2
 +
 +#define TG3_DEF_RX_MODE               0
 +#define TG3_DEF_TX_MODE               0
 +#define TG3_DEF_MSG_ENABLE      \
 +      (NETIF_MSG_DRV          | \
 +       NETIF_MSG_PROBE        | \
 +       NETIF_MSG_LINK         | \
 +       NETIF_MSG_TIMER        | \
 +       NETIF_MSG_IFDOWN       | \
 +       NETIF_MSG_IFUP         | \
 +       NETIF_MSG_RX_ERR       | \
 +       NETIF_MSG_TX_ERR)
 +
 +#define TG3_GRC_LCLCTL_PWRSW_DELAY    100
 +
 +/* length of time before we decide the hardware is borked,
 + * and dev->tx_timeout() should be called to fix the problem
 + */
 +
 +#define TG3_TX_TIMEOUT                        (5 * HZ)
 +
 +/* hardware minimum and maximum for a single frame's data payload */
 +#define TG3_MIN_MTU                   60
 +#define TG3_MAX_MTU(tp)       \
 +      (tg3_flag(tp, JUMBO_CAPABLE) ? 9000 : 1500)
 +
 +/* These numbers seem to be hard coded in the NIC firmware somehow.
 + * You can't change the ring sizes, but you can change where you place
 + * them in the NIC onboard memory.
 + */
 +#define TG3_RX_STD_RING_SIZE(tp) \
 +      (tg3_flag(tp, LRG_PROD_RING_CAP) ? \
 +       TG3_RX_STD_MAX_SIZE_5717 : TG3_RX_STD_MAX_SIZE_5700)
 +#define TG3_DEF_RX_RING_PENDING               200
 +#define TG3_RX_JMB_RING_SIZE(tp) \
 +      (tg3_flag(tp, LRG_PROD_RING_CAP) ? \
 +       TG3_RX_JMB_MAX_SIZE_5717 : TG3_RX_JMB_MAX_SIZE_5700)
 +#define TG3_DEF_RX_JUMBO_RING_PENDING 100
 +#define TG3_RSS_INDIR_TBL_SIZE                128
 +
 +/* Do not place this n-ring entries value into the tp struct itself,
 + * we really want to expose these constants to GCC so that modulo et
 + * al.  operations are done with shifts and masks instead of with
 + * hw multiply/modulo instructions.  Another solution would be to
 + * replace things like '% foo' with '& (foo - 1)'.
 + */
 +
 +#define TG3_TX_RING_SIZE              512
 +#define TG3_DEF_TX_RING_PENDING               (TG3_TX_RING_SIZE - 1)
 +
 +#define TG3_RX_STD_RING_BYTES(tp) \
 +      (sizeof(struct tg3_rx_buffer_desc) * TG3_RX_STD_RING_SIZE(tp))
 +#define TG3_RX_JMB_RING_BYTES(tp) \
 +      (sizeof(struct tg3_ext_rx_buffer_desc) * TG3_RX_JMB_RING_SIZE(tp))
 +#define TG3_RX_RCB_RING_BYTES(tp) \
 +      (sizeof(struct tg3_rx_buffer_desc) * (tp->rx_ret_ring_mask + 1))
 +#define TG3_TX_RING_BYTES     (sizeof(struct tg3_tx_buffer_desc) * \
 +                               TG3_TX_RING_SIZE)
 +#define NEXT_TX(N)            (((N) + 1) & (TG3_TX_RING_SIZE - 1))
 +
 +#define TG3_DMA_BYTE_ENAB             64
 +
 +#define TG3_RX_STD_DMA_SZ             1536
 +#define TG3_RX_JMB_DMA_SZ             9046
 +
 +#define TG3_RX_DMA_TO_MAP_SZ(x)               ((x) + TG3_DMA_BYTE_ENAB)
 +
 +#define TG3_RX_STD_MAP_SZ             TG3_RX_DMA_TO_MAP_SZ(TG3_RX_STD_DMA_SZ)
 +#define TG3_RX_JMB_MAP_SZ             TG3_RX_DMA_TO_MAP_SZ(TG3_RX_JMB_DMA_SZ)
 +
 +#define TG3_RX_STD_BUFF_RING_SIZE(tp) \
 +      (sizeof(struct ring_info) * TG3_RX_STD_RING_SIZE(tp))
 +
 +#define TG3_RX_JMB_BUFF_RING_SIZE(tp) \
 +      (sizeof(struct ring_info) * TG3_RX_JMB_RING_SIZE(tp))
 +
 +/* Due to a hardware bug, the 5701 can only DMA to memory addresses
 + * that are at least dword aligned when used in PCIX mode.  The driver
 + * works around this bug by double copying the packet.  This workaround
 + * is built into the normal double copy length check for efficiency.
 + *
 + * However, the double copy is only necessary on those architectures
 + * where unaligned memory accesses are inefficient.  For those architectures
 + * where unaligned memory accesses incur little penalty, we can reintegrate
 + * the 5701 in the normal rx path.  Doing so saves a device structure
 + * dereference by hardcoding the double copy threshold in place.
 + */
 +#define TG3_RX_COPY_THRESHOLD         256
 +#if NET_IP_ALIGN == 0 || defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
 +      #define TG3_RX_COPY_THRESH(tp)  TG3_RX_COPY_THRESHOLD
 +#else
 +      #define TG3_RX_COPY_THRESH(tp)  ((tp)->rx_copy_thresh)
 +#endif
 +
 +#if (NET_IP_ALIGN != 0)
 +#define TG3_RX_OFFSET(tp)     ((tp)->rx_offset)
 +#else
 +#define TG3_RX_OFFSET(tp)     0
 +#endif
 +
 +/* minimum number of free TX descriptors required to wake up TX process */
 +#define TG3_TX_WAKEUP_THRESH(tnapi)           ((tnapi)->tx_pending / 4)
 +#define TG3_TX_BD_DMA_MAX             4096
 +
 +#define TG3_RAW_IP_ALIGN 2
 +
 +#define TG3_FW_UPDATE_TIMEOUT_SEC     5
 +
 +#define FIRMWARE_TG3          "tigon/tg3.bin"
 +#define FIRMWARE_TG3TSO               "tigon/tg3_tso.bin"
 +#define FIRMWARE_TG3TSO5      "tigon/tg3_tso5.bin"
 +
 +static char version[] __devinitdata =
 +      DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")";
 +
 +MODULE_AUTHOR("David S. Miller (davem@redhat.com) and Jeff Garzik (jgarzik@pobox.com)");
 +MODULE_DESCRIPTION("Broadcom Tigon3 ethernet driver");
 +MODULE_LICENSE("GPL");
 +MODULE_VERSION(DRV_MODULE_VERSION);
 +MODULE_FIRMWARE(FIRMWARE_TG3);
 +MODULE_FIRMWARE(FIRMWARE_TG3TSO);
 +MODULE_FIRMWARE(FIRMWARE_TG3TSO5);
 +
 +static int tg3_debug = -1;    /* -1 == use TG3_DEF_MSG_ENABLE as value */
 +module_param(tg3_debug, int, 0);
 +MODULE_PARM_DESC(tg3_debug, "Tigon3 bitmapped debugging message enable value");
 +
 +static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = {
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5700)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5701)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702FE)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705_2)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705M_2)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702X)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703X)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5702A3)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5703A3)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5782)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5788)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5789)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5901_2)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5704S_2)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5705F)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5721)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5722)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751M)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5751F)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5752M)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753M)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5753F)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5754M)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5755M)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5756)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5786)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787M)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5787F)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5714S)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5715S)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5780S)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5781)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5906M)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5784)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5764)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5723)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_TIGON3_5761E)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761S)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5761SE)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_G)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5785_F)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57780)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57760)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57790)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57788)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5717)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5718)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57781)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57785)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57761)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57765)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57791)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1001)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1003)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC9100)},
 +      {PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_TIGON3)},
 +      {PCI_DEVICE(0x10cf, 0x11a2)}, /* Fujitsu 1000base-SX with BCM5703SKHB */
 +      {}
 +};
 +
 +MODULE_DEVICE_TABLE(pci, tg3_pci_tbl);
 +
 +static const struct {
 +      const char string[ETH_GSTRING_LEN];
 +} ethtool_stats_keys[] = {
 +      { "rx_octets" },
 +      { "rx_fragments" },
 +      { "rx_ucast_packets" },
 +      { "rx_mcast_packets" },
 +      { "rx_bcast_packets" },
 +      { "rx_fcs_errors" },
 +      { "rx_align_errors" },
 +      { "rx_xon_pause_rcvd" },
 +      { "rx_xoff_pause_rcvd" },
 +      { "rx_mac_ctrl_rcvd" },
 +      { "rx_xoff_entered" },
 +      { "rx_frame_too_long_errors" },
 +      { "rx_jabbers" },
 +      { "rx_undersize_packets" },
 +      { "rx_in_length_errors" },
 +      { "rx_out_length_errors" },
 +      { "rx_64_or_less_octet_packets" },
 +      { "rx_65_to_127_octet_packets" },
 +      { "rx_128_to_255_octet_packets" },
 +      { "rx_256_to_511_octet_packets" },
 +      { "rx_512_to_1023_octet_packets" },
 +      { "rx_1024_to_1522_octet_packets" },
 +      { "rx_1523_to_2047_octet_packets" },
 +      { "rx_2048_to_4095_octet_packets" },
 +      { "rx_4096_to_8191_octet_packets" },
 +      { "rx_8192_to_9022_octet_packets" },
 +
 +      { "tx_octets" },
 +      { "tx_collisions" },
 +
 +      { "tx_xon_sent" },
 +      { "tx_xoff_sent" },
 +      { "tx_flow_control" },
 +      { "tx_mac_errors" },
 +      { "tx_single_collisions" },
 +      { "tx_mult_collisions" },
 +      { "tx_deferred" },
 +      { "tx_excessive_collisions" },
 +      { "tx_late_collisions" },
 +      { "tx_collide_2times" },
 +      { "tx_collide_3times" },
 +      { "tx_collide_4times" },
 +      { "tx_collide_5times" },
 +      { "tx_collide_6times" },
 +      { "tx_collide_7times" },
 +      { "tx_collide_8times" },
 +      { "tx_collide_9times" },
 +      { "tx_collide_10times" },
 +      { "tx_collide_11times" },
 +      { "tx_collide_12times" },
 +      { "tx_collide_13times" },
 +      { "tx_collide_14times" },
 +      { "tx_collide_15times" },
 +      { "tx_ucast_packets" },
 +      { "tx_mcast_packets" },
 +      { "tx_bcast_packets" },
 +      { "tx_carrier_sense_errors" },
 +      { "tx_discards" },
 +      { "tx_errors" },
 +
 +      { "dma_writeq_full" },
 +      { "dma_write_prioq_full" },
 +      { "rxbds_empty" },
 +      { "rx_discards" },
 +      { "rx_errors" },
 +      { "rx_threshold_hit" },
 +
 +      { "dma_readq_full" },
 +      { "dma_read_prioq_full" },
 +      { "tx_comp_queue_full" },
 +
 +      { "ring_set_send_prod_index" },
 +      { "ring_status_update" },
 +      { "nic_irqs" },
 +      { "nic_avoided_irqs" },
 +      { "nic_tx_threshold_hit" },
 +
 +      { "mbuf_lwm_thresh_hit" },
 +};
 +
 +#define TG3_NUM_STATS ARRAY_SIZE(ethtool_stats_keys)
 +
 +
 +static const struct {
 +      const char string[ETH_GSTRING_LEN];
 +} ethtool_test_keys[] = {
 +      { "nvram test        (online) " },
 +      { "link test         (online) " },
 +      { "register test     (offline)" },
 +      { "memory test       (offline)" },
 +      { "mac loopback test (offline)" },
 +      { "phy loopback test (offline)" },
 +      { "ext loopback test (offline)" },
 +      { "interrupt test    (offline)" },
 +};
 +
 +#define TG3_NUM_TEST  ARRAY_SIZE(ethtool_test_keys)
 +
 +
 +static void tg3_write32(struct tg3 *tp, u32 off, u32 val)
 +{
 +      writel(val, tp->regs + off);
 +}
 +
 +static u32 tg3_read32(struct tg3 *tp, u32 off)
 +{
 +      return readl(tp->regs + off);
 +}
 +
 +static void tg3_ape_write32(struct tg3 *tp, u32 off, u32 val)
 +{
 +      writel(val, tp->aperegs + off);
 +}
 +
 +static u32 tg3_ape_read32(struct tg3 *tp, u32 off)
 +{
 +      return readl(tp->aperegs + off);
 +}
 +
 +static void tg3_write_indirect_reg32(struct tg3 *tp, u32 off, u32 val)
 +{
 +      unsigned long flags;
 +
 +      spin_lock_irqsave(&tp->indirect_lock, flags);
 +      pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
 +      pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
 +      spin_unlock_irqrestore(&tp->indirect_lock, flags);
 +}
 +
 +static void tg3_write_flush_reg32(struct tg3 *tp, u32 off, u32 val)
 +{
 +      writel(val, tp->regs + off);
 +      readl(tp->regs + off);
 +}
 +
 +static u32 tg3_read_indirect_reg32(struct tg3 *tp, u32 off)
 +{
 +      unsigned long flags;
 +      u32 val;
 +
 +      spin_lock_irqsave(&tp->indirect_lock, flags);
 +      pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off);
 +      pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val);
 +      spin_unlock_irqrestore(&tp->indirect_lock, flags);
 +      return val;
 +}
 +
 +static void tg3_write_indirect_mbox(struct tg3 *tp, u32 off, u32 val)
 +{
 +      unsigned long flags;
 +
 +      if (off == (MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW)) {
 +              pci_write_config_dword(tp->pdev, TG3PCI_RCV_RET_RING_CON_IDX +
 +                                     TG3_64BIT_REG_LOW, val);
 +              return;
 +      }
 +      if (off == TG3_RX_STD_PROD_IDX_REG) {
 +              pci_write_config_dword(tp->pdev, TG3PCI_STD_RING_PROD_IDX +
 +                                     TG3_64BIT_REG_LOW, val);
 +              return;
 +      }
 +
 +      spin_lock_irqsave(&tp->indirect_lock, flags);
 +      pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600);
 +      pci_write_config_dword(tp->pdev, TG3PCI_REG_DATA, val);
 +      spin_unlock_irqrestore(&tp->indirect_lock, flags);
 +
 +      /* In indirect mode when disabling interrupts, we also need
 +       * to clear the interrupt bit in the GRC local ctrl register.
 +       */
 +      if ((off == (MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW)) &&
 +          (val == 0x1)) {
 +              pci_write_config_dword(tp->pdev, TG3PCI_MISC_LOCAL_CTRL,
 +                                     tp->grc_local_ctrl|GRC_LCLCTRL_CLEARINT);
 +      }
 +}
 +
 +static u32 tg3_read_indirect_mbox(struct tg3 *tp, u32 off)
 +{
 +      unsigned long flags;
 +      u32 val;
 +
 +      spin_lock_irqsave(&tp->indirect_lock, flags);
 +      pci_write_config_dword(tp->pdev, TG3PCI_REG_BASE_ADDR, off + 0x5600);
 +      pci_read_config_dword(tp->pdev, TG3PCI_REG_DATA, &val);
 +      spin_unlock_irqrestore(&tp->indirect_lock, flags);
 +      return val;
 +}
 +
 +/* usec_wait specifies the wait time in usec when writing to certain registers
 + * where it is unsafe to read back the register without some delay.
 + * GRC_LOCAL_CTRL is one example if the GPIOs are toggled to switch power.
 + * TG3PCI_CLOCK_CTRL is another example if the clock frequencies are changed.
 + */
 +static void _tw32_flush(struct tg3 *tp, u32 off, u32 val, u32 usec_wait)
 +{
 +      if (tg3_flag(tp, PCIX_TARGET_HWBUG) || tg3_flag(tp, ICH_WORKAROUND))
 +              /* Non-posted methods */
 +              tp->write32(tp, off, val);
 +      else {
 +              /* Posted method */
 +              tg3_write32(tp, off, val);
 +              if (usec_wait)
 +                      udelay(usec_wait);
 +              tp->read32(tp, off);
 +      }
 +      /* Wait again after the read for the posted method to guarantee that
 +       * the wait time is met.
 +       */
 +      if (usec_wait)
 +              udelay(usec_wait);
 +}
 +
 +static inline void tw32_mailbox_flush(struct tg3 *tp, u32 off, u32 val)
 +{
 +      tp->write32_mbox(tp, off, val);
 +      if (!tg3_flag(tp, MBOX_WRITE_REORDER) && !tg3_flag(tp, ICH_WORKAROUND))
 +              tp->read32_mbox(tp, off);
 +}
 +
 +static void tg3_write32_tx_mbox(struct tg3 *tp, u32 off, u32 val)
 +{
 +      void __iomem *mbox = tp->regs + off;
 +      writel(val, mbox);
 +      if (tg3_flag(tp, TXD_MBOX_HWBUG))
 +              writel(val, mbox);
 +      if (tg3_flag(tp, MBOX_WRITE_REORDER))
 +              readl(mbox);
 +}
 +
 +static u32 tg3_read32_mbox_5906(struct tg3 *tp, u32 off)
 +{
 +      return readl(tp->regs + off + GRCMBOX_BASE);
 +}
 +
 +static void tg3_write32_mbox_5906(struct tg3 *tp, u32 off, u32 val)
 +{
 +      writel(val, tp->regs + off + GRCMBOX_BASE);
 +}
 +
 +#define tw32_mailbox(reg, val)                tp->write32_mbox(tp, reg, val)
 +#define tw32_mailbox_f(reg, val)      tw32_mailbox_flush(tp, (reg), (val))
 +#define tw32_rx_mbox(reg, val)                tp->write32_rx_mbox(tp, reg, val)
 +#define tw32_tx_mbox(reg, val)                tp->write32_tx_mbox(tp, reg, val)
 +#define tr32_mailbox(reg)             tp->read32_mbox(tp, reg)
 +
 +#define tw32(reg, val)                        tp->write32(tp, reg, val)
 +#define tw32_f(reg, val)              _tw32_flush(tp, (reg), (val), 0)
 +#define tw32_wait_f(reg, val, us)     _tw32_flush(tp, (reg), (val), (us))
 +#define tr32(reg)                     tp->read32(tp, reg)
 +
 +static void tg3_write_mem(struct tg3 *tp, u32 off, u32 val)
 +{
 +      unsigned long flags;
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 &&
 +          (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC))
 +              return;
 +
 +      spin_lock_irqsave(&tp->indirect_lock, flags);
 +      if (tg3_flag(tp, SRAM_USE_CONFIG)) {
 +              pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
 +              pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
 +
 +              /* Always leave this as zero. */
 +              pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
 +      } else {
 +              tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
 +              tw32_f(TG3PCI_MEM_WIN_DATA, val);
 +
 +              /* Always leave this as zero. */
 +              tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
 +      }
 +      spin_unlock_irqrestore(&tp->indirect_lock, flags);
 +}
 +
 +static void tg3_read_mem(struct tg3 *tp, u32 off, u32 *val)
 +{
 +      unsigned long flags;
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906 &&
 +          (off >= NIC_SRAM_STATS_BLK) && (off < NIC_SRAM_TX_BUFFER_DESC)) {
 +              *val = 0;
 +              return;
 +      }
 +
 +      spin_lock_irqsave(&tp->indirect_lock, flags);
 +      if (tg3_flag(tp, SRAM_USE_CONFIG)) {
 +              pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, off);
 +              pci_read_config_dword(tp->pdev, TG3PCI_MEM_WIN_DATA, val);
 +
 +              /* Always leave this as zero. */
 +              pci_write_config_dword(tp->pdev, TG3PCI_MEM_WIN_BASE_ADDR, 0);
 +      } else {
 +              tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, off);
 +              *val = tr32(TG3PCI_MEM_WIN_DATA);
 +
 +              /* Always leave this as zero. */
 +              tw32_f(TG3PCI_MEM_WIN_BASE_ADDR, 0);
 +      }
 +      spin_unlock_irqrestore(&tp->indirect_lock, flags);
 +}
 +
 +static void tg3_ape_lock_init(struct tg3 *tp)
 +{
 +      int i;
 +      u32 regbase, bit;
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
 +              regbase = TG3_APE_LOCK_GRANT;
 +      else
 +              regbase = TG3_APE_PER_LOCK_GRANT;
 +
 +      /* Make sure the driver hasn't any stale locks. */
 +      for (i = 0; i < 8; i++) {
 +              if (i == TG3_APE_LOCK_GPIO)
 +                      continue;
 +              tg3_ape_write32(tp, regbase + 4 * i, APE_LOCK_GRANT_DRIVER);
 +      }
 +
 +      /* Clear the correct bit of the GPIO lock too. */
 +      if (!tp->pci_fn)
 +              bit = APE_LOCK_GRANT_DRIVER;
 +      else
 +              bit = 1 << tp->pci_fn;
 +
 +      tg3_ape_write32(tp, regbase + 4 * TG3_APE_LOCK_GPIO, bit);
 +}
 +
 +static int tg3_ape_lock(struct tg3 *tp, int locknum)
 +{
 +      int i, off;
 +      int ret = 0;
 +      u32 status, req, gnt, bit;
 +
 +      if (!tg3_flag(tp, ENABLE_APE))
 +              return 0;
 +
 +      switch (locknum) {
 +      case TG3_APE_LOCK_GPIO:
 +              if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
 +                      return 0;
 +      case TG3_APE_LOCK_GRC:
 +      case TG3_APE_LOCK_MEM:
 +              break;
 +      default:
 +              return -EINVAL;
 +      }
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761) {
 +              req = TG3_APE_LOCK_REQ;
 +              gnt = TG3_APE_LOCK_GRANT;
 +      } else {
 +              req = TG3_APE_PER_LOCK_REQ;
 +              gnt = TG3_APE_PER_LOCK_GRANT;
 +      }
 +
 +      off = 4 * locknum;
 +
 +      if (locknum != TG3_APE_LOCK_GPIO || !tp->pci_fn)
 +              bit = APE_LOCK_REQ_DRIVER;
 +      else
 +              bit = 1 << tp->pci_fn;
 +
 +      tg3_ape_write32(tp, req + off, bit);
 +
 +      /* Wait for up to 1 millisecond to acquire lock. */
 +      for (i = 0; i < 100; i++) {
 +              status = tg3_ape_read32(tp, gnt + off);
 +              if (status == bit)
 +                      break;
 +              udelay(10);
 +      }
 +
 +      if (status != bit) {
 +              /* Revoke the lock request. */
 +              tg3_ape_write32(tp, gnt + off, bit);
 +              ret = -EBUSY;
 +      }
 +
 +      return ret;
 +}
 +
 +static void tg3_ape_unlock(struct tg3 *tp, int locknum)
 +{
 +      u32 gnt, bit;
 +
 +      if (!tg3_flag(tp, ENABLE_APE))
 +              return;
 +
 +      switch (locknum) {
 +      case TG3_APE_LOCK_GPIO:
 +              if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
 +                      return;
 +      case TG3_APE_LOCK_GRC:
 +      case TG3_APE_LOCK_MEM:
 +              break;
 +      default:
 +              return;
 +      }
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5761)
 +              gnt = TG3_APE_LOCK_GRANT;
 +      else
 +              gnt = TG3_APE_PER_LOCK_GRANT;
 +
 +      if (locknum != TG3_APE_LOCK_GPIO || !tp->pci_fn)
 +              bit = APE_LOCK_GRANT_DRIVER;
 +      else
 +              bit = 1 << tp->pci_fn;
 +
 +      tg3_ape_write32(tp, gnt + 4 * locknum, bit);
 +}
 +
 +static void tg3_ape_send_event(struct tg3 *tp, u32 event)
 +{
 +      int i;
 +      u32 apedata;
 +
 +      /* NCSI does not support APE events */
 +      if (tg3_flag(tp, APE_HAS_NCSI))
 +              return;
 +
 +      apedata = tg3_ape_read32(tp, TG3_APE_SEG_SIG);
 +      if (apedata != APE_SEG_SIG_MAGIC)
 +              return;
 +
 +      apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS);
 +      if (!(apedata & APE_FW_STATUS_READY))
 +              return;
 +
 +      /* Wait for up to 1 millisecond for APE to service previous event. */
 +      for (i = 0; i < 10; i++) {
 +              if (tg3_ape_lock(tp, TG3_APE_LOCK_MEM))
 +                      return;
 +
 +              apedata = tg3_ape_read32(tp, TG3_APE_EVENT_STATUS);
 +
 +              if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
 +                      tg3_ape_write32(tp, TG3_APE_EVENT_STATUS,
 +                                      event | APE_EVENT_STATUS_EVENT_PENDING);
 +
 +              tg3_ape_unlock(tp, TG3_APE_LOCK_MEM);
 +
 +              if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
 +                      break;
 +
 +              udelay(100);
 +      }
 +
 +      if (!(apedata & APE_EVENT_STATUS_EVENT_PENDING))
 +              tg3_ape_write32(tp, TG3_APE_EVENT, APE_EVENT_1);
 +}
 +
 +static void tg3_ape_driver_state_change(struct tg3 *tp, int kind)
 +{
 +      u32 event;
 +      u32 apedata;
 +
 +      if (!tg3_flag(tp, ENABLE_APE))
 +              return;
 +
 +      switch (kind) {
 +      case RESET_KIND_INIT:
 +              tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG,
 +                              APE_HOST_SEG_SIG_MAGIC);
 +              tg3_ape_write32(tp, TG3_APE_HOST_SEG_LEN,
 +                              APE_HOST_SEG_LEN_MAGIC);
 +              apedata = tg3_ape_read32(tp, TG3_APE_HOST_INIT_COUNT);
 +              tg3_ape_write32(tp, TG3_APE_HOST_INIT_COUNT, ++apedata);
 +              tg3_ape_write32(tp, TG3_APE_HOST_DRIVER_ID,
 +                      APE_HOST_DRIVER_ID_MAGIC(TG3_MAJ_NUM, TG3_MIN_NUM));
 +              tg3_ape_write32(tp, TG3_APE_HOST_BEHAVIOR,
 +                              APE_HOST_BEHAV_NO_PHYLOCK);
 +              tg3_ape_write32(tp, TG3_APE_HOST_DRVR_STATE,
 +                                  TG3_APE_HOST_DRVR_STATE_START);
 +
 +              event = APE_EVENT_STATUS_STATE_START;
 +              break;
 +      case RESET_KIND_SHUTDOWN:
 +              /* With the interface we are currently using,
 +               * APE does not track driver state.  Wiping
 +               * out the HOST SEGMENT SIGNATURE forces
 +               * the APE to assume OS absent status.
 +               */
 +              tg3_ape_write32(tp, TG3_APE_HOST_SEG_SIG, 0x0);
 +
 +              if (device_may_wakeup(&tp->pdev->dev) &&
 +                  tg3_flag(tp, WOL_ENABLE)) {
 +                      tg3_ape_write32(tp, TG3_APE_HOST_WOL_SPEED,
 +                                          TG3_APE_HOST_WOL_SPEED_AUTO);
 +                      apedata = TG3_APE_HOST_DRVR_STATE_WOL;
 +              } else
 +                      apedata = TG3_APE_HOST_DRVR_STATE_UNLOAD;
 +
 +              tg3_ape_write32(tp, TG3_APE_HOST_DRVR_STATE, apedata);
 +
 +              event = APE_EVENT_STATUS_STATE_UNLOAD;
 +              break;
 +      case RESET_KIND_SUSPEND:
 +              event = APE_EVENT_STATUS_STATE_SUSPEND;
 +              break;
 +      default:
 +              return;
 +      }
 +
 +      event |= APE_EVENT_STATUS_DRIVER_EVNT | APE_EVENT_STATUS_STATE_CHNGE;
 +
 +      tg3_ape_send_event(tp, event);
 +}
 +
 +static void tg3_disable_ints(struct tg3 *tp)
 +{
 +      int i;
 +
 +      tw32(TG3PCI_MISC_HOST_CTRL,
 +           (tp->misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT));
 +      for (i = 0; i < tp->irq_max; i++)
 +              tw32_mailbox_f(tp->napi[i].int_mbox, 0x00000001);
 +}
 +
 +static void tg3_enable_ints(struct tg3 *tp)
 +{
 +      int i;
 +
 +      tp->irq_sync = 0;
 +      wmb();
 +
 +      tw32(TG3PCI_MISC_HOST_CTRL,
 +           (tp->misc_host_ctrl & ~MISC_HOST_CTRL_MASK_PCI_INT));
 +
 +      tp->coal_now = tp->coalesce_mode | HOSTCC_MODE_ENABLE;
 +      for (i = 0; i < tp->irq_cnt; i++) {
 +              struct tg3_napi *tnapi = &tp->napi[i];
 +
 +              tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24);
 +              if (tg3_flag(tp, 1SHOT_MSI))
 +                      tw32_mailbox_f(tnapi->int_mbox, tnapi->last_tag << 24);
 +
 +              tp->coal_now |= tnapi->coal_now;
 +      }
 +
 +      /* Force an initial interrupt */
 +      if (!tg3_flag(tp, TAGGED_STATUS) &&
 +          (tp->napi[0].hw_status->status & SD_STATUS_UPDATED))
 +              tw32(GRC_LOCAL_CTRL, tp->grc_local_ctrl | GRC_LCLCTRL_SETINT);
 +      else
 +              tw32(HOSTCC_MODE, tp->coal_now);
 +
 +      tp->coal_now &= ~(tp->napi[0].coal_now | tp->napi[1].coal_now);
 +}
 +
 +static inline unsigned int tg3_has_work(struct tg3_napi *tnapi)
 +{
 +      struct tg3 *tp = tnapi->tp;
 +      struct tg3_hw_status *sblk = tnapi->hw_status;
 +      unsigned int work_exists = 0;
 +
 +      /* check for phy events */
 +      if (!(tg3_flag(tp, USE_LINKCHG_REG) || tg3_flag(tp, POLL_SERDES))) {
 +              if (sblk->status & SD_STATUS_LINK_CHG)
 +                      work_exists = 1;
 +      }
 +      /* check for RX/TX work to do */
 +      if (sblk->idx[0].tx_consumer != tnapi->tx_cons ||
 +          *(tnapi->rx_rcb_prod_idx) != tnapi->rx_rcb_ptr)
 +              work_exists = 1;
 +
 +      return work_exists;
 +}
 +
 +/* tg3_int_reenable
 + *  similar to tg3_enable_ints, but it accurately determines whether there
 + *  is new work pending and can return without flushing the PIO write
 + *  which reenables interrupts
 + */
 +static void tg3_int_reenable(struct tg3_napi *tnapi)
 +{
 +      struct tg3 *tp = tnapi->tp;
 +
 +      tw32_mailbox(tnapi->int_mbox, tnapi->last_tag << 24);
 +      mmiowb();
 +
 +      /* When doing tagged status, this work check is unnecessary.
 +       * The last_tag we write above tells the chip which piece of
 +       * work we've completed.
 +       */
 +      if (!tg3_flag(tp, TAGGED_STATUS) && tg3_has_work(tnapi))
 +              tw32(HOSTCC_MODE, tp->coalesce_mode |
 +                   HOSTCC_MODE_ENABLE | tnapi->coal_now);
 +}
 +
 +static void tg3_switch_clocks(struct tg3 *tp)
 +{
 +      u32 clock_ctrl;
 +      u32 orig_clock_ctrl;
 +
 +      if (tg3_flag(tp, CPMU_PRESENT) || tg3_flag(tp, 5780_CLASS))
 +              return;
 +
 +      clock_ctrl = tr32(TG3PCI_CLOCK_CTRL);
 +
 +      orig_clock_ctrl = clock_ctrl;
 +      clock_ctrl &= (CLOCK_CTRL_FORCE_CLKRUN |
 +                     CLOCK_CTRL_CLKRUN_OENABLE |
 +                     0x1f);
 +      tp->pci_clock_ctrl = clock_ctrl;
 +
 +      if (tg3_flag(tp, 5705_PLUS)) {
 +              if (orig_clock_ctrl & CLOCK_CTRL_625_CORE) {
 +                      tw32_wait_f(TG3PCI_CLOCK_CTRL,
 +                                  clock_ctrl | CLOCK_CTRL_625_CORE, 40);
 +              }
 +      } else if ((orig_clock_ctrl & CLOCK_CTRL_44MHZ_CORE) != 0) {
 +              tw32_wait_f(TG3PCI_CLOCK_CTRL,
 +                          clock_ctrl |
 +                          (CLOCK_CTRL_44MHZ_CORE | CLOCK_CTRL_ALTCLK),
 +                          40);
 +              tw32_wait_f(TG3PCI_CLOCK_CTRL,
 +                          clock_ctrl | (CLOCK_CTRL_ALTCLK),
 +                          40);
 +      }
 +      tw32_wait_f(TG3PCI_CLOCK_CTRL, clock_ctrl, 40);
 +}
 +
 +#define PHY_BUSY_LOOPS        5000
 +
 +static int tg3_readphy(struct tg3 *tp, int reg, u32 *val)
 +{
 +      u32 frame_val;
 +      unsigned int loops;
 +      int ret;
 +
 +      if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
 +              tw32_f(MAC_MI_MODE,
 +                   (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
 +              udelay(80);
 +      }
 +
 +      *val = 0x0;
 +
 +      frame_val  = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
 +                    MI_COM_PHY_ADDR_MASK);
 +      frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
 +                    MI_COM_REG_ADDR_MASK);
 +      frame_val |= (MI_COM_CMD_READ | MI_COM_START);
 +
 +      tw32_f(MAC_MI_COM, frame_val);
 +
 +      loops = PHY_BUSY_LOOPS;
 +      while (loops != 0) {
 +              udelay(10);
 +              frame_val = tr32(MAC_MI_COM);
 +
 +              if ((frame_val & MI_COM_BUSY) == 0) {
 +                      udelay(5);
 +                      frame_val = tr32(MAC_MI_COM);
 +                      break;
 +              }
 +              loops -= 1;
 +      }
 +
 +      ret = -EBUSY;
 +      if (loops != 0) {
 +              *val = frame_val & MI_COM_DATA_MASK;
 +              ret = 0;
 +      }
 +
 +      if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
 +              tw32_f(MAC_MI_MODE, tp->mi_mode);
 +              udelay(80);
 +      }
 +
 +      return ret;
 +}
 +
 +static int tg3_writephy(struct tg3 *tp, int reg, u32 val)
 +{
 +      u32 frame_val;
 +      unsigned int loops;
 +      int ret;
 +
 +      if ((tp->phy_flags & TG3_PHYFLG_IS_FET) &&
 +          (reg == MII_CTRL1000 || reg == MII_TG3_AUX_CTRL))
 +              return 0;
 +
 +      if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
 +              tw32_f(MAC_MI_MODE,
 +                   (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
 +              udelay(80);
 +      }
 +
 +      frame_val  = ((tp->phy_addr << MI_COM_PHY_ADDR_SHIFT) &
 +                    MI_COM_PHY_ADDR_MASK);
 +      frame_val |= ((reg << MI_COM_REG_ADDR_SHIFT) &
 +                    MI_COM_REG_ADDR_MASK);
 +      frame_val |= (val & MI_COM_DATA_MASK);
 +      frame_val |= (MI_COM_CMD_WRITE | MI_COM_START);
 +
 +      tw32_f(MAC_MI_COM, frame_val);
 +
 +      loops = PHY_BUSY_LOOPS;
 +      while (loops != 0) {
 +              udelay(10);
 +              frame_val = tr32(MAC_MI_COM);
 +              if ((frame_val & MI_COM_BUSY) == 0) {
 +                      udelay(5);
 +                      frame_val = tr32(MAC_MI_COM);
 +                      break;
 +              }
 +              loops -= 1;
 +      }
 +
 +      ret = -EBUSY;
 +      if (loops != 0)
 +              ret = 0;
 +
 +      if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
 +              tw32_f(MAC_MI_MODE, tp->mi_mode);
 +              udelay(80);
 +      }
 +
 +      return ret;
 +}
 +
 +static int tg3_phy_cl45_write(struct tg3 *tp, u32 devad, u32 addr, u32 val)
 +{
 +      int err;
 +
 +      err = tg3_writephy(tp, MII_TG3_MMD_CTRL, devad);
 +      if (err)
 +              goto done;
 +
 +      err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, addr);
 +      if (err)
 +              goto done;
 +
 +      err = tg3_writephy(tp, MII_TG3_MMD_CTRL,
 +                         MII_TG3_MMD_CTRL_DATA_NOINC | devad);
 +      if (err)
 +              goto done;
 +
 +      err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, val);
 +
 +done:
 +      return err;
 +}
 +
 +static int tg3_phy_cl45_read(struct tg3 *tp, u32 devad, u32 addr, u32 *val)
 +{
 +      int err;
 +
 +      err = tg3_writephy(tp, MII_TG3_MMD_CTRL, devad);
 +      if (err)
 +              goto done;
 +
 +      err = tg3_writephy(tp, MII_TG3_MMD_ADDRESS, addr);
 +      if (err)
 +              goto done;
 +
 +      err = tg3_writephy(tp, MII_TG3_MMD_CTRL,
 +                         MII_TG3_MMD_CTRL_DATA_NOINC | devad);
 +      if (err)
 +              goto done;
 +
 +      err = tg3_readphy(tp, MII_TG3_MMD_ADDRESS, val);
 +
 +done:
 +      return err;
 +}
 +
 +static int tg3_phydsp_read(struct tg3 *tp, u32 reg, u32 *val)
 +{
 +      int err;
 +
 +      err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg);
 +      if (!err)
 +              err = tg3_readphy(tp, MII_TG3_DSP_RW_PORT, val);
 +
 +      return err;
 +}
 +
 +static int tg3_phydsp_write(struct tg3 *tp, u32 reg, u32 val)
 +{
 +      int err;
 +
 +      err = tg3_writephy(tp, MII_TG3_DSP_ADDRESS, reg);
 +      if (!err)
 +              err = tg3_writephy(tp, MII_TG3_DSP_RW_PORT, val);
 +
 +      return err;
 +}
 +
 +static int tg3_phy_auxctl_read(struct tg3 *tp, int reg, u32 *val)
 +{
 +      int err;
 +
 +      err = tg3_writephy(tp, MII_TG3_AUX_CTRL,
 +                         (reg << MII_TG3_AUXCTL_MISC_RDSEL_SHIFT) |
 +                         MII_TG3_AUXCTL_SHDWSEL_MISC);
 +      if (!err)
 +              err = tg3_readphy(tp, MII_TG3_AUX_CTRL, val);
 +
 +      return err;
 +}
 +
 +static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set)
 +{
 +      if (reg == MII_TG3_AUXCTL_SHDWSEL_MISC)
 +              set |= MII_TG3_AUXCTL_MISC_WREN;
 +
 +      return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg);
 +}
 +
 +#define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \
 +      tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \
 +                           MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \
 +                           MII_TG3_AUXCTL_ACTL_TX_6DB)
 +
 +#define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \
 +      tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \
 +                           MII_TG3_AUXCTL_ACTL_TX_6DB);
 +
 +static int tg3_bmcr_reset(struct tg3 *tp)
 +{
 +      u32 phy_control;
 +      int limit, err;
 +
 +      /* OK, reset it, and poll the BMCR_RESET bit until it
 +       * clears or we time out.
 +       */
 +      phy_control = BMCR_RESET;
 +      err = tg3_writephy(tp, MII_BMCR, phy_control);
 +      if (err != 0)
 +              return -EBUSY;
 +
 +      limit = 5000;
 +      while (limit--) {
 +              err = tg3_readphy(tp, MII_BMCR, &phy_control);
 +              if (err != 0)
 +                      return -EBUSY;
 +
 +              if ((phy_control & BMCR_RESET) == 0) {
 +                      udelay(40);
 +                      break;
 +              }
 +              udelay(10);
 +      }
 +      if (limit < 0)
 +              return -EBUSY;
 +
 +      return 0;
 +}
 +
 +static int tg3_mdio_read(struct mii_bus *bp, int mii_id, int reg)
 +{
 +      struct tg3 *tp = bp->priv;
 +      u32 val;
 +
 +      spin_lock_bh(&tp->lock);
 +
 +      if (tg3_readphy(tp, reg, &val))
 +              val = -EIO;
 +
 +      spin_unlock_bh(&tp->lock);
 +
 +      return val;
 +}
 +
 +static int tg3_mdio_write(struct mii_bus *bp, int mii_id, int reg, u16 val)
 +{
 +      struct tg3 *tp = bp->priv;
 +      u32 ret = 0;
 +
 +      spin_lock_bh(&tp->lock);
 +
 +      if (tg3_writephy(tp, reg, val))
 +              ret = -EIO;
 +
 +      spin_unlock_bh(&tp->lock);
 +
 +      return ret;
 +}
 +
 +static int tg3_mdio_reset(struct mii_bus *bp)
 +{
 +      return 0;
 +}
 +
 +static void tg3_mdio_config_5785(struct tg3 *tp)
 +{
 +      u32 val;
 +      struct phy_device *phydev;
 +
 +      phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR];
 +      switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) {
 +      case PHY_ID_BCM50610:
 +      case PHY_ID_BCM50610M:
 +              val = MAC_PHYCFG2_50610_LED_MODES;
 +              break;
 +      case PHY_ID_BCMAC131:
 +              val = MAC_PHYCFG2_AC131_LED_MODES;
 +              break;
 +      case PHY_ID_RTL8211C:
 +              val = MAC_PHYCFG2_RTL8211C_LED_MODES;
 +              break;
 +      case PHY_ID_RTL8201E:
 +              val = MAC_PHYCFG2_RTL8201E_LED_MODES;
 +              break;
 +      default:
 +              return;
 +      }
 +
 +      if (phydev->interface != PHY_INTERFACE_MODE_RGMII) {
 +              tw32(MAC_PHYCFG2, val);
 +
 +              val = tr32(MAC_PHYCFG1);
 +              val &= ~(MAC_PHYCFG1_RGMII_INT |
 +                       MAC_PHYCFG1_RXCLK_TO_MASK | MAC_PHYCFG1_TXCLK_TO_MASK);
 +              val |= MAC_PHYCFG1_RXCLK_TIMEOUT | MAC_PHYCFG1_TXCLK_TIMEOUT;
 +              tw32(MAC_PHYCFG1, val);
 +
 +              return;
 +      }
 +
 +      if (!tg3_flag(tp, RGMII_INBAND_DISABLE))
 +              val |= MAC_PHYCFG2_EMODE_MASK_MASK |
 +                     MAC_PHYCFG2_FMODE_MASK_MASK |
 +                     MAC_PHYCFG2_GMODE_MASK_MASK |
 +                     MAC_PHYCFG2_ACT_MASK_MASK   |
 +                     MAC_PHYCFG2_QUAL_MASK_MASK |
 +                     MAC_PHYCFG2_INBAND_ENABLE;
 +
 +      tw32(MAC_PHYCFG2, val);
 +
 +      val = tr32(MAC_PHYCFG1);
 +      val &= ~(MAC_PHYCFG1_RXCLK_TO_MASK | MAC_PHYCFG1_TXCLK_TO_MASK |
 +               MAC_PHYCFG1_RGMII_EXT_RX_DEC | MAC_PHYCFG1_RGMII_SND_STAT_EN);
 +      if (!tg3_flag(tp, RGMII_INBAND_DISABLE)) {
 +              if (tg3_flag(tp, RGMII_EXT_IBND_RX_EN))
 +                      val |= MAC_PHYCFG1_RGMII_EXT_RX_DEC;
 +              if (tg3_flag(tp, RGMII_EXT_IBND_TX_EN))
 +                      val |= MAC_PHYCFG1_RGMII_SND_STAT_EN;
 +      }
 +      val |= MAC_PHYCFG1_RXCLK_TIMEOUT | MAC_PHYCFG1_TXCLK_TIMEOUT |
 +             MAC_PHYCFG1_RGMII_INT | MAC_PHYCFG1_TXC_DRV;
 +      tw32(MAC_PHYCFG1, val);
 +
 +      val = tr32(MAC_EXT_RGMII_MODE);
 +      val &= ~(MAC_RGMII_MODE_RX_INT_B |
 +               MAC_RGMII_MODE_RX_QUALITY |
 +               MAC_RGMII_MODE_RX_ACTIVITY |
 +               MAC_RGMII_MODE_RX_ENG_DET |
 +               MAC_RGMII_MODE_TX_ENABLE |
 +               MAC_RGMII_MODE_TX_LOWPWR |
 +               MAC_RGMII_MODE_TX_RESET);
 +      if (!tg3_flag(tp, RGMII_INBAND_DISABLE)) {
 +              if (tg3_flag(tp, RGMII_EXT_IBND_RX_EN))
 +                      val |= MAC_RGMII_MODE_RX_INT_B |
 +                             MAC_RGMII_MODE_RX_QUALITY |
 +                             MAC_RGMII_MODE_RX_ACTIVITY |
 +                             MAC_RGMII_MODE_RX_ENG_DET;
 +              if (tg3_flag(tp, RGMII_EXT_IBND_TX_EN))
 +                      val |= MAC_RGMII_MODE_TX_ENABLE |
 +                             MAC_RGMII_MODE_TX_LOWPWR |
 +                             MAC_RGMII_MODE_TX_RESET;
 +      }
 +      tw32(MAC_EXT_RGMII_MODE, val);
 +}
 +
 +static void tg3_mdio_start(struct tg3 *tp)
 +{
 +      tp->mi_mode &= ~MAC_MI_MODE_AUTO_POLL;
 +      tw32_f(MAC_MI_MODE, tp->mi_mode);
 +      udelay(80);
 +
 +      if (tg3_flag(tp, MDIOBUS_INITED) &&
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
 +              tg3_mdio_config_5785(tp);
 +}
 +
 +static int tg3_mdio_init(struct tg3 *tp)
 +{
 +      int i;
 +      u32 reg;
 +      struct phy_device *phydev;
 +
 +      if (tg3_flag(tp, 5717_PLUS)) {
 +              u32 is_serdes;
 +
 +              tp->phy_addr = tp->pci_fn + 1;
 +
 +              if (tp->pci_chip_rev_id != CHIPREV_ID_5717_A0)
 +                      is_serdes = tr32(SG_DIG_STATUS) & SG_DIG_IS_SERDES;
 +              else
 +                      is_serdes = tr32(TG3_CPMU_PHY_STRAP) &
 +                                  TG3_CPMU_PHY_STRAP_IS_SERDES;
 +              if (is_serdes)
 +                      tp->phy_addr += 7;
 +      } else
 +              tp->phy_addr = TG3_PHY_MII_ADDR;
 +
 +      tg3_mdio_start(tp);
 +
 +      if (!tg3_flag(tp, USE_PHYLIB) || tg3_flag(tp, MDIOBUS_INITED))
 +              return 0;
 +
 +      tp->mdio_bus = mdiobus_alloc();
 +      if (tp->mdio_bus == NULL)
 +              return -ENOMEM;
 +
 +      tp->mdio_bus->name     = "tg3 mdio bus";
 +      snprintf(tp->mdio_bus->id, MII_BUS_ID_SIZE, "%x",
 +               (tp->pdev->bus->number << 8) | tp->pdev->devfn);
 +      tp->mdio_bus->priv     = tp;
 +      tp->mdio_bus->parent   = &tp->pdev->dev;
 +      tp->mdio_bus->read     = &tg3_mdio_read;
 +      tp->mdio_bus->write    = &tg3_mdio_write;
 +      tp->mdio_bus->reset    = &tg3_mdio_reset;
 +      tp->mdio_bus->phy_mask = ~(1 << TG3_PHY_MII_ADDR);
 +      tp->mdio_bus->irq      = &tp->mdio_irq[0];
 +
 +      for (i = 0; i < PHY_MAX_ADDR; i++)
 +              tp->mdio_bus->irq[i] = PHY_POLL;
 +
 +      /* The bus registration will look for all the PHYs on the mdio bus.
 +       * Unfortunately, it does not ensure the PHY is powered up before
 +       * accessing the PHY ID registers.  A chip reset is the
 +       * quickest way to bring the device back to an operational state..
 +       */
 +      if (tg3_readphy(tp, MII_BMCR, &reg) || (reg & BMCR_PDOWN))
 +              tg3_bmcr_reset(tp);
 +
 +      i = mdiobus_register(tp->mdio_bus);
 +      if (i) {
 +              dev_warn(&tp->pdev->dev, "mdiobus_reg failed (0x%x)\n", i);
 +              mdiobus_free(tp->mdio_bus);
 +              return i;
 +      }
 +
 +      phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR];
 +
 +      if (!phydev || !phydev->drv) {
 +              dev_warn(&tp->pdev->dev, "No PHY devices\n");
 +              mdiobus_unregister(tp->mdio_bus);
 +              mdiobus_free(tp->mdio_bus);
 +              return -ENODEV;
 +      }
 +
 +      switch (phydev->drv->phy_id & phydev->drv->phy_id_mask) {
 +      case PHY_ID_BCM57780:
 +              phydev->interface = PHY_INTERFACE_MODE_GMII;
 +              phydev->dev_flags |= PHY_BRCM_AUTO_PWRDWN_ENABLE;
 +              break;
 +      case PHY_ID_BCM50610:
 +      case PHY_ID_BCM50610M:
 +              phydev->dev_flags |= PHY_BRCM_CLEAR_RGMII_MODE |
 +                                   PHY_BRCM_RX_REFCLK_UNUSED |
 +                                   PHY_BRCM_DIS_TXCRXC_NOENRGY |
 +                                   PHY_BRCM_AUTO_PWRDWN_ENABLE;
 +              if (tg3_flag(tp, RGMII_INBAND_DISABLE))
 +                      phydev->dev_flags |= PHY_BRCM_STD_IBND_DISABLE;
 +              if (tg3_flag(tp, RGMII_EXT_IBND_RX_EN))
 +                      phydev->dev_flags |= PHY_BRCM_EXT_IBND_RX_ENABLE;
 +              if (tg3_flag(tp, RGMII_EXT_IBND_TX_EN))
 +                      phydev->dev_flags |= PHY_BRCM_EXT_IBND_TX_ENABLE;
 +              /* fallthru */
 +      case PHY_ID_RTL8211C:
 +              phydev->interface = PHY_INTERFACE_MODE_RGMII;
 +              break;
 +      case PHY_ID_RTL8201E:
 +      case PHY_ID_BCMAC131:
 +              phydev->interface = PHY_INTERFACE_MODE_MII;
 +              phydev->dev_flags |= PHY_BRCM_AUTO_PWRDWN_ENABLE;
 +              tp->phy_flags |= TG3_PHYFLG_IS_FET;
 +              break;
 +      }
 +
 +      tg3_flag_set(tp, MDIOBUS_INITED);
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785)
 +              tg3_mdio_config_5785(tp);
 +
 +      return 0;
 +}
 +
 +static void tg3_mdio_fini(struct tg3 *tp)
 +{
 +      if (tg3_flag(tp, MDIOBUS_INITED)) {
 +              tg3_flag_clear(tp, MDIOBUS_INITED);
 +              mdiobus_unregister(tp->mdio_bus);
 +              mdiobus_free(tp->mdio_bus);
 +      }
 +}
 +
 +/* tp->lock is held. */
 +static inline void tg3_generate_fw_event(struct tg3 *tp)
 +{
 +      u32 val;
 +
 +      val = tr32(GRC_RX_CPU_EVENT);
 +      val |= GRC_RX_CPU_DRIVER_EVENT;
 +      tw32_f(GRC_RX_CPU_EVENT, val);
 +
 +      tp->last_event_jiffies = jiffies;
 +}
 +
 +#define TG3_FW_EVENT_TIMEOUT_USEC 2500
 +
 +/* tp->lock is held. */
 +static void tg3_wait_for_event_ack(struct tg3 *tp)
 +{
 +      int i;
 +      unsigned int delay_cnt;
 +      long time_remain;
 +
 +      /* If enough time has passed, no wait is necessary. */
 +      time_remain = (long)(tp->last_event_jiffies + 1 +
 +                    usecs_to_jiffies(TG3_FW_EVENT_TIMEOUT_USEC)) -
 +                    (long)jiffies;
 +      if (time_remain < 0)
 +              return;
 +
 +      /* Check if we can shorten the wait time. */
 +      delay_cnt = jiffies_to_usecs(time_remain);
 +      if (delay_cnt > TG3_FW_EVENT_TIMEOUT_USEC)
 +              delay_cnt = TG3_FW_EVENT_TIMEOUT_USEC;
 +      delay_cnt = (delay_cnt >> 3) + 1;
 +
 +      for (i = 0; i < delay_cnt; i++) {
 +              if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT))
 +                      break;
 +              udelay(8);
 +      }
 +}
 +
 +/* tp->lock is held. */
 +static void tg3_ump_link_report(struct tg3 *tp)
 +{
 +      u32 reg;
 +      u32 val;
 +
 +      if (!tg3_flag(tp, 5780_CLASS) || !tg3_flag(tp, ENABLE_ASF))
 +              return;
 +
 +      tg3_wait_for_event_ack(tp);
 +
 +      tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_LINK_UPDATE);
 +
 +      tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 14);
 +
 +      val = 0;
 +      if (!tg3_readphy(tp, MII_BMCR, &reg))
 +              val = reg << 16;
 +      if (!tg3_readphy(tp, MII_BMSR, &reg))
 +              val |= (reg & 0xffff);
 +      tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, val);
 +
 +      val = 0;
 +      if (!tg3_readphy(tp, MII_ADVERTISE, &reg))
 +              val = reg << 16;
 +      if (!tg3_readphy(tp, MII_LPA, &reg))
 +              val |= (reg & 0xffff);
 +      tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 4, val);
 +
 +      val = 0;
 +      if (!(tp->phy_flags & TG3_PHYFLG_MII_SERDES)) {
 +              if (!tg3_readphy(tp, MII_CTRL1000, &reg))
 +                      val = reg << 16;
 +              if (!tg3_readphy(tp, MII_STAT1000, &reg))
 +                      val |= (reg & 0xffff);
 +      }
 +      tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 8, val);
 +
 +      if (!tg3_readphy(tp, MII_PHYADDR, &reg))
 +              val = reg << 16;
 +      else
 +              val = 0;
 +      tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val);
 +
 +      tg3_generate_fw_event(tp);
 +}
 +
 +/* tp->lock is held. */
 +static void tg3_stop_fw(struct tg3 *tp)
 +{
 +      if (tg3_flag(tp, ENABLE_ASF) && !tg3_flag(tp, ENABLE_APE)) {
 +              /* Wait for RX cpu to ACK the previous event. */
 +              tg3_wait_for_event_ack(tp);
 +
 +              tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW);
 +
 +              tg3_generate_fw_event(tp);
 +
 +              /* Wait for RX cpu to ACK this event. */
 +              tg3_wait_for_event_ack(tp);
 +      }
 +}
 +
 +/* tp->lock is held. */
 +static void tg3_write_sig_pre_reset(struct tg3 *tp, int kind)
 +{
 +      tg3_write_mem(tp, NIC_SRAM_FIRMWARE_MBOX,
 +                    NIC_SRAM_FIRMWARE_MBOX_MAGIC1);
 +
 +      if (tg3_flag(tp, ASF_NEW_HANDSHAKE)) {
 +              switch (kind) {
 +              case RESET_KIND_INIT:
 +                      tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
 +                                    DRV_STATE_START);
 +                      break;
 +
 +              case RESET_KIND_SHUTDOWN:
 +                      tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
 +                                    DRV_STATE_UNLOAD);
 +                      break;
 +
 +              case RESET_KIND_SUSPEND:
 +                      tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
 +                                    DRV_STATE_SUSPEND);
 +                      break;
 +
 +              default:
 +                      break;
 +              }
 +      }
 +
 +      if (kind == RESET_KIND_INIT ||
 +          kind == RESET_KIND_SUSPEND)
 +              tg3_ape_driver_state_change(tp, kind);
 +}
 +
 +/* tp->lock is held. */
 +static void tg3_write_sig_post_reset(struct tg3 *tp, int kind)
 +{
 +      if (tg3_flag(tp, ASF_NEW_HANDSHAKE)) {
 +              switch (kind) {
 +              case RESET_KIND_INIT:
 +                      tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
 +                                    DRV_STATE_START_DONE);
 +                      break;
 +
 +              case RESET_KIND_SHUTDOWN:
 +                      tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
 +                                    DRV_STATE_UNLOAD_DONE);
 +                      break;
 +
 +              default:
 +                      break;
 +              }
 +      }
 +
 +      if (kind == RESET_KIND_SHUTDOWN)
 +              tg3_ape_driver_state_change(tp, kind);
 +}
 +
 +/* tp->lock is held. */
 +static void tg3_write_sig_legacy(struct tg3 *tp, int kind)
 +{
 +      if (tg3_flag(tp, ENABLE_ASF)) {
 +              switch (kind) {
 +              case RESET_KIND_INIT:
 +                      tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
 +                                    DRV_STATE_START);
 +                      break;
 +
 +              case RESET_KIND_SHUTDOWN:
 +                      tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
 +                                    DRV_STATE_UNLOAD);
 +                      break;
 +
 +              case RESET_KIND_SUSPEND:
 +                      tg3_write_mem(tp, NIC_SRAM_FW_DRV_STATE_MBOX,
 +                                    DRV_STATE_SUSPEND);
 +                      break;
 +
 +              default:
 +                      break;
 +              }
 +      }
 +}
 +
 +static int tg3_poll_fw(struct tg3 *tp)
 +{
 +      int i;
 +      u32 val;
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 +              /* Wait up to 20ms for init done. */
 +              for (i = 0; i < 200; i++) {
 +                      if (tr32(VCPU_STATUS) & VCPU_STATUS_INIT_DONE)
 +                              return 0;
 +                      udelay(100);
 +              }
 +              return -ENODEV;
 +      }
 +
 +      /* Wait for firmware initialization to complete. */
 +      for (i = 0; i < 100000; i++) {
 +              tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
 +              if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
 +                      break;
 +              udelay(10);
 +      }
 +
 +      /* Chip might not be fitted with firmware.  Some Sun onboard
 +       * parts are configured like that.  So don't signal the timeout
 +       * of the above loop as an error, but do report the lack of
 +       * running firmware once.
 +       */
 +      if (i >= 100000 && !tg3_flag(tp, NO_FWARE_REPORTED)) {
 +              tg3_flag_set(tp, NO_FWARE_REPORTED);
 +
 +              netdev_info(tp->dev, "No firmware running\n");
 +      }
 +
 +      if (tp->pci_chip_rev_id == CHIPREV_ID_57765_A0) {
 +              /* The 57765 A0 needs a little more
 +               * time to do some important work.
 +               */
 +              mdelay(10);
 +      }
 +
 +      return 0;
 +}
 +
 +static void tg3_link_report(struct tg3 *tp)
 +{
 +      if (!netif_carrier_ok(tp->dev)) {
 +              netif_info(tp, link, tp->dev, "Link is down\n");
 +              tg3_ump_link_report(tp);
 +      } else if (netif_msg_link(tp)) {
 +              netdev_info(tp->dev, "Link is up at %d Mbps, %s duplex\n",
 +                          (tp->link_config.active_speed == SPEED_1000 ?
 +                           1000 :
 +                           (tp->link_config.active_speed == SPEED_100 ?
 +                            100 : 10)),
 +                          (tp->link_config.active_duplex == DUPLEX_FULL ?
 +                           "full" : "half"));
 +
 +              netdev_info(tp->dev, "Flow control is %s for TX and %s for RX\n",
 +                          (tp->link_config.active_flowctrl & FLOW_CTRL_TX) ?
 +                          "on" : "off",
 +                          (tp->link_config.active_flowctrl & FLOW_CTRL_RX) ?
 +                          "on" : "off");
 +
 +              if (tp->phy_flags & TG3_PHYFLG_EEE_CAP)
 +                      netdev_info(tp->dev, "EEE is %s\n",
 +                                  tp->setlpicnt ? "enabled" : "disabled");
 +
 +              tg3_ump_link_report(tp);
 +      }
 +}
 +
 +static u16 tg3_advert_flowctrl_1000T(u8 flow_ctrl)
 +{
 +      u16 miireg;
 +
 +      if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX))
 +              miireg = ADVERTISE_PAUSE_CAP;
 +      else if (flow_ctrl & FLOW_CTRL_TX)
 +              miireg = ADVERTISE_PAUSE_ASYM;
 +      else if (flow_ctrl & FLOW_CTRL_RX)
 +              miireg = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
 +      else
 +              miireg = 0;
 +
 +      return miireg;
 +}
 +
 +static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl)
 +{
 +      u16 miireg;
 +
 +      if ((flow_ctrl & FLOW_CTRL_TX) && (flow_ctrl & FLOW_CTRL_RX))
 +              miireg = ADVERTISE_1000XPAUSE;
 +      else if (flow_ctrl & FLOW_CTRL_TX)
 +              miireg = ADVERTISE_1000XPSE_ASYM;
 +      else if (flow_ctrl & FLOW_CTRL_RX)
 +              miireg = ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM;
 +      else
 +              miireg = 0;
 +
 +      return miireg;
 +}
 +
 +static u8 tg3_resolve_flowctrl_1000X(u16 lcladv, u16 rmtadv)
 +{
 +      u8 cap = 0;
 +
 +      if (lcladv & ADVERTISE_1000XPAUSE) {
 +              if (lcladv & ADVERTISE_1000XPSE_ASYM) {
 +                      if (rmtadv & LPA_1000XPAUSE)
 +                              cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
 +                      else if (rmtadv & LPA_1000XPAUSE_ASYM)
 +                              cap = FLOW_CTRL_RX;
 +              } else {
 +                      if (rmtadv & LPA_1000XPAUSE)
 +                              cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
 +              }
 +      } else if (lcladv & ADVERTISE_1000XPSE_ASYM) {
 +              if ((rmtadv & LPA_1000XPAUSE) && (rmtadv & LPA_1000XPAUSE_ASYM))
 +                      cap = FLOW_CTRL_TX;
 +      }
 +
 +      return cap;
 +}
 +
 +static void tg3_setup_flow_control(struct tg3 *tp, u32 lcladv, u32 rmtadv)
 +{
 +      u8 autoneg;
 +      u8 flowctrl = 0;
 +      u32 old_rx_mode = tp->rx_mode;
 +      u32 old_tx_mode = tp->tx_mode;
 +
 +      if (tg3_flag(tp, USE_PHYLIB))
 +              autoneg = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]->autoneg;
 +      else
 +              autoneg = tp->link_config.autoneg;
 +
 +      if (autoneg == AUTONEG_ENABLE && tg3_flag(tp, PAUSE_AUTONEG)) {
 +              if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES)
 +                      flowctrl = tg3_resolve_flowctrl_1000X(lcladv, rmtadv);
 +              else
 +                      flowctrl = mii_resolve_flowctrl_fdx(lcladv, rmtadv);
 +      } else
 +              flowctrl = tp->link_config.flowctrl;
 +
 +      tp->link_config.active_flowctrl = flowctrl;
 +
 +      if (flowctrl & FLOW_CTRL_RX)
 +              tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
 +      else
 +              tp->rx_mode &= ~RX_MODE_FLOW_CTRL_ENABLE;
 +
 +      if (old_rx_mode != tp->rx_mode)
 +              tw32_f(MAC_RX_MODE, tp->rx_mode);
 +
 +      if (flowctrl & FLOW_CTRL_TX)
 +              tp->tx_mode |= TX_MODE_FLOW_CTRL_ENABLE;
 +      else
 +              tp->tx_mode &= ~TX_MODE_FLOW_CTRL_ENABLE;
 +
 +      if (old_tx_mode != tp->tx_mode)
 +              tw32_f(MAC_TX_MODE, tp->tx_mode);
 +}
 +
 +static void tg3_adjust_link(struct net_device *dev)
 +{
 +      u8 oldflowctrl, linkmesg = 0;
 +      u32 mac_mode, lcl_adv, rmt_adv;
 +      struct tg3 *tp = netdev_priv(dev);
 +      struct phy_device *phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR];
 +
 +      spin_lock_bh(&tp->lock);
 +
 +      mac_mode = tp->mac_mode & ~(MAC_MODE_PORT_MODE_MASK |
 +                                  MAC_MODE_HALF_DUPLEX);
 +
 +      oldflowctrl = tp->link_config.active_flowctrl;
 +
 +      if (phydev->link) {
 +              lcl_adv = 0;
 +              rmt_adv = 0;
 +
 +              if (phydev->speed == SPEED_100 || phydev->speed == SPEED_10)
 +                      mac_mode |= MAC_MODE_PORT_MODE_MII;
 +              else if (phydev->speed == SPEED_1000 ||
 +                       GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5785)
 +                      mac_mode |= MAC_MODE_PORT_MODE_GMII;
 +              else
 +                      mac_mode |= MAC_MODE_PORT_MODE_MII;
 +
 +              if (phydev->duplex == DUPLEX_HALF)
 +                      mac_mode |= MAC_MODE_HALF_DUPLEX;
 +              else {
 +                      lcl_adv = tg3_advert_flowctrl_1000T(
 +                                tp->link_config.flowctrl);
 +
 +                      if (phydev->pause)
 +                              rmt_adv = LPA_PAUSE_CAP;
 +                      if (phydev->asym_pause)
 +                              rmt_adv |= LPA_PAUSE_ASYM;
 +              }
 +
 +              tg3_setup_flow_control(tp, lcl_adv, rmt_adv);
 +      } else
 +              mac_mode |= MAC_MODE_PORT_MODE_GMII;
 +
 +      if (mac_mode != tp->mac_mode) {
 +              tp->mac_mode = mac_mode;
 +              tw32_f(MAC_MODE, tp->mac_mode);
 +              udelay(40);
 +      }
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5785) {
 +              if (phydev->speed == SPEED_10)
 +                      tw32(MAC_MI_STAT,
 +                           MAC_MI_STAT_10MBPS_MODE |
 +                           MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
 +              else
 +                      tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB);
 +      }
 +
 +      if (phydev->speed == SPEED_1000 && phydev->duplex == DUPLEX_HALF)
 +              tw32(MAC_TX_LENGTHS,
 +                   ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
 +                    (6 << TX_LENGTHS_IPG_SHIFT) |
 +                    (0xff << TX_LENGTHS_SLOT_TIME_SHIFT)));
 +      else
 +              tw32(MAC_TX_LENGTHS,
 +                   ((2 << TX_LENGTHS_IPG_CRS_SHIFT) |
 +                    (6 << TX_LENGTHS_IPG_SHIFT) |
 +                    (32 << TX_LENGTHS_SLOT_TIME_SHIFT)));
 +
 +      if ((phydev->link && tp->link_config.active_speed == SPEED_INVALID) ||
 +          (!phydev->link && tp->link_config.active_speed != SPEED_INVALID) ||
 +          phydev->speed != tp->link_config.active_speed ||
 +          phydev->duplex != tp->link_config.active_duplex ||
 +          oldflowctrl != tp->link_config.active_flowctrl)
 +              linkmesg = 1;
 +
 +      tp->link_config.active_speed = phydev->speed;
 +      tp->link_config.active_duplex = phydev->duplex;
 +
 +      spin_unlock_bh(&tp->lock);
 +
 +      if (linkmesg)
 +              tg3_link_report(tp);
 +}
 +
 +static int tg3_phy_init(struct tg3 *tp)
 +{
 +      struct phy_device *phydev;
 +
 +      if (tp->phy_flags & TG3_PHYFLG_IS_CONNECTED)
 +              return 0;
 +
 +      /* Bring the PHY back to a known state. */
 +      tg3_bmcr_reset(tp);
 +
 +      phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR];
 +
 +      /* Attach the MAC to the PHY. */
 +      phydev = phy_connect(tp->dev, dev_name(&phydev->dev), tg3_adjust_link,
 +                           phydev->dev_flags, phydev->interface);
 +      if (IS_ERR(phydev)) {
 +              dev_err(&tp->pdev->dev, "Could not attach to PHY\n");
 +              return PTR_ERR(phydev);
 +      }
 +
 +      /* Mask with MAC supported features. */
 +      switch (phydev->interface) {
 +      case PHY_INTERFACE_MODE_GMII:
 +      case PHY_INTERFACE_MODE_RGMII:
 +              if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
 +                      phydev->supported &= (PHY_GBIT_FEATURES |
 +                                            SUPPORTED_Pause |
 +                                            SUPPORTED_Asym_Pause);
 +                      break;
 +              }
 +              /* fallthru */
 +      case PHY_INTERFACE_MODE_MII:
 +              phydev->supported &= (PHY_BASIC_FEATURES |
 +                                    SUPPORTED_Pause |
 +                                    SUPPORTED_Asym_Pause);
 +              break;
 +      default:
 +              phy_disconnect(tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]);
 +              return -EINVAL;
 +      }
 +
 +      tp->phy_flags |= TG3_PHYFLG_IS_CONNECTED;
 +
 +      phydev->advertising = phydev->supported;
 +
 +      return 0;
 +}
 +
 +static void tg3_phy_start(struct tg3 *tp)
 +{
 +      struct phy_device *phydev;
 +
 +      if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED))
 +              return;
 +
 +      phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR];
 +
 +      if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
 +              tp->phy_flags &= ~TG3_PHYFLG_IS_LOW_POWER;
 +              phydev->speed = tp->link_config.orig_speed;
 +              phydev->duplex = tp->link_config.orig_duplex;
 +              phydev->autoneg = tp->link_config.orig_autoneg;
 +              phydev->advertising = tp->link_config.orig_advertising;
 +      }
 +
 +      phy_start(phydev);
 +
 +      phy_start_aneg(phydev);
 +}
 +
 +static void tg3_phy_stop(struct tg3 *tp)
 +{
 +      if (!(tp->phy_flags & TG3_PHYFLG_IS_CONNECTED))
 +              return;
 +
 +      phy_stop(tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]);
 +}
 +
 +static void tg3_phy_fini(struct tg3 *tp)
 +{
 +      if (tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) {
 +              phy_disconnect(tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR]);
 +              tp->phy_flags &= ~TG3_PHYFLG_IS_CONNECTED;
 +      }
 +}
 +
 +static int tg3_phy_set_extloopbk(struct tg3 *tp)
 +{
 +      int err;
 +      u32 val;
 +
 +      if (tp->phy_flags & TG3_PHYFLG_IS_FET)
 +              return 0;
 +
 +      if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
 +              /* Cannot do read-modify-write on 5401 */
 +              err = tg3_phy_auxctl_write(tp,
 +                                         MII_TG3_AUXCTL_SHDWSEL_AUXCTL,
 +                                         MII_TG3_AUXCTL_ACTL_EXTLOOPBK |
 +                                         0x4c20);
 +              goto done;
 +      }
 +
 +      err = tg3_phy_auxctl_read(tp,
 +                                MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val);
 +      if (err)
 +              return err;
 +
 +      val |= MII_TG3_AUXCTL_ACTL_EXTLOOPBK;
 +      err = tg3_phy_auxctl_write(tp,
 +                                 MII_TG3_AUXCTL_SHDWSEL_AUXCTL, val);
 +
 +done:
 +      return err;
 +}
 +
 +static void tg3_phy_fet_toggle_apd(struct tg3 *tp, bool enable)
 +{
 +      u32 phytest;
 +
 +      if (!tg3_readphy(tp, MII_TG3_FET_TEST, &phytest)) {
 +              u32 phy;
 +
 +              tg3_writephy(tp, MII_TG3_FET_TEST,
 +                           phytest | MII_TG3_FET_SHADOW_EN);
 +              if (!tg3_readphy(tp, MII_TG3_FET_SHDW_AUXSTAT2, &phy)) {
 +                      if (enable)
 +                              phy |= MII_TG3_FET_SHDW_AUXSTAT2_APD;
 +                      else
 +                              phy &= ~MII_TG3_FET_SHDW_AUXSTAT2_APD;
 +                      tg3_writephy(tp, MII_TG3_FET_SHDW_AUXSTAT2, phy);
 +              }
 +              tg3_writephy(tp, MII_TG3_FET_TEST, phytest);
 +      }
 +}
 +
 +static void tg3_phy_toggle_apd(struct tg3 *tp, bool enable)
 +{
 +      u32 reg;
 +
 +      if (!tg3_flag(tp, 5705_PLUS) ||
 +          (tg3_flag(tp, 5717_PLUS) &&
 +           (tp->phy_flags & TG3_PHYFLG_MII_SERDES)))
 +              return;
 +
 +      if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
 +              tg3_phy_fet_toggle_apd(tp, enable);
 +              return;
 +      }
 +
 +      reg = MII_TG3_MISC_SHDW_WREN |
 +            MII_TG3_MISC_SHDW_SCR5_SEL |
 +            MII_TG3_MISC_SHDW_SCR5_LPED |
 +            MII_TG3_MISC_SHDW_SCR5_DLPTLM |
 +            MII_TG3_MISC_SHDW_SCR5_SDTL |
 +            MII_TG3_MISC_SHDW_SCR5_C125OE;
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5784 || !enable)
 +              reg |= MII_TG3_MISC_SHDW_SCR5_DLLAPD;
 +
 +      tg3_writephy(tp, MII_TG3_MISC_SHDW, reg);
 +
 +
 +      reg = MII_TG3_MISC_SHDW_WREN |
 +            MII_TG3_MISC_SHDW_APD_SEL |
 +            MII_TG3_MISC_SHDW_APD_WKTM_84MS;
 +      if (enable)
 +              reg |= MII_TG3_MISC_SHDW_APD_ENABLE;
 +
 +      tg3_writephy(tp, MII_TG3_MISC_SHDW, reg);
 +}
 +
 +static void tg3_phy_toggle_automdix(struct tg3 *tp, int enable)
 +{
 +      u32 phy;
 +
 +      if (!tg3_flag(tp, 5705_PLUS) ||
 +          (tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
 +              return;
 +
 +      if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
 +              u32 ephy;
 +
 +              if (!tg3_readphy(tp, MII_TG3_FET_TEST, &ephy)) {
 +                      u32 reg = MII_TG3_FET_SHDW_MISCCTRL;
 +
 +                      tg3_writephy(tp, MII_TG3_FET_TEST,
 +                                   ephy | MII_TG3_FET_SHADOW_EN);
 +                      if (!tg3_readphy(tp, reg, &phy)) {
 +                              if (enable)
 +                                      phy |= MII_TG3_FET_SHDW_MISCCTRL_MDIX;
 +                              else
 +                                      phy &= ~MII_TG3_FET_SHDW_MISCCTRL_MDIX;
 +                              tg3_writephy(tp, reg, phy);
 +                      }
 +                      tg3_writephy(tp, MII_TG3_FET_TEST, ephy);
 +              }
 +      } else {
 +              int ret;
 +
 +              ret = tg3_phy_auxctl_read(tp,
 +                                        MII_TG3_AUXCTL_SHDWSEL_MISC, &phy);
 +              if (!ret) {
 +                      if (enable)
 +                              phy |= MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
 +                      else
 +                              phy &= ~MII_TG3_AUXCTL_MISC_FORCE_AMDIX;
 +                      tg3_phy_auxctl_write(tp,
 +                                           MII_TG3_AUXCTL_SHDWSEL_MISC, phy);
 +              }
 +      }
 +}
 +
 +static void tg3_phy_set_wirespeed(struct tg3 *tp)
 +{
 +      int ret;
 +      u32 val;
 +
 +      if (tp->phy_flags & TG3_PHYFLG_NO_ETH_WIRE_SPEED)
 +              return;
 +
 +      ret = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_MISC, &val);
 +      if (!ret)
 +              tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_MISC,
 +                                   val | MII_TG3_AUXCTL_MISC_WIRESPD_EN);
 +}
 +
 +static void tg3_phy_apply_otp(struct tg3 *tp)
 +{
 +      u32 otp, phy;
 +
 +      if (!tp->phy_otp)
 +              return;
 +
 +      otp = tp->phy_otp;
 +
 +      if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp))
 +              return;
 +
 +      phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT);
 +      phy |= MII_TG3_DSP_TAP1_AGCTGT_DFLT;
 +      tg3_phydsp_write(tp, MII_TG3_DSP_TAP1, phy);
 +
 +      phy = ((otp & TG3_OTP_HPFFLTR_MASK) >> TG3_OTP_HPFFLTR_SHIFT) |
 +            ((otp & TG3_OTP_HPFOVER_MASK) >> TG3_OTP_HPFOVER_SHIFT);
 +      tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH0, phy);
 +
 +      phy = ((otp & TG3_OTP_LPFDIS_MASK) >> TG3_OTP_LPFDIS_SHIFT);
 +      phy |= MII_TG3_DSP_AADJ1CH3_ADCCKADJ;
 +      tg3_phydsp_write(tp, MII_TG3_DSP_AADJ1CH3, phy);
 +
 +      phy = ((otp & TG3_OTP_VDAC_MASK) >> TG3_OTP_VDAC_SHIFT);
 +      tg3_phydsp_write(tp, MII_TG3_DSP_EXP75, phy);
 +
 +      phy = ((otp & TG3_OTP_10BTAMP_MASK) >> TG3_OTP_10BTAMP_SHIFT);
 +      tg3_phydsp_write(tp, MII_TG3_DSP_EXP96, phy);
 +
 +      phy = ((otp & TG3_OTP_ROFF_MASK) >> TG3_OTP_ROFF_SHIFT) |
 +            ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT);
 +      tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy);
 +
 +      TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
 +}
 +
 +static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
 +{
 +      u32 val;
 +
 +      if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
 +              return;
 +
 +      tp->setlpicnt = 0;
 +
 +      if (tp->link_config.autoneg == AUTONEG_ENABLE &&
 +          current_link_up == 1 &&
 +          tp->link_config.active_duplex == DUPLEX_FULL &&
 +          (tp->link_config.active_speed == SPEED_100 ||
 +           tp->link_config.active_speed == SPEED_1000)) {
 +              u32 eeectl;
 +
 +              if (tp->link_config.active_speed == SPEED_1000)
 +                      eeectl = TG3_CPMU_EEE_CTRL_EXIT_16_5_US;
 +              else
 +                      eeectl = TG3_CPMU_EEE_CTRL_EXIT_36_US;
 +
 +              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)
 +                      tp->setlpicnt = 2;
 +      }
 +
 +      if (!tp->setlpicnt) {
 +              if (current_link_up == 1 &&
 +                 !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
 +                      tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000);
 +                      TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
 +              }
 +
 +              val = tr32(TG3_CPMU_EEE_MODE);
 +              tw32(TG3_CPMU_EEE_MODE, val & ~TG3_CPMU_EEEMD_LPI_ENABLE);
 +      }
 +}
 +
 +static void tg3_phy_eee_enable(struct tg3 *tp)
 +{
 +      u32 val;
 +
 +      if (tp->link_config.active_speed == SPEED_1000 &&
 +          (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
 +           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
 +           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) &&
 +          !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
 +              val = MII_TG3_DSP_TAP26_ALNOKO |
 +                    MII_TG3_DSP_TAP26_RMRXSTO;
 +              tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val);
 +              TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
 +      }
 +
 +      val = tr32(TG3_CPMU_EEE_MODE);
 +      tw32(TG3_CPMU_EEE_MODE, val | TG3_CPMU_EEEMD_LPI_ENABLE);
 +}
 +
 +static int tg3_wait_macro_done(struct tg3 *tp)
 +{
 +      int limit = 100;
 +
 +      while (limit--) {
 +              u32 tmp32;
 +
 +              if (!tg3_readphy(tp, MII_TG3_DSP_CONTROL, &tmp32)) {
 +                      if ((tmp32 & 0x1000) == 0)
 +                              break;
 +              }
 +      }
 +      if (limit < 0)
 +              return -EBUSY;
 +
 +      return 0;
 +}
 +
 +static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp)
 +{
 +      static const u32 test_pat[4][6] = {
 +      { 0x00005555, 0x00000005, 0x00002aaa, 0x0000000a, 0x00003456, 0x00000003 },
 +      { 0x00002aaa, 0x0000000a, 0x00003333, 0x00000003, 0x0000789a, 0x00000005 },
 +      { 0x00005a5a, 0x00000005, 0x00002a6a, 0x0000000a, 0x00001bcd, 0x00000003 },
 +      { 0x00002a5a, 0x0000000a, 0x000033c3, 0x00000003, 0x00002ef1, 0x00000005 }
 +      };
 +      int chan;
 +
 +      for (chan = 0; chan < 4; chan++) {
 +              int i;
 +
 +              tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
 +                           (chan * 0x2000) | 0x0200);
 +              tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0002);
 +
 +              for (i = 0; i < 6; i++)
 +                      tg3_writephy(tp, MII_TG3_DSP_RW_PORT,
 +                                   test_pat[chan][i]);
 +
 +              tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0202);
 +              if (tg3_wait_macro_done(tp)) {
 +                      *resetp = 1;
 +                      return -EBUSY;
 +              }
 +
 +              tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
 +                           (chan * 0x2000) | 0x0200);
 +              tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0082);
 +              if (tg3_wait_macro_done(tp)) {
 +                      *resetp = 1;
 +                      return -EBUSY;
 +              }
 +
 +              tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0802);
 +              if (tg3_wait_macro_done(tp)) {
 +                      *resetp = 1;
 +                      return -EBUSY;
 +              }
 +
 +              for (i = 0; i < 6; i += 2) {
 +                      u32 low, high;
 +
 +                      if (tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low) ||
 +                          tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high) ||
 +                          tg3_wait_macro_done(tp)) {
 +                              *resetp = 1;
 +                              return -EBUSY;
 +                      }
 +                      low &= 0x7fff;
 +                      high &= 0x000f;
 +                      if (low != test_pat[chan][i] ||
 +                          high != test_pat[chan][i+1]) {
 +                              tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000b);
 +                              tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4001);
 +                              tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x4005);
 +
 +                              return -EBUSY;
 +                      }
 +              }
 +      }
 +
 +      return 0;
 +}
 +
 +static int tg3_phy_reset_chanpat(struct tg3 *tp)
 +{
 +      int chan;
 +
 +      for (chan = 0; chan < 4; chan++) {
 +              int i;
 +
 +              tg3_writephy(tp, MII_TG3_DSP_ADDRESS,
 +                           (chan * 0x2000) | 0x0200);
 +              tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0002);
 +              for (i = 0; i < 6; i++)
 +                      tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x000);
 +              tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0202);
 +              if (tg3_wait_macro_done(tp))
 +                      return -EBUSY;
 +      }
 +
 +      return 0;
 +}
 +
 +static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
 +{
 +      u32 reg32, phy9_orig;
 +      int retries, do_phy_reset, err;
 +
 +      retries = 10;
 +      do_phy_reset = 1;
 +      do {
 +              if (do_phy_reset) {
 +                      err = tg3_bmcr_reset(tp);
 +                      if (err)
 +                              return err;
 +                      do_phy_reset = 0;
 +              }
 +
 +              /* Disable transmitter and interrupt.  */
 +              if (tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32))
 +                      continue;
 +
 +              reg32 |= 0x3000;
 +              tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
 +
 +              /* Set full-duplex, 1000 mbps.  */
 +              tg3_writephy(tp, MII_BMCR,
 +                           BMCR_FULLDPLX | BMCR_SPEED1000);
 +
 +              /* Set to master mode.  */
 +              if (tg3_readphy(tp, MII_CTRL1000, &phy9_orig))
 +                      continue;
 +
 +              tg3_writephy(tp, MII_CTRL1000,
 +                           CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER);
 +
 +              err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
 +              if (err)
 +                      return err;
 +
 +              /* Block the PHY control access.  */
 +              tg3_phydsp_write(tp, 0x8005, 0x0800);
 +
 +              err = tg3_phy_write_and_check_testpat(tp, &do_phy_reset);
 +              if (!err)
 +                      break;
 +      } while (--retries);
 +
 +      err = tg3_phy_reset_chanpat(tp);
 +      if (err)
 +              return err;
 +
 +      tg3_phydsp_write(tp, 0x8005, 0x0000);
 +
 +      tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
 +      tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000);
 +
 +      TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
 +
 +      tg3_writephy(tp, MII_CTRL1000, phy9_orig);
 +
 +      if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32)) {
 +              reg32 &= ~0x3000;
 +              tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
 +      } else if (!err)
 +              err = -EBUSY;
 +
 +      return err;
 +}
 +
 +/* This will reset the tigon3 PHY if there is no valid
 + * link unless the FORCE argument is non-zero.
 + */
 +static int tg3_phy_reset(struct tg3 *tp)
 +{
 +      u32 val, cpmuctrl;
 +      int err;
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 +              val = tr32(GRC_MISC_CFG);
 +              tw32_f(GRC_MISC_CFG, val & ~GRC_MISC_CFG_EPHY_IDDQ);
 +              udelay(40);
 +      }
 +      err  = tg3_readphy(tp, MII_BMSR, &val);
 +      err |= tg3_readphy(tp, MII_BMSR, &val);
 +      if (err != 0)
 +              return -EBUSY;
 +
 +      if (netif_running(tp->dev) && netif_carrier_ok(tp->dev)) {
 +              netif_carrier_off(tp->dev);
 +              tg3_link_report(tp);
 +      }
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
 +              err = tg3_phy_reset_5703_4_5(tp);
 +              if (err)
 +                      return err;
 +              goto out;
 +      }
 +
 +      cpmuctrl = 0;
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5784 &&
 +          GET_CHIP_REV(tp->pci_chip_rev_id) != CHIPREV_5784_AX) {
 +              cpmuctrl = tr32(TG3_CPMU_CTRL);
 +              if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY)
 +                      tw32(TG3_CPMU_CTRL,
 +                           cpmuctrl & ~CPMU_CTRL_GPHY_10MB_RXONLY);
 +      }
 +
 +      err = tg3_bmcr_reset(tp);
 +      if (err)
 +              return err;
 +
 +      if (cpmuctrl & CPMU_CTRL_GPHY_10MB_RXONLY) {
 +              val = MII_TG3_DSP_EXP8_AEDW | MII_TG3_DSP_EXP8_REJ2MHz;
 +              tg3_phydsp_write(tp, MII_TG3_DSP_EXP8, val);
 +
 +              tw32(TG3_CPMU_CTRL, cpmuctrl);
 +      }
 +
 +      if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
 +          GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
 +              val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
 +              if ((val & CPMU_LSPD_1000MB_MACCLK_MASK) ==
 +                  CPMU_LSPD_1000MB_MACCLK_12_5) {
 +                      val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
 +                      udelay(40);
 +                      tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
 +              }
 +      }
 +
 +      if (tg3_flag(tp, 5717_PLUS) &&
 +          (tp->phy_flags & TG3_PHYFLG_MII_SERDES))
 +              return 0;
 +
 +      tg3_phy_apply_otp(tp);
 +
 +      if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD)
 +              tg3_phy_toggle_apd(tp, true);
 +      else
 +              tg3_phy_toggle_apd(tp, false);
 +
 +out:
 +      if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) &&
 +          !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
 +              tg3_phydsp_write(tp, 0x201f, 0x2aaa);
 +              tg3_phydsp_write(tp, 0x000a, 0x0323);
 +              TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
 +      }
 +
 +      if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) {
 +              tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
 +              tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
 +      }
 +
 +      if (tp->phy_flags & TG3_PHYFLG_BER_BUG) {
 +              if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
 +                      tg3_phydsp_write(tp, 0x000a, 0x310b);
 +                      tg3_phydsp_write(tp, 0x201f, 0x9506);
 +                      tg3_phydsp_write(tp, 0x401f, 0x14e2);
 +                      TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
 +              }
 +      } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) {
 +              if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
 +                      tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
 +                      if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) {
 +                              tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b);
 +                              tg3_writephy(tp, MII_TG3_TEST1,
 +                                           MII_TG3_TEST1_TRIM_EN | 0x4);
 +                      } else
 +                              tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);
 +
 +                      TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
 +              }
 +      }
 +
 +      /* Set Extended packet length bit (bit 14) on all chips that */
 +      /* support jumbo frames */
 +      if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
 +              /* Cannot do read-modify-write on 5401 */
 +              tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20);
 +      } else if (tg3_flag(tp, JUMBO_CAPABLE)) {
 +              /* Set bit 14 with read-modify-write to preserve other bits */
 +              err = tg3_phy_auxctl_read(tp,
 +                                        MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val);
 +              if (!err)
 +                      tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL,
 +                                         val | MII_TG3_AUXCTL_ACTL_EXTPKTLEN);
 +      }
 +
 +      /* Set phy register 0x10 bit 0 to high fifo elasticity to support
 +       * jumbo frames transmission.
 +       */
 +      if (tg3_flag(tp, JUMBO_CAPABLE)) {
 +              if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &val))
 +                      tg3_writephy(tp, MII_TG3_EXT_CTRL,
 +                                   val | MII_TG3_EXT_CTRL_FIFO_ELASTIC);
 +      }
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 +              /* adjust output voltage */
 +              tg3_writephy(tp, MII_TG3_FET_PTEST, 0x12);
 +      }
 +
 +      tg3_phy_toggle_automdix(tp, 1);
 +      tg3_phy_set_wirespeed(tp);
 +      return 0;
 +}
 +
 +#define TG3_GPIO_MSG_DRVR_PRES                 0x00000001
 +#define TG3_GPIO_MSG_NEED_VAUX                 0x00000002
 +#define TG3_GPIO_MSG_MASK              (TG3_GPIO_MSG_DRVR_PRES | \
 +                                        TG3_GPIO_MSG_NEED_VAUX)
 +#define TG3_GPIO_MSG_ALL_DRVR_PRES_MASK \
 +      ((TG3_GPIO_MSG_DRVR_PRES << 0) | \
 +       (TG3_GPIO_MSG_DRVR_PRES << 4) | \
 +       (TG3_GPIO_MSG_DRVR_PRES << 8) | \
 +       (TG3_GPIO_MSG_DRVR_PRES << 12))
 +
 +#define TG3_GPIO_MSG_ALL_NEED_VAUX_MASK \
 +      ((TG3_GPIO_MSG_NEED_VAUX << 0) | \
 +       (TG3_GPIO_MSG_NEED_VAUX << 4) | \
 +       (TG3_GPIO_MSG_NEED_VAUX << 8) | \
 +       (TG3_GPIO_MSG_NEED_VAUX << 12))
 +
 +static inline u32 tg3_set_function_status(struct tg3 *tp, u32 newstat)
 +{
 +      u32 status, shift;
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
 +              status = tg3_ape_read32(tp, TG3_APE_GPIO_MSG);
 +      else
 +              status = tr32(TG3_CPMU_DRV_STATUS);
 +
 +      shift = TG3_APE_GPIO_MSG_SHIFT + 4 * tp->pci_fn;
 +      status &= ~(TG3_GPIO_MSG_MASK << shift);
 +      status |= (newstat << shift);
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
 +              tg3_ape_write32(tp, TG3_APE_GPIO_MSG, status);
 +      else
 +              tw32(TG3_CPMU_DRV_STATUS, status);
 +
 +      return status >> TG3_APE_GPIO_MSG_SHIFT;
 +}
 +
 +static inline int tg3_pwrsrc_switch_to_vmain(struct tg3 *tp)
 +{
 +      if (!tg3_flag(tp, IS_NIC))
 +              return 0;
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
 +              if (tg3_ape_lock(tp, TG3_APE_LOCK_GPIO))
 +                      return -EIO;
 +
 +              tg3_set_function_status(tp, TG3_GPIO_MSG_DRVR_PRES);
 +
 +              tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl,
 +                          TG3_GRC_LCLCTL_PWRSW_DELAY);
 +
 +              tg3_ape_unlock(tp, TG3_APE_LOCK_GPIO);
 +      } else {
 +              tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl,
 +                          TG3_GRC_LCLCTL_PWRSW_DELAY);
 +      }
 +
 +      return 0;
 +}
 +
 +static void tg3_pwrsrc_die_with_vmain(struct tg3 *tp)
 +{
 +      u32 grc_local_ctrl;
 +
 +      if (!tg3_flag(tp, IS_NIC) ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)
 +              return;
 +
 +      grc_local_ctrl = tp->grc_local_ctrl | GRC_LCLCTRL_GPIO_OE1;
 +
 +      tw32_wait_f(GRC_LOCAL_CTRL,
 +                  grc_local_ctrl | GRC_LCLCTRL_GPIO_OUTPUT1,
 +                  TG3_GRC_LCLCTL_PWRSW_DELAY);
 +
 +      tw32_wait_f(GRC_LOCAL_CTRL,
 +                  grc_local_ctrl,
 +                  TG3_GRC_LCLCTL_PWRSW_DELAY);
 +
 +      tw32_wait_f(GRC_LOCAL_CTRL,
 +                  grc_local_ctrl | GRC_LCLCTRL_GPIO_OUTPUT1,
 +                  TG3_GRC_LCLCTL_PWRSW_DELAY);
 +}
 +
 +static void tg3_pwrsrc_switch_to_vaux(struct tg3 *tp)
 +{
 +      if (!tg3_flag(tp, IS_NIC))
 +              return;
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
 +              tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 +                          (GRC_LCLCTRL_GPIO_OE0 |
 +                           GRC_LCLCTRL_GPIO_OE1 |
 +                           GRC_LCLCTRL_GPIO_OE2 |
 +                           GRC_LCLCTRL_GPIO_OUTPUT0 |
 +                           GRC_LCLCTRL_GPIO_OUTPUT1),
 +                          TG3_GRC_LCLCTL_PWRSW_DELAY);
 +      } else if (tp->pdev->device == PCI_DEVICE_ID_TIGON3_5761 ||
 +                 tp->pdev->device == TG3PCI_DEVICE_TIGON3_5761S) {
 +              /* The 5761 non-e device swaps GPIO 0 and GPIO 2. */
 +              u32 grc_local_ctrl = GRC_LCLCTRL_GPIO_OE0 |
 +                                   GRC_LCLCTRL_GPIO_OE1 |
 +                                   GRC_LCLCTRL_GPIO_OE2 |
 +                                   GRC_LCLCTRL_GPIO_OUTPUT0 |
 +                                   GRC_LCLCTRL_GPIO_OUTPUT1 |
 +                                   tp->grc_local_ctrl;
 +              tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl,
 +                          TG3_GRC_LCLCTL_PWRSW_DELAY);
 +
 +              grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT2;
 +              tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl,
 +                          TG3_GRC_LCLCTL_PWRSW_DELAY);
 +
 +              grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT0;
 +              tw32_wait_f(GRC_LOCAL_CTRL, grc_local_ctrl,
 +                          TG3_GRC_LCLCTL_PWRSW_DELAY);
 +      } else {
 +              u32 no_gpio2;
 +              u32 grc_local_ctrl = 0;
 +
 +              /* Workaround to prevent overdrawing Amps. */
 +              if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) {
 +                      grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE3;
 +                      tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 +                                  grc_local_ctrl,
 +                                  TG3_GRC_LCLCTL_PWRSW_DELAY);
 +              }
 +
 +              /* On 5753 and variants, GPIO2 cannot be used. */
 +              no_gpio2 = tp->nic_sram_data_cfg &
 +                         NIC_SRAM_DATA_CFG_NO_GPIO2;
 +
 +              grc_local_ctrl |= GRC_LCLCTRL_GPIO_OE0 |
 +                                GRC_LCLCTRL_GPIO_OE1 |
 +                                GRC_LCLCTRL_GPIO_OE2 |
 +                                GRC_LCLCTRL_GPIO_OUTPUT1 |
 +                                GRC_LCLCTRL_GPIO_OUTPUT2;
 +              if (no_gpio2) {
 +                      grc_local_ctrl &= ~(GRC_LCLCTRL_GPIO_OE2 |
 +                                          GRC_LCLCTRL_GPIO_OUTPUT2);
 +              }
 +              tw32_wait_f(GRC_LOCAL_CTRL,
 +                          tp->grc_local_ctrl | grc_local_ctrl,
 +                          TG3_GRC_LCLCTL_PWRSW_DELAY);
 +
 +              grc_local_ctrl |= GRC_LCLCTRL_GPIO_OUTPUT0;
 +
 +              tw32_wait_f(GRC_LOCAL_CTRL,
 +                          tp->grc_local_ctrl | grc_local_ctrl,
 +                          TG3_GRC_LCLCTL_PWRSW_DELAY);
 +
 +              if (!no_gpio2) {
 +                      grc_local_ctrl &= ~GRC_LCLCTRL_GPIO_OUTPUT2;
 +                      tw32_wait_f(GRC_LOCAL_CTRL,
 +                                  tp->grc_local_ctrl | grc_local_ctrl,
 +                                  TG3_GRC_LCLCTL_PWRSW_DELAY);
 +              }
 +      }
 +}
 +
 +static void tg3_frob_aux_power_5717(struct tg3 *tp, bool wol_enable)
 +{
 +      u32 msg = 0;
 +
 +      /* Serialize power state transitions */
 +      if (tg3_ape_lock(tp, TG3_APE_LOCK_GPIO))
 +              return;
 +
 +      if (tg3_flag(tp, ENABLE_ASF) || tg3_flag(tp, ENABLE_APE) || wol_enable)
 +              msg = TG3_GPIO_MSG_NEED_VAUX;
 +
 +      msg = tg3_set_function_status(tp, msg);
 +
 +      if (msg & TG3_GPIO_MSG_ALL_DRVR_PRES_MASK)
 +              goto done;
 +
 +      if (msg & TG3_GPIO_MSG_ALL_NEED_VAUX_MASK)
 +              tg3_pwrsrc_switch_to_vaux(tp);
 +      else
 +              tg3_pwrsrc_die_with_vmain(tp);
 +
 +done:
 +      tg3_ape_unlock(tp, TG3_APE_LOCK_GPIO);
 +}
 +
 +static void tg3_frob_aux_power(struct tg3 *tp, bool include_wol)
 +{
 +      bool need_vaux = false;
 +
 +      /* The GPIOs do something completely different on 57765. */
 +      if (!tg3_flag(tp, IS_NIC) ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
 +              return;
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) {
 +              tg3_frob_aux_power_5717(tp, include_wol ?
 +                                      tg3_flag(tp, WOL_ENABLE) != 0 : 0);
 +              return;
 +      }
 +
 +      if (tp->pdev_peer && tp->pdev_peer != tp->pdev) {
 +              struct net_device *dev_peer;
 +
 +              dev_peer = pci_get_drvdata(tp->pdev_peer);
 +
 +              /* remove_one() may have been run on the peer. */
 +              if (dev_peer) {
 +                      struct tg3 *tp_peer = netdev_priv(dev_peer);
 +
 +                      if (tg3_flag(tp_peer, INIT_COMPLETE))
 +                              return;
 +
 +                      if ((include_wol && tg3_flag(tp_peer, WOL_ENABLE)) ||
 +                          tg3_flag(tp_peer, ENABLE_ASF))
 +                              need_vaux = true;
 +              }
 +      }
 +
 +      if ((include_wol && tg3_flag(tp, WOL_ENABLE)) ||
 +          tg3_flag(tp, ENABLE_ASF))
 +              need_vaux = true;
 +
 +      if (need_vaux)
 +              tg3_pwrsrc_switch_to_vaux(tp);
 +      else
 +              tg3_pwrsrc_die_with_vmain(tp);
 +}
 +
 +static int tg3_5700_link_polarity(struct tg3 *tp, u32 speed)
 +{
 +      if (tp->led_ctrl == LED_CTRL_MODE_PHY_2)
 +              return 1;
 +      else if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411) {
 +              if (speed != SPEED_10)
 +                      return 1;
 +      } else if (speed == SPEED_10)
 +              return 1;
 +
 +      return 0;
 +}
 +
 +static int tg3_setup_phy(struct tg3 *, int);
 +static int tg3_halt_cpu(struct tg3 *, u32);
 +
 +static void tg3_power_down_phy(struct tg3 *tp, bool do_low_power)
 +{
 +      u32 val;
 +
 +      if (tp->phy_flags & TG3_PHYFLG_PHY_SERDES) {
 +              if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
 +                      u32 sg_dig_ctrl = tr32(SG_DIG_CTRL);
 +                      u32 serdes_cfg = tr32(MAC_SERDES_CFG);
 +
 +                      sg_dig_ctrl |=
 +                              SG_DIG_USING_HW_AUTONEG | SG_DIG_SOFT_RESET;
 +                      tw32(SG_DIG_CTRL, sg_dig_ctrl);
 +                      tw32(MAC_SERDES_CFG, serdes_cfg | (1 << 15));
 +              }
 +              return;
 +      }
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 +              tg3_bmcr_reset(tp);
 +              val = tr32(GRC_MISC_CFG);
 +              tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ);
 +              udelay(40);
 +              return;
 +      } else if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
 +              u32 phytest;
 +              if (!tg3_readphy(tp, MII_TG3_FET_TEST, &phytest)) {
 +                      u32 phy;
 +
 +                      tg3_writephy(tp, MII_ADVERTISE, 0);
 +                      tg3_writephy(tp, MII_BMCR,
 +                                   BMCR_ANENABLE | BMCR_ANRESTART);
 +
 +                      tg3_writephy(tp, MII_TG3_FET_TEST,
 +                                   phytest | MII_TG3_FET_SHADOW_EN);
 +                      if (!tg3_readphy(tp, MII_TG3_FET_SHDW_AUXMODE4, &phy)) {
 +                              phy |= MII_TG3_FET_SHDW_AUXMODE4_SBPD;
 +                              tg3_writephy(tp,
 +                                           MII_TG3_FET_SHDW_AUXMODE4,
 +                                           phy);
 +                      }
 +                      tg3_writephy(tp, MII_TG3_FET_TEST, phytest);
 +              }
 +              return;
 +      } else if (do_low_power) {
 +              tg3_writephy(tp, MII_TG3_EXT_CTRL,
 +                           MII_TG3_EXT_CTRL_FORCE_LED_OFF);
 +
 +              val = MII_TG3_AUXCTL_PCTL_100TX_LPWR |
 +                    MII_TG3_AUXCTL_PCTL_SPR_ISOLATE |
 +                    MII_TG3_AUXCTL_PCTL_VREG_11V;
 +              tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_PWRCTL, val);
 +      }
 +
 +      /* The PHY should not be powered down on some chips because
 +       * of bugs.
 +       */
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
 +          (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 &&
 +           (tp->phy_flags & TG3_PHYFLG_MII_SERDES)))
 +              return;
 +
 +      if (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5784_AX ||
 +          GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5761_AX) {
 +              val = tr32(TG3_CPMU_LSPD_1000MB_CLK);
 +              val &= ~CPMU_LSPD_1000MB_MACCLK_MASK;
 +              val |= CPMU_LSPD_1000MB_MACCLK_12_5;
 +              tw32_f(TG3_CPMU_LSPD_1000MB_CLK, val);
 +      }
 +
 +      tg3_writephy(tp, MII_BMCR, BMCR_PDOWN);
 +}
 +
 +/* tp->lock is held. */
 +static int tg3_nvram_lock(struct tg3 *tp)
 +{
 +      if (tg3_flag(tp, NVRAM)) {
 +              int i;
 +
 +              if (tp->nvram_lock_cnt == 0) {
 +                      tw32(NVRAM_SWARB, SWARB_REQ_SET1);
 +                      for (i = 0; i < 8000; i++) {
 +                              if (tr32(NVRAM_SWARB) & SWARB_GNT1)
 +                                      break;
 +                              udelay(20);
 +                      }
 +                      if (i == 8000) {
 +                              tw32(NVRAM_SWARB, SWARB_REQ_CLR1);
 +                              return -ENODEV;
 +                      }
 +              }
 +              tp->nvram_lock_cnt++;
 +      }
 +      return 0;
 +}
 +
 +/* tp->lock is held. */
 +static void tg3_nvram_unlock(struct tg3 *tp)
 +{
 +      if (tg3_flag(tp, NVRAM)) {
 +              if (tp->nvram_lock_cnt > 0)
 +                      tp->nvram_lock_cnt--;
 +              if (tp->nvram_lock_cnt == 0)
 +                      tw32_f(NVRAM_SWARB, SWARB_REQ_CLR1);
 +      }
 +}
 +
 +/* tp->lock is held. */
 +static void tg3_enable_nvram_access(struct tg3 *tp)
 +{
 +      if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) {
 +              u32 nvaccess = tr32(NVRAM_ACCESS);
 +
 +              tw32(NVRAM_ACCESS, nvaccess | ACCESS_ENABLE);
 +      }
 +}
 +
 +/* tp->lock is held. */
 +static void tg3_disable_nvram_access(struct tg3 *tp)
 +{
 +      if (tg3_flag(tp, 5750_PLUS) && !tg3_flag(tp, PROTECTED_NVRAM)) {
 +              u32 nvaccess = tr32(NVRAM_ACCESS);
 +
 +              tw32(NVRAM_ACCESS, nvaccess & ~ACCESS_ENABLE);
 +      }
 +}
 +
 +static int tg3_nvram_read_using_eeprom(struct tg3 *tp,
 +                                      u32 offset, u32 *val)
 +{
 +      u32 tmp;
 +      int i;
 +
 +      if (offset > EEPROM_ADDR_ADDR_MASK || (offset % 4) != 0)
 +              return -EINVAL;
 +
 +      tmp = tr32(GRC_EEPROM_ADDR) & ~(EEPROM_ADDR_ADDR_MASK |
 +                                      EEPROM_ADDR_DEVID_MASK |
 +                                      EEPROM_ADDR_READ);
 +      tw32(GRC_EEPROM_ADDR,
 +           tmp |
 +           (0 << EEPROM_ADDR_DEVID_SHIFT) |
 +           ((offset << EEPROM_ADDR_ADDR_SHIFT) &
 +            EEPROM_ADDR_ADDR_MASK) |
 +           EEPROM_ADDR_READ | EEPROM_ADDR_START);
 +
 +      for (i = 0; i < 1000; i++) {
 +              tmp = tr32(GRC_EEPROM_ADDR);
 +
 +              if (tmp & EEPROM_ADDR_COMPLETE)
 +                      break;
 +              msleep(1);
 +      }
 +      if (!(tmp & EEPROM_ADDR_COMPLETE))
 +              return -EBUSY;
 +
 +      tmp = tr32(GRC_EEPROM_DATA);
 +
 +      /*
 +       * The data will always be opposite the native endian
 +       * format.  Perform a blind byteswap to compensate.
 +       */
 +      *val = swab32(tmp);
 +
 +      return 0;
 +}
 +
 +#define NVRAM_CMD_TIMEOUT 10000
 +
 +static int tg3_nvram_exec_cmd(struct tg3 *tp, u32 nvram_cmd)
 +{
 +      int i;
 +
 +      tw32(NVRAM_CMD, nvram_cmd);
 +      for (i = 0; i < NVRAM_CMD_TIMEOUT; i++) {
 +              udelay(10);
 +              if (tr32(NVRAM_CMD) & NVRAM_CMD_DONE) {
 +                      udelay(10);
 +                      break;
 +              }
 +      }
 +
 +      if (i == NVRAM_CMD_TIMEOUT)
 +              return -EBUSY;
 +
 +      return 0;
 +}
 +
 +static u32 tg3_nvram_phys_addr(struct tg3 *tp, u32 addr)
 +{
 +      if (tg3_flag(tp, NVRAM) &&
 +          tg3_flag(tp, NVRAM_BUFFERED) &&
 +          tg3_flag(tp, FLASH) &&
 +          !tg3_flag(tp, NO_NVRAM_ADDR_TRANS) &&
 +          (tp->nvram_jedecnum == JEDEC_ATMEL))
 +
 +              addr = ((addr / tp->nvram_pagesize) <<
 +                      ATMEL_AT45DB0X1B_PAGE_POS) +
 +                     (addr % tp->nvram_pagesize);
 +
 +      return addr;
 +}
 +
 +static u32 tg3_nvram_logical_addr(struct tg3 *tp, u32 addr)
 +{
 +      if (tg3_flag(tp, NVRAM) &&
 +          tg3_flag(tp, NVRAM_BUFFERED) &&
 +          tg3_flag(tp, FLASH) &&
 +          !tg3_flag(tp, NO_NVRAM_ADDR_TRANS) &&
 +          (tp->nvram_jedecnum == JEDEC_ATMEL))
 +
 +              addr = ((addr >> ATMEL_AT45DB0X1B_PAGE_POS) *
 +                      tp->nvram_pagesize) +
 +                     (addr & ((1 << ATMEL_AT45DB0X1B_PAGE_POS) - 1));
 +
 +      return addr;
 +}
 +
 +/* NOTE: Data read in from NVRAM is byteswapped according to
 + * the byteswapping settings for all other register accesses.
 + * tg3 devices are BE devices, so on a BE machine, the data
 + * returned will be exactly as it is seen in NVRAM.  On a LE
 + * machine, the 32-bit value will be byteswapped.
 + */
 +static int tg3_nvram_read(struct tg3 *tp, u32 offset, u32 *val)
 +{
 +      int ret;
 +
 +      if (!tg3_flag(tp, NVRAM))
 +              return tg3_nvram_read_using_eeprom(tp, offset, val);
 +
 +      offset = tg3_nvram_phys_addr(tp, offset);
 +
 +      if (offset > NVRAM_ADDR_MSK)
 +              return -EINVAL;
 +
 +      ret = tg3_nvram_lock(tp);
 +      if (ret)
 +              return ret;
 +
 +      tg3_enable_nvram_access(tp);
 +
 +      tw32(NVRAM_ADDR, offset);
 +      ret = tg3_nvram_exec_cmd(tp, NVRAM_CMD_RD | NVRAM_CMD_GO |
 +              NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE);
 +
 +      if (ret == 0)
 +              *val = tr32(NVRAM_RDDATA);
 +
 +      tg3_disable_nvram_access(tp);
 +
 +      tg3_nvram_unlock(tp);
 +
 +      return ret;
 +}
 +
 +/* Ensures NVRAM data is in bytestream format. */
 +static int tg3_nvram_read_be32(struct tg3 *tp, u32 offset, __be32 *val)
 +{
 +      u32 v;
 +      int res = tg3_nvram_read(tp, offset, &v);
 +      if (!res)
 +              *val = cpu_to_be32(v);
 +      return res;
 +}
 +
 +#define RX_CPU_SCRATCH_BASE   0x30000
 +#define RX_CPU_SCRATCH_SIZE   0x04000
 +#define TX_CPU_SCRATCH_BASE   0x34000
 +#define TX_CPU_SCRATCH_SIZE   0x04000
 +
 +/* tp->lock is held. */
 +static int tg3_halt_cpu(struct tg3 *tp, u32 offset)
 +{
 +      int i;
 +
 +      BUG_ON(offset == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS));
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 +              u32 val = tr32(GRC_VCPU_EXT_CTRL);
 +
 +              tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_HALT_CPU);
 +              return 0;
 +      }
 +      if (offset == RX_CPU_BASE) {
 +              for (i = 0; i < 10000; i++) {
 +                      tw32(offset + CPU_STATE, 0xffffffff);
 +                      tw32(offset + CPU_MODE,  CPU_MODE_HALT);
 +                      if (tr32(offset + CPU_MODE) & CPU_MODE_HALT)
 +                              break;
 +              }
 +
 +              tw32(offset + CPU_STATE, 0xffffffff);
 +              tw32_f(offset + CPU_MODE,  CPU_MODE_HALT);
 +              udelay(10);
 +      } else {
 +              for (i = 0; i < 10000; i++) {
 +                      tw32(offset + CPU_STATE, 0xffffffff);
 +                      tw32(offset + CPU_MODE,  CPU_MODE_HALT);
 +                      if (tr32(offset + CPU_MODE) & CPU_MODE_HALT)
 +                              break;
 +              }
 +      }
 +
 +      if (i >= 10000) {
 +              netdev_err(tp->dev, "%s timed out, %s CPU\n",
 +                         __func__, offset == RX_CPU_BASE ? "RX" : "TX");
 +              return -ENODEV;
 +      }
 +
 +      /* Clear firmware's nvram arbitration. */
 +      if (tg3_flag(tp, NVRAM))
 +              tw32(NVRAM_SWARB, SWARB_REQ_CLR0);
 +      return 0;
 +}
 +
 +struct fw_info {
 +      unsigned int fw_base;
 +      unsigned int fw_len;
 +      const __be32 *fw_data;
 +};
 +
 +/* tp->lock is held. */
 +static int tg3_load_firmware_cpu(struct tg3 *tp, u32 cpu_base,
 +                               u32 cpu_scratch_base, int cpu_scratch_size,
 +                               struct fw_info *info)
 +{
 +      int err, lock_err, i;
 +      void (*write_op)(struct tg3 *, u32, u32);
 +
 +      if (cpu_base == TX_CPU_BASE && tg3_flag(tp, 5705_PLUS)) {
 +              netdev_err(tp->dev,
 +                         "%s: Trying to load TX cpu firmware which is 5705\n",
 +                         __func__);
 +              return -EINVAL;
 +      }
 +
 +      if (tg3_flag(tp, 5705_PLUS))
 +              write_op = tg3_write_mem;
 +      else
 +              write_op = tg3_write_indirect_reg32;
 +
 +      /* It is possible that bootcode is still loading at this point.
 +       * Get the nvram lock first before halting the cpu.
 +       */
 +      lock_err = tg3_nvram_lock(tp);
 +      err = tg3_halt_cpu(tp, cpu_base);
 +      if (!lock_err)
 +              tg3_nvram_unlock(tp);
 +      if (err)
 +              goto out;
 +
 +      for (i = 0; i < cpu_scratch_size; i += sizeof(u32))
 +              write_op(tp, cpu_scratch_base + i, 0);
 +      tw32(cpu_base + CPU_STATE, 0xffffffff);
 +      tw32(cpu_base + CPU_MODE, tr32(cpu_base+CPU_MODE)|CPU_MODE_HALT);
 +      for (i = 0; i < (info->fw_len / sizeof(u32)); i++)
 +              write_op(tp, (cpu_scratch_base +
 +                            (info->fw_base & 0xffff) +
 +                            (i * sizeof(u32))),
 +                            be32_to_cpu(info->fw_data[i]));
 +
 +      err = 0;
 +
 +out:
 +      return err;
 +}
 +
 +/* tp->lock is held. */
 +static int tg3_load_5701_a0_firmware_fix(struct tg3 *tp)
 +{
 +      struct fw_info info;
 +      const __be32 *fw_data;
 +      int err, i;
 +
 +      fw_data = (void *)tp->fw->data;
 +
 +      /* Firmware blob starts with version numbers, followed by
 +         start address and length. We are setting complete length.
 +         length = end_address_of_bss - start_address_of_text.
 +         Remainder is the blob to be loaded contiguously
 +         from start address. */
 +
 +      info.fw_base = be32_to_cpu(fw_data[1]);
 +      info.fw_len = tp->fw->size - 12;
 +      info.fw_data = &fw_data[3];
 +
 +      err = tg3_load_firmware_cpu(tp, RX_CPU_BASE,
 +                                  RX_CPU_SCRATCH_BASE, RX_CPU_SCRATCH_SIZE,
 +                                  &info);
 +      if (err)
 +              return err;
 +
 +      err = tg3_load_firmware_cpu(tp, TX_CPU_BASE,
 +                                  TX_CPU_SCRATCH_BASE, TX_CPU_SCRATCH_SIZE,
 +                                  &info);
 +      if (err)
 +              return err;
 +
 +      /* Now startup only the RX cpu. */
 +      tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
 +      tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
 +
 +      for (i = 0; i < 5; i++) {
 +              if (tr32(RX_CPU_BASE + CPU_PC) == info.fw_base)
 +                      break;
 +              tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
 +              tw32(RX_CPU_BASE + CPU_MODE,  CPU_MODE_HALT);
 +              tw32_f(RX_CPU_BASE + CPU_PC, info.fw_base);
 +              udelay(1000);
 +      }
 +      if (i >= 5) {
 +              netdev_err(tp->dev, "%s fails to set RX CPU PC, is %08x "
 +                         "should be %08x\n", __func__,
 +                         tr32(RX_CPU_BASE + CPU_PC), info.fw_base);
 +              return -ENODEV;
 +      }
 +      tw32(RX_CPU_BASE + CPU_STATE, 0xffffffff);
 +      tw32_f(RX_CPU_BASE + CPU_MODE,  0x00000000);
 +
 +      return 0;
 +}
 +
 +/* tp->lock is held. */
 +static int tg3_load_tso_firmware(struct tg3 *tp)
 +{
 +      struct fw_info info;
 +      const __be32 *fw_data;
 +      unsigned long cpu_base, cpu_scratch_base, cpu_scratch_size;
 +      int err, i;
 +
 +      if (tg3_flag(tp, HW_TSO_1) ||
 +          tg3_flag(tp, HW_TSO_2) ||
 +          tg3_flag(tp, HW_TSO_3))
 +              return 0;
 +
 +      fw_data = (void *)tp->fw->data;
 +
 +      /* Firmware blob starts with version numbers, followed by
 +         start address and length. We are setting complete length.
 +         length = end_address_of_bss - start_address_of_text.
 +         Remainder is the blob to be loaded contiguously
 +         from start address. */
 +
 +      info.fw_base = be32_to_cpu(fw_data[1]);
 +      cpu_scratch_size = tp->fw_len;
 +      info.fw_len = tp->fw->size - 12;
 +      info.fw_data = &fw_data[3];
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
 +              cpu_base = RX_CPU_BASE;
 +              cpu_scratch_base = NIC_SRAM_MBUF_POOL_BASE5705;
 +      } else {
 +              cpu_base = TX_CPU_BASE;
 +              cpu_scratch_base = TX_CPU_SCRATCH_BASE;
 +              cpu_scratch_size = TX_CPU_SCRATCH_SIZE;
 +      }
 +
 +      err = tg3_load_firmware_cpu(tp, cpu_base,
 +                                  cpu_scratch_base, cpu_scratch_size,
 +                                  &info);
 +      if (err)
 +              return err;
 +
 +      /* Now startup the cpu. */
 +      tw32(cpu_base + CPU_STATE, 0xffffffff);
 +      tw32_f(cpu_base + CPU_PC, info.fw_base);
 +
 +      for (i = 0; i < 5; i++) {
 +              if (tr32(cpu_base + CPU_PC) == info.fw_base)
 +                      break;
 +              tw32(cpu_base + CPU_STATE, 0xffffffff);
 +              tw32(cpu_base + CPU_MODE,  CPU_MODE_HALT);
 +              tw32_f(cpu_base + CPU_PC, info.fw_base);
 +              udelay(1000);
 +      }
 +      if (i >= 5) {
 +              netdev_err(tp->dev,
 +                         "%s fails to set CPU PC, is %08x should be %08x\n",
 +                         __func__, tr32(cpu_base + CPU_PC), info.fw_base);
 +              return -ENODEV;
 +      }
 +      tw32(cpu_base + CPU_STATE, 0xffffffff);
 +      tw32_f(cpu_base + CPU_MODE,  0x00000000);
 +      return 0;
 +}
 +
 +
 +/* tp->lock is held. */
 +static void __tg3_set_mac_addr(struct tg3 *tp, int skip_mac_1)
 +{
 +      u32 addr_high, addr_low;
 +      int i;
 +
 +      addr_high = ((tp->dev->dev_addr[0] << 8) |
 +                   tp->dev->dev_addr[1]);
 +      addr_low = ((tp->dev->dev_addr[2] << 24) |
 +                  (tp->dev->dev_addr[3] << 16) |
 +                  (tp->dev->dev_addr[4] <<  8) |
 +                  (tp->dev->dev_addr[5] <<  0));
 +      for (i = 0; i < 4; i++) {
 +              if (i == 1 && skip_mac_1)
 +                      continue;
 +              tw32(MAC_ADDR_0_HIGH + (i * 8), addr_high);
 +              tw32(MAC_ADDR_0_LOW + (i * 8), addr_low);
 +      }
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704) {
 +              for (i = 0; i < 12; i++) {
 +                      tw32(MAC_EXTADDR_0_HIGH + (i * 8), addr_high);
 +                      tw32(MAC_EXTADDR_0_LOW + (i * 8), addr_low);
 +              }
 +      }
 +
 +      addr_high = (tp->dev->dev_addr[0] +
 +                   tp->dev->dev_addr[1] +
 +                   tp->dev->dev_addr[2] +
 +                   tp->dev->dev_addr[3] +
 +                   tp->dev->dev_addr[4] +
 +                   tp->dev->dev_addr[5]) &
 +              TX_BACKOFF_SEED_MASK;
 +      tw32(MAC_TX_BACKOFF_SEED, addr_high);
 +}
 +
 +static void tg3_enable_register_access(struct tg3 *tp)
 +{
 +      /*
 +       * Make sure register accesses (indirect or otherwise) will function
 +       * correctly.
 +       */
 +      pci_write_config_dword(tp->pdev,
 +                             TG3PCI_MISC_HOST_CTRL, tp->misc_host_ctrl);
 +}
 +
 +static int tg3_power_up(struct tg3 *tp)
 +{
 +      int err;
 +
 +      tg3_enable_register_access(tp);
 +
 +      err = pci_set_power_state(tp->pdev, PCI_D0);
 +      if (!err) {
 +              /* Switch out of Vaux if it is a NIC */
 +              tg3_pwrsrc_switch_to_vmain(tp);
 +      } else {
 +              netdev_err(tp->dev, "Transition to D0 failed\n");
 +      }
 +
 +      return err;
 +}
 +
 +static int tg3_power_down_prepare(struct tg3 *tp)
 +{
 +      u32 misc_host_ctrl;
 +      bool device_should_wake, do_low_power;
 +
 +      tg3_enable_register_access(tp);
 +
 +      /* Restore the CLKREQ setting. */
 +      if (tg3_flag(tp, CLKREQ_BUG)) {
 +              u16 lnkctl;
 +
 +              pci_read_config_word(tp->pdev,
 +                                   pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
 +                                   &lnkctl);
 +              lnkctl |= PCI_EXP_LNKCTL_CLKREQ_EN;
 +              pci_write_config_word(tp->pdev,
 +                                    pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
 +                                    lnkctl);
 +      }
 +
 +      misc_host_ctrl = tr32(TG3PCI_MISC_HOST_CTRL);
 +      tw32(TG3PCI_MISC_HOST_CTRL,
 +           misc_host_ctrl | MISC_HOST_CTRL_MASK_PCI_INT);
 +
 +      device_should_wake = device_may_wakeup(&tp->pdev->dev) &&
 +                           tg3_flag(tp, WOL_ENABLE);
 +
 +      if (tg3_flag(tp, USE_PHYLIB)) {
 +              do_low_power = false;
 +              if ((tp->phy_flags & TG3_PHYFLG_IS_CONNECTED) &&
 +                  !(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
 +                      struct phy_device *phydev;
 +                      u32 phyid, advertising;
 +
 +                      phydev = tp->mdio_bus->phy_map[TG3_PHY_MII_ADDR];
 +
 +                      tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER;
 +
 +                      tp->link_config.orig_speed = phydev->speed;
 +                      tp->link_config.orig_duplex = phydev->duplex;
 +                      tp->link_config.orig_autoneg = phydev->autoneg;
 +                      tp->link_config.orig_advertising = phydev->advertising;
 +
 +                      advertising = ADVERTISED_TP |
 +                                    ADVERTISED_Pause |
 +                                    ADVERTISED_Autoneg |
 +                                    ADVERTISED_10baseT_Half;
 +
 +                      if (tg3_flag(tp, ENABLE_ASF) || device_should_wake) {
 +                              if (tg3_flag(tp, WOL_SPEED_100MB))
 +                                      advertising |=
 +                                              ADVERTISED_100baseT_Half |
 +                                              ADVERTISED_100baseT_Full |
 +                                              ADVERTISED_10baseT_Full;
 +                              else
 +                                      advertising |= ADVERTISED_10baseT_Full;
 +                      }
 +
 +                      phydev->advertising = advertising;
 +
 +                      phy_start_aneg(phydev);
 +
 +                      phyid = phydev->drv->phy_id & phydev->drv->phy_id_mask;
 +                      if (phyid != PHY_ID_BCMAC131) {
 +                              phyid &= PHY_BCM_OUI_MASK;
 +                              if (phyid == PHY_BCM_OUI_1 ||
 +                                  phyid == PHY_BCM_OUI_2 ||
 +                                  phyid == PHY_BCM_OUI_3)
 +                                      do_low_power = true;
 +                      }
 +              }
 +      } else {
 +              do_low_power = true;
 +
 +              if (!(tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
 +                      tp->phy_flags |= TG3_PHYFLG_IS_LOW_POWER;
 +                      tp->link_config.orig_speed = tp->link_config.speed;
 +                      tp->link_config.orig_duplex = tp->link_config.duplex;
 +                      tp->link_config.orig_autoneg = tp->link_config.autoneg;
 +              }
 +
 +              if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES)) {
 +                      tp->link_config.speed = SPEED_10;
 +                      tp->link_config.duplex = DUPLEX_HALF;
 +                      tp->link_config.autoneg = AUTONEG_ENABLE;
 +                      tg3_setup_phy(tp, 0);
 +              }
 +      }
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 +              u32 val;
 +
 +              val = tr32(GRC_VCPU_EXT_CTRL);
 +              tw32(GRC_VCPU_EXT_CTRL, val | GRC_VCPU_EXT_CTRL_DISABLE_WOL);
 +      } else if (!tg3_flag(tp, ENABLE_ASF)) {
 +              int i;
 +              u32 val;
 +
 +              for (i = 0; i < 200; i++) {
 +                      tg3_read_mem(tp, NIC_SRAM_FW_ASF_STATUS_MBOX, &val);
 +                      if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
 +                              break;
 +                      msleep(1);
 +              }
 +      }
 +      if (tg3_flag(tp, WOL_CAP))
 +              tg3_write_mem(tp, NIC_SRAM_WOL_MBOX, WOL_SIGNATURE |
 +                                                   WOL_DRV_STATE_SHUTDOWN |
 +                                                   WOL_DRV_WOL |
 +                                                   WOL_SET_MAGIC_PKT);
 +
 +      if (device_should_wake) {
 +              u32 mac_mode;
 +
 +              if (!(tp->phy_flags & TG3_PHYFLG_PHY_SERDES)) {
 +                      if (do_low_power &&
 +                          !(tp->phy_flags & TG3_PHYFLG_IS_FET)) {
 +                              tg3_phy_auxctl_write(tp,
 +                                             MII_TG3_AUXCTL_SHDWSEL_PWRCTL,
 +                                             MII_TG3_AUXCTL_PCTL_WOL_EN |
 +                                             MII_TG3_AUXCTL_PCTL_100TX_LPWR |
 +                                             MII_TG3_AUXCTL_PCTL_CL_AB_TXDAC);
 +                              udelay(40);
 +                      }
 +
 +                      if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
 +                              mac_mode = MAC_MODE_PORT_MODE_GMII;
 +                      else
 +                              mac_mode = MAC_MODE_PORT_MODE_MII;
 +
 +                      mac_mode |= tp->mac_mode & MAC_MODE_LINK_POLARITY;
 +                      if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
 +                          ASIC_REV_5700) {
 +                              u32 speed = tg3_flag(tp, WOL_SPEED_100MB) ?
 +                                           SPEED_100 : SPEED_10;
 +                              if (tg3_5700_link_polarity(tp, speed))
 +                                      mac_mode |= MAC_MODE_LINK_POLARITY;
 +                              else
 +                                      mac_mode &= ~MAC_MODE_LINK_POLARITY;
 +                      }
 +              } else {
 +                      mac_mode = MAC_MODE_PORT_MODE_TBI;
 +              }
 +
 +              if (!tg3_flag(tp, 5750_PLUS))
 +                      tw32(MAC_LED_CTRL, tp->led_ctrl);
 +
 +              mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE;
 +              if ((tg3_flag(tp, 5705_PLUS) && !tg3_flag(tp, 5780_CLASS)) &&
 +                  (tg3_flag(tp, ENABLE_ASF) || tg3_flag(tp, ENABLE_APE)))
 +                      mac_mode |= MAC_MODE_KEEP_FRAME_IN_WOL;
 +
 +              if (tg3_flag(tp, ENABLE_APE))
 +                      mac_mode |= MAC_MODE_APE_TX_EN |
 +                                  MAC_MODE_APE_RX_EN |
 +                                  MAC_MODE_TDE_ENABLE;
 +
 +              tw32_f(MAC_MODE, mac_mode);
 +              udelay(100);
 +
 +              tw32_f(MAC_RX_MODE, RX_MODE_ENABLE);
 +              udelay(10);
 +      }
 +
 +      if (!tg3_flag(tp, WOL_SPEED_100MB) &&
 +          (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 +           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701)) {
 +              u32 base_val;
 +
 +              base_val = tp->pci_clock_ctrl;
 +              base_val |= (CLOCK_CTRL_RXCLK_DISABLE |
 +                           CLOCK_CTRL_TXCLK_DISABLE);
 +
 +              tw32_wait_f(TG3PCI_CLOCK_CTRL, base_val | CLOCK_CTRL_ALTCLK |
 +                          CLOCK_CTRL_PWRDOWN_PLL133, 40);
 +      } else if (tg3_flag(tp, 5780_CLASS) ||
 +                 tg3_flag(tp, CPMU_PRESENT) ||
 +                 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) {
 +              /* do nothing */
 +      } else if (!(tg3_flag(tp, 5750_PLUS) && tg3_flag(tp, ENABLE_ASF))) {
 +              u32 newbits1, newbits2;
 +
 +              if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 +                  GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
 +                      newbits1 = (CLOCK_CTRL_RXCLK_DISABLE |
 +                                  CLOCK_CTRL_TXCLK_DISABLE |
 +                                  CLOCK_CTRL_ALTCLK);
 +                      newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE;
 +              } else if (tg3_flag(tp, 5705_PLUS)) {
 +                      newbits1 = CLOCK_CTRL_625_CORE;
 +                      newbits2 = newbits1 | CLOCK_CTRL_ALTCLK;
 +              } else {
 +                      newbits1 = CLOCK_CTRL_ALTCLK;
 +                      newbits2 = newbits1 | CLOCK_CTRL_44MHZ_CORE;
 +              }
 +
 +              tw32_wait_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits1,
 +                          40);
 +
 +              tw32_wait_f(TG3PCI_CLOCK_CTRL, tp->pci_clock_ctrl | newbits2,
 +                          40);
 +
 +              if (!tg3_flag(tp, 5705_PLUS)) {
 +                      u32 newbits3;
 +
 +                      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 +                          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
 +                              newbits3 = (CLOCK_CTRL_RXCLK_DISABLE |
 +                                          CLOCK_CTRL_TXCLK_DISABLE |
 +                                          CLOCK_CTRL_44MHZ_CORE);
 +                      } else {
 +                              newbits3 = CLOCK_CTRL_44MHZ_CORE;
 +                      }
 +
 +                      tw32_wait_f(TG3PCI_CLOCK_CTRL,
 +                                  tp->pci_clock_ctrl | newbits3, 40);
 +              }
 +      }
 +
 +      if (!(device_should_wake) && !tg3_flag(tp, ENABLE_ASF))
 +              tg3_power_down_phy(tp, do_low_power);
 +
 +      tg3_frob_aux_power(tp, true);
 +
 +      /* Workaround for unstable PLL clock */
 +      if ((GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_AX) ||
 +          (GET_CHIP_REV(tp->pci_chip_rev_id) == CHIPREV_5750_BX)) {
 +              u32 val = tr32(0x7d00);
 +
 +              val &= ~((1 << 16) | (1 << 4) | (1 << 2) | (1 << 1) | 1);
 +              tw32(0x7d00, val);
 +              if (!tg3_flag(tp, ENABLE_ASF)) {
 +                      int err;
 +
 +                      err = tg3_nvram_lock(tp);
 +                      tg3_halt_cpu(tp, RX_CPU_BASE);
 +                      if (!err)
 +                              tg3_nvram_unlock(tp);
 +              }
 +      }
 +
 +      tg3_write_sig_post_reset(tp, RESET_KIND_SHUTDOWN);
 +
 +      return 0;
 +}
 +
 +static void tg3_power_down(struct tg3 *tp)
 +{
 +      tg3_power_down_prepare(tp);
 +
 +      pci_wake_from_d3(tp->pdev, tg3_flag(tp, WOL_ENABLE));
 +      pci_set_power_state(tp->pdev, PCI_D3hot);
 +}
 +
 +static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 *duplex)
 +{
 +      switch (val & MII_TG3_AUX_STAT_SPDMASK) {
 +      case MII_TG3_AUX_STAT_10HALF:
 +              *speed = SPEED_10;
 +              *duplex = DUPLEX_HALF;
 +              break;
 +
 +      case MII_TG3_AUX_STAT_10FULL:
 +              *speed = SPEED_10;
 +              *duplex = DUPLEX_FULL;
 +              break;
 +
 +      case MII_TG3_AUX_STAT_100HALF:
 +              *speed = SPEED_100;
 +              *duplex = DUPLEX_HALF;
 +              break;
 +
 +      case MII_TG3_AUX_STAT_100FULL:
 +              *speed = SPEED_100;
 +              *duplex = DUPLEX_FULL;
 +              break;
 +
 +      case MII_TG3_AUX_STAT_1000HALF:
 +              *speed = SPEED_1000;
 +              *duplex = DUPLEX_HALF;
 +              break;
 +
 +      case MII_TG3_AUX_STAT_1000FULL:
 +              *speed = SPEED_1000;
 +              *duplex = DUPLEX_FULL;
 +              break;
 +
 +      default:
 +              if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
 +                      *speed = (val & MII_TG3_AUX_STAT_100) ? SPEED_100 :
 +                               SPEED_10;
 +                      *duplex = (val & MII_TG3_AUX_STAT_FULL) ? DUPLEX_FULL :
 +                                DUPLEX_HALF;
 +                      break;
 +              }
 +              *speed = SPEED_INVALID;
 +              *duplex = DUPLEX_INVALID;
 +              break;
 +      }
 +}
 +
 +static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl)
 +{
 +      int err = 0;
 +      u32 val, new_adv;
 +
 +      new_adv = ADVERTISE_CSMA;
 +      if (advertise & ADVERTISED_10baseT_Half)
 +              new_adv |= ADVERTISE_10HALF;
 +      if (advertise & ADVERTISED_10baseT_Full)
 +              new_adv |= ADVERTISE_10FULL;
 +      if (advertise & ADVERTISED_100baseT_Half)
 +              new_adv |= ADVERTISE_100HALF;
 +      if (advertise & ADVERTISED_100baseT_Full)
 +              new_adv |= ADVERTISE_100FULL;
 +
 +      new_adv |= tg3_advert_flowctrl_1000T(flowctrl);
 +
 +      err = tg3_writephy(tp, MII_ADVERTISE, new_adv);
 +      if (err)
 +              goto done;
 +
 +      if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
 +              goto done;
 +
 +      new_adv = 0;
 +      if (advertise & ADVERTISED_1000baseT_Half)
 +              new_adv |= ADVERTISE_1000HALF;
 +      if (advertise & ADVERTISED_1000baseT_Full)
 +              new_adv |= ADVERTISE_1000FULL;
 +
 +      if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
 +          tp->pci_chip_rev_id == CHIPREV_ID_5701_B0)
 +              new_adv |= CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER;
 +
 +      err = tg3_writephy(tp, MII_CTRL1000, new_adv);
 +      if (err)
 +              goto done;
 +
 +      if (!(tp->phy_flags & TG3_PHYFLG_EEE_CAP))
 +              goto done;
 +
 +      tw32(TG3_CPMU_EEE_MODE,
 +           tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE);
 +
 +      err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
 +      if (!err) {
 +              u32 err2;
 +
 +              val = 0;
 +              /* Advertise 100-BaseTX EEE ability */
 +              if (advertise & ADVERTISED_100baseT_Full)
 +                      val |= MDIO_AN_EEE_ADV_100TX;
 +              /* Advertise 1000-BaseT EEE ability */
 +              if (advertise & ADVERTISED_1000baseT_Full)
 +                      val |= MDIO_AN_EEE_ADV_1000T;
 +              err = tg3_phy_cl45_write(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, val);
 +              if (err)
 +                      val = 0;
 +
 +              switch (GET_ASIC_REV(tp->pci_chip_rev_id)) {
 +              case ASIC_REV_5717:
 +              case ASIC_REV_57765:
 +              case ASIC_REV_5719:
 +                      /* If we advertised any eee advertisements above... */
 +                      if (val)
 +                              val = MII_TG3_DSP_TAP26_ALNOKO |
 +                                    MII_TG3_DSP_TAP26_RMRXSTO |
 +                                    MII_TG3_DSP_TAP26_OPCSINPT;
 +                      tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val);
 +                      /* Fall through */
 +              case ASIC_REV_5720:
 +                      if (!tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val))
 +                              tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2, val |
 +                                               MII_TG3_DSP_CH34TP2_HIBW01);
 +              }
 +
 +              err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
 +              if (!err)
 +                      err = err2;
 +      }
 +
 +done:
 +      return err;
 +}
 +
 +static void tg3_phy_copper_begin(struct tg3 *tp)
 +{
 +      u32 new_adv;
 +      int i;
 +
 +      if (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER) {
 +              new_adv = ADVERTISED_10baseT_Half |
 +                        ADVERTISED_10baseT_Full;
 +              if (tg3_flag(tp, WOL_SPEED_100MB))
 +                      new_adv |= ADVERTISED_100baseT_Half |
 +                                 ADVERTISED_100baseT_Full;
 +
 +              tg3_phy_autoneg_cfg(tp, new_adv,
 +                                  FLOW_CTRL_TX | FLOW_CTRL_RX);
 +      } else if (tp->link_config.speed == SPEED_INVALID) {
 +              if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
 +                      tp->link_config.advertising &=
 +                              ~(ADVERTISED_1000baseT_Half |
 +                                ADVERTISED_1000baseT_Full);
 +
 +              tg3_phy_autoneg_cfg(tp, tp->link_config.advertising,
 +                                  tp->link_config.flowctrl);
 +      } else {
 +              /* Asking for a specific link mode. */
 +              if (tp->link_config.speed == SPEED_1000) {
 +                      if (tp->link_config.duplex == DUPLEX_FULL)
 +                              new_adv = ADVERTISED_1000baseT_Full;
 +                      else
 +                              new_adv = ADVERTISED_1000baseT_Half;
 +              } else if (tp->link_config.speed == SPEED_100) {
 +                      if (tp->link_config.duplex == DUPLEX_FULL)
 +                              new_adv = ADVERTISED_100baseT_Full;
 +                      else
 +                              new_adv = ADVERTISED_100baseT_Half;
 +              } else {
 +                      if (tp->link_config.duplex == DUPLEX_FULL)
 +                              new_adv = ADVERTISED_10baseT_Full;
 +                      else
 +                              new_adv = ADVERTISED_10baseT_Half;
 +              }
 +
 +              tg3_phy_autoneg_cfg(tp, new_adv,
 +                                  tp->link_config.flowctrl);
 +      }
 +
 +      if (tp->link_config.autoneg == AUTONEG_DISABLE &&
 +          tp->link_config.speed != SPEED_INVALID) {
 +              u32 bmcr, orig_bmcr;
 +
 +              tp->link_config.active_speed = tp->link_config.speed;
 +              tp->link_config.active_duplex = tp->link_config.duplex;
 +
 +              bmcr = 0;
 +              switch (tp->link_config.speed) {
 +              default:
 +              case SPEED_10:
 +                      break;
 +
 +              case SPEED_100:
 +                      bmcr |= BMCR_SPEED100;
 +                      break;
 +
 +              case SPEED_1000:
 +                      bmcr |= BMCR_SPEED1000;
 +                      break;
 +              }
 +
 +              if (tp->link_config.duplex == DUPLEX_FULL)
 +                      bmcr |= BMCR_FULLDPLX;
 +
 +              if (!tg3_readphy(tp, MII_BMCR, &orig_bmcr) &&
 +                  (bmcr != orig_bmcr)) {
 +                      tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK);
 +                      for (i = 0; i < 1500; i++) {
 +                              u32 tmp;
 +
 +                              udelay(10);
 +                              if (tg3_readphy(tp, MII_BMSR, &tmp) ||
 +                                  tg3_readphy(tp, MII_BMSR, &tmp))
 +                                      continue;
 +                              if (!(tmp & BMSR_LSTATUS)) {
 +                                      udelay(40);
 +                                      break;
 +                              }
 +                      }
 +                      tg3_writephy(tp, MII_BMCR, bmcr);
 +                      udelay(40);
 +              }
 +      } else {
 +              tg3_writephy(tp, MII_BMCR,
 +                           BMCR_ANENABLE | BMCR_ANRESTART);
 +      }
 +}
 +
 +static int tg3_init_5401phy_dsp(struct tg3 *tp)
 +{
 +      int err;
 +
 +      /* Turn off tap power management. */
 +      /* Set Extended packet length bit */
 +      err = tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, 0x4c20);
 +
 +      err |= tg3_phydsp_write(tp, 0x0012, 0x1804);
 +      err |= tg3_phydsp_write(tp, 0x0013, 0x1204);
 +      err |= tg3_phydsp_write(tp, 0x8006, 0x0132);
 +      err |= tg3_phydsp_write(tp, 0x8006, 0x0232);
 +      err |= tg3_phydsp_write(tp, 0x201f, 0x0a20);
 +
 +      udelay(40);
 +
 +      return err;
 +}
 +
 +static int tg3_copper_is_advertising_all(struct tg3 *tp, u32 mask)
 +{
 +      u32 adv_reg, all_mask = 0;
 +
 +      if (mask & ADVERTISED_10baseT_Half)
 +              all_mask |= ADVERTISE_10HALF;
 +      if (mask & ADVERTISED_10baseT_Full)
 +              all_mask |= ADVERTISE_10FULL;
 +      if (mask & ADVERTISED_100baseT_Half)
 +              all_mask |= ADVERTISE_100HALF;
 +      if (mask & ADVERTISED_100baseT_Full)
 +              all_mask |= ADVERTISE_100FULL;
 +
 +      if (tg3_readphy(tp, MII_ADVERTISE, &adv_reg))
 +              return 0;
 +
 +      if ((adv_reg & ADVERTISE_ALL) != all_mask)
 +              return 0;
 +
 +      if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY)) {
 +              u32 tg3_ctrl;
 +
 +              all_mask = 0;
 +              if (mask & ADVERTISED_1000baseT_Half)
 +                      all_mask |= ADVERTISE_1000HALF;
 +              if (mask & ADVERTISED_1000baseT_Full)
 +                      all_mask |= ADVERTISE_1000FULL;
 +
 +              if (tg3_readphy(tp, MII_CTRL1000, &tg3_ctrl))
 +                      return 0;
 +
 +              tg3_ctrl &= (ADVERTISE_1000HALF | ADVERTISE_1000FULL);
 +              if (tg3_ctrl != all_mask)
 +                      return 0;
 +      }
 +
 +      return 1;
 +}
 +
 +static int tg3_adv_1000T_flowctrl_ok(struct tg3 *tp, u32 *lcladv, u32 *rmtadv)
 +{
 +      u32 curadv, reqadv;
 +
 +      if (tg3_readphy(tp, MII_ADVERTISE, lcladv))
 +              return 1;
 +
 +      curadv = *lcladv & (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
 +      reqadv = tg3_advert_flowctrl_1000T(tp->link_config.flowctrl);
 +
 +      if (tp->link_config.active_duplex == DUPLEX_FULL) {
 +              if (curadv != reqadv)
 +                      return 0;
 +
 +              if (tg3_flag(tp, PAUSE_AUTONEG))
 +                      tg3_readphy(tp, MII_LPA, rmtadv);
 +      } else {
 +              /* Reprogram the advertisement register, even if it
 +               * does not affect the current link.  If the link
 +               * gets renegotiated in the future, we can save an
 +               * additional renegotiation cycle by advertising
 +               * it correctly in the first place.
 +               */
 +              if (curadv != reqadv) {
 +                      *lcladv &= ~(ADVERTISE_PAUSE_CAP |
 +                                   ADVERTISE_PAUSE_ASYM);
 +                      tg3_writephy(tp, MII_ADVERTISE, *lcladv | reqadv);
 +              }
 +      }
 +
 +      return 1;
 +}
 +
 +static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
 +{
 +      int current_link_up;
 +      u32 bmsr, val;
 +      u32 lcl_adv, rmt_adv;
 +      u16 current_speed;
 +      u8 current_duplex;
 +      int i, err;
 +
 +      tw32(MAC_EVENT, 0);
 +
 +      tw32_f(MAC_STATUS,
 +           (MAC_STATUS_SYNC_CHANGED |
 +            MAC_STATUS_CFG_CHANGED |
 +            MAC_STATUS_MI_COMPLETION |
 +            MAC_STATUS_LNKSTATE_CHANGED));
 +      udelay(40);
 +
 +      if ((tp->mi_mode & MAC_MI_MODE_AUTO_POLL) != 0) {
 +              tw32_f(MAC_MI_MODE,
 +                   (tp->mi_mode & ~MAC_MI_MODE_AUTO_POLL));
 +              udelay(80);
 +      }
 +
 +      tg3_phy_auxctl_write(tp, MII_TG3_AUXCTL_SHDWSEL_PWRCTL, 0);
 +
 +      /* Some third-party PHYs need to be reset on link going
 +       * down.
 +       */
 +      if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 ||
 +           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
 +           GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
 +          netif_carrier_ok(tp->dev)) {
 +              tg3_readphy(tp, MII_BMSR, &bmsr);
 +              if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
 +                  !(bmsr & BMSR_LSTATUS))
 +                      force_reset = 1;
 +      }
 +      if (force_reset)
 +              tg3_phy_reset(tp);
 +
 +      if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5401) {
 +              tg3_readphy(tp, MII_BMSR, &bmsr);
 +              if (tg3_readphy(tp, MII_BMSR, &bmsr) ||
 +                  !tg3_flag(tp, INIT_COMPLETE))
 +                      bmsr = 0;
 +
 +              if (!(bmsr & BMSR_LSTATUS)) {
 +                      err = tg3_init_5401phy_dsp(tp);
 +                      if (err)
 +                              return err;
 +
 +                      tg3_readphy(tp, MII_BMSR, &bmsr);
 +                      for (i = 0; i < 1000; i++) {
 +                              udelay(10);
 +                              if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
 +                                  (bmsr & BMSR_LSTATUS)) {
 +                                      udelay(40);
 +                                      break;
 +                              }
 +                      }
 +
 +                      if ((tp->phy_id & TG3_PHY_ID_REV_MASK) ==
 +                          TG3_PHY_REV_BCM5401_B0 &&
 +                          !(bmsr & BMSR_LSTATUS) &&
 +                          tp->link_config.active_speed == SPEED_1000) {
 +                              err = tg3_phy_reset(tp);
 +                              if (!err)
 +                                      err = tg3_init_5401phy_dsp(tp);
 +                              if (err)
 +                                      return err;
 +                      }
 +              }
 +      } else if (tp->pci_chip_rev_id == CHIPREV_ID_5701_A0 ||
 +                 tp->pci_chip_rev_id == CHIPREV_ID_5701_B0) {
 +              /* 5701 {A0,B0} CRC bug workaround */
 +              tg3_writephy(tp, 0x15, 0x0a75);
 +              tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68);
 +              tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8d68);
 +              tg3_writephy(tp, MII_TG3_MISC_SHDW, 0x8c68);
 +      }
 +
 +      /* Clear pending interrupts... */
 +      tg3_readphy(tp, MII_TG3_ISTAT, &val);
 +      tg3_readphy(tp, MII_TG3_ISTAT, &val);
 +
 +      if (tp->phy_flags & TG3_PHYFLG_USE_MI_INTERRUPT)
 +              tg3_writephy(tp, MII_TG3_IMASK, ~MII_TG3_INT_LINKCHG);
 +      else if (!(tp->phy_flags & TG3_PHYFLG_IS_FET))
 +              tg3_writephy(tp, MII_TG3_IMASK, ~0);
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 +          GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
 +              if (tp->led_ctrl == LED_CTRL_MODE_PHY_1)
 +                      tg3_writephy(tp, MII_TG3_EXT_CTRL,
 +                                   MII_TG3_EXT_CTRL_LNK3_LED_MODE);
 +              else
 +                      tg3_writephy(tp, MII_TG3_EXT_CTRL, 0);
 +      }
 +
 +      current_link_up = 0;
 +      current_speed = SPEED_INVALID;
 +      current_duplex = DUPLEX_INVALID;
 +
 +      if (tp->phy_flags & TG3_PHYFLG_CAPACITIVE_COUPLING) {
 +              err = tg3_phy_auxctl_read(tp,
 +                                        MII_TG3_AUXCTL_SHDWSEL_MISCTEST,
 +                                        &val);
 +              if (!err && !(val & (1 << 10))) {
 +                      tg3_phy_auxctl_write(tp,
 +                                           MII_TG3_AUXCTL_SHDWSEL_MISCTEST,
 +                                           val | (1 << 10));
 +                      goto relink;
 +              }
 +      }
 +
 +      bmsr = 0;
 +      for (i = 0; i < 100; i++) {
 +              tg3_readphy(tp, MII_BMSR, &bmsr);
 +              if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
 +                  (bmsr & BMSR_LSTATUS))
 +                      break;
 +              udelay(40);
 +      }
 +
 +      if (bmsr & BMSR_LSTATUS) {
 +              u32 aux_stat, bmcr;
 +
 +              tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
 +              for (i = 0; i < 2000; i++) {
 +                      udelay(10);
 +                      if (!tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat) &&
 +                          aux_stat)
 +                              break;
 +              }
 +
 +              tg3_aux_stat_to_speed_duplex(tp, aux_stat,
 +                                           &current_speed,
 +                                           &current_duplex);
 +
 +              bmcr = 0;
 +              for (i = 0; i < 200; i++) {
 +                      tg3_readphy(tp, MII_BMCR, &bmcr);
 +                      if (tg3_readphy(tp, MII_BMCR, &bmcr))
 +                              continue;
 +                      if (bmcr && bmcr != 0x7fff)
 +                              break;
 +                      udelay(10);
 +              }
 +
 +              lcl_adv = 0;
 +              rmt_adv = 0;
 +
 +              tp->link_config.active_speed = current_speed;
 +              tp->link_config.active_duplex = current_duplex;
 +
 +              if (tp->link_config.autoneg == AUTONEG_ENABLE) {
 +                      if ((bmcr & BMCR_ANENABLE) &&
 +                          tg3_copper_is_advertising_all(tp,
 +                                              tp->link_config.advertising)) {
 +                              if (tg3_adv_1000T_flowctrl_ok(tp, &lcl_adv,
 +                                                                &rmt_adv))
 +                                      current_link_up = 1;
 +                      }
 +              } else {
 +                      if (!(bmcr & BMCR_ANENABLE) &&
 +                          tp->link_config.speed == current_speed &&
 +                          tp->link_config.duplex == current_duplex &&
 +                          tp->link_config.flowctrl ==
 +                          tp->link_config.active_flowctrl) {
 +                              current_link_up = 1;
 +                      }
 +              }
 +
 +              if (current_link_up == 1 &&
 +                  tp->link_config.active_duplex == DUPLEX_FULL)
 +                      tg3_setup_flow_control(tp, lcl_adv, rmt_adv);
 +      }
 +
 +relink:
 +      if (current_link_up == 0 || (tp->phy_flags & TG3_PHYFLG_IS_LOW_POWER)) {
 +              tg3_phy_copper_begin(tp);
 +
 +              tg3_readphy(tp, MII_BMSR, &bmsr);
 +              if ((!tg3_readphy(tp, MII_BMSR, &bmsr) && (bmsr & BMSR_LSTATUS)) ||
 +                  (tp->mac_mode & MAC_MODE_PORT_INT_LPBACK))
 +                      current_link_up = 1;
 +      }
 +
 +      tp->mac_mode &= ~MAC_MODE_PORT_MODE_MASK;
 +      if (current_link_up == 1) {
 +              if (tp->link_config.active_speed == SPEED_100 ||
 +                  tp->link_config.active_speed == SPEED_10)
 +                      tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
 +              else
 +                      tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
 +      } else if (tp->phy_flags & TG3_PHYFLG_IS_FET)
 +              tp->mac_mode |= MAC_MODE_PORT_MODE_MII;
 +      else
 +              tp->mac_mode |= MAC_MODE_PORT_MODE_GMII;
 +
 +      tp->mac_mode &= ~MAC_MODE_HALF_DUPLEX;
 +      if (tp->link_config.active_duplex == DUPLEX_HALF)
 +              tp->mac_mode |= MAC_MODE_HALF_DUPLEX;
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700) {
 +              if (current_link_up == 1 &&
 +                  tg3_5700_link_polarity(tp, tp->link_config.active_speed))
 +                      tp->mac_mode |= MAC_MODE_LINK_POLARITY;
 +              else
 +                      tp->mac_mode &= ~MAC_MODE_LINK_POLARITY;
 +      }
 +
 +      /* ??? Without this setting Netgear GA302T PHY does not
 +       * ??? send/receive packets...
 +       */
 +      if ((tp->phy_id & TG3_PHY_ID_MASK) == TG3_PHY_ID_BCM5411 &&
 +          tp->pci_chip_rev_id == CHIPREV_ID_5700_ALTIMA) {
 +              tp->mi_mode |= MAC_MI_MODE_AUTO_POLL;
 +              tw32_f(MAC_MI_MODE, tp->mi_mode);
 +              udelay(80);
 +      }
 +
 +      tw32_f(MAC_MODE, tp->mac_mode);
 +      udelay(40);
 +
 +      tg3_phy_eee_adjust(tp, current_link_up);
 +
 +      if (tg3_flag(tp, USE_LINKCHG_REG)) {
 +              /* Polled via timer. */
 +              tw32_f(MAC_EVENT, 0);
 +      } else {
 +              tw32_f(MAC_EVENT, MAC_EVENT_LNKSTATE_CHANGED);
 +      }
 +      udelay(40);
 +
 +      if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 &&
 +          current_link_up == 1 &&
 +          tp->link_config.active_speed == SPEED_1000 &&
 +          (tg3_flag(tp, PCIX_MODE) || tg3_flag(tp, PCI_HIGH_SPEED))) {
 +              udelay(120);
 +              tw32_f(MAC_STATUS,
 +                   (MAC_STATUS_SYNC_CHANGED |
 +                    MAC_STATUS_CFG_CHANGED));
 +              udelay(40);
 +              tg3_write_mem(tp,
 +                            NIC_SRAM_FIRMWARE_MBOX,
 +                            NIC_SRAM_FIRMWARE_MBOX_MAGIC2);
 +      }
 +
 +      /* Prevent send BD corruption. */
 +      if (tg3_flag(tp, CLKREQ_BUG)) {
 +              u16 oldlnkctl, newlnkctl;
 +
 +              pci_read_config_word(tp->pdev,
 +                                   pci_pcie_cap(tp->pdev) + PCI_EXP_LNKCTL,
 +                                   &oldlnkctl);
 +              if (tp->link_config.active_speed == SPEED_100 ||
 +                  tp->link_config.active_speed == SPEED_10)
 +                      newlnkctl = oldlnkctl & ~PCI_EXP_LNKCTL_CLKREQ_EN;
 +              else
 +                      newlnkctl = oldlnkctl | PCI_EXP_LNKCTL_CLKREQ_EN;
 +              if (newlnkctl != oldlnkctl)
 +                      pci_write_config_word(tp->pdev,
 +                                            pci_pcie_cap(tp->pdev) +
 +                                            PCI_EXP_LNKCTL, newlnkctl);
 +      }
 +
 +      if (current_link_up != netif_carrier_ok(tp->dev)) {
 +              if (current_link_up)
 +                      netif_carrier_on(tp->dev);
 +              else
 +                      netif_carrier_off(tp->dev);
 +              tg3_link_report(tp);
 +      }
 +
 +      return 0;
 +}
 +
 +struct tg3_fiber_aneginfo {
 +      int state;
 +#define ANEG_STATE_UNKNOWN            0
 +#define ANEG_STATE_AN_ENABLE          1
 +#define ANEG_STATE_RESTART_INIT               2
 +#define ANEG_STATE_RESTART            3
 +#define ANEG_STATE_DISABLE_LINK_OK    4
 +#define ANEG_STATE_ABILITY_DETECT_INIT        5
 +#define ANEG_STATE_ABILITY_DETECT     6
 +#define ANEG_STATE_ACK_DETECT_INIT    7
 +#define ANEG_STATE_ACK_DETECT         8
 +#define ANEG_STATE_COMPLETE_ACK_INIT  9
 +#define ANEG_STATE_COMPLETE_ACK               10
 +#define ANEG_STATE_IDLE_DETECT_INIT   11
 +#define ANEG_STATE_IDLE_DETECT                12
 +#define ANEG_STATE_LINK_OK            13
 +#define ANEG_STATE_NEXT_PAGE_WAIT_INIT        14
 +#define ANEG_STATE_NEXT_PAGE_WAIT     15
 +
 +      u32 flags;
 +#define MR_AN_ENABLE          0x00000001
 +#define MR_RESTART_AN         0x00000002
 +#define MR_AN_COMPLETE                0x00000004
 +#define MR_PAGE_RX            0x00000008
 +#define MR_NP_LOADED          0x00000010
 +#define MR_TOGGLE_TX          0x00000020
 +#define MR_LP_ADV_FULL_DUPLEX 0x00000040
 +#define MR_LP_ADV_HALF_DUPLEX 0x00000080
 +#define MR_LP_ADV_SYM_PAUSE   0x00000100
 +#define MR_LP_ADV_ASYM_PAUSE  0x00000200
 +#define MR_LP_ADV_REMOTE_FAULT1       0x00000400
 +#define MR_LP_ADV_REMOTE_FAULT2       0x00000800
 +#define MR_LP_ADV_NEXT_PAGE   0x00001000
 +#define MR_TOGGLE_RX          0x00002000
 +#define MR_NP_RX              0x00004000
 +
 +#define MR_LINK_OK            0x80000000
 +
 +      unsigned long link_time, cur_time;
 +
 +      u32 ability_match_cfg;
 +      int ability_match_count;
 +
 +      char ability_match, idle_match, ack_match;
 +
 +      u32 txconfig, rxconfig;
 +#define ANEG_CFG_NP           0x00000080
 +#define ANEG_CFG_ACK          0x00000040
 +#define ANEG_CFG_RF2          0x00000020
 +#define ANEG_CFG_RF1          0x00000010
 +#define ANEG_CFG_PS2          0x00000001
 +#define ANEG_CFG_PS1          0x00008000
 +#define ANEG_CFG_HD           0x00004000
 +#define ANEG_CFG_FD           0x00002000
 +#define ANEG_CFG_INVAL                0x00001f06
 +
 +};
 +#define ANEG_OK               0
 +#define ANEG_DONE     1
 +#define ANEG_TIMER_ENAB       2
 +#define ANEG_FAILED   -1
 +
 +#define ANEG_STATE_SETTLE_TIME        10000
 +
 +static int tg3_fiber_aneg_smachine(struct tg3 *tp,
 +                                 struct tg3_fiber_aneginfo *ap)
 +{
 +      u16 flowctrl;
 +      unsigned long delta;
 +      u32 rx_cfg_reg;
 +      int ret;
 +
 +      if (ap->state == ANEG_STATE_UNKNOWN) {
 +              ap->rxconfig = 0;
 +              ap->link_time = 0;
 +              ap->cur_time = 0;
 +              ap->ability_match_cfg = 0;
 +              ap->ability_match_count = 0;
 +              ap->ability_match = 0;
 +              ap->idle_match = 0;
 +              ap->ack_match = 0;
 +      }
 +      ap->cur_time++;
 +
 +      if (tr32(MAC_STATUS) & MAC_STATUS_RCVD_CFG) {
 +              rx_cfg_reg = tr32(MAC_RX_AUTO_NEG);
 +
 +              if (rx_cfg_reg != ap->ability_match_cfg) {
 +                      ap->ability_match_cfg = rx_cfg_reg;
 +                      ap->ability_match = 0;
 +                      ap->ability_match_count = 0;
 +              } else {
 +                      if (++ap->ability_match_count > 1) {
 +                              ap->ability_match = 1;
 +                              ap->ability_match_cfg = rx_cfg_reg;
 +                      }
 +              }
 +              if (rx_cfg_reg & ANEG_CFG_ACK)
 +                      ap->ack_match = 1;
 +              else
 +                      ap->ack_match = 0;
 +
 +              ap->idle_match = 0;
 +      } else {
 +              ap->idle_match = 1;
 +              ap->ability_match_cfg = 0;
 +              ap->ability_match_count = 0;
 +              ap->ability_match = 0;
 +              ap->ack_match = 0;
 +
 +              rx_cfg_reg = 0;
 +      }
 +
 +      ap->rxconfig = rx_cfg_reg;
 +      ret = ANEG_OK;
 +
 +      switch (ap->state) {
 +      case ANEG_STATE_UNKNOWN:
 +              if (ap->flags & (MR_AN_ENABLE | MR_RESTART_AN))
 +                      ap->state = ANEG_STATE_AN_ENABLE;
 +
 +              /* fallthru */
 +      case ANEG_STATE_AN_ENABLE:
 +              ap->flags &= ~(MR_AN_COMPLETE | MR_PAGE_RX);
 +              if (ap->flags & MR_AN_ENABLE) {
 +                      ap->link_time = 0;
 +                      ap->cur_time = 0;
 +                      ap->ability_match_cfg = 0;
 +                      ap->ability_match_count = 0;
 +                      ap->ability_match = 0;
 +                      ap->idle_match = 0;
 +                      ap->ack_match = 0;
 +
 +                      ap->state = ANEG_STATE_RESTART_INIT;
 +              } else {
 +                      ap->state = ANEG_STATE_DISABLE_LINK_OK;
 +              }
 +              break;
 +
 +      case ANEG_STATE_RESTART_INIT:
 +              ap->link_time = ap->cur_time;
 +              ap->flags &= ~(MR_NP_LOADED);
 +              ap->txconfig = 0;
 +              tw32(MAC_TX_AUTO_NEG, 0);
 +              tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
 +              tw32_f(MAC_MODE, tp->mac_mode);
 +              udelay(40);
 +
 +              ret = ANEG_TIMER_ENAB;
 +              ap->state = ANEG_STATE_RESTART;
 +
 +              /* fallthru */
 +      case ANEG_STATE_RESTART:
 +              delta = ap->cur_time - ap->link_time;
 +              if (delta > ANEG_STATE_SETTLE_TIME)
 +                      ap->state = ANEG_STATE_ABILITY_DETECT_INIT;
 +              else
 +                      ret = ANEG_TIMER_ENAB;
 +              break;
 +
 +      case ANEG_STATE_DISABLE_LINK_OK:
 +              ret = ANEG_DONE;
 +              break;
 +
 +      case ANEG_STATE_ABILITY_DETECT_INIT:
 +              ap->flags &= ~(MR_TOGGLE_TX);
 +              ap->txconfig = ANEG_CFG_FD;
 +              flowctrl = tg3_advert_flowctrl_1000X(tp->link_config.flowctrl);
 +              if (flowctrl & ADVERTISE_1000XPAUSE)
 +                      ap->txconfig |= ANEG_CFG_PS1;
 +              if (flowctrl & ADVERTISE_1000XPSE_ASYM)
 +                      ap->txconfig |= ANEG_CFG_PS2;
 +              tw32(MAC_TX_AUTO_NEG, ap->txconfig);
 +              tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
 +              tw32_f(MAC_MODE, tp->mac_mode);
 +              udelay(40);
 +
 +              ap->state = ANEG_STATE_ABILITY_DETECT;
 +              break;
 +
 +      case ANEG_STATE_ABILITY_DETECT:
 +              if (ap->ability_match != 0 && ap->rxconfig != 0)
 +                      ap->state = ANEG_STATE_ACK_DETECT_INIT;
 +              break;
 +
 +      case ANEG_STATE_ACK_DETECT_INIT:
 +              ap->txconfig |= ANEG_CFG_ACK;
 +              tw32(MAC_TX_AUTO_NEG, ap->txconfig);
 +              tp->mac_mode |= MAC_MODE_SEND_CONFIGS;
 +              tw32_f(MAC_MODE, tp->mac_mode);
 +              udelay(40);
 +
 +              ap->state = ANEG_STATE_ACK_DETECT;
 +
 +              /* fallthru */
 +      case ANEG_STATE_ACK_DETECT:
 +              if (ap->ack_match != 0) {
 +                      if ((ap->rxconfig & ~ANEG_CFG_ACK) ==
 +                          (ap->ability_match_cfg & ~ANEG_CFG_ACK)) {
 +                              ap->state = ANEG_STATE_COMPLETE_ACK_INIT;
 +                      } else {
 +                              ap->state = ANEG_STATE_AN_ENABLE;
 +                      }
 +              } else if (ap->ability_match != 0 &&
 +                         ap->rxconfig == 0) {
 +                      ap->state = ANEG_STATE_AN_ENABLE;
 +              }
 +              break;
 +
 +      case ANEG_STATE_COMPLETE_ACK_INIT:
 +              if (ap->rxconfig & ANEG_CFG_INVAL) {
 +                      ret = ANEG_FAILED;
 +                      break;
 +              }
 +              ap->flags &= ~(MR_LP_ADV_FULL_DUPLEX |
 +                             MR_LP_ADV_HALF_DUPLEX |
 +                             MR_LP_ADV_SYM_PAUSE |
 +                             MR_LP_ADV_ASYM_PAUSE |
 +                             MR_LP_ADV_REMOTE_FAULT1 |
 +                             MR_LP_ADV_REMOTE_FAULT2 |
 +                             MR_LP_ADV_NEXT_PAGE |
 +                             MR_TOGGLE_RX |
 +                             MR_NP_RX);
 +              if (ap->rxconfig & ANEG_CFG_FD)
 +                      ap->flags |= MR_LP_ADV_FULL_DUPLEX;
 +              if (ap->rxconfig & ANEG_CFG_HD)
 +                      ap->flags |= MR_LP_ADV_HALF_DUPLEX;
 +              if (ap->rxconfig & ANEG_CFG_PS1)
 +                      ap->flags |= MR_LP_ADV_SYM_PAUSE;
 +              if (ap->rxconfig & ANEG_CFG_PS2)
 +                      ap->flags |= MR_LP_ADV_ASYM_PAUSE;
 +              if (ap->rxconfig & ANEG_CFG_RF1)
 +                      ap->flags |= MR_LP_ADV_REMOTE_FAULT1;
 +              if (ap->rxconfig & ANEG_CFG_RF2)
 +                      ap->flags |= MR_LP_ADV_REMOTE_FAULT2;
 +              if (ap->rxconfig & ANEG_CFG_NP)
 +                      ap->flags |= MR_LP_ADV_NEXT_PAGE;
 +
 +              ap->link_time = ap->cur_time;
 +
 +              ap->flags ^= (MR_TOGGLE_TX);
 +              if (ap->rxconfig & 0x0008)
 +                      ap->flags |= MR_TOGGLE_RX;
 +              if (ap->rxconfig & ANEG_CFG_NP)
 +                      ap->flags |= MR_NP_RX;
 +              ap->flags |= MR_PAGE_RX;
 +
 +              ap->state = ANEG_STATE_COMPLETE_ACK;
 +              ret = ANEG_TIMER_ENAB;
 +              break;
 +
 +      case ANEG_STATE_COMPLETE_ACK:
 +              if (ap->ability_match != 0 &&
 +                  ap->rxconfig == 0) {
 +                      ap->state = ANEG_STATE_AN_ENABLE;
 +                      break;
 +              }
 +              delta = ap->cur_time - ap->link_time;
 +              if (delta > ANEG_STATE_SETTLE_TIME) {
 +                      if (!(ap->flags & (MR_LP_ADV_NEXT_PAGE))) {
 +                              ap->state = ANEG_STATE_IDLE_DETECT_INIT;
 +                      } else {
 +                              if ((ap->txconfig & ANEG_CFG_NP) == 0 &&
 +                                  !(ap->flags & MR_NP_RX)) {
 +                                      ap->state = ANEG_STATE_IDLE_DETECT_INIT;
 +                              } else {
 +                                      ret = ANEG_FAILED;
 +                              }
 +                      }
 +              }
 +              break;
 +
 +      case ANEG_STATE_IDLE_DETECT_INIT:
 +              ap->link_time = ap->cur_time;
 +              tp->mac_mode &= ~MAC_MODE_SEND_CONFIGS;
 +              tw32_f(MAC_MODE, tp->mac_mode);
 +              udelay(40);
 +
 +