Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/net/ethernet/freescale/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 107 kB image not shown  

Quelle  ucc_geth.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 2006-2009 Freescale Semicondutor, Inc. All rights reserved.
 *
 * Author: Shlomi Gridish <gridish@freescale.com>
 *    Li Yang <leoli@freescale.com>
 *
 * Description:
 * QE UCC Gigabit Ethernet Driver
 */


#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/stddef.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/mm.h>
#include <linux/dma-mapping.h>
#include <linux/mii.h>
#include <linux/phy.h>
#include <linux/phylink.h>
#include <linux/workqueue.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/platform_device.h>
#include <linux/rtnetlink.h>

#include <linux/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <soc/fsl/qe/immap_qe.h>
#include <soc/fsl/qe/qe.h>
#include <soc/fsl/qe/ucc.h>
#include <soc/fsl/qe/ucc_fast.h>
#include <asm/machdep.h>

#include "ucc_geth.h"

#undef DEBUG

#define ugeth_printk(level, format, arg...)  \
        printk(level format "\n"## arg)

#define ugeth_dbg(format, arg...)            \
        ugeth_printk(KERN_DEBUG , format , ## arg)

#ifdef UGETH_VERBOSE_DEBUG
#define ugeth_vdbg ugeth_dbg
#else
#define ugeth_vdbg(fmt, args...) do { } while (0)
#endif    /* UGETH_VERBOSE_DEBUG */
#define UGETH_MSG_DEFAULT (NETIF_MSG_IFUP << 1 ) - 1


static DEFINE_SPINLOCK(ugeth_lock);

static struct {
 u32 msg_enable;
} debug = { -1 };

module_param_named(debug, debug.msg_enable, int, 0);
MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 0xffff=all)");

static int ucc_geth_thread_count(enum ucc_geth_num_of_threads idx)
{
 static const u8 count[] = {
  [UCC_GETH_NUM_OF_THREADS_1] = 1,
  [UCC_GETH_NUM_OF_THREADS_2] = 2,
  [UCC_GETH_NUM_OF_THREADS_4] = 4,
  [UCC_GETH_NUM_OF_THREADS_6] = 6,
  [UCC_GETH_NUM_OF_THREADS_8] = 8,
 };
 if (idx >= ARRAY_SIZE(count))
  return 0;
 return count[idx];
}

static inline int ucc_geth_tx_queues(const struct ucc_geth_info *info)
{
 return 1;
}

static inline int ucc_geth_rx_queues(const struct ucc_geth_info *info)
{
 return 1;
}

static const struct ucc_geth_info ugeth_primary_info = {
 .uf_info = {
      .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES,
      .max_rx_buf_length = 1536,
      /* adjusted at startup if max-speed 1000 */
      .urfs = UCC_GETH_URFS_INIT,
      .urfet = UCC_GETH_URFET_INIT,
      .urfset = UCC_GETH_URFSET_INIT,
      .utfs = UCC_GETH_UTFS_INIT,
      .utfet = UCC_GETH_UTFET_INIT,
      .utftt = UCC_GETH_UTFTT_INIT,
      .ufpt = 256,
      .mode = UCC_FAST_PROTOCOL_MODE_ETHERNET,
      .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL,
      .tenc = UCC_FAST_TX_ENCODING_NRZ,
      .renc = UCC_FAST_RX_ENCODING_NRZ,
      .tcrc = UCC_FAST_16_BIT_CRC,
      .synl = UCC_FAST_SYNC_LEN_NOT_USED,
      },
 .extendedFilteringChainPointer = ((uint32_t) NULL),
 .typeorlen = 3072 /*1536 */ ,
 .nonBackToBackIfgPart1 = 0x40,
 .nonBackToBackIfgPart2 = 0x60,
 .miminumInterFrameGapEnforcement = 0x50,
 .backToBackInterFrameGap = 0x60,
 .mblinterval = 128,
 .nortsrbytetime = 5,
 .fracsiz = 1,
 .strictpriorityq = 0xff,
 .altBebTruncation = 0xa,
 .excessDefer = 1,
 .maxRetransmission = 0xf,
 .collisionWindow = 0x37,
 .receiveFlowControl = 1,
 .transmitFlowControl = 1,
 .maxGroupAddrInHash = 4,
 .maxIndAddrInHash = 4,
 .maxFrameLength = 1518+16, /* Add extra bytes for VLANs etc. */
 .minFrameLength = 64,
 .maxD1Length = 1520+16, /* Add extra bytes for VLANs etc. */
 .maxD2Length = 1520+16, /* Add extra bytes for VLANs etc. */
 .vlantype = 0x8100,
 .ecamptr = ((uint32_t) NULL),
 .eventRegMask = UCCE_OTHER,
 .pausePeriod = 0xf000,
 .interruptcoalescingmaxvalue = {1, 1, 1, 1, 1, 1, 1, 1},
 .bdRingLenTx = {
   TX_BD_RING_LEN,
   TX_BD_RING_LEN,
   TX_BD_RING_LEN,
   TX_BD_RING_LEN,
   TX_BD_RING_LEN,
   TX_BD_RING_LEN,
   TX_BD_RING_LEN,
   TX_BD_RING_LEN},

 .bdRingLenRx = {
   RX_BD_RING_LEN,
   RX_BD_RING_LEN,
   RX_BD_RING_LEN,
   RX_BD_RING_LEN,
   RX_BD_RING_LEN,
   RX_BD_RING_LEN,
   RX_BD_RING_LEN,
   RX_BD_RING_LEN},

 .numStationAddresses = UCC_GETH_NUM_OF_STATION_ADDRESSES_1,
 .largestexternallookupkeysize =
     QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE,
 .statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE |
  UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX |
  UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX,
 .vlanOperationTagged = UCC_GETH_VLAN_OPERATION_TAGGED_NOP,
 .vlanOperationNonTagged = UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP,
 .rxQoSMode = UCC_GETH_QOS_MODE_DEFAULT,
 .aufc = UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE,
 .padAndCrc = MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC,
 .numThreadsTx = UCC_GETH_NUM_OF_THREADS_1,
 .numThreadsRx = UCC_GETH_NUM_OF_THREADS_1,
 .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
 .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
};

#ifdef DEBUG
static void mem_disp(u8 *addr, int size)
{
 u8 *i;
 int size16Aling = (size >> 4) << 4;
 int size4Aling = (size >> 2) << 2;
 int notAlign = 0;
 if (size % 16)
  notAlign = 1;

 for (i = addr; (u32) i < (u32) addr + size16Aling; i += 16)
  printk("0x%08x: %08x %08x %08x %08x\r\n",
         (u32) i,
         *((u32 *) (i)),
         *((u32 *) (i + 4)),
         *((u32 *) (i + 8)), *((u32 *) (i + 12)));
 if (notAlign == 1)
  printk("0x%08x: ", (u32) i);
 for (; (u32) i < (u32) addr + size4Aling; i += 4)
  printk("%08x ", *((u32 *) (i)));
 for (; (u32) i < (u32) addr + size; i++)
  printk("%02x", *((i)));
 if (notAlign == 1)
  printk("\r\n");
}
#endif /* DEBUG */

static struct list_head *dequeue(struct list_head *lh)
{
 unsigned long flags;

 spin_lock_irqsave(&ugeth_lock, flags);
 if (!list_empty(lh)) {
  struct list_head *node = lh->next;
  list_del(node);
  spin_unlock_irqrestore(&ugeth_lock, flags);
  return node;
 } else {
  spin_unlock_irqrestore(&ugeth_lock, flags);
  return NULL;
 }
}

static struct sk_buff *get_new_skb(struct ucc_geth_private *ugeth,
  u8 __iomem *bd)
{
 struct sk_buff *skb;

 skb = netdev_alloc_skb(ugeth->ndev,
          ugeth->ug_info->uf_info.max_rx_buf_length +
          UCC_GETH_RX_DATA_BUF_ALIGNMENT);
 if (!skb)
  return NULL;

 /* We need the data buffer to be aligned properly.  We will reserve
 * as many bytes as needed to align the data properly
 */

 skb_reserve(skb,
      UCC_GETH_RX_DATA_BUF_ALIGNMENT -
      (((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT -
           1)));

 out_be32(&((struct qe_bd __iomem *)bd)->buf,
        dma_map_single(ugeth->dev,
         skb->data,
         ugeth->ug_info->uf_info.max_rx_buf_length +
         UCC_GETH_RX_DATA_BUF_ALIGNMENT,
         DMA_FROM_DEVICE));

 out_be32((u32 __iomem *)bd,
   (R_E | R_I | (in_be32((u32 __iomem*)bd) & R_W)));

 return skb;
}

static int rx_bd_buffer_set(struct ucc_geth_private *ugeth, u8 rxQ)
{
 u8 __iomem *bd;
 u32 bd_status;
 struct sk_buff *skb;
 int i;

 bd = ugeth->p_rx_bd_ring[rxQ];
 i = 0;

 do {
  bd_status = in_be32((u32 __iomem *)bd);
  skb = get_new_skb(ugeth, bd);

  if (!skb) /* If can not allocate data buffer,
abort. Cleanup will be elsewhere */

   return -ENOMEM;

  ugeth->rx_skbuff[rxQ][i] = skb;

  /* advance the BD pointer */
  bd += sizeof(struct qe_bd);
  i++;
 } while (!(bd_status & R_W));

 return 0;
}

static int fill_init_enet_entries(struct ucc_geth_private *ugeth,
      u32 *p_start,
      u8 num_entries,
      u32 thread_size,
      u32 thread_alignment,
      unsigned int risc,
      int skip_page_for_first_entry)
{
 u32 init_enet_offset;
 u8 i;
 int snum;

 for (i = 0; i < num_entries; i++) {
  if ((snum = qe_get_snum()) < 0) {
   if (netif_msg_ifup(ugeth))
    pr_err("Can not get SNUM\n");
   return snum;
  }
  if ((i == 0) && skip_page_for_first_entry)
  /* First entry of Rx does not have page */
   init_enet_offset = 0;
  else {
   init_enet_offset =
       qe_muram_alloc(thread_size, thread_alignment);
   if (IS_ERR_VALUE(init_enet_offset)) {
    if (netif_msg_ifup(ugeth))
     pr_err("Can not allocate DPRAM memory\n");
    qe_put_snum((u8) snum);
    return -ENOMEM;
   }
  }
  *(p_start++) =
      ((u8) snum << ENET_INIT_PARAM_SNUM_SHIFT) | init_enet_offset
      | risc;
 }

 return 0;
}

static int return_init_enet_entries(struct ucc_geth_private *ugeth,
        u32 *p_start,
        u8 num_entries,
        unsigned int risc,
        int skip_page_for_first_entry)
{
 u32 init_enet_offset;
 u8 i;
 int snum;

 for (i = 0; i < num_entries; i++) {
  u32 val = *p_start;

  /* Check that this entry was actually valid --
needed in case failed in allocations */

  if ((val & ENET_INIT_PARAM_RISC_MASK) == risc) {
   snum =
       (u32) (val & ENET_INIT_PARAM_SNUM_MASK) >>
       ENET_INIT_PARAM_SNUM_SHIFT;
   qe_put_snum((u8) snum);
   if (!((i == 0) && skip_page_for_first_entry)) {
   /* First entry of Rx does not have page */
    init_enet_offset =
        (val & ENET_INIT_PARAM_PTR_MASK);
    qe_muram_free(init_enet_offset);
   }
   *p_start++ = 0;
  }
 }

 return 0;
}

#ifdef DEBUG
static int dump_init_enet_entries(struct ucc_geth_private *ugeth,
      u32 __iomem *p_start,
      u8 num_entries,
      u32 thread_size,
      unsigned int risc,
      int skip_page_for_first_entry)
{
 u32 init_enet_offset;
 u8 i;
 int snum;

 for (i = 0; i < num_entries; i++) {
  u32 val = in_be32(p_start);

  /* Check that this entry was actually valid --
needed in case failed in allocations */

  if ((val & ENET_INIT_PARAM_RISC_MASK) == risc) {
   snum =
       (u32) (val & ENET_INIT_PARAM_SNUM_MASK) >>
       ENET_INIT_PARAM_SNUM_SHIFT;
   qe_put_snum((u8) snum);
   if (!((i == 0) && skip_page_for_first_entry)) {
   /* First entry of Rx does not have page */
    init_enet_offset =
        (in_be32(p_start) &
         ENET_INIT_PARAM_PTR_MASK);
    pr_info("Init enet entry %d:\n", i);
    pr_info("Base address: 0x%08x\n",
     (u32)qe_muram_addr(init_enet_offset));
    mem_disp(qe_muram_addr(init_enet_offset),
      thread_size);
   }
   p_start++;
  }
 }

 return 0;
}
#endif

static void put_enet_addr_container(struct enet_addr_container *enet_addr_cont)
{
 kfree(enet_addr_cont);
}

static void set_mac_addr(__be16 __iomem *reg, u8 *mac)
{
 out_be16(®[0], ((u16)mac[5] << 8) | mac[4]);
 out_be16(®[1], ((u16)mac[3] << 8) | mac[2]);
 out_be16(®[2], ((u16)mac[1] << 8) | mac[0]);
}

static int hw_clear_addr_in_paddr(struct ucc_geth_private *ugeth, u8 paddr_num)
{
 struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt;

 if (paddr_num >= NUM_OF_PADDRS) {
  pr_warn("%s: Invalid paddr_num: %u\n", __func__, paddr_num);
  return -EINVAL;
 }

 p_82xx_addr_filt =
     (struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth->p_rx_glbl_pram->
     addressfiltering;

 /* Writing address ff.ff.ff.ff.ff.ff disables address
recognition for this register */

 out_be16(&p_82xx_addr_filt->paddr[paddr_num].h, 0xffff);
 out_be16(&p_82xx_addr_filt->paddr[paddr_num].m, 0xffff);
 out_be16(&p_82xx_addr_filt->paddr[paddr_num].l, 0xffff);

 return 0;
}

static void hw_add_addr_in_hash(struct ucc_geth_private *ugeth,
                                u8 *p_enet_addr)
{
 struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt;
 u32 cecr_subblock;

 p_82xx_addr_filt =
     (struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth->p_rx_glbl_pram->
     addressfiltering;

 cecr_subblock =
     ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);

 /* Ethernet frames are defined in Little Endian mode,
therefore to insert */

 /* the address to the hash (Big Endian mode), we reverse the bytes.*/

 set_mac_addr(&p_82xx_addr_filt->taddr.h, p_enet_addr);

 qe_issue_cmd(QE_SET_GROUP_ADDRESS, cecr_subblock,
       QE_CR_PROTOCOL_ETHERNET, 0);
}

#ifdef DEBUG
static void get_statistics(struct ucc_geth_private *ugeth,
      struct ucc_geth_tx_firmware_statistics *
      tx_firmware_statistics,
      struct ucc_geth_rx_firmware_statistics *
      rx_firmware_statistics,
      struct ucc_geth_hardware_statistics *hardware_statistics)
{
 struct ucc_fast __iomem *uf_regs;
 struct ucc_geth __iomem *ug_regs;
 struct ucc_geth_tx_firmware_statistics_pram *p_tx_fw_statistics_pram;
 struct ucc_geth_rx_firmware_statistics_pram *p_rx_fw_statistics_pram;

 ug_regs = ugeth->ug_regs;
 uf_regs = (struct ucc_fast __iomem *) ug_regs;
 p_tx_fw_statistics_pram = ugeth->p_tx_fw_statistics_pram;
 p_rx_fw_statistics_pram = ugeth->p_rx_fw_statistics_pram;

 /* Tx firmware only if user handed pointer and driver actually
gathers Tx firmware statistics */

 if (tx_firmware_statistics && p_tx_fw_statistics_pram) {
  tx_firmware_statistics->sicoltx =
      in_be32(&p_tx_fw_statistics_pram->sicoltx);
  tx_firmware_statistics->mulcoltx =
      in_be32(&p_tx_fw_statistics_pram->mulcoltx);
  tx_firmware_statistics->latecoltxfr =
      in_be32(&p_tx_fw_statistics_pram->latecoltxfr);
  tx_firmware_statistics->frabortduecol =
      in_be32(&p_tx_fw_statistics_pram->frabortduecol);
  tx_firmware_statistics->frlostinmactxer =
      in_be32(&p_tx_fw_statistics_pram->frlostinmactxer);
  tx_firmware_statistics->carriersenseertx =
      in_be32(&p_tx_fw_statistics_pram->carriersenseertx);
  tx_firmware_statistics->frtxok =
      in_be32(&p_tx_fw_statistics_pram->frtxok);
  tx_firmware_statistics->txfrexcessivedefer =
      in_be32(&p_tx_fw_statistics_pram->txfrexcessivedefer);
  tx_firmware_statistics->txpkts256 =
      in_be32(&p_tx_fw_statistics_pram->txpkts256);
  tx_firmware_statistics->txpkts512 =
      in_be32(&p_tx_fw_statistics_pram->txpkts512);
  tx_firmware_statistics->txpkts1024 =
      in_be32(&p_tx_fw_statistics_pram->txpkts1024);
  tx_firmware_statistics->txpktsjumbo =
      in_be32(&p_tx_fw_statistics_pram->txpktsjumbo);
 }

 /* Rx firmware only if user handed pointer and driver actually
 * gathers Rx firmware statistics */

 if (rx_firmware_statistics && p_rx_fw_statistics_pram) {
  int i;
  rx_firmware_statistics->frrxfcser =
      in_be32(&p_rx_fw_statistics_pram->frrxfcser);
  rx_firmware_statistics->fraligner =
      in_be32(&p_rx_fw_statistics_pram->fraligner);
  rx_firmware_statistics->inrangelenrxer =
      in_be32(&p_rx_fw_statistics_pram->inrangelenrxer);
  rx_firmware_statistics->outrangelenrxer =
      in_be32(&p_rx_fw_statistics_pram->outrangelenrxer);
  rx_firmware_statistics->frtoolong =
      in_be32(&p_rx_fw_statistics_pram->frtoolong);
  rx_firmware_statistics->runt =
      in_be32(&p_rx_fw_statistics_pram->runt);
  rx_firmware_statistics->verylongevent =
      in_be32(&p_rx_fw_statistics_pram->verylongevent);
  rx_firmware_statistics->symbolerror =
      in_be32(&p_rx_fw_statistics_pram->symbolerror);
  rx_firmware_statistics->dropbsy =
      in_be32(&p_rx_fw_statistics_pram->dropbsy);
  for (i = 0; i < 0x8; i++)
   rx_firmware_statistics->res0[i] =
       p_rx_fw_statistics_pram->res0[i];
  rx_firmware_statistics->mismatchdrop =
      in_be32(&p_rx_fw_statistics_pram->mismatchdrop);
  rx_firmware_statistics->underpkts =
      in_be32(&p_rx_fw_statistics_pram->underpkts);
  rx_firmware_statistics->pkts256 =
      in_be32(&p_rx_fw_statistics_pram->pkts256);
  rx_firmware_statistics->pkts512 =
      in_be32(&p_rx_fw_statistics_pram->pkts512);
  rx_firmware_statistics->pkts1024 =
      in_be32(&p_rx_fw_statistics_pram->pkts1024);
  rx_firmware_statistics->pktsjumbo =
      in_be32(&p_rx_fw_statistics_pram->pktsjumbo);
  rx_firmware_statistics->frlossinmacer =
      in_be32(&p_rx_fw_statistics_pram->frlossinmacer);
  rx_firmware_statistics->pausefr =
      in_be32(&p_rx_fw_statistics_pram->pausefr);
  for (i = 0; i < 0x4; i++)
   rx_firmware_statistics->res1[i] =
       p_rx_fw_statistics_pram->res1[i];
  rx_firmware_statistics->removevlan =
      in_be32(&p_rx_fw_statistics_pram->removevlan);
  rx_firmware_statistics->replacevlan =
      in_be32(&p_rx_fw_statistics_pram->replacevlan);
  rx_firmware_statistics->insertvlan =
      in_be32(&p_rx_fw_statistics_pram->insertvlan);
 }

 /* Hardware only if user handed pointer and driver actually
gathers hardware statistics */

 if (hardware_statistics &&
     (in_be32(&uf_regs->upsmr) & UCC_GETH_UPSMR_HSE)) {
  hardware_statistics->tx64 = in_be32(&ug_regs->tx64);
  hardware_statistics->tx127 = in_be32(&ug_regs->tx127);
  hardware_statistics->tx255 = in_be32(&ug_regs->tx255);
  hardware_statistics->rx64 = in_be32(&ug_regs->rx64);
  hardware_statistics->rx127 = in_be32(&ug_regs->rx127);
  hardware_statistics->rx255 = in_be32(&ug_regs->rx255);
  hardware_statistics->txok = in_be32(&ug_regs->txok);
  hardware_statistics->txcf = in_be16(&ug_regs->txcf);
  hardware_statistics->tmca = in_be32(&ug_regs->tmca);
  hardware_statistics->tbca = in_be32(&ug_regs->tbca);
  hardware_statistics->rxfok = in_be32(&ug_regs->rxfok);
  hardware_statistics->rxbok = in_be32(&ug_regs->rxbok);
  hardware_statistics->rbyt = in_be32(&ug_regs->rbyt);
  hardware_statistics->rmca = in_be32(&ug_regs->rmca);
  hardware_statistics->rbca = in_be32(&ug_regs->rbca);
 }
}

static void dump_bds(struct ucc_geth_private *ugeth)
{
 int i;
 int length;

 for (i = 0; i < ucc_geth_tx_queues(ugeth->ug_info); i++) {
  if (ugeth->p_tx_bd_ring[i]) {
   length =
       (ugeth->ug_info->bdRingLenTx[i] *
        sizeof(struct qe_bd));
   pr_info("TX BDs[%d]\n", i);
   mem_disp(ugeth->p_tx_bd_ring[i], length);
  }
 }
 for (i = 0; i < ucc_geth_rx_queues(ugeth->ug_info); i++) {
  if (ugeth->p_rx_bd_ring[i]) {
   length =
       (ugeth->ug_info->bdRingLenRx[i] *
        sizeof(struct qe_bd));
   pr_info("RX BDs[%d]\n", i);
   mem_disp(ugeth->p_rx_bd_ring[i], length);
  }
 }
}

static void dump_regs(struct ucc_geth_private *ugeth)
{
 int i;

 pr_info("UCC%d Geth registers:\n", ugeth->ug_info->uf_info.ucc_num + 1);
 pr_info("Base address: 0x%08x\n", (u32)ugeth->ug_regs);

 pr_info("maccfg1 : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->maccfg1,
  in_be32(&ugeth->ug_regs->maccfg1));
 pr_info("maccfg2 : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->maccfg2,
  in_be32(&ugeth->ug_regs->maccfg2));
 pr_info("ipgifg : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->ipgifg,
  in_be32(&ugeth->ug_regs->ipgifg));
 pr_info("hafdup : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->hafdup,
  in_be32(&ugeth->ug_regs->hafdup));
 pr_info("ifctl : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->ifctl,
  in_be32(&ugeth->ug_regs->ifctl));
 pr_info("ifstat : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->ifstat,
  in_be32(&ugeth->ug_regs->ifstat));
 pr_info("macstnaddr1: addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->macstnaddr1,
  in_be32(&ugeth->ug_regs->macstnaddr1));
 pr_info("macstnaddr2: addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->macstnaddr2,
  in_be32(&ugeth->ug_regs->macstnaddr2));
 pr_info("uempr : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->uempr,
  in_be32(&ugeth->ug_regs->uempr));
 pr_info("utbipar : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->utbipar,
  in_be32(&ugeth->ug_regs->utbipar));
 pr_info("uescr : addr - 0x%08x, val - 0x%04x\n",
  (u32)&ugeth->ug_regs->uescr,
  in_be16(&ugeth->ug_regs->uescr));
 pr_info("tx64 : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->tx64,
  in_be32(&ugeth->ug_regs->tx64));
 pr_info("tx127 : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->tx127,
  in_be32(&ugeth->ug_regs->tx127));
 pr_info("tx255 : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->tx255,
  in_be32(&ugeth->ug_regs->tx255));
 pr_info("rx64 : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->rx64,
  in_be32(&ugeth->ug_regs->rx64));
 pr_info("rx127 : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->rx127,
  in_be32(&ugeth->ug_regs->rx127));
 pr_info("rx255 : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->rx255,
  in_be32(&ugeth->ug_regs->rx255));
 pr_info("txok : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->txok,
  in_be32(&ugeth->ug_regs->txok));
 pr_info("txcf : addr - 0x%08x, val - 0x%04x\n",
  (u32)&ugeth->ug_regs->txcf,
  in_be16(&ugeth->ug_regs->txcf));
 pr_info("tmca : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->tmca,
  in_be32(&ugeth->ug_regs->tmca));
 pr_info("tbca : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->tbca,
  in_be32(&ugeth->ug_regs->tbca));
 pr_info("rxfok : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->rxfok,
  in_be32(&ugeth->ug_regs->rxfok));
 pr_info("rxbok : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->rxbok,
  in_be32(&ugeth->ug_regs->rxbok));
 pr_info("rbyt : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->rbyt,
  in_be32(&ugeth->ug_regs->rbyt));
 pr_info("rmca : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->rmca,
  in_be32(&ugeth->ug_regs->rmca));
 pr_info("rbca : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->rbca,
  in_be32(&ugeth->ug_regs->rbca));
 pr_info("scar : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->scar,
  in_be32(&ugeth->ug_regs->scar));
 pr_info("scam : addr - 0x%08x, val - 0x%08x\n",
  (u32)&ugeth->ug_regs->scam,
  in_be32(&ugeth->ug_regs->scam));

 if (ugeth->p_thread_data_tx) {
  int count = ucc_geth_thread_count(ugeth->ug_info->numThreadsTx);

  pr_info("Thread data TXs:\n");
  pr_info("Base address: 0x%08x\n",
   (u32)ugeth->p_thread_data_tx);
  for (i = 0; i < count; i++) {
   pr_info("Thread data TX[%d]:\n", i);
   pr_info("Base address: 0x%08x\n",
    (u32)&ugeth->p_thread_data_tx[i]);
   mem_disp((u8 *) & ugeth->p_thread_data_tx[i],
     sizeof(struct ucc_geth_thread_data_tx));
  }
 }
 if (ugeth->p_thread_data_rx) {
  int count = ucc_geth_thread_count(ugeth->ug_info->numThreadsRx);

  pr_info("Thread data RX:\n");
  pr_info("Base address: 0x%08x\n",
   (u32)ugeth->p_thread_data_rx);
  for (i = 0; i < count; i++) {
   pr_info("Thread data RX[%d]:\n", i);
   pr_info("Base address: 0x%08x\n",
    (u32)&ugeth->p_thread_data_rx[i]);
   mem_disp((u8 *) & ugeth->p_thread_data_rx[i],
     sizeof(struct ucc_geth_thread_data_rx));
  }
 }
 if (ugeth->p_exf_glbl_param) {
  pr_info("EXF global param:\n");
  pr_info("Base address: 0x%08x\n",
   (u32)ugeth->p_exf_glbl_param);
  mem_disp((u8 *) ugeth->p_exf_glbl_param,
    sizeof(*ugeth->p_exf_glbl_param));
 }
 if (ugeth->p_tx_glbl_pram) {
  pr_info("TX global param:\n");
  pr_info("Base address: 0x%08x\n", (u32)ugeth->p_tx_glbl_pram);
  pr_info("temoder : addr - 0x%08x, val - 0x%04x\n",
   (u32)&ugeth->p_tx_glbl_pram->temoder,
   in_be16(&ugeth->p_tx_glbl_pram->temoder));
        pr_info("sqptr : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_tx_glbl_pram->sqptr,
   in_be32(&ugeth->p_tx_glbl_pram->sqptr));
  pr_info("schedulerbasepointer: addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_tx_glbl_pram->schedulerbasepointer,
   in_be32(&ugeth->p_tx_glbl_pram->schedulerbasepointer));
  pr_info("txrmonbaseptr: addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_tx_glbl_pram->txrmonbaseptr,
   in_be32(&ugeth->p_tx_glbl_pram->txrmonbaseptr));
  pr_info("tstate : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_tx_glbl_pram->tstate,
   in_be32(&ugeth->p_tx_glbl_pram->tstate));
  pr_info("iphoffset[0] : addr - 0x%08x, val - 0x%02x\n",
   (u32)&ugeth->p_tx_glbl_pram->iphoffset[0],
   ugeth->p_tx_glbl_pram->iphoffset[0]);
  pr_info("iphoffset[1] : addr - 0x%08x, val - 0x%02x\n",
   (u32)&ugeth->p_tx_glbl_pram->iphoffset[1],
   ugeth->p_tx_glbl_pram->iphoffset[1]);
  pr_info("iphoffset[2] : addr - 0x%08x, val - 0x%02x\n",
   (u32)&ugeth->p_tx_glbl_pram->iphoffset[2],
   ugeth->p_tx_glbl_pram->iphoffset[2]);
  pr_info("iphoffset[3] : addr - 0x%08x, val - 0x%02x\n",
   (u32)&ugeth->p_tx_glbl_pram->iphoffset[3],
   ugeth->p_tx_glbl_pram->iphoffset[3]);
  pr_info("iphoffset[4] : addr - 0x%08x, val - 0x%02x\n",
   (u32)&ugeth->p_tx_glbl_pram->iphoffset[4],
   ugeth->p_tx_glbl_pram->iphoffset[4]);
  pr_info("iphoffset[5] : addr - 0x%08x, val - 0x%02x\n",
   (u32)&ugeth->p_tx_glbl_pram->iphoffset[5],
   ugeth->p_tx_glbl_pram->iphoffset[5]);
  pr_info("iphoffset[6] : addr - 0x%08x, val - 0x%02x\n",
   (u32)&ugeth->p_tx_glbl_pram->iphoffset[6],
   ugeth->p_tx_glbl_pram->iphoffset[6]);
  pr_info("iphoffset[7] : addr - 0x%08x, val - 0x%02x\n",
   (u32)&ugeth->p_tx_glbl_pram->iphoffset[7],
   ugeth->p_tx_glbl_pram->iphoffset[7]);
  pr_info("vtagtable[0] : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_tx_glbl_pram->vtagtable[0],
   in_be32(&ugeth->p_tx_glbl_pram->vtagtable[0]));
  pr_info("vtagtable[1] : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_tx_glbl_pram->vtagtable[1],
   in_be32(&ugeth->p_tx_glbl_pram->vtagtable[1]));
  pr_info("vtagtable[2] : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_tx_glbl_pram->vtagtable[2],
   in_be32(&ugeth->p_tx_glbl_pram->vtagtable[2]));
  pr_info("vtagtable[3] : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_tx_glbl_pram->vtagtable[3],
   in_be32(&ugeth->p_tx_glbl_pram->vtagtable[3]));
  pr_info("vtagtable[4] : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_tx_glbl_pram->vtagtable[4],
   in_be32(&ugeth->p_tx_glbl_pram->vtagtable[4]));
  pr_info("vtagtable[5] : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_tx_glbl_pram->vtagtable[5],
   in_be32(&ugeth->p_tx_glbl_pram->vtagtable[5]));
  pr_info("vtagtable[6] : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_tx_glbl_pram->vtagtable[6],
   in_be32(&ugeth->p_tx_glbl_pram->vtagtable[6]));
  pr_info("vtagtable[7] : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_tx_glbl_pram->vtagtable[7],
   in_be32(&ugeth->p_tx_glbl_pram->vtagtable[7]));
  pr_info("tqptr : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_tx_glbl_pram->tqptr,
   in_be32(&ugeth->p_tx_glbl_pram->tqptr));
 }
 if (ugeth->p_rx_glbl_pram) {
  pr_info("RX global param:\n");
  pr_info("Base address: 0x%08x\n", (u32)ugeth->p_rx_glbl_pram);
  pr_info("remoder : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_rx_glbl_pram->remoder,
   in_be32(&ugeth->p_rx_glbl_pram->remoder));
  pr_info("rqptr : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_rx_glbl_pram->rqptr,
   in_be32(&ugeth->p_rx_glbl_pram->rqptr));
  pr_info("typeorlen : addr - 0x%08x, val - 0x%04x\n",
   (u32)&ugeth->p_rx_glbl_pram->typeorlen,
   in_be16(&ugeth->p_rx_glbl_pram->typeorlen));
  pr_info("rxgstpack : addr - 0x%08x, val - 0x%02x\n",
   (u32)&ugeth->p_rx_glbl_pram->rxgstpack,
   ugeth->p_rx_glbl_pram->rxgstpack);
  pr_info("rxrmonbaseptr : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_rx_glbl_pram->rxrmonbaseptr,
   in_be32(&ugeth->p_rx_glbl_pram->rxrmonbaseptr));
  pr_info("intcoalescingptr: addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_rx_glbl_pram->intcoalescingptr,
   in_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr));
  pr_info("rstate : addr - 0x%08x, val - 0x%02x\n",
   (u32)&ugeth->p_rx_glbl_pram->rstate,
   ugeth->p_rx_glbl_pram->rstate);
  pr_info("mrblr : addr - 0x%08x, val - 0x%04x\n",
   (u32)&ugeth->p_rx_glbl_pram->mrblr,
   in_be16(&ugeth->p_rx_glbl_pram->mrblr));
  pr_info("rbdqptr : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_rx_glbl_pram->rbdqptr,
   in_be32(&ugeth->p_rx_glbl_pram->rbdqptr));
  pr_info("mflr : addr - 0x%08x, val - 0x%04x\n",
   (u32)&ugeth->p_rx_glbl_pram->mflr,
   in_be16(&ugeth->p_rx_glbl_pram->mflr));
  pr_info("minflr : addr - 0x%08x, val - 0x%04x\n",
   (u32)&ugeth->p_rx_glbl_pram->minflr,
   in_be16(&ugeth->p_rx_glbl_pram->minflr));
  pr_info("maxd1 : addr - 0x%08x, val - 0x%04x\n",
   (u32)&ugeth->p_rx_glbl_pram->maxd1,
   in_be16(&ugeth->p_rx_glbl_pram->maxd1));
  pr_info("maxd2 : addr - 0x%08x, val - 0x%04x\n",
   (u32)&ugeth->p_rx_glbl_pram->maxd2,
   in_be16(&ugeth->p_rx_glbl_pram->maxd2));
  pr_info("ecamptr : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_rx_glbl_pram->ecamptr,
   in_be32(&ugeth->p_rx_glbl_pram->ecamptr));
  pr_info("l2qt : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_rx_glbl_pram->l2qt,
   in_be32(&ugeth->p_rx_glbl_pram->l2qt));
  pr_info("l3qt[0] : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_rx_glbl_pram->l3qt[0],
   in_be32(&ugeth->p_rx_glbl_pram->l3qt[0]));
  pr_info("l3qt[1] : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_rx_glbl_pram->l3qt[1],
   in_be32(&ugeth->p_rx_glbl_pram->l3qt[1]));
  pr_info("l3qt[2] : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_rx_glbl_pram->l3qt[2],
   in_be32(&ugeth->p_rx_glbl_pram->l3qt[2]));
  pr_info("l3qt[3] : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_rx_glbl_pram->l3qt[3],
   in_be32(&ugeth->p_rx_glbl_pram->l3qt[3]));
  pr_info("l3qt[4] : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_rx_glbl_pram->l3qt[4],
   in_be32(&ugeth->p_rx_glbl_pram->l3qt[4]));
  pr_info("l3qt[5] : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_rx_glbl_pram->l3qt[5],
   in_be32(&ugeth->p_rx_glbl_pram->l3qt[5]));
  pr_info("l3qt[6] : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_rx_glbl_pram->l3qt[6],
   in_be32(&ugeth->p_rx_glbl_pram->l3qt[6]));
  pr_info("l3qt[7] : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_rx_glbl_pram->l3qt[7],
   in_be32(&ugeth->p_rx_glbl_pram->l3qt[7]));
  pr_info("vlantype : addr - 0x%08x, val - 0x%04x\n",
   (u32)&ugeth->p_rx_glbl_pram->vlantype,
   in_be16(&ugeth->p_rx_glbl_pram->vlantype));
  pr_info("vlantci : addr - 0x%08x, val - 0x%04x\n",
   (u32)&ugeth->p_rx_glbl_pram->vlantci,
   in_be16(&ugeth->p_rx_glbl_pram->vlantci));
  for (i = 0; i < 64; i++)
   pr_info("addressfiltering[%d]: addr - 0x%08x, val - 0x%02x\n",
    i,
    (u32)&ugeth->p_rx_glbl_pram->addressfiltering[i],
    ugeth->p_rx_glbl_pram->addressfiltering[i]);
  pr_info("exfGlobalParam : addr - 0x%08x, val - 0x%08x\n",
   (u32)&ugeth->p_rx_glbl_pram->exfGlobalParam,
   in_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam));
 }
 if (ugeth->p_send_q_mem_reg) {
  pr_info("Send Q memory registers:\n");
  pr_info("Base address: 0x%08x\n", (u32)ugeth->p_send_q_mem_reg);
  for (i = 0; i < ucc_geth_tx_queues(ugeth->ug_info); i++) {
   pr_info("SQQD[%d]:\n", i);
   pr_info("Base address: 0x%08x\n",
    (u32)&ugeth->p_send_q_mem_reg->sqqd[i]);
   mem_disp((u8 *) & ugeth->p_send_q_mem_reg->sqqd[i],
     sizeof(struct ucc_geth_send_queue_qd));
  }
 }
 if (ugeth->p_scheduler) {
  pr_info("Scheduler:\n");
  pr_info("Base address: 0x%08x\n", (u32)ugeth->p_scheduler);
  mem_disp((u8 *) ugeth->p_scheduler,
    sizeof(*ugeth->p_scheduler));
 }
 if (ugeth->p_tx_fw_statistics_pram) {
  pr_info("TX FW statistics pram:\n");
  pr_info("Base address: 0x%08x\n",
   (u32)ugeth->p_tx_fw_statistics_pram);
  mem_disp((u8 *) ugeth->p_tx_fw_statistics_pram,
    sizeof(*ugeth->p_tx_fw_statistics_pram));
 }
 if (ugeth->p_rx_fw_statistics_pram) {
  pr_info("RX FW statistics pram:\n");
  pr_info("Base address: 0x%08x\n",
   (u32)ugeth->p_rx_fw_statistics_pram);
  mem_disp((u8 *) ugeth->p_rx_fw_statistics_pram,
    sizeof(*ugeth->p_rx_fw_statistics_pram));
 }
 if (ugeth->p_rx_irq_coalescing_tbl) {
  pr_info("RX IRQ coalescing tables:\n");
  pr_info("Base address: 0x%08x\n",
   (u32)ugeth->p_rx_irq_coalescing_tbl);
  for (i = 0; i < ucc_geth_rx_queues(ugeth->ug_info); i++) {
   pr_info("RX IRQ coalescing table entry[%d]:\n", i);
   pr_info("Base address: 0x%08x\n",
    (u32)&ugeth->p_rx_irq_coalescing_tbl->
    coalescingentry[i]);
   pr_info("interruptcoalescingmaxvalue: addr - 0x%08x, val - 0x%08x\n",
    (u32)&ugeth->p_rx_irq_coalescing_tbl->
    coalescingentry[i].interruptcoalescingmaxvalue,
    in_be32(&ugeth->p_rx_irq_coalescing_tbl->
     coalescingentry[i].
     interruptcoalescingmaxvalue));
   pr_info("interruptcoalescingcounter : addr - 0x%08x, val - 0x%08x\n",
    (u32)&ugeth->p_rx_irq_coalescing_tbl->
    coalescingentry[i].interruptcoalescingcounter,
    in_be32(&ugeth->p_rx_irq_coalescing_tbl->
     coalescingentry[i].
     interruptcoalescingcounter));
  }
 }
 if (ugeth->p_rx_bd_qs_tbl) {
  pr_info("RX BD QS tables:\n");
  pr_info("Base address: 0x%08x\n", (u32)ugeth->p_rx_bd_qs_tbl);
  for (i = 0; i < ucc_geth_rx_queues(ugeth->ug_info); i++) {
   pr_info("RX BD QS table[%d]:\n", i);
   pr_info("Base address: 0x%08x\n",
    (u32)&ugeth->p_rx_bd_qs_tbl[i]);
   pr_info("bdbaseptr : addr - 0x%08x, val - 0x%08x\n",
    (u32)&ugeth->p_rx_bd_qs_tbl[i].bdbaseptr,
    in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdbaseptr));
   pr_info("bdptr : addr - 0x%08x, val - 0x%08x\n",
    (u32)&ugeth->p_rx_bd_qs_tbl[i].bdptr,
    in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdptr));
   pr_info("externalbdbaseptr: addr - 0x%08x, val - 0x%08x\n",
    (u32)&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,
    in_be32(&ugeth->p_rx_bd_qs_tbl[i].
     externalbdbaseptr));
   pr_info("externalbdptr : addr - 0x%08x, val - 0x%08x\n",
    (u32)&ugeth->p_rx_bd_qs_tbl[i].externalbdptr,
    in_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdptr));
   pr_info("ucode RX Prefetched BDs:\n");
   pr_info("Base address: 0x%08x\n",
    (u32)qe_muram_addr(in_be32
         (&ugeth->p_rx_bd_qs_tbl[i].
          bdbaseptr)));
   mem_disp((u8 *)
     qe_muram_addr(in_be32
            (&ugeth->p_rx_bd_qs_tbl[i].
      bdbaseptr)),
     sizeof(struct ucc_geth_rx_prefetched_bds));
  }
 }
 if (ugeth->p_init_enet_param_shadow) {
  int size;
  pr_info("Init enet param shadow:\n");
  pr_info("Base address: 0x%08x\n",
   (u32) ugeth->p_init_enet_param_shadow);
  mem_disp((u8 *) ugeth->p_init_enet_param_shadow,
    sizeof(*ugeth->p_init_enet_param_shadow));

  size = sizeof(struct ucc_geth_thread_rx_pram);
  if (ugeth->ug_info->rxExtendedFiltering) {
   size +=
       THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING;
   if (ugeth->ug_info->largestexternallookupkeysize ==
       QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES)
    size +=
   THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8;
   if (ugeth->ug_info->largestexternallookupkeysize ==
       QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES)
    size +=
   THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16;
  }

  dump_init_enet_entries(ugeth,
           &(ugeth->p_init_enet_param_shadow->
      txthread[0]),
           ENET_INIT_PARAM_MAX_ENTRIES_TX,
           sizeof(struct ucc_geth_thread_tx_pram),
           ugeth->ug_info->riscTx, 0);
  dump_init_enet_entries(ugeth,
           &(ugeth->p_init_enet_param_shadow->
      rxthread[0]),
           ENET_INIT_PARAM_MAX_ENTRIES_RX, size,
           ugeth->ug_info->riscRx, 1);
 }
}
#endif /* DEBUG */

static void init_default_reg_vals(u32 __iomem *upsmr_register,
      u32 __iomem *maccfg1_register,
      u32 __iomem *maccfg2_register)
{
 out_be32(upsmr_register, UCC_GETH_UPSMR_INIT);
 out_be32(maccfg1_register, UCC_GETH_MACCFG1_INIT);
 out_be32(maccfg2_register, UCC_GETH_MACCFG2_INIT);
}

static int init_half_duplex_params(int alt_beb,
       int back_pressure_no_backoff,
       int no_backoff,
       int excess_defer,
       u8 alt_beb_truncation,
       u8 max_retransmissions,
       u8 collision_window,
       u32 __iomem *hafdup_register)
{
 u32 value = 0;

 if ((alt_beb_truncation > HALFDUP_ALT_BEB_TRUNCATION_MAX) ||
     (max_retransmissions > HALFDUP_MAX_RETRANSMISSION_MAX) ||
     (collision_window > HALFDUP_COLLISION_WINDOW_MAX))
  return -EINVAL;

 value = (u32) (alt_beb_truncation << HALFDUP_ALT_BEB_TRUNCATION_SHIFT);

 if (alt_beb)
  value |= HALFDUP_ALT_BEB;
 if (back_pressure_no_backoff)
  value |= HALFDUP_BACK_PRESSURE_NO_BACKOFF;
 if (no_backoff)
  value |= HALFDUP_NO_BACKOFF;
 if (excess_defer)
  value |= HALFDUP_EXCESSIVE_DEFER;

 value |= (max_retransmissions << HALFDUP_MAX_RETRANSMISSION_SHIFT);

 value |= collision_window;

 out_be32(hafdup_register, value);
 return 0;
}

static int init_inter_frame_gap_params(u8 non_btb_cs_ipg,
           u8 non_btb_ipg,
           u8 min_ifg,
           u8 btb_ipg,
           u32 __iomem *ipgifg_register)
{
 u32 value = 0;

 /* Non-Back-to-back IPG part 1 should be <= Non-Back-to-back
IPG part 2 */

 if (non_btb_cs_ipg > non_btb_ipg)
  return -EINVAL;

 if ((non_btb_cs_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART1_MAX) ||
     (non_btb_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART2_MAX) ||
     /*(min_ifg        > IPGIFG_MINIMUM_IFG_ENFORCEMENT_MAX) || */
     (btb_ipg > IPGIFG_BACK_TO_BACK_IFG_MAX))
  return -EINVAL;

 value |=
     ((non_btb_cs_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART1_SHIFT) &
      IPGIFG_NBTB_CS_IPG_MASK);
 value |=
     ((non_btb_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART2_SHIFT) &
      IPGIFG_NBTB_IPG_MASK);
 value |=
     ((min_ifg << IPGIFG_MINIMUM_IFG_ENFORCEMENT_SHIFT) &
      IPGIFG_MIN_IFG_MASK);
 value |= (btb_ipg & IPGIFG_BTB_IPG_MASK);

 out_be32(ipgifg_register, value);
 return 0;
}

int init_flow_control_params(u32 automatic_flow_control_mode,
        int rx_flow_control_enable,
        int tx_flow_control_enable,
        u16 pause_period,
        u16 extension_field,
        u32 __iomem *upsmr_register,
        u32 __iomem *uempr_register,
        u32 __iomem *maccfg1_register)
{
 u32 value = 0;

 /* Set UEMPR register */
 value = (u32) pause_period << UEMPR_PAUSE_TIME_VALUE_SHIFT;
 value |= (u32) extension_field << UEMPR_EXTENDED_PAUSE_TIME_VALUE_SHIFT;
 out_be32(uempr_register, value);

 /* Set UPSMR register */
 setbits32(upsmr_register, automatic_flow_control_mode);

 value = in_be32(maccfg1_register);
 if (rx_flow_control_enable)
  value |= MACCFG1_FLOW_RX;
 if (tx_flow_control_enable)
  value |= MACCFG1_FLOW_TX;
 out_be32(maccfg1_register, value);

 return 0;
}

static int init_hw_statistics_gathering_mode(int enable_hardware_statistics,
          int auto_zero_hardware_statistics,
          u32 __iomem *upsmr_register,
          u16 __iomem *uescr_register)
{
 u16 uescr_value = 0;

 /* Enable hardware statistics gathering if requested */
 if (enable_hardware_statistics)
  setbits32(upsmr_register, UCC_GETH_UPSMR_HSE);

 /* Clear hardware statistics counters */
 uescr_value = in_be16(uescr_register);
 uescr_value |= UESCR_CLRCNT;
 /* Automatically zero hardware statistics counters on read,
if requested */

 if (auto_zero_hardware_statistics)
  uescr_value |= UESCR_AUTOZ;
 out_be16(uescr_register, uescr_value);

 return 0;
}

static int init_firmware_statistics_gathering_mode(int
  enable_tx_firmware_statistics,
  int enable_rx_firmware_statistics,
  u32 __iomem *tx_rmon_base_ptr,
  u32 tx_firmware_statistics_structure_address,
  u32 __iomem *rx_rmon_base_ptr,
  u32 rx_firmware_statistics_structure_address,
  u16 __iomem *temoder_register,
  u32 __iomem *remoder_register)
{
 /* Note: this function does not check if */
 /* the parameters it receives are NULL   */

 if (enable_tx_firmware_statistics) {
  out_be32(tx_rmon_base_ptr,
    tx_firmware_statistics_structure_address);
  setbits16(temoder_register, TEMODER_TX_RMON_STATISTICS_ENABLE);
 }

 if (enable_rx_firmware_statistics) {
  out_be32(rx_rmon_base_ptr,
    rx_firmware_statistics_structure_address);
  setbits32(remoder_register, REMODER_RX_RMON_STATISTICS_ENABLE);
 }

 return 0;
}

static int init_mac_station_addr_regs(u8 address_byte_0,
          u8 address_byte_1,
          u8 address_byte_2,
          u8 address_byte_3,
          u8 address_byte_4,
          u8 address_byte_5,
          u32 __iomem *macstnaddr1_register,
          u32 __iomem *macstnaddr2_register)
{
 u32 value = 0;

 /* Example: for a station address of 0x12345678ABCD, */
 /* 0x12 is byte 0, 0x34 is byte 1 and so on and 0xCD is byte 5 */

 /* MACSTNADDR1 Register: */

 /* 0                      7   8                      15  */
 /* station address byte 5     station address byte 4     */
 /* 16                     23  24                     31  */
 /* station address byte 3     station address byte 2     */
 value |= (u32) ((address_byte_2 << 0) & 0x000000FF);
 value |= (u32) ((address_byte_3 << 8) & 0x0000FF00);
 value |= (u32) ((address_byte_4 << 16) & 0x00FF0000);
 value |= (u32) ((address_byte_5 << 24) & 0xFF000000);

 out_be32(macstnaddr1_register, value);

 /* MACSTNADDR2 Register: */

 /* 0                      7   8                      15  */
 /* station address byte 1     station address byte 0     */
 /* 16                     23  24                     31  */
 /*         reserved                   reserved           */
 value = 0;
 value |= (u32) ((address_byte_0 << 16) & 0x00FF0000);
 value |= (u32) ((address_byte_1 << 24) & 0xFF000000);

 out_be32(macstnaddr2_register, value);

 return 0;
}

static int init_rx_parameters(int reject_broadcast,
         int receive_short_frames,
         int promiscuous, u32 __iomem *upsmr_register)
{
 u32 value = 0;

 value = in_be32(upsmr_register);

 if (reject_broadcast)
  value |= UCC_GETH_UPSMR_BRO;
 else
  value &= ~UCC_GETH_UPSMR_BRO;

 if (receive_short_frames)
  value |= UCC_GETH_UPSMR_RSH;
 else
  value &= ~UCC_GETH_UPSMR_RSH;

 if (promiscuous)
  value |= UCC_GETH_UPSMR_PRO;
 else
  value &= ~UCC_GETH_UPSMR_PRO;

 out_be32(upsmr_register, value);

 return 0;
}

static int init_max_rx_buff_len(u16 max_rx_buf_len,
    u16 __iomem *mrblr_register)
{
 /* max_rx_buf_len value must be a multiple of 128 */
 if ((max_rx_buf_len == 0) ||
     (max_rx_buf_len % UCC_GETH_MRBLR_ALIGNMENT))
  return -EINVAL;

 out_be16(mrblr_register, max_rx_buf_len);
 return 0;
}

static int init_min_frame_len(u16 min_frame_length,
         u16 __iomem *minflr_register,
         u16 __iomem *mrblr_register)
{
 u16 mrblr_value = 0;

 mrblr_value = in_be16(mrblr_register);
 if (min_frame_length >= (mrblr_value - 4))
  return -EINVAL;

 out_be16(minflr_register, min_frame_length);
 return 0;
}

static bool phy_interface_mode_is_reduced(phy_interface_t interface)
{
 return phy_interface_mode_is_rgmii(interface) ||
        interface == PHY_INTERFACE_MODE_RMII ||
        interface == PHY_INTERFACE_MODE_RTBI;
}

static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth)
{
 struct ucc_fast_private *uccf;
 u32 cecr_subblock;
 u32 temp;
 int i = 10;

 uccf = ugeth->uccf;

 /* Mask GRACEFUL STOP TX interrupt bit and clear it */
 clrbits32(uccf->p_uccm, UCC_GETH_UCCE_GRA);
 out_be32(uccf->p_ucce, UCC_GETH_UCCE_GRA);  /* clear by writing 1 */

 /* Issue host command */
 cecr_subblock =
     ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
 qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock,
       QE_CR_PROTOCOL_ETHERNET, 0);

 /* Wait for command to complete */
 do {
  msleep(10);
  temp = in_be32(uccf->p_ucce);
 } while (!(temp & UCC_GETH_UCCE_GRA) && --i);

 uccf->stopped_tx = 1;

 return 0;
}

static int ugeth_graceful_stop_rx(struct ucc_geth_private *ugeth)
{
 struct ucc_fast_private *uccf;
 u32 cecr_subblock;
 u8 temp;
 int i = 10;

 uccf = ugeth->uccf;

 /* Clear acknowledge bit */
 temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack);
 temp &= ~GRACEFUL_STOP_ACKNOWLEDGE_RX;
 out_8(&ugeth->p_rx_glbl_pram->rxgstpack, temp);

 /* Keep issuing command and checking acknowledge bit until
it is asserted, according to spec */

 do {
  /* Issue host command */
  cecr_subblock =
      ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.
      ucc_num);
  qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock,
        QE_CR_PROTOCOL_ETHERNET, 0);
  msleep(10);
  temp = in_8(&ugeth->p_rx_glbl_pram->rxgstpack);
 } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX) && --i);

 uccf->stopped_rx = 1;

 return 0;
}

static int ugeth_restart_tx(struct ucc_geth_private *ugeth)
{
 struct ucc_fast_private *uccf;
 u32 cecr_subblock;

 uccf = ugeth->uccf;

 cecr_subblock =
     ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
 qe_issue_cmd(QE_RESTART_TX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET, 0);
 uccf->stopped_tx = 0;

 return 0;
}

static int ugeth_restart_rx(struct ucc_geth_private *ugeth)
{
 struct ucc_fast_private *uccf;
 u32 cecr_subblock;

 uccf = ugeth->uccf;

 cecr_subblock =
     ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
 qe_issue_cmd(QE_RESTART_RX, cecr_subblock, QE_CR_PROTOCOL_ETHERNET,
       0);
 uccf->stopped_rx = 0;

 return 0;
}

static int ugeth_enable(struct ucc_geth_private *ugeth, enum comm_dir mode)
{
 struct ucc_fast_private *uccf;
 int enabled_tx, enabled_rx;

 uccf = ugeth->uccf;

 /* check if the UCC number is in range. */
 if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
  if (netif_msg_probe(ugeth))
   pr_err("ucc_num out of range\n");
  return -EINVAL;
 }

 enabled_tx = uccf->enabled_tx;
 enabled_rx = uccf->enabled_rx;

 /* Get Tx and Rx going again, in case this channel was actively
disabled. */

 if ((mode & COMM_DIR_TX) && (!enabled_tx) && uccf->stopped_tx)
  ugeth_restart_tx(ugeth);
 if ((mode & COMM_DIR_RX) && (!enabled_rx) && uccf->stopped_rx)
  ugeth_restart_rx(ugeth);

 ucc_fast_enable(uccf, mode); /* OK to do even if not disabled */

 return 0;

}

static int ugeth_disable(struct ucc_geth_private *ugeth, enum comm_dir mode)
{
 struct ucc_fast_private *uccf;

 uccf = ugeth->uccf;

 /* check if the UCC number is in range. */
 if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
  if (netif_msg_probe(ugeth))
   pr_err("ucc_num out of range\n");
  return -EINVAL;
 }

 /* Stop any transmissions */
 if ((mode & COMM_DIR_TX) && uccf->enabled_tx && !uccf->stopped_tx)
  ugeth_graceful_stop_tx(ugeth);

 /* Stop any receptions */
 if ((mode & COMM_DIR_RX) && uccf->enabled_rx && !uccf->stopped_rx)
  ugeth_graceful_stop_rx(ugeth);

 ucc_fast_disable(ugeth->uccf, mode); /* OK to do even if not enabled */

 return 0;
}

static void ugeth_quiesce(struct ucc_geth_private *ugeth)
{
 /* Prevent any further xmits */
 netif_tx_stop_all_queues(ugeth->ndev);

 /* Disable the interrupt to avoid NAPI rescheduling. */
 disable_irq(ugeth->ug_info->uf_info.irq);

 /* Stop NAPI, and possibly wait for its completion. */
 napi_disable(&ugeth->napi);
}

static void ugeth_activate(struct ucc_geth_private *ugeth)
{
 napi_enable(&ugeth->napi);
 enable_irq(ugeth->ug_info->uf_info.irq);

 /* allow to xmit again  */
 netif_tx_wake_all_queues(ugeth->ndev);
 netdev_watchdog_up(ugeth->ndev);
}

/* Initialize TBI PHY interface for communicating with the
 * SERDES lynx PHY on the chip.  We communicate with this PHY
 * through the MDIO bus on each controller, treating it as a
 * "normal" PHY at the address found in the UTBIPA register.  We assume
 * that the UTBIPA register is valid.  Either the MDIO bus code will set
 * it to a value that doesn't conflict with other PHYs on the bus, or the
 * value doesn't matter, as there are no other PHYs on the bus.
 */

static void uec_configure_serdes(struct net_device *dev)
{
 struct ucc_geth_private *ugeth = netdev_priv(dev);
 struct ucc_geth_info *ug_info = ugeth->ug_info;
 struct phy_device *tbiphy;

 if (!ug_info->tbi_node) {
  dev_warn(&dev->dev, "SGMII mode requires that the device tree specify a tbi-handle\n");
  return;
 }

 tbiphy = of_phy_find_device(ug_info->tbi_node);
 if (!tbiphy) {
  dev_err(&dev->dev, "error: Could not get TBI device\n");
  return;
 }

 /*
 * If the link is already up, we must already be ok, and don't need to
 * configure and reset the TBI<->SerDes link.  Maybe U-Boot configured
 * everything for us?  Resetting it takes the link down and requires
 * several seconds for it to come back.
 */

 if (phy_read(tbiphy, ENET_TBI_MII_SR) & TBISR_LSTATUS) {
  put_device(&tbiphy->mdio.dev);
  return;
 }

 /* Single clk mode, mii mode off(for serdes communication) */
 phy_write(tbiphy, ENET_TBI_MII_ANA, TBIANA_SETTINGS);

 phy_write(tbiphy, ENET_TBI_MII_TBICON, TBICON_CLK_SELECT);

 phy_write(tbiphy, ENET_TBI_MII_CR, TBICR_SETTINGS);

 put_device(&tbiphy->mdio.dev);
}

static void ugeth_mac_link_up(struct phylink_config *config, struct phy_device *phy,
         unsigned int mode, phy_interface_t interface,
         int speed, int duplex, bool tx_pause, bool rx_pause)
{
 struct net_device *ndev = to_net_dev(config->dev);
 struct ucc_geth_private *ugeth = netdev_priv(ndev);
 struct ucc_geth_info *ug_info = ugeth->ug_info;
 struct ucc_geth __iomem *ug_regs = ugeth->ug_regs;
 struct ucc_fast __iomem *uf_regs = ugeth->uccf->uf_regs;
 u32 old_maccfg2, maccfg2 = in_be32(&ug_regs->maccfg2);
 u32 old_upsmr, upsmr = in_be32(&uf_regs->upsmr);

 old_maccfg2 = maccfg2;
 old_upsmr = upsmr;

 /* No length check */
 maccfg2 &= ~MACCFG2_LC;
 maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK;
 upsmr &= ~(UCC_GETH_UPSMR_RPM | UCC_GETH_UPSMR_R10M |
     UCC_GETH_UPSMR_TBIM | UCC_GETH_UPSMR_RMM);

 if (speed == SPEED_10 || speed == SPEED_100)
  maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
 else if (speed == SPEED_1000)
  maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;

 maccfg2 |= ug_info->padAndCrc;

 if (phy_interface_mode_is_reduced(interface)) {

  if (interface != PHY_INTERFACE_MODE_RMII)
   upsmr |= UCC_GETH_UPSMR_RPM;

  switch (speed) {
  case SPEED_10:
   upsmr |= UCC_GETH_UPSMR_R10M;
   fallthrough;
  case SPEED_100:
   if (interface != PHY_INTERFACE_MODE_RTBI)
    upsmr |= UCC_GETH_UPSMR_RMM;
  }
 }

 if (interface == PHY_INTERFACE_MODE_TBI ||
     interface == PHY_INTERFACE_MODE_RTBI)
  upsmr |= UCC_GETH_UPSMR_TBIM;

 if (interface == PHY_INTERFACE_MODE_SGMII)
  upsmr |= UCC_GETH_UPSMR_SGMM;

 if (duplex == DUPLEX_HALF)
  maccfg2 &= ~(MACCFG2_FDX);
 else
  maccfg2 |= MACCFG2_FDX;

 if (maccfg2 != old_maccfg2 || upsmr != old_upsmr) {
  /*
 * To change the MAC configuration we need to disable
 * the controller. To do so, we have to either grab
 * ugeth->lock, which is a bad idea since 'graceful
 * stop' commands might take quite a while, or we can
 * quiesce driver's activity.
 */

  ugeth_quiesce(ugeth);
  ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);

  out_be32(&ug_regs->maccfg2, maccfg2);
  out_be32(&uf_regs->upsmr, upsmr);

  ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
  ugeth_activate(ugeth);
 }

 if (interface == PHY_INTERFACE_MODE_SGMII)
  uec_configure_serdes(ndev);

 if (!phylink_autoneg_inband(mode)) {
  ug_info->aufc = 0;
  ug_info->receiveFlowControl = rx_pause;
  ug_info->transmitFlowControl = tx_pause;

  init_flow_control_params(ug_info->aufc,
      ug_info->receiveFlowControl,
      ug_info->transmitFlowControl,
      ug_info->pausePeriod,
      ug_info->extensionField,
      &ugeth->uccf->uf_regs->upsmr,
      &ugeth->ug_regs->uempr,
      &ugeth->ug_regs->maccfg1);
 }

 ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
}

static void ugeth_mac_link_down(struct phylink_config *config,
    unsigned int mode, phy_interface_t interface)
{
 struct net_device *ndev = to_net_dev(config->dev);
 struct ucc_geth_private *ugeth = netdev_priv(ndev);

 ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
}

static void ugeth_mac_config(struct phylink_config *config, unsigned int mode,
        const struct phylink_link_state *state)
{
 struct net_device *ndev = to_net_dev(config->dev);
 struct ucc_geth_private *ugeth = netdev_priv(ndev);
 struct ucc_geth_info *ug_info = ugeth->ug_info;
 u16 value;

 if (state->interface == PHY_INTERFACE_MODE_TBI ||
     state->interface == PHY_INTERFACE_MODE_RTBI) {
  struct phy_device *tbiphy;

  if (!ug_info->tbi_node)
   pr_warn("TBI mode requires that the device tree specify a tbi-handle\n");

  tbiphy = of_phy_find_device(ug_info->tbi_node);
  if (!tbiphy)
   pr_warn("Could not get TBI device\n");

  value = phy_read(tbiphy, ENET_TBI_MII_CR);
  value &= ~0x1000; /* Turn off autonegotiation */
  phy_write(tbiphy, ENET_TBI_MII_CR, value);

  put_device(&tbiphy->mdio.dev);
 }

 if (phylink_autoneg_inband(mode)) {
  ug_info->aufc = 1;

  init_flow_control_params(ug_info->aufc, 1, 1,
      ug_info->pausePeriod,
      ug_info->extensionField,
      &ugeth->uccf->uf_regs->upsmr,
      &ugeth->ug_regs->uempr,
      &ugeth->ug_regs->maccfg1);
 }
}

static void ugeth_dump_regs(struct ucc_geth_private *ugeth)
{
#ifdef DEBUG
 ucc_fast_dump_regs(ugeth->uccf);
 dump_regs(ugeth);
 dump_bds(ugeth);
#endif
}

static int ugeth_82xx_filtering_clear_all_addr_in_hash(struct ucc_geth_private *
             ugeth,
             enum enet_addr_type
             enet_addr_type)
{
 struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt;
 struct ucc_fast_private *uccf;
 enum comm_dir comm_dir;
 struct list_head *p_lh;
 u16 i, num;
 u32 __iomem *addr_h;
 u32 __iomem *addr_l;
 u8 *p_counter;

 uccf = ugeth->uccf;

 p_82xx_addr_filt =
     (struct ucc_geth_82xx_address_filtering_pram __iomem *)
     ugeth->p_rx_glbl_pram->addressfiltering;

 if (enet_addr_type == ENET_ADDR_TYPE_GROUP) {
  addr_h = &(p_82xx_addr_filt->gaddr_h);
  addr_l = &(p_82xx_addr_filt->gaddr_l);
  p_lh = &ugeth->group_hash_q;
  p_counter = &(ugeth->numGroupAddrInHash);
 } else if (enet_addr_type == ENET_ADDR_TYPE_INDIVIDUAL) {
  addr_h = &(p_82xx_addr_filt->iaddr_h);
  addr_l = &(p_82xx_addr_filt->iaddr_l);
  p_lh = &ugeth->ind_hash_q;
  p_counter = &(ugeth->numIndAddrInHash);
 } else
  return -EINVAL;

 comm_dir = 0;
 if (uccf->enabled_tx)
  comm_dir |= COMM_DIR_TX;
 if (uccf->enabled_rx)
  comm_dir |= COMM_DIR_RX;
 if (comm_dir)
  ugeth_disable(ugeth, comm_dir);

 /* Clear the hash table. */
 out_be32(addr_h, 0x00000000);
 out_be32(addr_l, 0x00000000);

 if (!p_lh)
  return 0;

 num = *p_counter;

 /* Delete all remaining CQ elements */
 for (i = 0; i < num; i++)
  put_enet_addr_container(ENET_ADDR_CONT_ENTRY(dequeue(p_lh)));

 *p_counter = 0;

 if (comm_dir)
  ugeth_enable(ugeth, comm_dir);

 return 0;
}

static int ugeth_82xx_filtering_clear_addr_in_paddr(struct ucc_geth_private *ugeth,
          u8 paddr_num)
{
 ugeth->indAddrRegUsed[paddr_num] = 0; /* mark this paddr as not used */
 return hw_clear_addr_in_paddr(ugeth, paddr_num);/* clear in hardware */
}

static void ucc_geth_free_rx(struct ucc_geth_private *ugeth)
{
 struct ucc_geth_info *ug_info;
 struct ucc_fast_info *uf_info;
 u16 i, j;
 u8 __iomem *bd;


 ug_info = ugeth->ug_info;
 uf_info = &ug_info->uf_info;

 for (i = 0; i < ucc_geth_rx_queues(ugeth->ug_info); i++) {
  if (ugeth->p_rx_bd_ring[i]) {
   /* Return existing data buffers in ring */
   bd = ugeth->p_rx_bd_ring[i];
   for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) {
    if (ugeth->rx_skbuff[i][j]) {
     dma_unmap_single(ugeth->dev,
      in_be32(&((struct qe_bd __iomem *)bd)->buf),
      ugeth->ug_info->
      uf_info.max_rx_buf_length +
      UCC_GETH_RX_DATA_BUF_ALIGNMENT,
      DMA_FROM_DEVICE);
     dev_kfree_skb_any(
      ugeth->rx_skbuff[i][j]);
     ugeth->rx_skbuff[i][j] = NULL;
    }
    bd += sizeof(struct qe_bd);
   }

   kfree(ugeth->rx_skbuff[i]);

   kfree(ugeth->p_rx_bd_ring[i]);
   ugeth->p_rx_bd_ring[i] = NULL;
  }
 }

}

static void ucc_geth_free_tx(struct ucc_geth_private *ugeth)
{
 struct ucc_geth_info *ug_info;
 struct ucc_fast_info *uf_info;
 u16 i, j;
 u8 __iomem *bd;

 netdev_reset_queue(ugeth->ndev);

 ug_info = ugeth->ug_info;
 uf_info = &ug_info->uf_info;

 for (i = 0; i < ucc_geth_tx_queues(ugeth->ug_info); i++) {
  bd = ugeth->p_tx_bd_ring[i];
  if (!bd)
   continue;
  for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) {
   if (ugeth->tx_skbuff[i][j]) {
    dma_unmap_single(ugeth->dev,
       in_be32(&((struct qe_bd __iomem *)bd)->buf),
       (in_be32((u32 __iomem *)bd) &
        BD_LENGTH_MASK),
       DMA_TO_DEVICE);
    dev_kfree_skb_any(ugeth->tx_skbuff[i][j]);
    ugeth->tx_skbuff[i][j] = NULL;
   }
  }

  kfree(ugeth->tx_skbuff[i]);

  kfree(ugeth->p_tx_bd_ring[i]);
  ugeth->p_tx_bd_ring[i] = NULL;
 }

}

static void ucc_geth_memclean(struct ucc_geth_private *ugeth)
{
 if (!ugeth)
  return;

 if (ugeth->uccf) {
  ucc_fast_free(ugeth->uccf);
  ugeth->uccf = NULL;
 }

 qe_muram_free_addr(ugeth->p_thread_data_tx);
 ugeth->p_thread_data_tx = NULL;

 qe_muram_free_addr(ugeth->p_thread_data_rx);
 ugeth->p_thread_data_rx = NULL;

 qe_muram_free_addr(ugeth->p_exf_glbl_param);
 ugeth->p_exf_glbl_param = NULL;

 qe_muram_free_addr(ugeth->p_rx_glbl_pram);
 ugeth->p_rx_glbl_pram = NULL;

 qe_muram_free_addr(ugeth->p_tx_glbl_pram);
 ugeth->p_tx_glbl_pram = NULL;

 qe_muram_free_addr(ugeth->p_send_q_mem_reg);
 ugeth->p_send_q_mem_reg = NULL;

 qe_muram_free_addr(ugeth->p_scheduler);
 ugeth->p_scheduler = NULL;

 qe_muram_free_addr(ugeth->p_tx_fw_statistics_pram);
 ugeth->p_tx_fw_statistics_pram = NULL;

 qe_muram_free_addr(ugeth->p_rx_fw_statistics_pram);
 ugeth->p_rx_fw_statistics_pram = NULL;

 qe_muram_free_addr(ugeth->p_rx_irq_coalescing_tbl);
 ugeth->p_rx_irq_coalescing_tbl = NULL;

 qe_muram_free_addr(ugeth->p_rx_bd_qs_tbl);
 ugeth->p_rx_bd_qs_tbl = NULL;

 if (ugeth->p_init_enet_param_shadow) {
  return_init_enet_entries(ugeth,
      &(ugeth->p_init_enet_param_shadow->
        rxthread[0]),
      ENET_INIT_PARAM_MAX_ENTRIES_RX,
      ugeth->ug_info->riscRx, 1);
  return_init_enet_entries(ugeth,
      &(ugeth->p_init_enet_param_shadow->
        txthread[0]),
      ENET_INIT_PARAM_MAX_ENTRIES_TX,
      ugeth->ug_info->riscTx, 0);
  kfree(ugeth->p_init_enet_param_shadow);
  ugeth->p_init_enet_param_shadow = NULL;
 }
 ucc_geth_free_tx(ugeth);
 ucc_geth_free_rx(ugeth);
 while (!list_empty(&ugeth->group_hash_q))
  put_enet_addr_container(ENET_ADDR_CONT_ENTRY
     (dequeue(&ugeth->group_hash_q)));
 while (!list_empty(&ugeth->ind_hash_q))
  put_enet_addr_container(ENET_ADDR_CONT_ENTRY
     (dequeue(&ugeth->ind_hash_q)));
 if (ugeth->ug_regs) {
  iounmap(ugeth->ug_regs);
  ugeth->ug_regs = NULL;
 }
}

static void ucc_geth_set_multi(struct net_device *dev)
{
 struct ucc_geth_private *ugeth;
 struct netdev_hw_addr *ha;
 struct ucc_fast __iomem *uf_regs;
 struct ucc_geth_82xx_address_filtering_pram __iomem *p_82xx_addr_filt;

 ugeth = netdev_priv(dev);

 uf_regs = ugeth->uccf->uf_regs;

 if (dev->flags & IFF_PROMISC) {
  setbits32(&uf_regs->upsmr, UCC_GETH_UPSMR_PRO);
 } else {
  clrbits32(&uf_regs->upsmr, UCC_GETH_UPSMR_PRO);

  p_82xx_addr_filt =
      (struct ucc_geth_82xx_address_filtering_pram __iomem *) ugeth->
      p_rx_glbl_pram->addressfiltering;

  if (dev->flags & IFF_ALLMULTI) {
   /* Catch all multicast addresses, so set the
 * filter to all 1's.
 */

   out_be32(&p_82xx_addr_filt->gaddr_h, 0xffffffff);
   out_be32(&p_82xx_addr_filt->gaddr_l, 0xffffffff);
  } else {
   /* Clear filter and add the addresses in the list.
 */

   out_be32(&p_82xx_addr_filt->gaddr_h, 0x0);
   out_be32(&p_82xx_addr_filt->gaddr_l, 0x0);

   netdev_for_each_mc_addr(ha, dev) {
    /* Ask CPM to run CRC and set bit in
 * filter mask.
 */

    hw_add_addr_in_hash(ugeth, ha->addr);
   }
  }
 }
}

static void ucc_geth_stop(struct ucc_geth_private *ugeth)
{
 struct ucc_geth __iomem *ug_regs = ugeth->ug_regs;

 ugeth_vdbg("%s: IN", __func__);

 /*
 * Tell the kernel the link is down.
 * Must be done before disabling the controller
 * or deadlock may happen.
 */

 phylink_stop(ugeth->phylink);

 /* Disable the controller */
 ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);

 /* Mask all interrupts */
 out_be32(ugeth->uccf->p_uccm, 0x00000000);

 /* Clear all interrupts */
 out_be32(ugeth->uccf->p_ucce, 0xffffffff);

 /* Disable Rx and Tx */
 clrbits32(&ug_regs->maccfg1, MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);

 ucc_geth_memclean(ugeth);
}

static int ucc_struct_init(struct ucc_geth_private *ugeth)
{
 struct ucc_geth_info *ug_info;
 struct ucc_fast_info *uf_info;
 int i;

 ug_info = ugeth->ug_info;
 uf_info = &ug_info->uf_info;

 /* Rx BD lengths */
 for (i = 0; i < ucc_geth_rx_queues(ug_info); i++) {
  if ((ug_info->bdRingLenRx[i] < UCC_GETH_RX_BD_RING_SIZE_MIN) ||
      (ug_info->bdRingLenRx[i] %
       UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT)) {
   if (netif_msg_probe(ugeth))
    pr_err("Rx BD ring length must be multiple of 4, no smaller than 8\n");
   return -EINVAL;
  }
 }

 /* Tx BD lengths */
 for (i = 0; i < ucc_geth_tx_queues(ug_info); i++) {
  if (ug_info->bdRingLenTx[i] < UCC_GETH_TX_BD_RING_SIZE_MIN) {
   if (netif_msg_probe(ugeth))
    pr_err("Tx BD ring length must be no smaller than 2\n");
   return -EINVAL;
  }
 }

 /* mrblr */
 if ((uf_info->max_rx_buf_length == 0) ||
     (uf_info->max_rx_buf_length % UCC_GETH_MRBLR_ALIGNMENT)) {
  if (netif_msg_probe(ugeth))
   pr_err("max_rx_buf_length must be non-zero multiple of 128\n");
  return -EINVAL;
 }

 /* num Tx queues */
 if (ucc_geth_tx_queues(ug_info) > NUM_TX_QUEUES) {
  if (netif_msg_probe(ugeth))
   pr_err("number of tx queues too large\n");
  return -EINVAL;
 }

 /* num Rx queues */
 if (ucc_geth_rx_queues(ug_info) > NUM_RX_QUEUES) {
  if (netif_msg_probe(ugeth))
   pr_err("number of rx queues too large\n");
  return -EINVAL;
 }

 /* l2qt */
 for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) {
  if (ug_info->l2qt[i] >= ucc_geth_rx_queues(ug_info)) {
   if (netif_msg_probe(ugeth))
    pr_err("VLAN priority table entry must not be larger than number of Rx queues\n");
   return -EINVAL;
  }
 }

 /* l3qt */
 for (i = 0; i < UCC_GETH_IP_PRIORITY_MAX; i++) {
  if (ug_info->l3qt[i] >= ucc_geth_rx_queues(ug_info)) {
   if (netif_msg_probe(ugeth))
    pr_err("IP priority table entry must not be larger than number of Rx queues\n");
   return -EINVAL;
  }
 }

 if (ug_info->cam && !ug_info->ecamptr) {
  if (netif_msg_probe(ugeth))
   pr_err("If cam mode is chosen, must supply cam ptr\n");
  return -EINVAL;
 }

 if ((ug_info->numStationAddresses !=
      UCC_GETH_NUM_OF_STATION_ADDRESSES_1) &&
     ug_info->rxExtendedFiltering) {
  if (netif_msg_probe(ugeth))
   pr_err("Number of station addresses greater than 1 not allowed in extended parsing mode\n");
  return -EINVAL;
 }

 /* Generate uccm_mask for receive */
 uf_info->uccm_mask = ug_info->eventRegMask & UCCE_OTHER;/* Errors */
 for (i = 0; i < ucc_geth_rx_queues(ug_info); i++)
  uf_info->uccm_mask |= (UCC_GETH_UCCE_RXF0 << i);

 for (i = 0; i < ucc_geth_tx_queues(ug_info); i++)
  uf_info->uccm_mask |= (UCC_GETH_UCCE_TXB0 << i);
 /* Initialize the general fast UCC block. */
 if (ucc_fast_init(uf_info, &ugeth->uccf)) {
  if (netif_msg_probe(ugeth))
   pr_err("Failed to init uccf\n");
  return -ENOMEM;
 }

 /* read the number of risc engines, update the riscTx and riscRx
 * if there are 4 riscs in QE
 */

 if (qe_get_num_of_risc() == 4) {
  ug_info->riscTx = QE_RISC_ALLOCATION_FOUR_RISCS;
  ug_info->riscRx = QE_RISC_ALLOCATION_FOUR_RISCS;
 }

 ugeth->ug_regs = ioremap(uf_info->regs, sizeof(*ugeth->ug_regs));
 if (!ugeth->ug_regs) {
  if (netif_msg_probe(ugeth))
   pr_err("Failed to ioremap regs\n");
  return -ENOMEM;
 }

 return 0;
}

static int ucc_geth_alloc_tx(struct ucc_geth_private *ugeth)
{
 struct ucc_geth_info *ug_info;
 struct ucc_fast_info *uf_info;
 int length;
 u16 i, j;
 u8 __iomem *bd;

 ug_info = ugeth->ug_info;
 uf_info = &ug_info->uf_info;

 /* Allocate Tx bds */
 for (j = 0; j < ucc_geth_tx_queues(ug_info); j++) {
  u32 align = max(UCC_GETH_TX_BD_RING_ALIGNMENT,
    UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT);
  u32 alloc;

  length = ug_info->bdRingLenTx[j] * sizeof(struct qe_bd);
  alloc = round_up(length, align);
  alloc = roundup_pow_of_two(alloc);

  ugeth->p_tx_bd_ring[j] = kmalloc(alloc, GFP_KERNEL);

  if (!ugeth->p_tx_bd_ring[j]) {
   if (netif_msg_ifup(ugeth))
    pr_err("Can not allocate memory for Tx bd rings\n");
   return -ENOMEM;
  }
  /* Zero unused end of bd ring, according to spec */
  memset(ugeth->p_tx_bd_ring[j] + length, 0, alloc - length);
 }

 /* Init Tx bds */
 for (j = 0; j < ucc_geth_tx_queues(ug_info); j++) {
  /* Setup the skbuff rings */
  ugeth->tx_skbuff[j] =
   kcalloc(ugeth->ug_info->bdRingLenTx[j],
    sizeof(struct sk_buff *), GFP_KERNEL);

  if (ugeth->tx_skbuff[j] == NULL) {
   if (netif_msg_ifup(ugeth))
    pr_err("Could not allocate tx_skbuff\n");
   return -ENOMEM;
  }

  ugeth->skb_curtx[j] = ugeth->skb_dirtytx[j] = 0;
  bd = ugeth->confBd[j] = ugeth->txBd[j] = ugeth->p_tx_bd_ring[j];
  for (i = 0; i < ug_info->bdRingLenTx[j]; i++) {
   /* clear bd buffer */
   out_be32(&((struct qe_bd __iomem *)bd)->buf, 0);
   /* set bd status and length */
   out_be32((u32 __iomem *)bd, 0);
   bd += sizeof(struct qe_bd);
  }
  bd -= sizeof(struct qe_bd);
  /* set bd status and length */
  out_be32((u32 __iomem *)bd, T_W); /* for last BD set Wrap bit */
 }

 return 0;
}

static int ucc_geth_alloc_rx(struct ucc_geth_private *ugeth)
{
 struct ucc_geth_info *ug_info;
 struct ucc_fast_info *uf_info;
 int length;
 u16 i, j;
 u8 __iomem *bd;

 ug_info = ugeth->ug_info;
 uf_info = &ug_info->uf_info;

 /* Allocate Rx bds */
 for (j = 0; j < ucc_geth_rx_queues(ug_info); j++) {
  u32 align = UCC_GETH_RX_BD_RING_ALIGNMENT;
  u32 alloc;

  length = ug_info->bdRingLenRx[j] * sizeof(struct qe_bd);
  alloc = round_up(length, align);
  alloc = roundup_pow_of_two(alloc);

  ugeth->p_rx_bd_ring[j] = kmalloc(alloc, GFP_KERNEL);
  if (!ugeth->p_rx_bd_ring[j]) {
   if (netif_msg_ifup(ugeth))
    pr_err("Can not allocate memory for Rx bd rings\n");
   return -ENOMEM;
  }
 }

 /* Init Rx bds */
 for (j = 0; j < ucc_geth_rx_queues(ug_info); j++) {
  /* Setup the skbuff rings */
  ugeth->rx_skbuff[j] =
   kcalloc(ugeth->ug_info->bdRingLenRx[j],
    sizeof(struct sk_buff *), GFP_KERNEL);

  if (ugeth->rx_skbuff[j] == NULL) {
   if (netif_msg_ifup(ugeth))
    pr_err("Could not allocate rx_skbuff\n");
   return -ENOMEM;
  }

  ugeth->skb_currx[j] = 0;
  bd = ugeth->rxBd[j] = ugeth->p_rx_bd_ring[j];
  for (i = 0; i < ug_info->bdRingLenRx[j]; i++) {
   /* set bd status and length */
   out_be32((u32 __iomem *)bd, R_I);
   /* clear bd buffer */
   out_be32(&((struct qe_bd __iomem *)bd)->buf, 0);
   bd += sizeof(struct qe_bd);
  }
  bd -= sizeof(struct qe_bd);
  /* set bd status and length */
  out_be32((u32 __iomem *)bd, R_W); /* for last BD set Wrap bit */
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=96 H=84 G=90

¤ Dauer der Verarbeitung: 0.26 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.