ia64/linux-2.6.18-xen.hg

annotate drivers/net/ucc_geth.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
rev   line source
ian@0 1 /*
ian@0 2 * Copyright (C) Freescale Semicondutor, Inc. 2006. All rights reserved.
ian@0 3 *
ian@0 4 * Author: Shlomi Gridish <gridish@freescale.com>
ian@0 5 *
ian@0 6 * Description:
ian@0 7 * QE UCC Gigabit Ethernet Driver
ian@0 8 *
ian@0 9 * Changelog:
ian@0 10 * Jul 6, 2006 Li Yang <LeoLi@freescale.com>
ian@0 11 * - Rearrange code and style fixes
ian@0 12 *
ian@0 13 * This program is free software; you can redistribute it and/or modify it
ian@0 14 * under the terms of the GNU General Public License as published by the
ian@0 15 * Free Software Foundation; either version 2 of the License, or (at your
ian@0 16 * option) any later version.
ian@0 17 */
ian@0 18 #include <linux/kernel.h>
ian@0 19 #include <linux/init.h>
ian@0 20 #include <linux/errno.h>
ian@0 21 #include <linux/slab.h>
ian@0 22 #include <linux/stddef.h>
ian@0 23 #include <linux/interrupt.h>
ian@0 24 #include <linux/netdevice.h>
ian@0 25 #include <linux/etherdevice.h>
ian@0 26 #include <linux/skbuff.h>
ian@0 27 #include <linux/spinlock.h>
ian@0 28 #include <linux/mm.h>
ian@0 29 #include <linux/ethtool.h>
ian@0 30 #include <linux/delay.h>
ian@0 31 #include <linux/dma-mapping.h>
ian@0 32 #include <linux/fsl_devices.h>
ian@0 33 #include <linux/ethtool.h>
ian@0 34 #include <linux/platform_device.h>
ian@0 35 #include <linux/mii.h>
ian@0 36
ian@0 37 #include <asm/uaccess.h>
ian@0 38 #include <asm/irq.h>
ian@0 39 #include <asm/io.h>
ian@0 40 #include <asm/immap_qe.h>
ian@0 41 #include <asm/qe.h>
ian@0 42 #include <asm/ucc.h>
ian@0 43 #include <asm/ucc_fast.h>
ian@0 44
ian@0 45 #include "ucc_geth.h"
ian@0 46 #include "ucc_geth_phy.h"
ian@0 47
ian@0 48 #undef DEBUG
ian@0 49
ian@0 50 #define DRV_DESC "QE UCC Gigabit Ethernet Controller version:June 20, 2006"
ian@0 51 #define DRV_NAME "ucc_geth"
ian@0 52
ian@0 53 #define ugeth_printk(level, format, arg...) \
ian@0 54 printk(level format "\n", ## arg)
ian@0 55
ian@0 56 #define ugeth_dbg(format, arg...) \
ian@0 57 ugeth_printk(KERN_DEBUG , format , ## arg)
ian@0 58 #define ugeth_err(format, arg...) \
ian@0 59 ugeth_printk(KERN_ERR , format , ## arg)
ian@0 60 #define ugeth_info(format, arg...) \
ian@0 61 ugeth_printk(KERN_INFO , format , ## arg)
ian@0 62 #define ugeth_warn(format, arg...) \
ian@0 63 ugeth_printk(KERN_WARNING , format , ## arg)
ian@0 64
ian@0 65 #ifdef UGETH_VERBOSE_DEBUG
ian@0 66 #define ugeth_vdbg ugeth_dbg
ian@0 67 #else
ian@0 68 #define ugeth_vdbg(fmt, args...) do { } while (0)
ian@0 69 #endif /* UGETH_VERBOSE_DEBUG */
ian@0 70
ian@0 71 static DEFINE_SPINLOCK(ugeth_lock);
ian@0 72
ian@0 73 static ucc_geth_info_t ugeth_primary_info = {
ian@0 74 .uf_info = {
ian@0 75 .bd_mem_part = MEM_PART_SYSTEM,
ian@0 76 .rtsm = UCC_FAST_SEND_IDLES_BETWEEN_FRAMES,
ian@0 77 .max_rx_buf_length = 1536,
ian@0 78 /* FIXME: should be changed in run time for 1G and 100M */
ian@0 79 #ifdef CONFIG_UGETH_HAS_GIGA
ian@0 80 .urfs = UCC_GETH_URFS_GIGA_INIT,
ian@0 81 .urfet = UCC_GETH_URFET_GIGA_INIT,
ian@0 82 .urfset = UCC_GETH_URFSET_GIGA_INIT,
ian@0 83 .utfs = UCC_GETH_UTFS_GIGA_INIT,
ian@0 84 .utfet = UCC_GETH_UTFET_GIGA_INIT,
ian@0 85 .utftt = UCC_GETH_UTFTT_GIGA_INIT,
ian@0 86 #else
ian@0 87 .urfs = UCC_GETH_URFS_INIT,
ian@0 88 .urfet = UCC_GETH_URFET_INIT,
ian@0 89 .urfset = UCC_GETH_URFSET_INIT,
ian@0 90 .utfs = UCC_GETH_UTFS_INIT,
ian@0 91 .utfet = UCC_GETH_UTFET_INIT,
ian@0 92 .utftt = UCC_GETH_UTFTT_INIT,
ian@0 93 #endif
ian@0 94 .ufpt = 256,
ian@0 95 .mode = UCC_FAST_PROTOCOL_MODE_ETHERNET,
ian@0 96 .ttx_trx = UCC_FAST_GUMR_TRANSPARENT_TTX_TRX_NORMAL,
ian@0 97 .tenc = UCC_FAST_TX_ENCODING_NRZ,
ian@0 98 .renc = UCC_FAST_RX_ENCODING_NRZ,
ian@0 99 .tcrc = UCC_FAST_16_BIT_CRC,
ian@0 100 .synl = UCC_FAST_SYNC_LEN_NOT_USED,
ian@0 101 },
ian@0 102 .numQueuesTx = 1,
ian@0 103 .numQueuesRx = 1,
ian@0 104 .extendedFilteringChainPointer = ((uint32_t) NULL),
ian@0 105 .typeorlen = 3072 /*1536 */ ,
ian@0 106 .nonBackToBackIfgPart1 = 0x40,
ian@0 107 .nonBackToBackIfgPart2 = 0x60,
ian@0 108 .miminumInterFrameGapEnforcement = 0x50,
ian@0 109 .backToBackInterFrameGap = 0x60,
ian@0 110 .mblinterval = 128,
ian@0 111 .nortsrbytetime = 5,
ian@0 112 .fracsiz = 1,
ian@0 113 .strictpriorityq = 0xff,
ian@0 114 .altBebTruncation = 0xa,
ian@0 115 .excessDefer = 1,
ian@0 116 .maxRetransmission = 0xf,
ian@0 117 .collisionWindow = 0x37,
ian@0 118 .receiveFlowControl = 1,
ian@0 119 .maxGroupAddrInHash = 4,
ian@0 120 .maxIndAddrInHash = 4,
ian@0 121 .prel = 7,
ian@0 122 .maxFrameLength = 1518,
ian@0 123 .minFrameLength = 64,
ian@0 124 .maxD1Length = 1520,
ian@0 125 .maxD2Length = 1520,
ian@0 126 .vlantype = 0x8100,
ian@0 127 .ecamptr = ((uint32_t) NULL),
ian@0 128 .eventRegMask = UCCE_OTHER,
ian@0 129 .pausePeriod = 0xf000,
ian@0 130 .interruptcoalescingmaxvalue = {1, 1, 1, 1, 1, 1, 1, 1},
ian@0 131 .bdRingLenTx = {
ian@0 132 TX_BD_RING_LEN,
ian@0 133 TX_BD_RING_LEN,
ian@0 134 TX_BD_RING_LEN,
ian@0 135 TX_BD_RING_LEN,
ian@0 136 TX_BD_RING_LEN,
ian@0 137 TX_BD_RING_LEN,
ian@0 138 TX_BD_RING_LEN,
ian@0 139 TX_BD_RING_LEN},
ian@0 140
ian@0 141 .bdRingLenRx = {
ian@0 142 RX_BD_RING_LEN,
ian@0 143 RX_BD_RING_LEN,
ian@0 144 RX_BD_RING_LEN,
ian@0 145 RX_BD_RING_LEN,
ian@0 146 RX_BD_RING_LEN,
ian@0 147 RX_BD_RING_LEN,
ian@0 148 RX_BD_RING_LEN,
ian@0 149 RX_BD_RING_LEN},
ian@0 150
ian@0 151 .numStationAddresses = UCC_GETH_NUM_OF_STATION_ADDRESSES_1,
ian@0 152 .largestexternallookupkeysize =
ian@0 153 QE_FLTR_LARGEST_EXTERNAL_TABLE_LOOKUP_KEY_SIZE_NONE,
ian@0 154 .statisticsMode = UCC_GETH_STATISTICS_GATHERING_MODE_NONE,
ian@0 155 .vlanOperationTagged = UCC_GETH_VLAN_OPERATION_TAGGED_NOP,
ian@0 156 .vlanOperationNonTagged = UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP,
ian@0 157 .rxQoSMode = UCC_GETH_QOS_MODE_DEFAULT,
ian@0 158 .aufc = UPSMR_AUTOMATIC_FLOW_CONTROL_MODE_NONE,
ian@0 159 .padAndCrc = MACCFG2_PAD_AND_CRC_MODE_PAD_AND_CRC,
ian@0 160 .numThreadsTx = UCC_GETH_NUM_OF_THREADS_4,
ian@0 161 .numThreadsRx = UCC_GETH_NUM_OF_THREADS_4,
ian@0 162 .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
ian@0 163 .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2,
ian@0 164 };
ian@0 165
ian@0 166 static ucc_geth_info_t ugeth_info[8];
ian@0 167
ian@0 168 #ifdef DEBUG
ian@0 169 static void mem_disp(u8 *addr, int size)
ian@0 170 {
ian@0 171 u8 *i;
ian@0 172 int size16Aling = (size >> 4) << 4;
ian@0 173 int size4Aling = (size >> 2) << 2;
ian@0 174 int notAlign = 0;
ian@0 175 if (size % 16)
ian@0 176 notAlign = 1;
ian@0 177
ian@0 178 for (i = addr; (u32) i < (u32) addr + size16Aling; i += 16)
ian@0 179 printk("0x%08x: %08x %08x %08x %08x\r\n",
ian@0 180 (u32) i,
ian@0 181 *((u32 *) (i)),
ian@0 182 *((u32 *) (i + 4)),
ian@0 183 *((u32 *) (i + 8)), *((u32 *) (i + 12)));
ian@0 184 if (notAlign == 1)
ian@0 185 printk("0x%08x: ", (u32) i);
ian@0 186 for (; (u32) i < (u32) addr + size4Aling; i += 4)
ian@0 187 printk("%08x ", *((u32 *) (i)));
ian@0 188 for (; (u32) i < (u32) addr + size; i++)
ian@0 189 printk("%02x", *((u8 *) (i)));
ian@0 190 if (notAlign == 1)
ian@0 191 printk("\r\n");
ian@0 192 }
ian@0 193 #endif /* DEBUG */
ian@0 194
ian@0 195 #ifdef CONFIG_UGETH_FILTERING
ian@0 196 static void enqueue(struct list_head *node, struct list_head *lh)
ian@0 197 {
ian@0 198 unsigned long flags;
ian@0 199
ian@0 200 spin_lock_irqsave(ugeth_lock, flags);
ian@0 201 list_add_tail(node, lh);
ian@0 202 spin_unlock_irqrestore(ugeth_lock, flags);
ian@0 203 }
ian@0 204 #endif /* CONFIG_UGETH_FILTERING */
ian@0 205
ian@0 206 static struct list_head *dequeue(struct list_head *lh)
ian@0 207 {
ian@0 208 unsigned long flags;
ian@0 209
ian@0 210 spin_lock_irqsave(ugeth_lock, flags);
ian@0 211 if (!list_empty(lh)) {
ian@0 212 struct list_head *node = lh->next;
ian@0 213 list_del(node);
ian@0 214 spin_unlock_irqrestore(ugeth_lock, flags);
ian@0 215 return node;
ian@0 216 } else {
ian@0 217 spin_unlock_irqrestore(ugeth_lock, flags);
ian@0 218 return NULL;
ian@0 219 }
ian@0 220 }
ian@0 221
ian@0 222 static int get_interface_details(enet_interface_e enet_interface,
ian@0 223 enet_speed_e *speed,
ian@0 224 int *r10m,
ian@0 225 int *rmm,
ian@0 226 int *rpm,
ian@0 227 int *tbi, int *limited_to_full_duplex)
ian@0 228 {
ian@0 229 /* Analyze enet_interface according to Interface Mode
ian@0 230 Configuration table */
ian@0 231 switch (enet_interface) {
ian@0 232 case ENET_10_MII:
ian@0 233 *speed = ENET_SPEED_10BT;
ian@0 234 break;
ian@0 235 case ENET_10_RMII:
ian@0 236 *speed = ENET_SPEED_10BT;
ian@0 237 *r10m = 1;
ian@0 238 *rmm = 1;
ian@0 239 break;
ian@0 240 case ENET_10_RGMII:
ian@0 241 *speed = ENET_SPEED_10BT;
ian@0 242 *rpm = 1;
ian@0 243 *r10m = 1;
ian@0 244 *limited_to_full_duplex = 1;
ian@0 245 break;
ian@0 246 case ENET_100_MII:
ian@0 247 *speed = ENET_SPEED_100BT;
ian@0 248 break;
ian@0 249 case ENET_100_RMII:
ian@0 250 *speed = ENET_SPEED_100BT;
ian@0 251 *rmm = 1;
ian@0 252 break;
ian@0 253 case ENET_100_RGMII:
ian@0 254 *speed = ENET_SPEED_100BT;
ian@0 255 *rpm = 1;
ian@0 256 *limited_to_full_duplex = 1;
ian@0 257 break;
ian@0 258 case ENET_1000_GMII:
ian@0 259 *speed = ENET_SPEED_1000BT;
ian@0 260 *limited_to_full_duplex = 1;
ian@0 261 break;
ian@0 262 case ENET_1000_RGMII:
ian@0 263 *speed = ENET_SPEED_1000BT;
ian@0 264 *rpm = 1;
ian@0 265 *limited_to_full_duplex = 1;
ian@0 266 break;
ian@0 267 case ENET_1000_TBI:
ian@0 268 *speed = ENET_SPEED_1000BT;
ian@0 269 *tbi = 1;
ian@0 270 *limited_to_full_duplex = 1;
ian@0 271 break;
ian@0 272 case ENET_1000_RTBI:
ian@0 273 *speed = ENET_SPEED_1000BT;
ian@0 274 *rpm = 1;
ian@0 275 *tbi = 1;
ian@0 276 *limited_to_full_duplex = 1;
ian@0 277 break;
ian@0 278 default:
ian@0 279 return -EINVAL;
ian@0 280 break;
ian@0 281 }
ian@0 282
ian@0 283 return 0;
ian@0 284 }
ian@0 285
ian@0 286 static struct sk_buff *get_new_skb(ucc_geth_private_t *ugeth, u8 *bd)
ian@0 287 {
ian@0 288 struct sk_buff *skb = NULL;
ian@0 289
ian@0 290 skb = dev_alloc_skb(ugeth->ug_info->uf_info.max_rx_buf_length +
ian@0 291 UCC_GETH_RX_DATA_BUF_ALIGNMENT);
ian@0 292
ian@0 293 if (skb == NULL)
ian@0 294 return NULL;
ian@0 295
ian@0 296 /* We need the data buffer to be aligned properly. We will reserve
ian@0 297 * as many bytes as needed to align the data properly
ian@0 298 */
ian@0 299 skb_reserve(skb,
ian@0 300 UCC_GETH_RX_DATA_BUF_ALIGNMENT -
ian@0 301 (((unsigned)skb->data) & (UCC_GETH_RX_DATA_BUF_ALIGNMENT -
ian@0 302 1)));
ian@0 303
ian@0 304 skb->dev = ugeth->dev;
ian@0 305
ian@0 306 BD_BUFFER_SET(bd,
ian@0 307 dma_map_single(NULL,
ian@0 308 skb->data,
ian@0 309 ugeth->ug_info->uf_info.max_rx_buf_length +
ian@0 310 UCC_GETH_RX_DATA_BUF_ALIGNMENT,
ian@0 311 DMA_FROM_DEVICE));
ian@0 312
ian@0 313 BD_STATUS_AND_LENGTH_SET(bd,
ian@0 314 (R_E | R_I |
ian@0 315 (BD_STATUS_AND_LENGTH(bd) & R_W)));
ian@0 316
ian@0 317 return skb;
ian@0 318 }
ian@0 319
ian@0 320 static int rx_bd_buffer_set(ucc_geth_private_t *ugeth, u8 rxQ)
ian@0 321 {
ian@0 322 u8 *bd;
ian@0 323 u32 bd_status;
ian@0 324 struct sk_buff *skb;
ian@0 325 int i;
ian@0 326
ian@0 327 bd = ugeth->p_rx_bd_ring[rxQ];
ian@0 328 i = 0;
ian@0 329
ian@0 330 do {
ian@0 331 bd_status = BD_STATUS_AND_LENGTH(bd);
ian@0 332 skb = get_new_skb(ugeth, bd);
ian@0 333
ian@0 334 if (!skb) /* If can not allocate data buffer,
ian@0 335 abort. Cleanup will be elsewhere */
ian@0 336 return -ENOMEM;
ian@0 337
ian@0 338 ugeth->rx_skbuff[rxQ][i] = skb;
ian@0 339
ian@0 340 /* advance the BD pointer */
ian@0 341 bd += UCC_GETH_SIZE_OF_BD;
ian@0 342 i++;
ian@0 343 } while (!(bd_status & R_W));
ian@0 344
ian@0 345 return 0;
ian@0 346 }
ian@0 347
ian@0 348 static int fill_init_enet_entries(ucc_geth_private_t *ugeth,
ian@0 349 volatile u32 *p_start,
ian@0 350 u8 num_entries,
ian@0 351 u32 thread_size,
ian@0 352 u32 thread_alignment,
ian@0 353 qe_risc_allocation_e risc,
ian@0 354 int skip_page_for_first_entry)
ian@0 355 {
ian@0 356 u32 init_enet_offset;
ian@0 357 u8 i;
ian@0 358 int snum;
ian@0 359
ian@0 360 for (i = 0; i < num_entries; i++) {
ian@0 361 if ((snum = qe_get_snum()) < 0) {
ian@0 362 ugeth_err("fill_init_enet_entries: Can not get SNUM.");
ian@0 363 return snum;
ian@0 364 }
ian@0 365 if ((i == 0) && skip_page_for_first_entry)
ian@0 366 /* First entry of Rx does not have page */
ian@0 367 init_enet_offset = 0;
ian@0 368 else {
ian@0 369 init_enet_offset =
ian@0 370 qe_muram_alloc(thread_size, thread_alignment);
ian@0 371 if (IS_MURAM_ERR(init_enet_offset)) {
ian@0 372 ugeth_err
ian@0 373 ("fill_init_enet_entries: Can not allocate DPRAM memory.");
ian@0 374 qe_put_snum((u8) snum);
ian@0 375 return -ENOMEM;
ian@0 376 }
ian@0 377 }
ian@0 378 *(p_start++) =
ian@0 379 ((u8) snum << ENET_INIT_PARAM_SNUM_SHIFT) | init_enet_offset
ian@0 380 | risc;
ian@0 381 }
ian@0 382
ian@0 383 return 0;
ian@0 384 }
ian@0 385
ian@0 386 static int return_init_enet_entries(ucc_geth_private_t *ugeth,
ian@0 387 volatile u32 *p_start,
ian@0 388 u8 num_entries,
ian@0 389 qe_risc_allocation_e risc,
ian@0 390 int skip_page_for_first_entry)
ian@0 391 {
ian@0 392 u32 init_enet_offset;
ian@0 393 u8 i;
ian@0 394 int snum;
ian@0 395
ian@0 396 for (i = 0; i < num_entries; i++) {
ian@0 397 /* Check that this entry was actually valid --
ian@0 398 needed in case failed in allocations */
ian@0 399 if ((*p_start & ENET_INIT_PARAM_RISC_MASK) == risc) {
ian@0 400 snum =
ian@0 401 (u32) (*p_start & ENET_INIT_PARAM_SNUM_MASK) >>
ian@0 402 ENET_INIT_PARAM_SNUM_SHIFT;
ian@0 403 qe_put_snum((u8) snum);
ian@0 404 if (!((i == 0) && skip_page_for_first_entry)) {
ian@0 405 /* First entry of Rx does not have page */
ian@0 406 init_enet_offset =
ian@0 407 (in_be32(p_start) &
ian@0 408 ENET_INIT_PARAM_PTR_MASK);
ian@0 409 qe_muram_free(init_enet_offset);
ian@0 410 }
ian@0 411 *(p_start++) = 0; /* Just for cosmetics */
ian@0 412 }
ian@0 413 }
ian@0 414
ian@0 415 return 0;
ian@0 416 }
ian@0 417
ian@0 418 #ifdef DEBUG
ian@0 419 static int dump_init_enet_entries(ucc_geth_private_t *ugeth,
ian@0 420 volatile u32 *p_start,
ian@0 421 u8 num_entries,
ian@0 422 u32 thread_size,
ian@0 423 qe_risc_allocation_e risc,
ian@0 424 int skip_page_for_first_entry)
ian@0 425 {
ian@0 426 u32 init_enet_offset;
ian@0 427 u8 i;
ian@0 428 int snum;
ian@0 429
ian@0 430 for (i = 0; i < num_entries; i++) {
ian@0 431 /* Check that this entry was actually valid --
ian@0 432 needed in case failed in allocations */
ian@0 433 if ((*p_start & ENET_INIT_PARAM_RISC_MASK) == risc) {
ian@0 434 snum =
ian@0 435 (u32) (*p_start & ENET_INIT_PARAM_SNUM_MASK) >>
ian@0 436 ENET_INIT_PARAM_SNUM_SHIFT;
ian@0 437 qe_put_snum((u8) snum);
ian@0 438 if (!((i == 0) && skip_page_for_first_entry)) {
ian@0 439 /* First entry of Rx does not have page */
ian@0 440 init_enet_offset =
ian@0 441 (in_be32(p_start) &
ian@0 442 ENET_INIT_PARAM_PTR_MASK);
ian@0 443 ugeth_info("Init enet entry %d:", i);
ian@0 444 ugeth_info("Base address: 0x%08x",
ian@0 445 (u32)
ian@0 446 qe_muram_addr(init_enet_offset));
ian@0 447 mem_disp(qe_muram_addr(init_enet_offset),
ian@0 448 thread_size);
ian@0 449 }
ian@0 450 p_start++;
ian@0 451 }
ian@0 452 }
ian@0 453
ian@0 454 return 0;
ian@0 455 }
ian@0 456 #endif
ian@0 457
ian@0 458 #ifdef CONFIG_UGETH_FILTERING
ian@0 459 static enet_addr_container_t *get_enet_addr_container(void)
ian@0 460 {
ian@0 461 enet_addr_container_t *enet_addr_cont;
ian@0 462
ian@0 463 /* allocate memory */
ian@0 464 enet_addr_cont = kmalloc(sizeof(enet_addr_container_t), GFP_KERNEL);
ian@0 465 if (!enet_addr_cont) {
ian@0 466 ugeth_err("%s: No memory for enet_addr_container_t object.",
ian@0 467 __FUNCTION__);
ian@0 468 return NULL;
ian@0 469 }
ian@0 470
ian@0 471 return enet_addr_cont;
ian@0 472 }
ian@0 473 #endif /* CONFIG_UGETH_FILTERING */
ian@0 474
ian@0 475 static void put_enet_addr_container(enet_addr_container_t *enet_addr_cont)
ian@0 476 {
ian@0 477 kfree(enet_addr_cont);
ian@0 478 }
ian@0 479
ian@0 480 #ifdef CONFIG_UGETH_FILTERING
ian@0 481 static int hw_add_addr_in_paddr(ucc_geth_private_t *ugeth,
ian@0 482 enet_addr_t *p_enet_addr, u8 paddr_num)
ian@0 483 {
ian@0 484 ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
ian@0 485
ian@0 486 if (!(paddr_num < NUM_OF_PADDRS)) {
ian@0 487 ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__);
ian@0 488 return -EINVAL;
ian@0 489 }
ian@0 490
ian@0 491 p_82xx_addr_filt =
ian@0 492 (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
ian@0 493 addressfiltering;
ian@0 494
ian@0 495 /* Ethernet frames are defined in Little Endian mode, */
ian@0 496 /* therefore to insert the address we reverse the bytes. */
ian@0 497 out_be16(&p_82xx_addr_filt->paddr[paddr_num].h,
ian@0 498 (u16) (((u16) (((u16) ((*p_enet_addr)[5])) << 8)) |
ian@0 499 (u16) (*p_enet_addr)[4]));
ian@0 500 out_be16(&p_82xx_addr_filt->paddr[paddr_num].m,
ian@0 501 (u16) (((u16) (((u16) ((*p_enet_addr)[3])) << 8)) |
ian@0 502 (u16) (*p_enet_addr)[2]));
ian@0 503 out_be16(&p_82xx_addr_filt->paddr[paddr_num].l,
ian@0 504 (u16) (((u16) (((u16) ((*p_enet_addr)[1])) << 8)) |
ian@0 505 (u16) (*p_enet_addr)[0]));
ian@0 506
ian@0 507 return 0;
ian@0 508 }
ian@0 509 #endif /* CONFIG_UGETH_FILTERING */
ian@0 510
ian@0 511 static int hw_clear_addr_in_paddr(ucc_geth_private_t *ugeth, u8 paddr_num)
ian@0 512 {
ian@0 513 ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
ian@0 514
ian@0 515 if (!(paddr_num < NUM_OF_PADDRS)) {
ian@0 516 ugeth_warn("%s: Illagel paddr_num.", __FUNCTION__);
ian@0 517 return -EINVAL;
ian@0 518 }
ian@0 519
ian@0 520 p_82xx_addr_filt =
ian@0 521 (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
ian@0 522 addressfiltering;
ian@0 523
ian@0 524 /* Writing address ff.ff.ff.ff.ff.ff disables address
ian@0 525 recognition for this register */
ian@0 526 out_be16(&p_82xx_addr_filt->paddr[paddr_num].h, 0xffff);
ian@0 527 out_be16(&p_82xx_addr_filt->paddr[paddr_num].m, 0xffff);
ian@0 528 out_be16(&p_82xx_addr_filt->paddr[paddr_num].l, 0xffff);
ian@0 529
ian@0 530 return 0;
ian@0 531 }
ian@0 532
ian@0 533 static void hw_add_addr_in_hash(ucc_geth_private_t *ugeth,
ian@0 534 enet_addr_t *p_enet_addr)
ian@0 535 {
ian@0 536 ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
ian@0 537 u32 cecr_subblock;
ian@0 538
ian@0 539 p_82xx_addr_filt =
ian@0 540 (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
ian@0 541 addressfiltering;
ian@0 542
ian@0 543 cecr_subblock =
ian@0 544 ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
ian@0 545
ian@0 546 /* Ethernet frames are defined in Little Endian mode,
ian@0 547 therefor to insert */
ian@0 548 /* the address to the hash (Big Endian mode), we reverse the bytes.*/
ian@0 549 out_be16(&p_82xx_addr_filt->taddr.h,
ian@0 550 (u16) (((u16) (((u16) ((*p_enet_addr)[5])) << 8)) |
ian@0 551 (u16) (*p_enet_addr)[4]));
ian@0 552 out_be16(&p_82xx_addr_filt->taddr.m,
ian@0 553 (u16) (((u16) (((u16) ((*p_enet_addr)[3])) << 8)) |
ian@0 554 (u16) (*p_enet_addr)[2]));
ian@0 555 out_be16(&p_82xx_addr_filt->taddr.l,
ian@0 556 (u16) (((u16) (((u16) ((*p_enet_addr)[1])) << 8)) |
ian@0 557 (u16) (*p_enet_addr)[0]));
ian@0 558
ian@0 559 qe_issue_cmd(QE_SET_GROUP_ADDRESS, cecr_subblock,
ian@0 560 (u8) QE_CR_PROTOCOL_ETHERNET, 0);
ian@0 561 }
ian@0 562
ian@0 563 #ifdef CONFIG_UGETH_MAGIC_PACKET
ian@0 564 static void magic_packet_detection_enable(ucc_geth_private_t *ugeth)
ian@0 565 {
ian@0 566 ucc_fast_private_t *uccf;
ian@0 567 ucc_geth_t *ug_regs;
ian@0 568 u32 maccfg2, uccm;
ian@0 569
ian@0 570 uccf = ugeth->uccf;
ian@0 571 ug_regs = ugeth->ug_regs;
ian@0 572
ian@0 573 /* Enable interrupts for magic packet detection */
ian@0 574 uccm = in_be32(uccf->p_uccm);
ian@0 575 uccm |= UCCE_MPD;
ian@0 576 out_be32(uccf->p_uccm, uccm);
ian@0 577
ian@0 578 /* Enable magic packet detection */
ian@0 579 maccfg2 = in_be32(&ug_regs->maccfg2);
ian@0 580 maccfg2 |= MACCFG2_MPE;
ian@0 581 out_be32(&ug_regs->maccfg2, maccfg2);
ian@0 582 }
ian@0 583
ian@0 584 static void magic_packet_detection_disable(ucc_geth_private_t *ugeth)
ian@0 585 {
ian@0 586 ucc_fast_private_t *uccf;
ian@0 587 ucc_geth_t *ug_regs;
ian@0 588 u32 maccfg2, uccm;
ian@0 589
ian@0 590 uccf = ugeth->uccf;
ian@0 591 ug_regs = ugeth->ug_regs;
ian@0 592
ian@0 593 /* Disable interrupts for magic packet detection */
ian@0 594 uccm = in_be32(uccf->p_uccm);
ian@0 595 uccm &= ~UCCE_MPD;
ian@0 596 out_be32(uccf->p_uccm, uccm);
ian@0 597
ian@0 598 /* Disable magic packet detection */
ian@0 599 maccfg2 = in_be32(&ug_regs->maccfg2);
ian@0 600 maccfg2 &= ~MACCFG2_MPE;
ian@0 601 out_be32(&ug_regs->maccfg2, maccfg2);
ian@0 602 }
ian@0 603 #endif /* MAGIC_PACKET */
ian@0 604
ian@0 605 static inline int compare_addr(enet_addr_t *addr1, enet_addr_t *addr2)
ian@0 606 {
ian@0 607 return memcmp(addr1, addr2, ENET_NUM_OCTETS_PER_ADDRESS);
ian@0 608 }
ian@0 609
ian@0 610 #ifdef DEBUG
ian@0 611 static void get_statistics(ucc_geth_private_t *ugeth,
ian@0 612 ucc_geth_tx_firmware_statistics_t *
ian@0 613 tx_firmware_statistics,
ian@0 614 ucc_geth_rx_firmware_statistics_t *
ian@0 615 rx_firmware_statistics,
ian@0 616 ucc_geth_hardware_statistics_t *hardware_statistics)
ian@0 617 {
ian@0 618 ucc_fast_t *uf_regs;
ian@0 619 ucc_geth_t *ug_regs;
ian@0 620 ucc_geth_tx_firmware_statistics_pram_t *p_tx_fw_statistics_pram;
ian@0 621 ucc_geth_rx_firmware_statistics_pram_t *p_rx_fw_statistics_pram;
ian@0 622
ian@0 623 ug_regs = ugeth->ug_regs;
ian@0 624 uf_regs = (ucc_fast_t *) ug_regs;
ian@0 625 p_tx_fw_statistics_pram = ugeth->p_tx_fw_statistics_pram;
ian@0 626 p_rx_fw_statistics_pram = ugeth->p_rx_fw_statistics_pram;
ian@0 627
ian@0 628 /* Tx firmware only if user handed pointer and driver actually
ian@0 629 gathers Tx firmware statistics */
ian@0 630 if (tx_firmware_statistics && p_tx_fw_statistics_pram) {
ian@0 631 tx_firmware_statistics->sicoltx =
ian@0 632 in_be32(&p_tx_fw_statistics_pram->sicoltx);
ian@0 633 tx_firmware_statistics->mulcoltx =
ian@0 634 in_be32(&p_tx_fw_statistics_pram->mulcoltx);
ian@0 635 tx_firmware_statistics->latecoltxfr =
ian@0 636 in_be32(&p_tx_fw_statistics_pram->latecoltxfr);
ian@0 637 tx_firmware_statistics->frabortduecol =
ian@0 638 in_be32(&p_tx_fw_statistics_pram->frabortduecol);
ian@0 639 tx_firmware_statistics->frlostinmactxer =
ian@0 640 in_be32(&p_tx_fw_statistics_pram->frlostinmactxer);
ian@0 641 tx_firmware_statistics->carriersenseertx =
ian@0 642 in_be32(&p_tx_fw_statistics_pram->carriersenseertx);
ian@0 643 tx_firmware_statistics->frtxok =
ian@0 644 in_be32(&p_tx_fw_statistics_pram->frtxok);
ian@0 645 tx_firmware_statistics->txfrexcessivedefer =
ian@0 646 in_be32(&p_tx_fw_statistics_pram->txfrexcessivedefer);
ian@0 647 tx_firmware_statistics->txpkts256 =
ian@0 648 in_be32(&p_tx_fw_statistics_pram->txpkts256);
ian@0 649 tx_firmware_statistics->txpkts512 =
ian@0 650 in_be32(&p_tx_fw_statistics_pram->txpkts512);
ian@0 651 tx_firmware_statistics->txpkts1024 =
ian@0 652 in_be32(&p_tx_fw_statistics_pram->txpkts1024);
ian@0 653 tx_firmware_statistics->txpktsjumbo =
ian@0 654 in_be32(&p_tx_fw_statistics_pram->txpktsjumbo);
ian@0 655 }
ian@0 656
ian@0 657 /* Rx firmware only if user handed pointer and driver actually
ian@0 658 * gathers Rx firmware statistics */
ian@0 659 if (rx_firmware_statistics && p_rx_fw_statistics_pram) {
ian@0 660 int i;
ian@0 661 rx_firmware_statistics->frrxfcser =
ian@0 662 in_be32(&p_rx_fw_statistics_pram->frrxfcser);
ian@0 663 rx_firmware_statistics->fraligner =
ian@0 664 in_be32(&p_rx_fw_statistics_pram->fraligner);
ian@0 665 rx_firmware_statistics->inrangelenrxer =
ian@0 666 in_be32(&p_rx_fw_statistics_pram->inrangelenrxer);
ian@0 667 rx_firmware_statistics->outrangelenrxer =
ian@0 668 in_be32(&p_rx_fw_statistics_pram->outrangelenrxer);
ian@0 669 rx_firmware_statistics->frtoolong =
ian@0 670 in_be32(&p_rx_fw_statistics_pram->frtoolong);
ian@0 671 rx_firmware_statistics->runt =
ian@0 672 in_be32(&p_rx_fw_statistics_pram->runt);
ian@0 673 rx_firmware_statistics->verylongevent =
ian@0 674 in_be32(&p_rx_fw_statistics_pram->verylongevent);
ian@0 675 rx_firmware_statistics->symbolerror =
ian@0 676 in_be32(&p_rx_fw_statistics_pram->symbolerror);
ian@0 677 rx_firmware_statistics->dropbsy =
ian@0 678 in_be32(&p_rx_fw_statistics_pram->dropbsy);
ian@0 679 for (i = 0; i < 0x8; i++)
ian@0 680 rx_firmware_statistics->res0[i] =
ian@0 681 p_rx_fw_statistics_pram->res0[i];
ian@0 682 rx_firmware_statistics->mismatchdrop =
ian@0 683 in_be32(&p_rx_fw_statistics_pram->mismatchdrop);
ian@0 684 rx_firmware_statistics->underpkts =
ian@0 685 in_be32(&p_rx_fw_statistics_pram->underpkts);
ian@0 686 rx_firmware_statistics->pkts256 =
ian@0 687 in_be32(&p_rx_fw_statistics_pram->pkts256);
ian@0 688 rx_firmware_statistics->pkts512 =
ian@0 689 in_be32(&p_rx_fw_statistics_pram->pkts512);
ian@0 690 rx_firmware_statistics->pkts1024 =
ian@0 691 in_be32(&p_rx_fw_statistics_pram->pkts1024);
ian@0 692 rx_firmware_statistics->pktsjumbo =
ian@0 693 in_be32(&p_rx_fw_statistics_pram->pktsjumbo);
ian@0 694 rx_firmware_statistics->frlossinmacer =
ian@0 695 in_be32(&p_rx_fw_statistics_pram->frlossinmacer);
ian@0 696 rx_firmware_statistics->pausefr =
ian@0 697 in_be32(&p_rx_fw_statistics_pram->pausefr);
ian@0 698 for (i = 0; i < 0x4; i++)
ian@0 699 rx_firmware_statistics->res1[i] =
ian@0 700 p_rx_fw_statistics_pram->res1[i];
ian@0 701 rx_firmware_statistics->removevlan =
ian@0 702 in_be32(&p_rx_fw_statistics_pram->removevlan);
ian@0 703 rx_firmware_statistics->replacevlan =
ian@0 704 in_be32(&p_rx_fw_statistics_pram->replacevlan);
ian@0 705 rx_firmware_statistics->insertvlan =
ian@0 706 in_be32(&p_rx_fw_statistics_pram->insertvlan);
ian@0 707 }
ian@0 708
ian@0 709 /* Hardware only if user handed pointer and driver actually
ian@0 710 gathers hardware statistics */
ian@0 711 if (hardware_statistics && (in_be32(&uf_regs->upsmr) & UPSMR_HSE)) {
ian@0 712 hardware_statistics->tx64 = in_be32(&ug_regs->tx64);
ian@0 713 hardware_statistics->tx127 = in_be32(&ug_regs->tx127);
ian@0 714 hardware_statistics->tx255 = in_be32(&ug_regs->tx255);
ian@0 715 hardware_statistics->rx64 = in_be32(&ug_regs->rx64);
ian@0 716 hardware_statistics->rx127 = in_be32(&ug_regs->rx127);
ian@0 717 hardware_statistics->rx255 = in_be32(&ug_regs->rx255);
ian@0 718 hardware_statistics->txok = in_be32(&ug_regs->txok);
ian@0 719 hardware_statistics->txcf = in_be16(&ug_regs->txcf);
ian@0 720 hardware_statistics->tmca = in_be32(&ug_regs->tmca);
ian@0 721 hardware_statistics->tbca = in_be32(&ug_regs->tbca);
ian@0 722 hardware_statistics->rxfok = in_be32(&ug_regs->rxfok);
ian@0 723 hardware_statistics->rxbok = in_be32(&ug_regs->rxbok);
ian@0 724 hardware_statistics->rbyt = in_be32(&ug_regs->rbyt);
ian@0 725 hardware_statistics->rmca = in_be32(&ug_regs->rmca);
ian@0 726 hardware_statistics->rbca = in_be32(&ug_regs->rbca);
ian@0 727 }
ian@0 728 }
ian@0 729
ian@0 730 static void dump_bds(ucc_geth_private_t *ugeth)
ian@0 731 {
ian@0 732 int i;
ian@0 733 int length;
ian@0 734
ian@0 735 for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) {
ian@0 736 if (ugeth->p_tx_bd_ring[i]) {
ian@0 737 length =
ian@0 738 (ugeth->ug_info->bdRingLenTx[i] *
ian@0 739 UCC_GETH_SIZE_OF_BD);
ian@0 740 ugeth_info("TX BDs[%d]", i);
ian@0 741 mem_disp(ugeth->p_tx_bd_ring[i], length);
ian@0 742 }
ian@0 743 }
ian@0 744 for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
ian@0 745 if (ugeth->p_rx_bd_ring[i]) {
ian@0 746 length =
ian@0 747 (ugeth->ug_info->bdRingLenRx[i] *
ian@0 748 UCC_GETH_SIZE_OF_BD);
ian@0 749 ugeth_info("RX BDs[%d]", i);
ian@0 750 mem_disp(ugeth->p_rx_bd_ring[i], length);
ian@0 751 }
ian@0 752 }
ian@0 753 }
ian@0 754
ian@0 755 static void dump_regs(ucc_geth_private_t *ugeth)
ian@0 756 {
ian@0 757 int i;
ian@0 758
ian@0 759 ugeth_info("UCC%d Geth registers:", ugeth->ug_info->uf_info.ucc_num);
ian@0 760 ugeth_info("Base address: 0x%08x", (u32) ugeth->ug_regs);
ian@0 761
ian@0 762 ugeth_info("maccfg1 : addr - 0x%08x, val - 0x%08x",
ian@0 763 (u32) & ugeth->ug_regs->maccfg1,
ian@0 764 in_be32(&ugeth->ug_regs->maccfg1));
ian@0 765 ugeth_info("maccfg2 : addr - 0x%08x, val - 0x%08x",
ian@0 766 (u32) & ugeth->ug_regs->maccfg2,
ian@0 767 in_be32(&ugeth->ug_regs->maccfg2));
ian@0 768 ugeth_info("ipgifg : addr - 0x%08x, val - 0x%08x",
ian@0 769 (u32) & ugeth->ug_regs->ipgifg,
ian@0 770 in_be32(&ugeth->ug_regs->ipgifg));
ian@0 771 ugeth_info("hafdup : addr - 0x%08x, val - 0x%08x",
ian@0 772 (u32) & ugeth->ug_regs->hafdup,
ian@0 773 in_be32(&ugeth->ug_regs->hafdup));
ian@0 774 ugeth_info("miimcfg : addr - 0x%08x, val - 0x%08x",
ian@0 775 (u32) & ugeth->ug_regs->miimng.miimcfg,
ian@0 776 in_be32(&ugeth->ug_regs->miimng.miimcfg));
ian@0 777 ugeth_info("miimcom : addr - 0x%08x, val - 0x%08x",
ian@0 778 (u32) & ugeth->ug_regs->miimng.miimcom,
ian@0 779 in_be32(&ugeth->ug_regs->miimng.miimcom));
ian@0 780 ugeth_info("miimadd : addr - 0x%08x, val - 0x%08x",
ian@0 781 (u32) & ugeth->ug_regs->miimng.miimadd,
ian@0 782 in_be32(&ugeth->ug_regs->miimng.miimadd));
ian@0 783 ugeth_info("miimcon : addr - 0x%08x, val - 0x%08x",
ian@0 784 (u32) & ugeth->ug_regs->miimng.miimcon,
ian@0 785 in_be32(&ugeth->ug_regs->miimng.miimcon));
ian@0 786 ugeth_info("miimstat : addr - 0x%08x, val - 0x%08x",
ian@0 787 (u32) & ugeth->ug_regs->miimng.miimstat,
ian@0 788 in_be32(&ugeth->ug_regs->miimng.miimstat));
ian@0 789 ugeth_info("miimmind : addr - 0x%08x, val - 0x%08x",
ian@0 790 (u32) & ugeth->ug_regs->miimng.miimind,
ian@0 791 in_be32(&ugeth->ug_regs->miimng.miimind));
ian@0 792 ugeth_info("ifctl : addr - 0x%08x, val - 0x%08x",
ian@0 793 (u32) & ugeth->ug_regs->ifctl,
ian@0 794 in_be32(&ugeth->ug_regs->ifctl));
ian@0 795 ugeth_info("ifstat : addr - 0x%08x, val - 0x%08x",
ian@0 796 (u32) & ugeth->ug_regs->ifstat,
ian@0 797 in_be32(&ugeth->ug_regs->ifstat));
ian@0 798 ugeth_info("macstnaddr1: addr - 0x%08x, val - 0x%08x",
ian@0 799 (u32) & ugeth->ug_regs->macstnaddr1,
ian@0 800 in_be32(&ugeth->ug_regs->macstnaddr1));
ian@0 801 ugeth_info("macstnaddr2: addr - 0x%08x, val - 0x%08x",
ian@0 802 (u32) & ugeth->ug_regs->macstnaddr2,
ian@0 803 in_be32(&ugeth->ug_regs->macstnaddr2));
ian@0 804 ugeth_info("uempr : addr - 0x%08x, val - 0x%08x",
ian@0 805 (u32) & ugeth->ug_regs->uempr,
ian@0 806 in_be32(&ugeth->ug_regs->uempr));
ian@0 807 ugeth_info("utbipar : addr - 0x%08x, val - 0x%08x",
ian@0 808 (u32) & ugeth->ug_regs->utbipar,
ian@0 809 in_be32(&ugeth->ug_regs->utbipar));
ian@0 810 ugeth_info("uescr : addr - 0x%08x, val - 0x%04x",
ian@0 811 (u32) & ugeth->ug_regs->uescr,
ian@0 812 in_be16(&ugeth->ug_regs->uescr));
ian@0 813 ugeth_info("tx64 : addr - 0x%08x, val - 0x%08x",
ian@0 814 (u32) & ugeth->ug_regs->tx64,
ian@0 815 in_be32(&ugeth->ug_regs->tx64));
ian@0 816 ugeth_info("tx127 : addr - 0x%08x, val - 0x%08x",
ian@0 817 (u32) & ugeth->ug_regs->tx127,
ian@0 818 in_be32(&ugeth->ug_regs->tx127));
ian@0 819 ugeth_info("tx255 : addr - 0x%08x, val - 0x%08x",
ian@0 820 (u32) & ugeth->ug_regs->tx255,
ian@0 821 in_be32(&ugeth->ug_regs->tx255));
ian@0 822 ugeth_info("rx64 : addr - 0x%08x, val - 0x%08x",
ian@0 823 (u32) & ugeth->ug_regs->rx64,
ian@0 824 in_be32(&ugeth->ug_regs->rx64));
ian@0 825 ugeth_info("rx127 : addr - 0x%08x, val - 0x%08x",
ian@0 826 (u32) & ugeth->ug_regs->rx127,
ian@0 827 in_be32(&ugeth->ug_regs->rx127));
ian@0 828 ugeth_info("rx255 : addr - 0x%08x, val - 0x%08x",
ian@0 829 (u32) & ugeth->ug_regs->rx255,
ian@0 830 in_be32(&ugeth->ug_regs->rx255));
ian@0 831 ugeth_info("txok : addr - 0x%08x, val - 0x%08x",
ian@0 832 (u32) & ugeth->ug_regs->txok,
ian@0 833 in_be32(&ugeth->ug_regs->txok));
ian@0 834 ugeth_info("txcf : addr - 0x%08x, val - 0x%04x",
ian@0 835 (u32) & ugeth->ug_regs->txcf,
ian@0 836 in_be16(&ugeth->ug_regs->txcf));
ian@0 837 ugeth_info("tmca : addr - 0x%08x, val - 0x%08x",
ian@0 838 (u32) & ugeth->ug_regs->tmca,
ian@0 839 in_be32(&ugeth->ug_regs->tmca));
ian@0 840 ugeth_info("tbca : addr - 0x%08x, val - 0x%08x",
ian@0 841 (u32) & ugeth->ug_regs->tbca,
ian@0 842 in_be32(&ugeth->ug_regs->tbca));
ian@0 843 ugeth_info("rxfok : addr - 0x%08x, val - 0x%08x",
ian@0 844 (u32) & ugeth->ug_regs->rxfok,
ian@0 845 in_be32(&ugeth->ug_regs->rxfok));
ian@0 846 ugeth_info("rxbok : addr - 0x%08x, val - 0x%08x",
ian@0 847 (u32) & ugeth->ug_regs->rxbok,
ian@0 848 in_be32(&ugeth->ug_regs->rxbok));
ian@0 849 ugeth_info("rbyt : addr - 0x%08x, val - 0x%08x",
ian@0 850 (u32) & ugeth->ug_regs->rbyt,
ian@0 851 in_be32(&ugeth->ug_regs->rbyt));
ian@0 852 ugeth_info("rmca : addr - 0x%08x, val - 0x%08x",
ian@0 853 (u32) & ugeth->ug_regs->rmca,
ian@0 854 in_be32(&ugeth->ug_regs->rmca));
ian@0 855 ugeth_info("rbca : addr - 0x%08x, val - 0x%08x",
ian@0 856 (u32) & ugeth->ug_regs->rbca,
ian@0 857 in_be32(&ugeth->ug_regs->rbca));
ian@0 858 ugeth_info("scar : addr - 0x%08x, val - 0x%08x",
ian@0 859 (u32) & ugeth->ug_regs->scar,
ian@0 860 in_be32(&ugeth->ug_regs->scar));
ian@0 861 ugeth_info("scam : addr - 0x%08x, val - 0x%08x",
ian@0 862 (u32) & ugeth->ug_regs->scam,
ian@0 863 in_be32(&ugeth->ug_regs->scam));
ian@0 864
ian@0 865 if (ugeth->p_thread_data_tx) {
ian@0 866 int numThreadsTxNumerical;
ian@0 867 switch (ugeth->ug_info->numThreadsTx) {
ian@0 868 case UCC_GETH_NUM_OF_THREADS_1:
ian@0 869 numThreadsTxNumerical = 1;
ian@0 870 break;
ian@0 871 case UCC_GETH_NUM_OF_THREADS_2:
ian@0 872 numThreadsTxNumerical = 2;
ian@0 873 break;
ian@0 874 case UCC_GETH_NUM_OF_THREADS_4:
ian@0 875 numThreadsTxNumerical = 4;
ian@0 876 break;
ian@0 877 case UCC_GETH_NUM_OF_THREADS_6:
ian@0 878 numThreadsTxNumerical = 6;
ian@0 879 break;
ian@0 880 case UCC_GETH_NUM_OF_THREADS_8:
ian@0 881 numThreadsTxNumerical = 8;
ian@0 882 break;
ian@0 883 default:
ian@0 884 numThreadsTxNumerical = 0;
ian@0 885 break;
ian@0 886 }
ian@0 887
ian@0 888 ugeth_info("Thread data TXs:");
ian@0 889 ugeth_info("Base address: 0x%08x",
ian@0 890 (u32) ugeth->p_thread_data_tx);
ian@0 891 for (i = 0; i < numThreadsTxNumerical; i++) {
ian@0 892 ugeth_info("Thread data TX[%d]:", i);
ian@0 893 ugeth_info("Base address: 0x%08x",
ian@0 894 (u32) & ugeth->p_thread_data_tx[i]);
ian@0 895 mem_disp((u8 *) & ugeth->p_thread_data_tx[i],
ian@0 896 sizeof(ucc_geth_thread_data_tx_t));
ian@0 897 }
ian@0 898 }
ian@0 899 if (ugeth->p_thread_data_rx) {
ian@0 900 int numThreadsRxNumerical;
ian@0 901 switch (ugeth->ug_info->numThreadsRx) {
ian@0 902 case UCC_GETH_NUM_OF_THREADS_1:
ian@0 903 numThreadsRxNumerical = 1;
ian@0 904 break;
ian@0 905 case UCC_GETH_NUM_OF_THREADS_2:
ian@0 906 numThreadsRxNumerical = 2;
ian@0 907 break;
ian@0 908 case UCC_GETH_NUM_OF_THREADS_4:
ian@0 909 numThreadsRxNumerical = 4;
ian@0 910 break;
ian@0 911 case UCC_GETH_NUM_OF_THREADS_6:
ian@0 912 numThreadsRxNumerical = 6;
ian@0 913 break;
ian@0 914 case UCC_GETH_NUM_OF_THREADS_8:
ian@0 915 numThreadsRxNumerical = 8;
ian@0 916 break;
ian@0 917 default:
ian@0 918 numThreadsRxNumerical = 0;
ian@0 919 break;
ian@0 920 }
ian@0 921
ian@0 922 ugeth_info("Thread data RX:");
ian@0 923 ugeth_info("Base address: 0x%08x",
ian@0 924 (u32) ugeth->p_thread_data_rx);
ian@0 925 for (i = 0; i < numThreadsRxNumerical; i++) {
ian@0 926 ugeth_info("Thread data RX[%d]:", i);
ian@0 927 ugeth_info("Base address: 0x%08x",
ian@0 928 (u32) & ugeth->p_thread_data_rx[i]);
ian@0 929 mem_disp((u8 *) & ugeth->p_thread_data_rx[i],
ian@0 930 sizeof(ucc_geth_thread_data_rx_t));
ian@0 931 }
ian@0 932 }
ian@0 933 if (ugeth->p_exf_glbl_param) {
ian@0 934 ugeth_info("EXF global param:");
ian@0 935 ugeth_info("Base address: 0x%08x",
ian@0 936 (u32) ugeth->p_exf_glbl_param);
ian@0 937 mem_disp((u8 *) ugeth->p_exf_glbl_param,
ian@0 938 sizeof(*ugeth->p_exf_glbl_param));
ian@0 939 }
ian@0 940 if (ugeth->p_tx_glbl_pram) {
ian@0 941 ugeth_info("TX global param:");
ian@0 942 ugeth_info("Base address: 0x%08x", (u32) ugeth->p_tx_glbl_pram);
ian@0 943 ugeth_info("temoder : addr - 0x%08x, val - 0x%04x",
ian@0 944 (u32) & ugeth->p_tx_glbl_pram->temoder,
ian@0 945 in_be16(&ugeth->p_tx_glbl_pram->temoder));
ian@0 946 ugeth_info("sqptr : addr - 0x%08x, val - 0x%08x",
ian@0 947 (u32) & ugeth->p_tx_glbl_pram->sqptr,
ian@0 948 in_be32(&ugeth->p_tx_glbl_pram->sqptr));
ian@0 949 ugeth_info("schedulerbasepointer: addr - 0x%08x, val - 0x%08x",
ian@0 950 (u32) & ugeth->p_tx_glbl_pram->schedulerbasepointer,
ian@0 951 in_be32(&ugeth->p_tx_glbl_pram->
ian@0 952 schedulerbasepointer));
ian@0 953 ugeth_info("txrmonbaseptr: addr - 0x%08x, val - 0x%08x",
ian@0 954 (u32) & ugeth->p_tx_glbl_pram->txrmonbaseptr,
ian@0 955 in_be32(&ugeth->p_tx_glbl_pram->txrmonbaseptr));
ian@0 956 ugeth_info("tstate : addr - 0x%08x, val - 0x%08x",
ian@0 957 (u32) & ugeth->p_tx_glbl_pram->tstate,
ian@0 958 in_be32(&ugeth->p_tx_glbl_pram->tstate));
ian@0 959 ugeth_info("iphoffset[0] : addr - 0x%08x, val - 0x%02x",
ian@0 960 (u32) & ugeth->p_tx_glbl_pram->iphoffset[0],
ian@0 961 ugeth->p_tx_glbl_pram->iphoffset[0]);
ian@0 962 ugeth_info("iphoffset[1] : addr - 0x%08x, val - 0x%02x",
ian@0 963 (u32) & ugeth->p_tx_glbl_pram->iphoffset[1],
ian@0 964 ugeth->p_tx_glbl_pram->iphoffset[1]);
ian@0 965 ugeth_info("iphoffset[2] : addr - 0x%08x, val - 0x%02x",
ian@0 966 (u32) & ugeth->p_tx_glbl_pram->iphoffset[2],
ian@0 967 ugeth->p_tx_glbl_pram->iphoffset[2]);
ian@0 968 ugeth_info("iphoffset[3] : addr - 0x%08x, val - 0x%02x",
ian@0 969 (u32) & ugeth->p_tx_glbl_pram->iphoffset[3],
ian@0 970 ugeth->p_tx_glbl_pram->iphoffset[3]);
ian@0 971 ugeth_info("iphoffset[4] : addr - 0x%08x, val - 0x%02x",
ian@0 972 (u32) & ugeth->p_tx_glbl_pram->iphoffset[4],
ian@0 973 ugeth->p_tx_glbl_pram->iphoffset[4]);
ian@0 974 ugeth_info("iphoffset[5] : addr - 0x%08x, val - 0x%02x",
ian@0 975 (u32) & ugeth->p_tx_glbl_pram->iphoffset[5],
ian@0 976 ugeth->p_tx_glbl_pram->iphoffset[5]);
ian@0 977 ugeth_info("iphoffset[6] : addr - 0x%08x, val - 0x%02x",
ian@0 978 (u32) & ugeth->p_tx_glbl_pram->iphoffset[6],
ian@0 979 ugeth->p_tx_glbl_pram->iphoffset[6]);
ian@0 980 ugeth_info("iphoffset[7] : addr - 0x%08x, val - 0x%02x",
ian@0 981 (u32) & ugeth->p_tx_glbl_pram->iphoffset[7],
ian@0 982 ugeth->p_tx_glbl_pram->iphoffset[7]);
ian@0 983 ugeth_info("vtagtable[0] : addr - 0x%08x, val - 0x%08x",
ian@0 984 (u32) & ugeth->p_tx_glbl_pram->vtagtable[0],
ian@0 985 in_be32(&ugeth->p_tx_glbl_pram->vtagtable[0]));
ian@0 986 ugeth_info("vtagtable[1] : addr - 0x%08x, val - 0x%08x",
ian@0 987 (u32) & ugeth->p_tx_glbl_pram->vtagtable[1],
ian@0 988 in_be32(&ugeth->p_tx_glbl_pram->vtagtable[1]));
ian@0 989 ugeth_info("vtagtable[2] : addr - 0x%08x, val - 0x%08x",
ian@0 990 (u32) & ugeth->p_tx_glbl_pram->vtagtable[2],
ian@0 991 in_be32(&ugeth->p_tx_glbl_pram->vtagtable[2]));
ian@0 992 ugeth_info("vtagtable[3] : addr - 0x%08x, val - 0x%08x",
ian@0 993 (u32) & ugeth->p_tx_glbl_pram->vtagtable[3],
ian@0 994 in_be32(&ugeth->p_tx_glbl_pram->vtagtable[3]));
ian@0 995 ugeth_info("vtagtable[4] : addr - 0x%08x, val - 0x%08x",
ian@0 996 (u32) & ugeth->p_tx_glbl_pram->vtagtable[4],
ian@0 997 in_be32(&ugeth->p_tx_glbl_pram->vtagtable[4]));
ian@0 998 ugeth_info("vtagtable[5] : addr - 0x%08x, val - 0x%08x",
ian@0 999 (u32) & ugeth->p_tx_glbl_pram->vtagtable[5],
ian@0 1000 in_be32(&ugeth->p_tx_glbl_pram->vtagtable[5]));
ian@0 1001 ugeth_info("vtagtable[6] : addr - 0x%08x, val - 0x%08x",
ian@0 1002 (u32) & ugeth->p_tx_glbl_pram->vtagtable[6],
ian@0 1003 in_be32(&ugeth->p_tx_glbl_pram->vtagtable[6]));
ian@0 1004 ugeth_info("vtagtable[7] : addr - 0x%08x, val - 0x%08x",
ian@0 1005 (u32) & ugeth->p_tx_glbl_pram->vtagtable[7],
ian@0 1006 in_be32(&ugeth->p_tx_glbl_pram->vtagtable[7]));
ian@0 1007 ugeth_info("tqptr : addr - 0x%08x, val - 0x%08x",
ian@0 1008 (u32) & ugeth->p_tx_glbl_pram->tqptr,
ian@0 1009 in_be32(&ugeth->p_tx_glbl_pram->tqptr));
ian@0 1010 }
ian@0 1011 if (ugeth->p_rx_glbl_pram) {
ian@0 1012 ugeth_info("RX global param:");
ian@0 1013 ugeth_info("Base address: 0x%08x", (u32) ugeth->p_rx_glbl_pram);
ian@0 1014 ugeth_info("remoder : addr - 0x%08x, val - 0x%08x",
ian@0 1015 (u32) & ugeth->p_rx_glbl_pram->remoder,
ian@0 1016 in_be32(&ugeth->p_rx_glbl_pram->remoder));
ian@0 1017 ugeth_info("rqptr : addr - 0x%08x, val - 0x%08x",
ian@0 1018 (u32) & ugeth->p_rx_glbl_pram->rqptr,
ian@0 1019 in_be32(&ugeth->p_rx_glbl_pram->rqptr));
ian@0 1020 ugeth_info("typeorlen : addr - 0x%08x, val - 0x%04x",
ian@0 1021 (u32) & ugeth->p_rx_glbl_pram->typeorlen,
ian@0 1022 in_be16(&ugeth->p_rx_glbl_pram->typeorlen));
ian@0 1023 ugeth_info("rxgstpack : addr - 0x%08x, val - 0x%02x",
ian@0 1024 (u32) & ugeth->p_rx_glbl_pram->rxgstpack,
ian@0 1025 ugeth->p_rx_glbl_pram->rxgstpack);
ian@0 1026 ugeth_info("rxrmonbaseptr : addr - 0x%08x, val - 0x%08x",
ian@0 1027 (u32) & ugeth->p_rx_glbl_pram->rxrmonbaseptr,
ian@0 1028 in_be32(&ugeth->p_rx_glbl_pram->rxrmonbaseptr));
ian@0 1029 ugeth_info("intcoalescingptr: addr - 0x%08x, val - 0x%08x",
ian@0 1030 (u32) & ugeth->p_rx_glbl_pram->intcoalescingptr,
ian@0 1031 in_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr));
ian@0 1032 ugeth_info("rstate : addr - 0x%08x, val - 0x%02x",
ian@0 1033 (u32) & ugeth->p_rx_glbl_pram->rstate,
ian@0 1034 ugeth->p_rx_glbl_pram->rstate);
ian@0 1035 ugeth_info("mrblr : addr - 0x%08x, val - 0x%04x",
ian@0 1036 (u32) & ugeth->p_rx_glbl_pram->mrblr,
ian@0 1037 in_be16(&ugeth->p_rx_glbl_pram->mrblr));
ian@0 1038 ugeth_info("rbdqptr : addr - 0x%08x, val - 0x%08x",
ian@0 1039 (u32) & ugeth->p_rx_glbl_pram->rbdqptr,
ian@0 1040 in_be32(&ugeth->p_rx_glbl_pram->rbdqptr));
ian@0 1041 ugeth_info("mflr : addr - 0x%08x, val - 0x%04x",
ian@0 1042 (u32) & ugeth->p_rx_glbl_pram->mflr,
ian@0 1043 in_be16(&ugeth->p_rx_glbl_pram->mflr));
ian@0 1044 ugeth_info("minflr : addr - 0x%08x, val - 0x%04x",
ian@0 1045 (u32) & ugeth->p_rx_glbl_pram->minflr,
ian@0 1046 in_be16(&ugeth->p_rx_glbl_pram->minflr));
ian@0 1047 ugeth_info("maxd1 : addr - 0x%08x, val - 0x%04x",
ian@0 1048 (u32) & ugeth->p_rx_glbl_pram->maxd1,
ian@0 1049 in_be16(&ugeth->p_rx_glbl_pram->maxd1));
ian@0 1050 ugeth_info("maxd2 : addr - 0x%08x, val - 0x%04x",
ian@0 1051 (u32) & ugeth->p_rx_glbl_pram->maxd2,
ian@0 1052 in_be16(&ugeth->p_rx_glbl_pram->maxd2));
ian@0 1053 ugeth_info("ecamptr : addr - 0x%08x, val - 0x%08x",
ian@0 1054 (u32) & ugeth->p_rx_glbl_pram->ecamptr,
ian@0 1055 in_be32(&ugeth->p_rx_glbl_pram->ecamptr));
ian@0 1056 ugeth_info("l2qt : addr - 0x%08x, val - 0x%08x",
ian@0 1057 (u32) & ugeth->p_rx_glbl_pram->l2qt,
ian@0 1058 in_be32(&ugeth->p_rx_glbl_pram->l2qt));
ian@0 1059 ugeth_info("l3qt[0] : addr - 0x%08x, val - 0x%08x",
ian@0 1060 (u32) & ugeth->p_rx_glbl_pram->l3qt[0],
ian@0 1061 in_be32(&ugeth->p_rx_glbl_pram->l3qt[0]));
ian@0 1062 ugeth_info("l3qt[1] : addr - 0x%08x, val - 0x%08x",
ian@0 1063 (u32) & ugeth->p_rx_glbl_pram->l3qt[1],
ian@0 1064 in_be32(&ugeth->p_rx_glbl_pram->l3qt[1]));
ian@0 1065 ugeth_info("l3qt[2] : addr - 0x%08x, val - 0x%08x",
ian@0 1066 (u32) & ugeth->p_rx_glbl_pram->l3qt[2],
ian@0 1067 in_be32(&ugeth->p_rx_glbl_pram->l3qt[2]));
ian@0 1068 ugeth_info("l3qt[3] : addr - 0x%08x, val - 0x%08x",
ian@0 1069 (u32) & ugeth->p_rx_glbl_pram->l3qt[3],
ian@0 1070 in_be32(&ugeth->p_rx_glbl_pram->l3qt[3]));
ian@0 1071 ugeth_info("l3qt[4] : addr - 0x%08x, val - 0x%08x",
ian@0 1072 (u32) & ugeth->p_rx_glbl_pram->l3qt[4],
ian@0 1073 in_be32(&ugeth->p_rx_glbl_pram->l3qt[4]));
ian@0 1074 ugeth_info("l3qt[5] : addr - 0x%08x, val - 0x%08x",
ian@0 1075 (u32) & ugeth->p_rx_glbl_pram->l3qt[5],
ian@0 1076 in_be32(&ugeth->p_rx_glbl_pram->l3qt[5]));
ian@0 1077 ugeth_info("l3qt[6] : addr - 0x%08x, val - 0x%08x",
ian@0 1078 (u32) & ugeth->p_rx_glbl_pram->l3qt[6],
ian@0 1079 in_be32(&ugeth->p_rx_glbl_pram->l3qt[6]));
ian@0 1080 ugeth_info("l3qt[7] : addr - 0x%08x, val - 0x%08x",
ian@0 1081 (u32) & ugeth->p_rx_glbl_pram->l3qt[7],
ian@0 1082 in_be32(&ugeth->p_rx_glbl_pram->l3qt[7]));
ian@0 1083 ugeth_info("vlantype : addr - 0x%08x, val - 0x%04x",
ian@0 1084 (u32) & ugeth->p_rx_glbl_pram->vlantype,
ian@0 1085 in_be16(&ugeth->p_rx_glbl_pram->vlantype));
ian@0 1086 ugeth_info("vlantci : addr - 0x%08x, val - 0x%04x",
ian@0 1087 (u32) & ugeth->p_rx_glbl_pram->vlantci,
ian@0 1088 in_be16(&ugeth->p_rx_glbl_pram->vlantci));
ian@0 1089 for (i = 0; i < 64; i++)
ian@0 1090 ugeth_info
ian@0 1091 ("addressfiltering[%d]: addr - 0x%08x, val - 0x%02x",
ian@0 1092 i,
ian@0 1093 (u32) & ugeth->p_rx_glbl_pram->addressfiltering[i],
ian@0 1094 ugeth->p_rx_glbl_pram->addressfiltering[i]);
ian@0 1095 ugeth_info("exfGlobalParam : addr - 0x%08x, val - 0x%08x",
ian@0 1096 (u32) & ugeth->p_rx_glbl_pram->exfGlobalParam,
ian@0 1097 in_be32(&ugeth->p_rx_glbl_pram->exfGlobalParam));
ian@0 1098 }
ian@0 1099 if (ugeth->p_send_q_mem_reg) {
ian@0 1100 ugeth_info("Send Q memory registers:");
ian@0 1101 ugeth_info("Base address: 0x%08x",
ian@0 1102 (u32) ugeth->p_send_q_mem_reg);
ian@0 1103 for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) {
ian@0 1104 ugeth_info("SQQD[%d]:", i);
ian@0 1105 ugeth_info("Base address: 0x%08x",
ian@0 1106 (u32) & ugeth->p_send_q_mem_reg->sqqd[i]);
ian@0 1107 mem_disp((u8 *) & ugeth->p_send_q_mem_reg->sqqd[i],
ian@0 1108 sizeof(ucc_geth_send_queue_qd_t));
ian@0 1109 }
ian@0 1110 }
ian@0 1111 if (ugeth->p_scheduler) {
ian@0 1112 ugeth_info("Scheduler:");
ian@0 1113 ugeth_info("Base address: 0x%08x", (u32) ugeth->p_scheduler);
ian@0 1114 mem_disp((u8 *) ugeth->p_scheduler,
ian@0 1115 sizeof(*ugeth->p_scheduler));
ian@0 1116 }
ian@0 1117 if (ugeth->p_tx_fw_statistics_pram) {
ian@0 1118 ugeth_info("TX FW statistics pram:");
ian@0 1119 ugeth_info("Base address: 0x%08x",
ian@0 1120 (u32) ugeth->p_tx_fw_statistics_pram);
ian@0 1121 mem_disp((u8 *) ugeth->p_tx_fw_statistics_pram,
ian@0 1122 sizeof(*ugeth->p_tx_fw_statistics_pram));
ian@0 1123 }
ian@0 1124 if (ugeth->p_rx_fw_statistics_pram) {
ian@0 1125 ugeth_info("RX FW statistics pram:");
ian@0 1126 ugeth_info("Base address: 0x%08x",
ian@0 1127 (u32) ugeth->p_rx_fw_statistics_pram);
ian@0 1128 mem_disp((u8 *) ugeth->p_rx_fw_statistics_pram,
ian@0 1129 sizeof(*ugeth->p_rx_fw_statistics_pram));
ian@0 1130 }
ian@0 1131 if (ugeth->p_rx_irq_coalescing_tbl) {
ian@0 1132 ugeth_info("RX IRQ coalescing tables:");
ian@0 1133 ugeth_info("Base address: 0x%08x",
ian@0 1134 (u32) ugeth->p_rx_irq_coalescing_tbl);
ian@0 1135 for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
ian@0 1136 ugeth_info("RX IRQ coalescing table entry[%d]:", i);
ian@0 1137 ugeth_info("Base address: 0x%08x",
ian@0 1138 (u32) & ugeth->p_rx_irq_coalescing_tbl->
ian@0 1139 coalescingentry[i]);
ian@0 1140 ugeth_info
ian@0 1141 ("interruptcoalescingmaxvalue: addr - 0x%08x, val - 0x%08x",
ian@0 1142 (u32) & ugeth->p_rx_irq_coalescing_tbl->
ian@0 1143 coalescingentry[i].interruptcoalescingmaxvalue,
ian@0 1144 in_be32(&ugeth->p_rx_irq_coalescing_tbl->
ian@0 1145 coalescingentry[i].
ian@0 1146 interruptcoalescingmaxvalue));
ian@0 1147 ugeth_info
ian@0 1148 ("interruptcoalescingcounter : addr - 0x%08x, val - 0x%08x",
ian@0 1149 (u32) & ugeth->p_rx_irq_coalescing_tbl->
ian@0 1150 coalescingentry[i].interruptcoalescingcounter,
ian@0 1151 in_be32(&ugeth->p_rx_irq_coalescing_tbl->
ian@0 1152 coalescingentry[i].
ian@0 1153 interruptcoalescingcounter));
ian@0 1154 }
ian@0 1155 }
ian@0 1156 if (ugeth->p_rx_bd_qs_tbl) {
ian@0 1157 ugeth_info("RX BD QS tables:");
ian@0 1158 ugeth_info("Base address: 0x%08x", (u32) ugeth->p_rx_bd_qs_tbl);
ian@0 1159 for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
ian@0 1160 ugeth_info("RX BD QS table[%d]:", i);
ian@0 1161 ugeth_info("Base address: 0x%08x",
ian@0 1162 (u32) & ugeth->p_rx_bd_qs_tbl[i]);
ian@0 1163 ugeth_info
ian@0 1164 ("bdbaseptr : addr - 0x%08x, val - 0x%08x",
ian@0 1165 (u32) & ugeth->p_rx_bd_qs_tbl[i].bdbaseptr,
ian@0 1166 in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdbaseptr));
ian@0 1167 ugeth_info
ian@0 1168 ("bdptr : addr - 0x%08x, val - 0x%08x",
ian@0 1169 (u32) & ugeth->p_rx_bd_qs_tbl[i].bdptr,
ian@0 1170 in_be32(&ugeth->p_rx_bd_qs_tbl[i].bdptr));
ian@0 1171 ugeth_info
ian@0 1172 ("externalbdbaseptr: addr - 0x%08x, val - 0x%08x",
ian@0 1173 (u32) & ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,
ian@0 1174 in_be32(&ugeth->p_rx_bd_qs_tbl[i].
ian@0 1175 externalbdbaseptr));
ian@0 1176 ugeth_info
ian@0 1177 ("externalbdptr : addr - 0x%08x, val - 0x%08x",
ian@0 1178 (u32) & ugeth->p_rx_bd_qs_tbl[i].externalbdptr,
ian@0 1179 in_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdptr));
ian@0 1180 ugeth_info("ucode RX Prefetched BDs:");
ian@0 1181 ugeth_info("Base address: 0x%08x",
ian@0 1182 (u32)
ian@0 1183 qe_muram_addr(in_be32
ian@0 1184 (&ugeth->p_rx_bd_qs_tbl[i].
ian@0 1185 bdbaseptr)));
ian@0 1186 mem_disp((u8 *)
ian@0 1187 qe_muram_addr(in_be32
ian@0 1188 (&ugeth->p_rx_bd_qs_tbl[i].
ian@0 1189 bdbaseptr)),
ian@0 1190 sizeof(ucc_geth_rx_prefetched_bds_t));
ian@0 1191 }
ian@0 1192 }
ian@0 1193 if (ugeth->p_init_enet_param_shadow) {
ian@0 1194 int size;
ian@0 1195 ugeth_info("Init enet param shadow:");
ian@0 1196 ugeth_info("Base address: 0x%08x",
ian@0 1197 (u32) ugeth->p_init_enet_param_shadow);
ian@0 1198 mem_disp((u8 *) ugeth->p_init_enet_param_shadow,
ian@0 1199 sizeof(*ugeth->p_init_enet_param_shadow));
ian@0 1200
ian@0 1201 size = sizeof(ucc_geth_thread_rx_pram_t);
ian@0 1202 if (ugeth->ug_info->rxExtendedFiltering) {
ian@0 1203 size +=
ian@0 1204 THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING;
ian@0 1205 if (ugeth->ug_info->largestexternallookupkeysize ==
ian@0 1206 QE_FLTR_TABLE_LOOKUP_KEY_SIZE_8_BYTES)
ian@0 1207 size +=
ian@0 1208 THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_8;
ian@0 1209 if (ugeth->ug_info->largestexternallookupkeysize ==
ian@0 1210 QE_FLTR_TABLE_LOOKUP_KEY_SIZE_16_BYTES)
ian@0 1211 size +=
ian@0 1212 THREAD_RX_PRAM_ADDITIONAL_FOR_EXTENDED_FILTERING_16;
ian@0 1213 }
ian@0 1214
ian@0 1215 dump_init_enet_entries(ugeth,
ian@0 1216 &(ugeth->p_init_enet_param_shadow->
ian@0 1217 txthread[0]),
ian@0 1218 ENET_INIT_PARAM_MAX_ENTRIES_TX,
ian@0 1219 sizeof(ucc_geth_thread_tx_pram_t),
ian@0 1220 ugeth->ug_info->riscTx, 0);
ian@0 1221 dump_init_enet_entries(ugeth,
ian@0 1222 &(ugeth->p_init_enet_param_shadow->
ian@0 1223 rxthread[0]),
ian@0 1224 ENET_INIT_PARAM_MAX_ENTRIES_RX, size,
ian@0 1225 ugeth->ug_info->riscRx, 1);
ian@0 1226 }
ian@0 1227 }
ian@0 1228 #endif /* DEBUG */
ian@0 1229
ian@0 1230 static void init_default_reg_vals(volatile u32 *upsmr_register,
ian@0 1231 volatile u32 *maccfg1_register,
ian@0 1232 volatile u32 *maccfg2_register)
ian@0 1233 {
ian@0 1234 out_be32(upsmr_register, UCC_GETH_UPSMR_INIT);
ian@0 1235 out_be32(maccfg1_register, UCC_GETH_MACCFG1_INIT);
ian@0 1236 out_be32(maccfg2_register, UCC_GETH_MACCFG2_INIT);
ian@0 1237 }
ian@0 1238
ian@0 1239 static int init_half_duplex_params(int alt_beb,
ian@0 1240 int back_pressure_no_backoff,
ian@0 1241 int no_backoff,
ian@0 1242 int excess_defer,
ian@0 1243 u8 alt_beb_truncation,
ian@0 1244 u8 max_retransmissions,
ian@0 1245 u8 collision_window,
ian@0 1246 volatile u32 *hafdup_register)
ian@0 1247 {
ian@0 1248 u32 value = 0;
ian@0 1249
ian@0 1250 if ((alt_beb_truncation > HALFDUP_ALT_BEB_TRUNCATION_MAX) ||
ian@0 1251 (max_retransmissions > HALFDUP_MAX_RETRANSMISSION_MAX) ||
ian@0 1252 (collision_window > HALFDUP_COLLISION_WINDOW_MAX))
ian@0 1253 return -EINVAL;
ian@0 1254
ian@0 1255 value = (u32) (alt_beb_truncation << HALFDUP_ALT_BEB_TRUNCATION_SHIFT);
ian@0 1256
ian@0 1257 if (alt_beb)
ian@0 1258 value |= HALFDUP_ALT_BEB;
ian@0 1259 if (back_pressure_no_backoff)
ian@0 1260 value |= HALFDUP_BACK_PRESSURE_NO_BACKOFF;
ian@0 1261 if (no_backoff)
ian@0 1262 value |= HALFDUP_NO_BACKOFF;
ian@0 1263 if (excess_defer)
ian@0 1264 value |= HALFDUP_EXCESSIVE_DEFER;
ian@0 1265
ian@0 1266 value |= (max_retransmissions << HALFDUP_MAX_RETRANSMISSION_SHIFT);
ian@0 1267
ian@0 1268 value |= collision_window;
ian@0 1269
ian@0 1270 out_be32(hafdup_register, value);
ian@0 1271 return 0;
ian@0 1272 }
ian@0 1273
ian@0 1274 static int init_inter_frame_gap_params(u8 non_btb_cs_ipg,
ian@0 1275 u8 non_btb_ipg,
ian@0 1276 u8 min_ifg,
ian@0 1277 u8 btb_ipg,
ian@0 1278 volatile u32 *ipgifg_register)
ian@0 1279 {
ian@0 1280 u32 value = 0;
ian@0 1281
ian@0 1282 /* Non-Back-to-back IPG part 1 should be <= Non-Back-to-back
ian@0 1283 IPG part 2 */
ian@0 1284 if (non_btb_cs_ipg > non_btb_ipg)
ian@0 1285 return -EINVAL;
ian@0 1286
ian@0 1287 if ((non_btb_cs_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART1_MAX) ||
ian@0 1288 (non_btb_ipg > IPGIFG_NON_BACK_TO_BACK_IFG_PART2_MAX) ||
ian@0 1289 /*(min_ifg > IPGIFG_MINIMUM_IFG_ENFORCEMENT_MAX) || */
ian@0 1290 (btb_ipg > IPGIFG_BACK_TO_BACK_IFG_MAX))
ian@0 1291 return -EINVAL;
ian@0 1292
ian@0 1293 value |=
ian@0 1294 ((non_btb_cs_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART1_SHIFT) &
ian@0 1295 IPGIFG_NBTB_CS_IPG_MASK);
ian@0 1296 value |=
ian@0 1297 ((non_btb_ipg << IPGIFG_NON_BACK_TO_BACK_IFG_PART2_SHIFT) &
ian@0 1298 IPGIFG_NBTB_IPG_MASK);
ian@0 1299 value |=
ian@0 1300 ((min_ifg << IPGIFG_MINIMUM_IFG_ENFORCEMENT_SHIFT) &
ian@0 1301 IPGIFG_MIN_IFG_MASK);
ian@0 1302 value |= (btb_ipg & IPGIFG_BTB_IPG_MASK);
ian@0 1303
ian@0 1304 out_be32(ipgifg_register, value);
ian@0 1305 return 0;
ian@0 1306 }
ian@0 1307
ian@0 1308 static int init_flow_control_params(u32 automatic_flow_control_mode,
ian@0 1309 int rx_flow_control_enable,
ian@0 1310 int tx_flow_control_enable,
ian@0 1311 u16 pause_period,
ian@0 1312 u16 extension_field,
ian@0 1313 volatile u32 *upsmr_register,
ian@0 1314 volatile u32 *uempr_register,
ian@0 1315 volatile u32 *maccfg1_register)
ian@0 1316 {
ian@0 1317 u32 value = 0;
ian@0 1318
ian@0 1319 /* Set UEMPR register */
ian@0 1320 value = (u32) pause_period << UEMPR_PAUSE_TIME_VALUE_SHIFT;
ian@0 1321 value |= (u32) extension_field << UEMPR_EXTENDED_PAUSE_TIME_VALUE_SHIFT;
ian@0 1322 out_be32(uempr_register, value);
ian@0 1323
ian@0 1324 /* Set UPSMR register */
ian@0 1325 value = in_be32(upsmr_register);
ian@0 1326 value |= automatic_flow_control_mode;
ian@0 1327 out_be32(upsmr_register, value);
ian@0 1328
ian@0 1329 value = in_be32(maccfg1_register);
ian@0 1330 if (rx_flow_control_enable)
ian@0 1331 value |= MACCFG1_FLOW_RX;
ian@0 1332 if (tx_flow_control_enable)
ian@0 1333 value |= MACCFG1_FLOW_TX;
ian@0 1334 out_be32(maccfg1_register, value);
ian@0 1335
ian@0 1336 return 0;
ian@0 1337 }
ian@0 1338
ian@0 1339 static int init_hw_statistics_gathering_mode(int enable_hardware_statistics,
ian@0 1340 int auto_zero_hardware_statistics,
ian@0 1341 volatile u32 *upsmr_register,
ian@0 1342 volatile u16 *uescr_register)
ian@0 1343 {
ian@0 1344 u32 upsmr_value = 0;
ian@0 1345 u16 uescr_value = 0;
ian@0 1346 /* Enable hardware statistics gathering if requested */
ian@0 1347 if (enable_hardware_statistics) {
ian@0 1348 upsmr_value = in_be32(upsmr_register);
ian@0 1349 upsmr_value |= UPSMR_HSE;
ian@0 1350 out_be32(upsmr_register, upsmr_value);
ian@0 1351 }
ian@0 1352
ian@0 1353 /* Clear hardware statistics counters */
ian@0 1354 uescr_value = in_be16(uescr_register);
ian@0 1355 uescr_value |= UESCR_CLRCNT;
ian@0 1356 /* Automatically zero hardware statistics counters on read,
ian@0 1357 if requested */
ian@0 1358 if (auto_zero_hardware_statistics)
ian@0 1359 uescr_value |= UESCR_AUTOZ;
ian@0 1360 out_be16(uescr_register, uescr_value);
ian@0 1361
ian@0 1362 return 0;
ian@0 1363 }
ian@0 1364
ian@0 1365 static int init_firmware_statistics_gathering_mode(int
ian@0 1366 enable_tx_firmware_statistics,
ian@0 1367 int enable_rx_firmware_statistics,
ian@0 1368 volatile u32 *tx_rmon_base_ptr,
ian@0 1369 u32 tx_firmware_statistics_structure_address,
ian@0 1370 volatile u32 *rx_rmon_base_ptr,
ian@0 1371 u32 rx_firmware_statistics_structure_address,
ian@0 1372 volatile u16 *temoder_register,
ian@0 1373 volatile u32 *remoder_register)
ian@0 1374 {
ian@0 1375 /* Note: this function does not check if */
ian@0 1376 /* the parameters it receives are NULL */
ian@0 1377 u16 temoder_value;
ian@0 1378 u32 remoder_value;
ian@0 1379
ian@0 1380 if (enable_tx_firmware_statistics) {
ian@0 1381 out_be32(tx_rmon_base_ptr,
ian@0 1382 tx_firmware_statistics_structure_address);
ian@0 1383 temoder_value = in_be16(temoder_register);
ian@0 1384 temoder_value |= TEMODER_TX_RMON_STATISTICS_ENABLE;
ian@0 1385 out_be16(temoder_register, temoder_value);
ian@0 1386 }
ian@0 1387
ian@0 1388 if (enable_rx_firmware_statistics) {
ian@0 1389 out_be32(rx_rmon_base_ptr,
ian@0 1390 rx_firmware_statistics_structure_address);
ian@0 1391 remoder_value = in_be32(remoder_register);
ian@0 1392 remoder_value |= REMODER_RX_RMON_STATISTICS_ENABLE;
ian@0 1393 out_be32(remoder_register, remoder_value);
ian@0 1394 }
ian@0 1395
ian@0 1396 return 0;
ian@0 1397 }
ian@0 1398
ian@0 1399 static int init_mac_station_addr_regs(u8 address_byte_0,
ian@0 1400 u8 address_byte_1,
ian@0 1401 u8 address_byte_2,
ian@0 1402 u8 address_byte_3,
ian@0 1403 u8 address_byte_4,
ian@0 1404 u8 address_byte_5,
ian@0 1405 volatile u32 *macstnaddr1_register,
ian@0 1406 volatile u32 *macstnaddr2_register)
ian@0 1407 {
ian@0 1408 u32 value = 0;
ian@0 1409
ian@0 1410 /* Example: for a station address of 0x12345678ABCD, */
ian@0 1411 /* 0x12 is byte 0, 0x34 is byte 1 and so on and 0xCD is byte 5 */
ian@0 1412
ian@0 1413 /* MACSTNADDR1 Register: */
ian@0 1414
ian@0 1415 /* 0 7 8 15 */
ian@0 1416 /* station address byte 5 station address byte 4 */
ian@0 1417 /* 16 23 24 31 */
ian@0 1418 /* station address byte 3 station address byte 2 */
ian@0 1419 value |= (u32) ((address_byte_2 << 0) & 0x000000FF);
ian@0 1420 value |= (u32) ((address_byte_3 << 8) & 0x0000FF00);
ian@0 1421 value |= (u32) ((address_byte_4 << 16) & 0x00FF0000);
ian@0 1422 value |= (u32) ((address_byte_5 << 24) & 0xFF000000);
ian@0 1423
ian@0 1424 out_be32(macstnaddr1_register, value);
ian@0 1425
ian@0 1426 /* MACSTNADDR2 Register: */
ian@0 1427
ian@0 1428 /* 0 7 8 15 */
ian@0 1429 /* station address byte 1 station address byte 0 */
ian@0 1430 /* 16 23 24 31 */
ian@0 1431 /* reserved reserved */
ian@0 1432 value = 0;
ian@0 1433 value |= (u32) ((address_byte_0 << 16) & 0x00FF0000);
ian@0 1434 value |= (u32) ((address_byte_1 << 24) & 0xFF000000);
ian@0 1435
ian@0 1436 out_be32(macstnaddr2_register, value);
ian@0 1437
ian@0 1438 return 0;
ian@0 1439 }
ian@0 1440
ian@0 1441 static int init_mac_duplex_mode(int full_duplex,
ian@0 1442 int limited_to_full_duplex,
ian@0 1443 volatile u32 *maccfg2_register)
ian@0 1444 {
ian@0 1445 u32 value = 0;
ian@0 1446
ian@0 1447 /* some interfaces must work in full duplex mode */
ian@0 1448 if ((full_duplex == 0) && (limited_to_full_duplex == 1))
ian@0 1449 return -EINVAL;
ian@0 1450
ian@0 1451 value = in_be32(maccfg2_register);
ian@0 1452
ian@0 1453 if (full_duplex)
ian@0 1454 value |= MACCFG2_FDX;
ian@0 1455 else
ian@0 1456 value &= ~MACCFG2_FDX;
ian@0 1457
ian@0 1458 out_be32(maccfg2_register, value);
ian@0 1459 return 0;
ian@0 1460 }
ian@0 1461
ian@0 1462 static int init_check_frame_length_mode(int length_check,
ian@0 1463 volatile u32 *maccfg2_register)
ian@0 1464 {
ian@0 1465 u32 value = 0;
ian@0 1466
ian@0 1467 value = in_be32(maccfg2_register);
ian@0 1468
ian@0 1469 if (length_check)
ian@0 1470 value |= MACCFG2_LC;
ian@0 1471 else
ian@0 1472 value &= ~MACCFG2_LC;
ian@0 1473
ian@0 1474 out_be32(maccfg2_register, value);
ian@0 1475 return 0;
ian@0 1476 }
ian@0 1477
ian@0 1478 static int init_preamble_length(u8 preamble_length,
ian@0 1479 volatile u32 *maccfg2_register)
ian@0 1480 {
ian@0 1481 u32 value = 0;
ian@0 1482
ian@0 1483 if ((preamble_length < 3) || (preamble_length > 7))
ian@0 1484 return -EINVAL;
ian@0 1485
ian@0 1486 value = in_be32(maccfg2_register);
ian@0 1487 value &= ~MACCFG2_PREL_MASK;
ian@0 1488 value |= (preamble_length << MACCFG2_PREL_SHIFT);
ian@0 1489 out_be32(maccfg2_register, value);
ian@0 1490 return 0;
ian@0 1491 }
ian@0 1492
ian@0 1493 static int init_mii_management_configuration(int reset_mgmt,
ian@0 1494 int preamble_supress,
ian@0 1495 volatile u32 *miimcfg_register,
ian@0 1496 volatile u32 *miimind_register)
ian@0 1497 {
ian@0 1498 unsigned int timeout = PHY_INIT_TIMEOUT;
ian@0 1499 u32 value = 0;
ian@0 1500
ian@0 1501 value = in_be32(miimcfg_register);
ian@0 1502 if (reset_mgmt) {
ian@0 1503 value |= MIIMCFG_RESET_MANAGEMENT;
ian@0 1504 out_be32(miimcfg_register, value);
ian@0 1505 }
ian@0 1506
ian@0 1507 value = 0;
ian@0 1508
ian@0 1509 if (preamble_supress)
ian@0 1510 value |= MIIMCFG_NO_PREAMBLE;
ian@0 1511
ian@0 1512 value |= UCC_GETH_MIIMCFG_MNGMNT_CLC_DIV_INIT;
ian@0 1513 out_be32(miimcfg_register, value);
ian@0 1514
ian@0 1515 /* Wait until the bus is free */
ian@0 1516 while ((in_be32(miimind_register) & MIIMIND_BUSY) && timeout--)
ian@0 1517 cpu_relax();
ian@0 1518
ian@0 1519 if (timeout <= 0) {
ian@0 1520 ugeth_err("%s: The MII Bus is stuck!", __FUNCTION__);
ian@0 1521 return -ETIMEDOUT;
ian@0 1522 }
ian@0 1523
ian@0 1524 return 0;
ian@0 1525 }
ian@0 1526
ian@0 1527 static int init_rx_parameters(int reject_broadcast,
ian@0 1528 int receive_short_frames,
ian@0 1529 int promiscuous, volatile u32 *upsmr_register)
ian@0 1530 {
ian@0 1531 u32 value = 0;
ian@0 1532
ian@0 1533 value = in_be32(upsmr_register);
ian@0 1534
ian@0 1535 if (reject_broadcast)
ian@0 1536 value |= UPSMR_BRO;
ian@0 1537 else
ian@0 1538 value &= ~UPSMR_BRO;
ian@0 1539
ian@0 1540 if (receive_short_frames)
ian@0 1541 value |= UPSMR_RSH;
ian@0 1542 else
ian@0 1543 value &= ~UPSMR_RSH;
ian@0 1544
ian@0 1545 if (promiscuous)
ian@0 1546 value |= UPSMR_PRO;
ian@0 1547 else
ian@0 1548 value &= ~UPSMR_PRO;
ian@0 1549
ian@0 1550 out_be32(upsmr_register, value);
ian@0 1551
ian@0 1552 return 0;
ian@0 1553 }
ian@0 1554
ian@0 1555 static int init_max_rx_buff_len(u16 max_rx_buf_len,
ian@0 1556 volatile u16 *mrblr_register)
ian@0 1557 {
ian@0 1558 /* max_rx_buf_len value must be a multiple of 128 */
ian@0 1559 if ((max_rx_buf_len == 0)
ian@0 1560 || (max_rx_buf_len % UCC_GETH_MRBLR_ALIGNMENT))
ian@0 1561 return -EINVAL;
ian@0 1562
ian@0 1563 out_be16(mrblr_register, max_rx_buf_len);
ian@0 1564 return 0;
ian@0 1565 }
ian@0 1566
ian@0 1567 static int init_min_frame_len(u16 min_frame_length,
ian@0 1568 volatile u16 *minflr_register,
ian@0 1569 volatile u16 *mrblr_register)
ian@0 1570 {
ian@0 1571 u16 mrblr_value = 0;
ian@0 1572
ian@0 1573 mrblr_value = in_be16(mrblr_register);
ian@0 1574 if (min_frame_length >= (mrblr_value - 4))
ian@0 1575 return -EINVAL;
ian@0 1576
ian@0 1577 out_be16(minflr_register, min_frame_length);
ian@0 1578 return 0;
ian@0 1579 }
ian@0 1580
ian@0 1581 static int adjust_enet_interface(ucc_geth_private_t *ugeth)
ian@0 1582 {
ian@0 1583 ucc_geth_info_t *ug_info;
ian@0 1584 ucc_geth_t *ug_regs;
ian@0 1585 ucc_fast_t *uf_regs;
ian@0 1586 enet_speed_e speed;
ian@0 1587 int ret_val, rpm = 0, tbi = 0, r10m = 0, rmm =
ian@0 1588 0, limited_to_full_duplex = 0;
ian@0 1589 u32 upsmr, maccfg2, utbipar, tbiBaseAddress;
ian@0 1590 u16 value;
ian@0 1591
ian@0 1592 ugeth_vdbg("%s: IN", __FUNCTION__);
ian@0 1593
ian@0 1594 ug_info = ugeth->ug_info;
ian@0 1595 ug_regs = ugeth->ug_regs;
ian@0 1596 uf_regs = ugeth->uccf->uf_regs;
ian@0 1597
ian@0 1598 /* Analyze enet_interface according to Interface Mode Configuration
ian@0 1599 table */
ian@0 1600 ret_val =
ian@0 1601 get_interface_details(ug_info->enet_interface, &speed, &r10m, &rmm,
ian@0 1602 &rpm, &tbi, &limited_to_full_duplex);
ian@0 1603 if (ret_val != 0) {
ian@0 1604 ugeth_err
ian@0 1605 ("%s: half duplex not supported in requested configuration.",
ian@0 1606 __FUNCTION__);
ian@0 1607 return ret_val;
ian@0 1608 }
ian@0 1609
ian@0 1610 /* Set MACCFG2 */
ian@0 1611 maccfg2 = in_be32(&ug_regs->maccfg2);
ian@0 1612 maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK;
ian@0 1613 if ((speed == ENET_SPEED_10BT) || (speed == ENET_SPEED_100BT))
ian@0 1614 maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
ian@0 1615 else if (speed == ENET_SPEED_1000BT)
ian@0 1616 maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;
ian@0 1617 maccfg2 |= ug_info->padAndCrc;
ian@0 1618 out_be32(&ug_regs->maccfg2, maccfg2);
ian@0 1619
ian@0 1620 /* Set UPSMR */
ian@0 1621 upsmr = in_be32(&uf_regs->upsmr);
ian@0 1622 upsmr &= ~(UPSMR_RPM | UPSMR_R10M | UPSMR_TBIM | UPSMR_RMM);
ian@0 1623 if (rpm)
ian@0 1624 upsmr |= UPSMR_RPM;
ian@0 1625 if (r10m)
ian@0 1626 upsmr |= UPSMR_R10M;
ian@0 1627 if (tbi)
ian@0 1628 upsmr |= UPSMR_TBIM;
ian@0 1629 if (rmm)
ian@0 1630 upsmr |= UPSMR_RMM;
ian@0 1631 out_be32(&uf_regs->upsmr, upsmr);
ian@0 1632
ian@0 1633 /* Set UTBIPAR */
ian@0 1634 utbipar = in_be32(&ug_regs->utbipar);
ian@0 1635 utbipar &= ~UTBIPAR_PHY_ADDRESS_MASK;
ian@0 1636 if (tbi)
ian@0 1637 utbipar |=
ian@0 1638 (ug_info->phy_address +
ian@0 1639 ugeth->ug_info->uf_info.
ian@0 1640 ucc_num) << UTBIPAR_PHY_ADDRESS_SHIFT;
ian@0 1641 else
ian@0 1642 utbipar |=
ian@0 1643 (0x10 +
ian@0 1644 ugeth->ug_info->uf_info.
ian@0 1645 ucc_num) << UTBIPAR_PHY_ADDRESS_SHIFT;
ian@0 1646 out_be32(&ug_regs->utbipar, utbipar);
ian@0 1647
ian@0 1648 /* Disable autonegotiation in tbi mode, because by default it
ian@0 1649 comes up in autonegotiation mode. */
ian@0 1650 /* Note that this depends on proper setting in utbipar register. */
ian@0 1651 if (tbi) {
ian@0 1652 tbiBaseAddress = in_be32(&ug_regs->utbipar);
ian@0 1653 tbiBaseAddress &= UTBIPAR_PHY_ADDRESS_MASK;
ian@0 1654 tbiBaseAddress >>= UTBIPAR_PHY_ADDRESS_SHIFT;
ian@0 1655 value =
ian@0 1656 ugeth->mii_info->mdio_read(ugeth->dev, (u8) tbiBaseAddress,
ian@0 1657 ENET_TBI_MII_CR);
ian@0 1658 value &= ~0x1000; /* Turn off autonegotiation */
ian@0 1659 ugeth->mii_info->mdio_write(ugeth->dev, (u8) tbiBaseAddress,
ian@0 1660 ENET_TBI_MII_CR, value);
ian@0 1661 }
ian@0 1662
ian@0 1663 ret_val = init_mac_duplex_mode(1,
ian@0 1664 limited_to_full_duplex,
ian@0 1665 &ug_regs->maccfg2);
ian@0 1666 if (ret_val != 0) {
ian@0 1667 ugeth_err
ian@0 1668 ("%s: half duplex not supported in requested configuration.",
ian@0 1669 __FUNCTION__);
ian@0 1670 return ret_val;
ian@0 1671 }
ian@0 1672
ian@0 1673 init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2);
ian@0 1674
ian@0 1675 ret_val = init_preamble_length(ug_info->prel, &ug_regs->maccfg2);
ian@0 1676 if (ret_val != 0) {
ian@0 1677 ugeth_err
ian@0 1678 ("%s: Preamble length must be between 3 and 7 inclusive.",
ian@0 1679 __FUNCTION__);
ian@0 1680 return ret_val;
ian@0 1681 }
ian@0 1682
ian@0 1683 return 0;
ian@0 1684 }
ian@0 1685
ian@0 1686 /* Called every time the controller might need to be made
ian@0 1687 * aware of new link state. The PHY code conveys this
ian@0 1688 * information through variables in the ugeth structure, and this
ian@0 1689 * function converts those variables into the appropriate
ian@0 1690 * register values, and can bring down the device if needed.
ian@0 1691 */
ian@0 1692 static void adjust_link(struct net_device *dev)
ian@0 1693 {
ian@0 1694 ucc_geth_private_t *ugeth = netdev_priv(dev);
ian@0 1695 ucc_geth_t *ug_regs;
ian@0 1696 u32 tempval;
ian@0 1697 struct ugeth_mii_info *mii_info = ugeth->mii_info;
ian@0 1698
ian@0 1699 ug_regs = ugeth->ug_regs;
ian@0 1700
ian@0 1701 if (mii_info->link) {
ian@0 1702 /* Now we make sure that we can be in full duplex mode.
ian@0 1703 * If not, we operate in half-duplex mode. */
ian@0 1704 if (mii_info->duplex != ugeth->oldduplex) {
ian@0 1705 if (!(mii_info->duplex)) {
ian@0 1706 tempval = in_be32(&ug_regs->maccfg2);
ian@0 1707 tempval &= ~(MACCFG2_FDX);
ian@0 1708 out_be32(&ug_regs->maccfg2, tempval);
ian@0 1709
ian@0 1710 ugeth_info("%s: Half Duplex", dev->name);
ian@0 1711 } else {
ian@0 1712 tempval = in_be32(&ug_regs->maccfg2);
ian@0 1713 tempval |= MACCFG2_FDX;
ian@0 1714 out_be32(&ug_regs->maccfg2, tempval);
ian@0 1715
ian@0 1716 ugeth_info("%s: Full Duplex", dev->name);
ian@0 1717 }
ian@0 1718
ian@0 1719 ugeth->oldduplex = mii_info->duplex;
ian@0 1720 }
ian@0 1721
ian@0 1722 if (mii_info->speed != ugeth->oldspeed) {
ian@0 1723 switch (mii_info->speed) {
ian@0 1724 case 1000:
ian@0 1725 #ifdef CONFIG_MPC836x
ian@0 1726 /* FIXME: This code is for 100Mbs BUG fixing,
ian@0 1727 remove this when it is fixed!!! */
ian@0 1728 if (ugeth->ug_info->enet_interface ==
ian@0 1729 ENET_1000_GMII)
ian@0 1730 /* Run the commands which initialize the PHY */
ian@0 1731 {
ian@0 1732 tempval =
ian@0 1733 (u32) mii_info->mdio_read(ugeth->
ian@0 1734 dev, mii_info->mii_id, 0x1b);
ian@0 1735 tempval |= 0x000f;
ian@0 1736 mii_info->mdio_write(ugeth->dev,
ian@0 1737 mii_info->mii_id, 0x1b,
ian@0 1738 (u16) tempval);
ian@0 1739 tempval =
ian@0 1740 (u32) mii_info->mdio_read(ugeth->
ian@0 1741 dev, mii_info->mii_id,
ian@0 1742 MII_BMCR);
ian@0 1743 mii_info->mdio_write(ugeth->dev,
ian@0 1744 mii_info->mii_id, MII_BMCR,
ian@0 1745 (u16) (tempval | BMCR_RESET));
ian@0 1746 } else if (ugeth->ug_info->enet_interface ==
ian@0 1747 ENET_1000_RGMII)
ian@0 1748 /* Run the commands which initialize the PHY */
ian@0 1749 {
ian@0 1750 tempval =
ian@0 1751 (u32) mii_info->mdio_read(ugeth->
ian@0 1752 dev, mii_info->mii_id, 0x1b);
ian@0 1753 tempval = (tempval & ~0x000f) | 0x000b;
ian@0 1754 mii_info->mdio_write(ugeth->dev,
ian@0 1755 mii_info->mii_id, 0x1b,
ian@0 1756 (u16) tempval);
ian@0 1757 tempval =
ian@0 1758 (u32) mii_info->mdio_read(ugeth->
ian@0 1759 dev, mii_info->mii_id,
ian@0 1760 MII_BMCR);
ian@0 1761 mii_info->mdio_write(ugeth->dev,
ian@0 1762 mii_info->mii_id, MII_BMCR,
ian@0 1763 (u16) (tempval | BMCR_RESET));
ian@0 1764 }
ian@0 1765 msleep(4000);
ian@0 1766 #endif /* CONFIG_MPC8360 */
ian@0 1767 adjust_enet_interface(ugeth);
ian@0 1768 break;
ian@0 1769 case 100:
ian@0 1770 case 10:
ian@0 1771 #ifdef CONFIG_MPC836x
ian@0 1772 /* FIXME: This code is for 100Mbs BUG fixing,
ian@0 1773 remove this lines when it will be fixed!!! */
ian@0 1774 ugeth->ug_info->enet_interface = ENET_100_RGMII;
ian@0 1775 tempval =
ian@0 1776 (u32) mii_info->mdio_read(ugeth->dev,
ian@0 1777 mii_info->mii_id,
ian@0 1778 0x1b);
ian@0 1779 tempval = (tempval & ~0x000f) | 0x000b;
ian@0 1780 mii_info->mdio_write(ugeth->dev,
ian@0 1781 mii_info->mii_id, 0x1b,
ian@0 1782 (u16) tempval);
ian@0 1783 tempval =
ian@0 1784 (u32) mii_info->mdio_read(ugeth->dev,
ian@0 1785 mii_info->mii_id,
ian@0 1786 MII_BMCR);
ian@0 1787 mii_info->mdio_write(ugeth->dev,
ian@0 1788 mii_info->mii_id, MII_BMCR,
ian@0 1789 (u16) (tempval |
ian@0 1790 BMCR_RESET));
ian@0 1791 msleep(4000);
ian@0 1792 #endif /* CONFIG_MPC8360 */
ian@0 1793 adjust_enet_interface(ugeth);
ian@0 1794 break;
ian@0 1795 default:
ian@0 1796 ugeth_warn
ian@0 1797 ("%s: Ack! Speed (%d) is not 10/100/1000!",
ian@0 1798 dev->name, mii_info->speed);
ian@0 1799 break;
ian@0 1800 }
ian@0 1801
ian@0 1802 ugeth_info("%s: Speed %dBT", dev->name,
ian@0 1803 mii_info->speed);
ian@0 1804
ian@0 1805 ugeth->oldspeed = mii_info->speed;
ian@0 1806 }
ian@0 1807
ian@0 1808 if (!ugeth->oldlink) {
ian@0 1809 ugeth_info("%s: Link is up", dev->name);
ian@0 1810 ugeth->oldlink = 1;
ian@0 1811 netif_carrier_on(dev);
ian@0 1812 netif_schedule(dev);
ian@0 1813 }
ian@0 1814 } else {
ian@0 1815 if (ugeth->oldlink) {
ian@0 1816 ugeth_info("%s: Link is down", dev->name);
ian@0 1817 ugeth->oldlink = 0;
ian@0 1818 ugeth->oldspeed = 0;
ian@0 1819 ugeth->oldduplex = -1;
ian@0 1820 netif_carrier_off(dev);
ian@0 1821 }
ian@0 1822 }
ian@0 1823 }
ian@0 1824
ian@0 1825 /* Configure the PHY for dev.
ian@0 1826 * returns 0 if success. -1 if failure
ian@0 1827 */
ian@0 1828 static int init_phy(struct net_device *dev)
ian@0 1829 {
ian@0 1830 ucc_geth_private_t *ugeth = netdev_priv(dev);
ian@0 1831 struct phy_info *curphy;
ian@0 1832 ucc_mii_mng_t *mii_regs;
ian@0 1833 struct ugeth_mii_info *mii_info;
ian@0 1834 int err;
ian@0 1835
ian@0 1836 mii_regs = &ugeth->ug_regs->miimng;
ian@0 1837
ian@0 1838 ugeth->oldlink = 0;
ian@0 1839 ugeth->oldspeed = 0;
ian@0 1840 ugeth->oldduplex = -1;
ian@0 1841
ian@0 1842 mii_info = kmalloc(sizeof(struct ugeth_mii_info), GFP_KERNEL);
ian@0 1843
ian@0 1844 if (NULL == mii_info) {
ian@0 1845 ugeth_err("%s: Could not allocate mii_info", dev->name);
ian@0 1846 return -ENOMEM;
ian@0 1847 }
ian@0 1848
ian@0 1849 mii_info->mii_regs = mii_regs;
ian@0 1850 mii_info->speed = SPEED_1000;
ian@0 1851 mii_info->duplex = DUPLEX_FULL;
ian@0 1852 mii_info->pause = 0;
ian@0 1853 mii_info->link = 0;
ian@0 1854
ian@0 1855 mii_info->advertising = (ADVERTISED_10baseT_Half |
ian@0 1856 ADVERTISED_10baseT_Full |
ian@0 1857 ADVERTISED_100baseT_Half |
ian@0 1858 ADVERTISED_100baseT_Full |
ian@0 1859 ADVERTISED_1000baseT_Full);
ian@0 1860 mii_info->autoneg = 1;
ian@0 1861
ian@0 1862 mii_info->mii_id = ugeth->ug_info->phy_address;
ian@0 1863
ian@0 1864 mii_info->dev = dev;
ian@0 1865
ian@0 1866 mii_info->mdio_read = &read_phy_reg;
ian@0 1867 mii_info->mdio_write = &write_phy_reg;
ian@0 1868
ian@0 1869 ugeth->mii_info = mii_info;
ian@0 1870
ian@0 1871 spin_lock_irq(&ugeth->lock);
ian@0 1872
ian@0 1873 /* Set this UCC to be the master of the MII managment */
ian@0 1874 ucc_set_qe_mux_mii_mng(ugeth->ug_info->uf_info.ucc_num);
ian@0 1875
ian@0 1876 if (init_mii_management_configuration(1,
ian@0 1877 ugeth->ug_info->
ian@0 1878 miiPreambleSupress,
ian@0 1879 &mii_regs->miimcfg,
ian@0 1880 &mii_regs->miimind)) {
ian@0 1881 ugeth_err("%s: The MII Bus is stuck!", dev->name);
ian@0 1882 err = -1;
ian@0 1883 goto bus_fail;
ian@0 1884 }
ian@0 1885
ian@0 1886 spin_unlock_irq(&ugeth->lock);
ian@0 1887
ian@0 1888 /* get info for this PHY */
ian@0 1889 curphy = get_phy_info(ugeth->mii_info);
ian@0 1890
ian@0 1891 if (curphy == NULL) {
ian@0 1892 ugeth_err("%s: No PHY found", dev->name);
ian@0 1893 err = -1;
ian@0 1894 goto no_phy;
ian@0 1895 }
ian@0 1896
ian@0 1897 mii_info->phyinfo = curphy;
ian@0 1898
ian@0 1899 /* Run the commands which initialize the PHY */
ian@0 1900 if (curphy->init) {
ian@0 1901 err = curphy->init(ugeth->mii_info);
ian@0 1902 if (err)
ian@0 1903 goto phy_init_fail;
ian@0 1904 }
ian@0 1905
ian@0 1906 return 0;
ian@0 1907
ian@0 1908 phy_init_fail:
ian@0 1909 no_phy:
ian@0 1910 bus_fail:
ian@0 1911 kfree(mii_info);
ian@0 1912
ian@0 1913 return err;
ian@0 1914 }
ian@0 1915
ian@0 1916 #ifdef CONFIG_UGETH_TX_ON_DEMOND
ian@0 1917 static int ugeth_transmit_on_demand(ucc_geth_private_t *ugeth)
ian@0 1918 {
ian@0 1919 ucc_fast_transmit_on_demand(ugeth->uccf);
ian@0 1920
ian@0 1921 return 0;
ian@0 1922 }
ian@0 1923 #endif
ian@0 1924
ian@0 1925 static int ugeth_graceful_stop_tx(ucc_geth_private_t *ugeth)
ian@0 1926 {
ian@0 1927 ucc_fast_private_t *uccf;
ian@0 1928 u32 cecr_subblock;
ian@0 1929 u32 temp;
ian@0 1930
ian@0 1931 uccf = ugeth->uccf;
ian@0 1932
ian@0 1933 /* Mask GRACEFUL STOP TX interrupt bit and clear it */
ian@0 1934 temp = in_be32(uccf->p_uccm);
ian@0 1935 temp &= ~UCCE_GRA;
ian@0 1936 out_be32(uccf->p_uccm, temp);
ian@0 1937 out_be32(uccf->p_ucce, UCCE_GRA); /* clear by writing 1 */
ian@0 1938
ian@0 1939 /* Issue host command */
ian@0 1940 cecr_subblock =
ian@0 1941 ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
ian@0 1942 qe_issue_cmd(QE_GRACEFUL_STOP_TX, cecr_subblock,
ian@0 1943 (u8) QE_CR_PROTOCOL_ETHERNET, 0);
ian@0 1944
ian@0 1945 /* Wait for command to complete */
ian@0 1946 do {
ian@0 1947 temp = in_be32(uccf->p_ucce);
ian@0 1948 } while (!(temp & UCCE_GRA));
ian@0 1949
ian@0 1950 uccf->stopped_tx = 1;
ian@0 1951
ian@0 1952 return 0;
ian@0 1953 }
ian@0 1954
ian@0 1955 static int ugeth_graceful_stop_rx(ucc_geth_private_t * ugeth)
ian@0 1956 {
ian@0 1957 ucc_fast_private_t *uccf;
ian@0 1958 u32 cecr_subblock;
ian@0 1959 u8 temp;
ian@0 1960
ian@0 1961 uccf = ugeth->uccf;
ian@0 1962
ian@0 1963 /* Clear acknowledge bit */
ian@0 1964 temp = ugeth->p_rx_glbl_pram->rxgstpack;
ian@0 1965 temp &= ~GRACEFUL_STOP_ACKNOWLEDGE_RX;
ian@0 1966 ugeth->p_rx_glbl_pram->rxgstpack = temp;
ian@0 1967
ian@0 1968 /* Keep issuing command and checking acknowledge bit until
ian@0 1969 it is asserted, according to spec */
ian@0 1970 do {
ian@0 1971 /* Issue host command */
ian@0 1972 cecr_subblock =
ian@0 1973 ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.
ian@0 1974 ucc_num);
ian@0 1975 qe_issue_cmd(QE_GRACEFUL_STOP_RX, cecr_subblock,
ian@0 1976 (u8) QE_CR_PROTOCOL_ETHERNET, 0);
ian@0 1977
ian@0 1978 temp = ugeth->p_rx_glbl_pram->rxgstpack;
ian@0 1979 } while (!(temp & GRACEFUL_STOP_ACKNOWLEDGE_RX));
ian@0 1980
ian@0 1981 uccf->stopped_rx = 1;
ian@0 1982
ian@0 1983 return 0;
ian@0 1984 }
ian@0 1985
ian@0 1986 static int ugeth_restart_tx(ucc_geth_private_t *ugeth)
ian@0 1987 {
ian@0 1988 ucc_fast_private_t *uccf;
ian@0 1989 u32 cecr_subblock;
ian@0 1990
ian@0 1991 uccf = ugeth->uccf;
ian@0 1992
ian@0 1993 cecr_subblock =
ian@0 1994 ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
ian@0 1995 qe_issue_cmd(QE_RESTART_TX, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET,
ian@0 1996 0);
ian@0 1997 uccf->stopped_tx = 0;
ian@0 1998
ian@0 1999 return 0;
ian@0 2000 }
ian@0 2001
ian@0 2002 static int ugeth_restart_rx(ucc_geth_private_t *ugeth)
ian@0 2003 {
ian@0 2004 ucc_fast_private_t *uccf;
ian@0 2005 u32 cecr_subblock;
ian@0 2006
ian@0 2007 uccf = ugeth->uccf;
ian@0 2008
ian@0 2009 cecr_subblock =
ian@0 2010 ucc_fast_get_qe_cr_subblock(ugeth->ug_info->uf_info.ucc_num);
ian@0 2011 qe_issue_cmd(QE_RESTART_RX, cecr_subblock, (u8) QE_CR_PROTOCOL_ETHERNET,
ian@0 2012 0);
ian@0 2013 uccf->stopped_rx = 0;
ian@0 2014
ian@0 2015 return 0;
ian@0 2016 }
ian@0 2017
ian@0 2018 static int ugeth_enable(ucc_geth_private_t *ugeth, comm_dir_e mode)
ian@0 2019 {
ian@0 2020 ucc_fast_private_t *uccf;
ian@0 2021 int enabled_tx, enabled_rx;
ian@0 2022
ian@0 2023 uccf = ugeth->uccf;
ian@0 2024
ian@0 2025 /* check if the UCC number is in range. */
ian@0 2026 if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
ian@0 2027 ugeth_err("%s: ucc_num out of range.", __FUNCTION__);
ian@0 2028 return -EINVAL;
ian@0 2029 }
ian@0 2030
ian@0 2031 enabled_tx = uccf->enabled_tx;
ian@0 2032 enabled_rx = uccf->enabled_rx;
ian@0 2033
ian@0 2034 /* Get Tx and Rx going again, in case this channel was actively
ian@0 2035 disabled. */
ian@0 2036 if ((mode & COMM_DIR_TX) && (!enabled_tx) && uccf->stopped_tx)
ian@0 2037 ugeth_restart_tx(ugeth);
ian@0 2038 if ((mode & COMM_DIR_RX) && (!enabled_rx) && uccf->stopped_rx)
ian@0 2039 ugeth_restart_rx(ugeth);
ian@0 2040
ian@0 2041 ucc_fast_enable(uccf, mode); /* OK to do even if not disabled */
ian@0 2042
ian@0 2043 return 0;
ian@0 2044
ian@0 2045 }
ian@0 2046
ian@0 2047 static int ugeth_disable(ucc_geth_private_t * ugeth, comm_dir_e mode)
ian@0 2048 {
ian@0 2049 ucc_fast_private_t *uccf;
ian@0 2050
ian@0 2051 uccf = ugeth->uccf;
ian@0 2052
ian@0 2053 /* check if the UCC number is in range. */
ian@0 2054 if (ugeth->ug_info->uf_info.ucc_num >= UCC_MAX_NUM) {
ian@0 2055 ugeth_err("%s: ucc_num out of range.", __FUNCTION__);
ian@0 2056 return -EINVAL;
ian@0 2057 }
ian@0 2058
ian@0 2059 /* Stop any transmissions */
ian@0 2060 if ((mode & COMM_DIR_TX) && uccf->enabled_tx && !uccf->stopped_tx)
ian@0 2061 ugeth_graceful_stop_tx(ugeth);
ian@0 2062
ian@0 2063 /* Stop any receptions */
ian@0 2064 if ((mode & COMM_DIR_RX) && uccf->enabled_rx && !uccf->stopped_rx)
ian@0 2065 ugeth_graceful_stop_rx(ugeth);
ian@0 2066
ian@0 2067 ucc_fast_disable(ugeth->uccf, mode); /* OK to do even if not enabled */
ian@0 2068
ian@0 2069 return 0;
ian@0 2070 }
ian@0 2071
ian@0 2072 static void ugeth_dump_regs(ucc_geth_private_t *ugeth)
ian@0 2073 {
ian@0 2074 #ifdef DEBUG
ian@0 2075 ucc_fast_dump_regs(ugeth->uccf);
ian@0 2076 dump_regs(ugeth);
ian@0 2077 dump_bds(ugeth);
ian@0 2078 #endif
ian@0 2079 }
ian@0 2080
ian@0 2081 #ifdef CONFIG_UGETH_FILTERING
ian@0 2082 static int ugeth_ext_filtering_serialize_tad(ucc_geth_tad_params_t *
ian@0 2083 p_UccGethTadParams,
ian@0 2084 qe_fltr_tad_t *qe_fltr_tad)
ian@0 2085 {
ian@0 2086 u16 temp;
ian@0 2087
ian@0 2088 /* Zero serialized TAD */
ian@0 2089 memset(qe_fltr_tad, 0, QE_FLTR_TAD_SIZE);
ian@0 2090
ian@0 2091 qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_V; /* Must have this */
ian@0 2092 if (p_UccGethTadParams->rx_non_dynamic_extended_features_mode ||
ian@0 2093 (p_UccGethTadParams->vtag_op != UCC_GETH_VLAN_OPERATION_TAGGED_NOP)
ian@0 2094 || (p_UccGethTadParams->vnontag_op !=
ian@0 2095 UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP)
ian@0 2096 )
ian@0 2097 qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_EF;
ian@0 2098 if (p_UccGethTadParams->reject_frame)
ian@0 2099 qe_fltr_tad->serialized[0] |= UCC_GETH_TAD_REJ;
ian@0 2100 temp =
ian@0 2101 (u16) (((u16) p_UccGethTadParams->
ian@0 2102 vtag_op) << UCC_GETH_TAD_VTAG_OP_SHIFT);
ian@0 2103 qe_fltr_tad->serialized[0] |= (u8) (temp >> 8); /* upper bits */
ian@0 2104
ian@0 2105 qe_fltr_tad->serialized[1] |= (u8) (temp & 0x00ff); /* lower bits */
ian@0 2106 if (p_UccGethTadParams->vnontag_op ==
ian@0 2107 UCC_GETH_VLAN_OPERATION_NON_TAGGED_Q_TAG_INSERT)
ian@0 2108 qe_fltr_tad->serialized[1] |= UCC_GETH_TAD_V_NON_VTAG_OP;
ian@0 2109 qe_fltr_tad->serialized[1] |=
ian@0 2110 p_UccGethTadParams->rqos << UCC_GETH_TAD_RQOS_SHIFT;
ian@0 2111
ian@0 2112 qe_fltr_tad->serialized[2] |=
ian@0 2113 p_UccGethTadParams->vpri << UCC_GETH_TAD_V_PRIORITY_SHIFT;
ian@0 2114 /* upper bits */
ian@0 2115 qe_fltr_tad->serialized[2] |= (u8) (p_UccGethTadParams->vid >> 8);
ian@0 2116 /* lower bits */
ian@0 2117 qe_fltr_tad->serialized[3] |= (u8) (p_UccGethTadParams->vid & 0x00ff);
ian@0 2118
ian@0 2119 return 0;
ian@0 2120 }
ian@0 2121
ian@0 2122 static enet_addr_container_t
ian@0 2123 *ugeth_82xx_filtering_get_match_addr_in_hash(ucc_geth_private_t *ugeth,
ian@0 2124 enet_addr_t *p_enet_addr)
ian@0 2125 {
ian@0 2126 enet_addr_container_t *enet_addr_cont;
ian@0 2127 struct list_head *p_lh;
ian@0 2128 u16 i, num;
ian@0 2129 int32_t j;
ian@0 2130 u8 *p_counter;
ian@0 2131
ian@0 2132 if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
ian@0 2133 p_lh = &ugeth->group_hash_q;
ian@0 2134 p_counter = &(ugeth->numGroupAddrInHash);
ian@0 2135 } else {
ian@0 2136 p_lh = &ugeth->ind_hash_q;
ian@0 2137 p_counter = &(ugeth->numIndAddrInHash);
ian@0 2138 }
ian@0 2139
ian@0 2140 if (!p_lh)
ian@0 2141 return NULL;
ian@0 2142
ian@0 2143 num = *p_counter;
ian@0 2144
ian@0 2145 for (i = 0; i < num; i++) {
ian@0 2146 enet_addr_cont =
ian@0 2147 (enet_addr_container_t *)
ian@0 2148 ENET_ADDR_CONT_ENTRY(dequeue(p_lh));
ian@0 2149 for (j = ENET_NUM_OCTETS_PER_ADDRESS - 1; j >= 0; j--) {
ian@0 2150 if ((*p_enet_addr)[j] != (enet_addr_cont->address)[j])
ian@0 2151 break;
ian@0 2152 if (j == 0)
ian@0 2153 return enet_addr_cont; /* Found */
ian@0 2154 }
ian@0 2155 enqueue(p_lh, &enet_addr_cont->node); /* Put it back */
ian@0 2156 }
ian@0 2157 return NULL;
ian@0 2158 }
ian@0 2159
ian@0 2160 static int ugeth_82xx_filtering_add_addr_in_hash(ucc_geth_private_t *ugeth,
ian@0 2161 enet_addr_t *p_enet_addr)
ian@0 2162 {
ian@0 2163 ucc_geth_enet_address_recognition_location_e location;
ian@0 2164 enet_addr_container_t *enet_addr_cont;
ian@0 2165 struct list_head *p_lh;
ian@0 2166 u8 i;
ian@0 2167 u32 limit;
ian@0 2168 u8 *p_counter;
ian@0 2169
ian@0 2170 if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
ian@0 2171 p_lh = &ugeth->group_hash_q;
ian@0 2172 limit = ugeth->ug_info->maxGroupAddrInHash;
ian@0 2173 location =
ian@0 2174 UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_GROUP_HASH;
ian@0 2175 p_counter = &(ugeth->numGroupAddrInHash);
ian@0 2176 } else {
ian@0 2177 p_lh = &ugeth->ind_hash_q;
ian@0 2178 limit = ugeth->ug_info->maxIndAddrInHash;
ian@0 2179 location =
ian@0 2180 UCC_GETH_ENET_ADDRESS_RECOGNITION_LOCATION_INDIVIDUAL_HASH;
ian@0 2181 p_counter = &(ugeth->numIndAddrInHash);
ian@0 2182 }
ian@0 2183
ian@0 2184 if ((enet_addr_cont =
ian@0 2185 ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr))) {
ian@0 2186 list_add(p_lh, &enet_addr_cont->node); /* Put it back */
ian@0 2187 return 0;
ian@0 2188 }
ian@0 2189 if ((!p_lh) || (!(*p_counter < limit)))
ian@0 2190 return -EBUSY;
ian@0 2191 if (!(enet_addr_cont = get_enet_addr_container()))
ian@0 2192 return -ENOMEM;
ian@0 2193 for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++)
ian@0 2194 (enet_addr_cont->address)[i] = (*p_enet_addr)[i];
ian@0 2195 enet_addr_cont->location = location;
ian@0 2196 enqueue(p_lh, &enet_addr_cont->node); /* Put it back */
ian@0 2197 ++(*p_counter);
ian@0 2198
ian@0 2199 hw_add_addr_in_hash(ugeth, &(enet_addr_cont->address));
ian@0 2200
ian@0 2201 return 0;
ian@0 2202 }
ian@0 2203
ian@0 2204 static int ugeth_82xx_filtering_clear_addr_in_hash(ucc_geth_private_t *ugeth,
ian@0 2205 enet_addr_t *p_enet_addr)
ian@0 2206 {
ian@0 2207 ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
ian@0 2208 enet_addr_container_t *enet_addr_cont;
ian@0 2209 ucc_fast_private_t *uccf;
ian@0 2210 comm_dir_e comm_dir;
ian@0 2211 u16 i, num;
ian@0 2212 struct list_head *p_lh;
ian@0 2213 u32 *addr_h, *addr_l;
ian@0 2214 u8 *p_counter;
ian@0 2215
ian@0 2216 uccf = ugeth->uccf;
ian@0 2217
ian@0 2218 p_82xx_addr_filt =
ian@0 2219 (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
ian@0 2220 addressfiltering;
ian@0 2221
ian@0 2222 if (!
ian@0 2223 (enet_addr_cont =
ian@0 2224 ugeth_82xx_filtering_get_match_addr_in_hash(ugeth, p_enet_addr)))
ian@0 2225 return -ENOENT;
ian@0 2226
ian@0 2227 /* It's been found and removed from the CQ. */
ian@0 2228 /* Now destroy its container */
ian@0 2229 put_enet_addr_container(enet_addr_cont);
ian@0 2230
ian@0 2231 if ((*p_enet_addr)[0] & ENET_GROUP_ADDR) {
ian@0 2232 addr_h = &(p_82xx_addr_filt->gaddr_h);
ian@0 2233 addr_l = &(p_82xx_addr_filt->gaddr_l);
ian@0 2234 p_lh = &ugeth->group_hash_q;
ian@0 2235 p_counter = &(ugeth->numGroupAddrInHash);
ian@0 2236 } else {
ian@0 2237 addr_h = &(p_82xx_addr_filt->iaddr_h);
ian@0 2238 addr_l = &(p_82xx_addr_filt->iaddr_l);
ian@0 2239 p_lh = &ugeth->ind_hash_q;
ian@0 2240 p_counter = &(ugeth->numIndAddrInHash);
ian@0 2241 }
ian@0 2242
ian@0 2243 comm_dir = 0;
ian@0 2244 if (uccf->enabled_tx)
ian@0 2245 comm_dir |= COMM_DIR_TX;
ian@0 2246 if (uccf->enabled_rx)
ian@0 2247 comm_dir |= COMM_DIR_RX;
ian@0 2248 if (comm_dir)
ian@0 2249 ugeth_disable(ugeth, comm_dir);
ian@0 2250
ian@0 2251 /* Clear the hash table. */
ian@0 2252 out_be32(addr_h, 0x00000000);
ian@0 2253 out_be32(addr_l, 0x00000000);
ian@0 2254
ian@0 2255 /* Add all remaining CQ elements back into hash */
ian@0 2256 num = --(*p_counter);
ian@0 2257 for (i = 0; i < num; i++) {
ian@0 2258 enet_addr_cont =
ian@0 2259 (enet_addr_container_t *)
ian@0 2260 ENET_ADDR_CONT_ENTRY(dequeue(p_lh));
ian@0 2261 hw_add_addr_in_hash(ugeth, &(enet_addr_cont->address));
ian@0 2262 enqueue(p_lh, &enet_addr_cont->node); /* Put it back */
ian@0 2263 }
ian@0 2264
ian@0 2265 if (comm_dir)
ian@0 2266 ugeth_enable(ugeth, comm_dir);
ian@0 2267
ian@0 2268 return 0;
ian@0 2269 }
ian@0 2270 #endif /* CONFIG_UGETH_FILTERING */
ian@0 2271
ian@0 2272 static int ugeth_82xx_filtering_clear_all_addr_in_hash(ucc_geth_private_t *
ian@0 2273 ugeth,
ian@0 2274 enet_addr_type_e
ian@0 2275 enet_addr_type)
ian@0 2276 {
ian@0 2277 ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
ian@0 2278 ucc_fast_private_t *uccf;
ian@0 2279 comm_dir_e comm_dir;
ian@0 2280 struct list_head *p_lh;
ian@0 2281 u16 i, num;
ian@0 2282 u32 *addr_h, *addr_l;
ian@0 2283 u8 *p_counter;
ian@0 2284
ian@0 2285 uccf = ugeth->uccf;
ian@0 2286
ian@0 2287 p_82xx_addr_filt =
ian@0 2288 (ucc_geth_82xx_address_filtering_pram_t *) ugeth->p_rx_glbl_pram->
ian@0 2289 addressfiltering;
ian@0 2290
ian@0 2291 if (enet_addr_type == ENET_ADDR_TYPE_GROUP) {
ian@0 2292 addr_h = &(p_82xx_addr_filt->gaddr_h);
ian@0 2293 addr_l = &(p_82xx_addr_filt->gaddr_l);
ian@0 2294 p_lh = &ugeth->group_hash_q;
ian@0 2295 p_counter = &(ugeth->numGroupAddrInHash);
ian@0 2296 } else if (enet_addr_type == ENET_ADDR_TYPE_INDIVIDUAL) {
ian@0 2297 addr_h = &(p_82xx_addr_filt->iaddr_h);
ian@0 2298 addr_l = &(p_82xx_addr_filt->iaddr_l);
ian@0 2299 p_lh = &ugeth->ind_hash_q;
ian@0 2300 p_counter = &(ugeth->numIndAddrInHash);
ian@0 2301 } else
ian@0 2302 return -EINVAL;
ian@0 2303
ian@0 2304 comm_dir = 0;
ian@0 2305 if (uccf->enabled_tx)
ian@0 2306 comm_dir |= COMM_DIR_TX;
ian@0 2307 if (uccf->enabled_rx)
ian@0 2308 comm_dir |= COMM_DIR_RX;
ian@0 2309 if (comm_dir)
ian@0 2310 ugeth_disable(ugeth, comm_dir);
ian@0 2311
ian@0 2312 /* Clear the hash table. */
ian@0 2313 out_be32(addr_h, 0x00000000);
ian@0 2314 out_be32(addr_l, 0x00000000);
ian@0 2315
ian@0 2316 if (!p_lh)
ian@0 2317 return 0;
ian@0 2318
ian@0 2319 num = *p_counter;
ian@0 2320
ian@0 2321 /* Delete all remaining CQ elements */
ian@0 2322 for (i = 0; i < num; i++)
ian@0 2323 put_enet_addr_container(ENET_ADDR_CONT_ENTRY(dequeue(p_lh)));
ian@0 2324
ian@0 2325 *p_counter = 0;
ian@0 2326
ian@0 2327 if (comm_dir)
ian@0 2328 ugeth_enable(ugeth, comm_dir);
ian@0 2329
ian@0 2330 return 0;
ian@0 2331 }
ian@0 2332
ian@0 2333 #ifdef CONFIG_UGETH_FILTERING
ian@0 2334 static int ugeth_82xx_filtering_add_addr_in_paddr(ucc_geth_private_t *ugeth,
ian@0 2335 enet_addr_t *p_enet_addr,
ian@0 2336 u8 paddr_num)
ian@0 2337 {
ian@0 2338 int i;
ian@0 2339
ian@0 2340 if ((*p_enet_addr)[0] & ENET_GROUP_ADDR)
ian@0 2341 ugeth_warn
ian@0 2342 ("%s: multicast address added to paddr will have no "
ian@0 2343 "effect - is this what you wanted?",
ian@0 2344 __FUNCTION__);
ian@0 2345
ian@0 2346 ugeth->indAddrRegUsed[paddr_num] = 1; /* mark this paddr as used */
ian@0 2347 /* store address in our database */
ian@0 2348 for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++)
ian@0 2349 ugeth->paddr[paddr_num][i] = (*p_enet_addr)[i];
ian@0 2350 /* put in hardware */
ian@0 2351 return hw_add_addr_in_paddr(ugeth, p_enet_addr, paddr_num);
ian@0 2352 }
ian@0 2353 #endif /* CONFIG_UGETH_FILTERING */
ian@0 2354
ian@0 2355 static int ugeth_82xx_filtering_clear_addr_in_paddr(ucc_geth_private_t *ugeth,
ian@0 2356 u8 paddr_num)
ian@0 2357 {
ian@0 2358 ugeth->indAddrRegUsed[paddr_num] = 0; /* mark this paddr as not used */
ian@0 2359 return hw_clear_addr_in_paddr(ugeth, paddr_num);/* clear in hardware */
ian@0 2360 }
ian@0 2361
ian@0 2362 static void ucc_geth_memclean(ucc_geth_private_t *ugeth)
ian@0 2363 {
ian@0 2364 u16 i, j;
ian@0 2365 u8 *bd;
ian@0 2366
ian@0 2367 if (!ugeth)
ian@0 2368 return;
ian@0 2369
ian@0 2370 if (ugeth->uccf)
ian@0 2371 ucc_fast_free(ugeth->uccf);
ian@0 2372
ian@0 2373 if (ugeth->p_thread_data_tx) {
ian@0 2374 qe_muram_free(ugeth->thread_dat_tx_offset);
ian@0 2375 ugeth->p_thread_data_tx = NULL;
ian@0 2376 }
ian@0 2377 if (ugeth->p_thread_data_rx) {
ian@0 2378 qe_muram_free(ugeth->thread_dat_rx_offset);
ian@0 2379 ugeth->p_thread_data_rx = NULL;
ian@0 2380 }
ian@0 2381 if (ugeth->p_exf_glbl_param) {
ian@0 2382 qe_muram_free(ugeth->exf_glbl_param_offset);
ian@0 2383 ugeth->p_exf_glbl_param = NULL;
ian@0 2384 }
ian@0 2385 if (ugeth->p_rx_glbl_pram) {
ian@0 2386 qe_muram_free(ugeth->rx_glbl_pram_offset);
ian@0 2387 ugeth->p_rx_glbl_pram = NULL;
ian@0 2388 }
ian@0 2389 if (ugeth->p_tx_glbl_pram) {
ian@0 2390 qe_muram_free(ugeth->tx_glbl_pram_offset);
ian@0 2391 ugeth->p_tx_glbl_pram = NULL;
ian@0 2392 }
ian@0 2393 if (ugeth->p_send_q_mem_reg) {
ian@0 2394 qe_muram_free(ugeth->send_q_mem_reg_offset);
ian@0 2395 ugeth->p_send_q_mem_reg = NULL;
ian@0 2396 }
ian@0 2397 if (ugeth->p_scheduler) {
ian@0 2398 qe_muram_free(ugeth->scheduler_offset);
ian@0 2399 ugeth->p_scheduler = NULL;
ian@0 2400 }
ian@0 2401 if (ugeth->p_tx_fw_statistics_pram) {
ian@0 2402 qe_muram_free(ugeth->tx_fw_statistics_pram_offset);
ian@0 2403 ugeth->p_tx_fw_statistics_pram = NULL;
ian@0 2404 }
ian@0 2405 if (ugeth->p_rx_fw_statistics_pram) {
ian@0 2406 qe_muram_free(ugeth->rx_fw_statistics_pram_offset);
ian@0 2407 ugeth->p_rx_fw_statistics_pram = NULL;
ian@0 2408 }
ian@0 2409 if (ugeth->p_rx_irq_coalescing_tbl) {
ian@0 2410 qe_muram_free(ugeth->rx_irq_coalescing_tbl_offset);
ian@0 2411 ugeth->p_rx_irq_coalescing_tbl = NULL;
ian@0 2412 }
ian@0 2413 if (ugeth->p_rx_bd_qs_tbl) {
ian@0 2414 qe_muram_free(ugeth->rx_bd_qs_tbl_offset);
ian@0 2415 ugeth->p_rx_bd_qs_tbl = NULL;
ian@0 2416 }
ian@0 2417 if (ugeth->p_init_enet_param_shadow) {
ian@0 2418 return_init_enet_entries(ugeth,
ian@0 2419 &(ugeth->p_init_enet_param_shadow->
ian@0 2420 rxthread[0]),
ian@0 2421 ENET_INIT_PARAM_MAX_ENTRIES_RX,
ian@0 2422 ugeth->ug_info->riscRx, 1);
ian@0 2423 return_init_enet_entries(ugeth,
ian@0 2424 &(ugeth->p_init_enet_param_shadow->
ian@0 2425 txthread[0]),
ian@0 2426 ENET_INIT_PARAM_MAX_ENTRIES_TX,
ian@0 2427 ugeth->ug_info->riscTx, 0);
ian@0 2428 kfree(ugeth->p_init_enet_param_shadow);
ian@0 2429 ugeth->p_init_enet_param_shadow = NULL;
ian@0 2430 }
ian@0 2431 for (i = 0; i < ugeth->ug_info->numQueuesTx; i++) {
ian@0 2432 bd = ugeth->p_tx_bd_ring[i];
ian@0 2433 for (j = 0; j < ugeth->ug_info->bdRingLenTx[i]; j++) {
ian@0 2434 if (ugeth->tx_skbuff[i][j]) {
ian@0 2435 dma_unmap_single(NULL,
ian@0 2436 BD_BUFFER_ARG(bd),
ian@0 2437 (BD_STATUS_AND_LENGTH(bd) &
ian@0 2438 BD_LENGTH_MASK),
ian@0 2439 DMA_TO_DEVICE);
ian@0 2440 dev_kfree_skb_any(ugeth->tx_skbuff[i][j]);
ian@0 2441 ugeth->tx_skbuff[i][j] = NULL;
ian@0 2442 }
ian@0 2443 }
ian@0 2444
ian@0 2445 kfree(ugeth->tx_skbuff[i]);
ian@0 2446
ian@0 2447 if (ugeth->p_tx_bd_ring[i]) {
ian@0 2448 if (ugeth->ug_info->uf_info.bd_mem_part ==
ian@0 2449 MEM_PART_SYSTEM)
ian@0 2450 kfree((void *)ugeth->tx_bd_ring_offset[i]);
ian@0 2451 else if (ugeth->ug_info->uf_info.bd_mem_part ==
ian@0 2452 MEM_PART_MURAM)
ian@0 2453 qe_muram_free(ugeth->tx_bd_ring_offset[i]);
ian@0 2454 ugeth->p_tx_bd_ring[i] = NULL;
ian@0 2455 }
ian@0 2456 }
ian@0 2457 for (i = 0; i < ugeth->ug_info->numQueuesRx; i++) {
ian@0 2458 if (ugeth->p_rx_bd_ring[i]) {
ian@0 2459 /* Return existing data buffers in ring */
ian@0 2460 bd = ugeth->p_rx_bd_ring[i];
ian@0 2461 for (j = 0; j < ugeth->ug_info->bdRingLenRx[i]; j++) {
ian@0 2462 if (ugeth->rx_skbuff[i][j]) {
ian@0 2463 dma_unmap_single(NULL, BD_BUFFER(bd),
ian@0 2464 ugeth->ug_info->
ian@0 2465 uf_info.
ian@0 2466 max_rx_buf_length +
ian@0 2467 UCC_GETH_RX_DATA_BUF_ALIGNMENT,
ian@0 2468 DMA_FROM_DEVICE);
ian@0 2469
ian@0 2470 dev_kfree_skb_any(ugeth->
ian@0 2471 rx_skbuff[i][j]);
ian@0 2472 ugeth->rx_skbuff[i][j] = NULL;
ian@0 2473 }
ian@0 2474 bd += UCC_GETH_SIZE_OF_BD;
ian@0 2475 }
ian@0 2476
ian@0 2477 kfree(ugeth->rx_skbuff[i]);
ian@0 2478
ian@0 2479 if (ugeth->ug_info->uf_info.bd_mem_part ==
ian@0 2480 MEM_PART_SYSTEM)
ian@0 2481 kfree((void *)ugeth->rx_bd_ring_offset[i]);
ian@0 2482 else if (ugeth->ug_info->uf_info.bd_mem_part ==
ian@0 2483 MEM_PART_MURAM)
ian@0 2484 qe_muram_free(ugeth->rx_bd_ring_offset[i]);
ian@0 2485 ugeth->p_rx_bd_ring[i] = NULL;
ian@0 2486 }
ian@0 2487 }
ian@0 2488 while (!list_empty(&ugeth->group_hash_q))
ian@0 2489 put_enet_addr_container(ENET_ADDR_CONT_ENTRY
ian@0 2490 (dequeue(&ugeth->group_hash_q)));
ian@0 2491 while (!list_empty(&ugeth->ind_hash_q))
ian@0 2492 put_enet_addr_container(ENET_ADDR_CONT_ENTRY
ian@0 2493 (dequeue(&ugeth->ind_hash_q)));
ian@0 2494
ian@0 2495 }
ian@0 2496
ian@0 2497 static void ucc_geth_set_multi(struct net_device *dev)
ian@0 2498 {
ian@0 2499 ucc_geth_private_t *ugeth;
ian@0 2500 struct dev_mc_list *dmi;
ian@0 2501 ucc_fast_t *uf_regs;
ian@0 2502 ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
ian@0 2503 enet_addr_t tempaddr;
ian@0 2504 u8 *mcptr, *tdptr;
ian@0 2505 int i, j;
ian@0 2506
ian@0 2507 ugeth = netdev_priv(dev);
ian@0 2508
ian@0 2509 uf_regs = ugeth->uccf->uf_regs;
ian@0 2510
ian@0 2511 if (dev->flags & IFF_PROMISC) {
ian@0 2512
ian@0 2513 /* Log any net taps. */
ian@0 2514 printk("%s: Promiscuous mode enabled.\n", dev->name);
ian@0 2515 uf_regs->upsmr |= UPSMR_PRO;
ian@0 2516
ian@0 2517 } else {
ian@0 2518
ian@0 2519 uf_regs->upsmr &= ~UPSMR_PRO;
ian@0 2520
ian@0 2521 p_82xx_addr_filt =
ian@0 2522 (ucc_geth_82xx_address_filtering_pram_t *) ugeth->
ian@0 2523 p_rx_glbl_pram->addressfiltering;
ian@0 2524
ian@0 2525 if (dev->flags & IFF_ALLMULTI) {
ian@0 2526 /* Catch all multicast addresses, so set the
ian@0 2527 * filter to all 1's.
ian@0 2528 */
ian@0 2529 out_be32(&p_82xx_addr_filt->gaddr_h, 0xffffffff);
ian@0 2530 out_be32(&p_82xx_addr_filt->gaddr_l, 0xffffffff);
ian@0 2531 } else {
ian@0 2532 /* Clear filter and add the addresses in the list.
ian@0 2533 */
ian@0 2534 out_be32(&p_82xx_addr_filt->gaddr_h, 0x0);
ian@0 2535 out_be32(&p_82xx_addr_filt->gaddr_l, 0x0);
ian@0 2536
ian@0 2537 dmi = dev->mc_list;
ian@0 2538
ian@0 2539 for (i = 0; i < dev->mc_count; i++, dmi = dmi->next) {
ian@0 2540
ian@0 2541 /* Only support group multicast for now.
ian@0 2542 */
ian@0 2543 if (!(dmi->dmi_addr[0] & 1))
ian@0 2544 continue;
ian@0 2545
ian@0 2546 /* The address in dmi_addr is LSB first,
ian@0 2547 * and taddr is MSB first. We have to
ian@0 2548 * copy bytes MSB first from dmi_addr.
ian@0 2549 */
ian@0 2550 mcptr = (u8 *) dmi->dmi_addr + 5;
ian@0 2551 tdptr = (u8 *) & tempaddr;
ian@0 2552 for (j = 0; j < 6; j++)
ian@0 2553 *tdptr++ = *mcptr--;
ian@0 2554
ian@0 2555 /* Ask CPM to run CRC and set bit in
ian@0 2556 * filter mask.
ian@0 2557 */
ian@0 2558 hw_add_addr_in_hash(ugeth, &tempaddr);
ian@0 2559
ian@0 2560 }
ian@0 2561 }
ian@0 2562 }
ian@0 2563 }
ian@0 2564
ian@0 2565 static void ucc_geth_stop(ucc_geth_private_t *ugeth)
ian@0 2566 {
ian@0 2567 ucc_geth_t *ug_regs = ugeth->ug_regs;
ian@0 2568 u32 tempval;
ian@0 2569
ian@0 2570 ugeth_vdbg("%s: IN", __FUNCTION__);
ian@0 2571
ian@0 2572 /* Disable the controller */
ian@0 2573 ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
ian@0 2574
ian@0 2575 /* Tell the kernel the link is down */
ian@0 2576 ugeth->mii_info->link = 0;
ian@0 2577 adjust_link(ugeth->dev);
ian@0 2578
ian@0 2579 /* Mask all interrupts */
ian@0 2580 out_be32(ugeth->uccf->p_ucce, 0x00000000);
ian@0 2581
ian@0 2582 /* Clear all interrupts */
ian@0 2583 out_be32(ugeth->uccf->p_ucce, 0xffffffff);
ian@0 2584
ian@0 2585 /* Disable Rx and Tx */
ian@0 2586 tempval = in_be32(&ug_regs->maccfg1);
ian@0 2587 tempval &= ~(MACCFG1_ENABLE_RX | MACCFG1_ENABLE_TX);
ian@0 2588 out_be32(&ug_regs->maccfg1, tempval);
ian@0 2589
ian@0 2590 if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) {
ian@0 2591 /* Clear any pending interrupts */
ian@0 2592 mii_clear_phy_interrupt(ugeth->mii_info);
ian@0 2593
ian@0 2594 /* Disable PHY Interrupts */
ian@0 2595 mii_configure_phy_interrupt(ugeth->mii_info,
ian@0 2596 MII_INTERRUPT_DISABLED);
ian@0 2597 }
ian@0 2598
ian@0 2599 free_irq(ugeth->ug_info->uf_info.irq, ugeth->dev);
ian@0 2600
ian@0 2601 if (ugeth->ug_info->board_flags & FSL_UGETH_BRD_HAS_PHY_INTR) {
ian@0 2602 free_irq(ugeth->ug_info->phy_interrupt, ugeth->dev);
ian@0 2603 } else {
ian@0 2604 del_timer_sync(&ugeth->phy_info_timer);
ian@0 2605 }
ian@0 2606
ian@0 2607 ucc_geth_memclean(ugeth);
ian@0 2608 }
ian@0 2609
ian@0 2610 static int ucc_geth_startup(ucc_geth_private_t *ugeth)
ian@0 2611 {
ian@0 2612 ucc_geth_82xx_address_filtering_pram_t *p_82xx_addr_filt;
ian@0 2613 ucc_geth_init_pram_t *p_init_enet_pram;
ian@0 2614 ucc_fast_private_t *uccf;
ian@0 2615 ucc_geth_info_t *ug_info;
ian@0 2616 ucc_fast_info_t *uf_info;
ian@0 2617 ucc_fast_t *uf_regs;
ian@0 2618 ucc_geth_t *ug_regs;
ian@0 2619 int ret_val = -EINVAL;
ian@0 2620 u32 remoder = UCC_GETH_REMODER_INIT;
ian@0 2621 u32 init_enet_pram_offset, cecr_subblock, command, maccfg1;
ian@0 2622 u32 ifstat, i, j, size, l2qt, l3qt, length;
ian@0 2623 u16 temoder = UCC_GETH_TEMODER_INIT;
ian@0 2624 u16 test;
ian@0 2625 u8 function_code = 0;
ian@0 2626 u8 *bd, *endOfRing;
ian@0 2627 u8 numThreadsRxNumerical, numThreadsTxNumerical;
ian@0 2628
ian@0 2629 ugeth_vdbg("%s: IN", __FUNCTION__);
ian@0 2630
ian@0 2631 ug_info = ugeth->ug_info;
ian@0 2632 uf_info = &ug_info->uf_info;
ian@0 2633
ian@0 2634 if (!((uf_info->bd_mem_part == MEM_PART_SYSTEM) ||
ian@0 2635 (uf_info->bd_mem_part == MEM_PART_MURAM))) {
ian@0 2636 ugeth_err("%s: Bad memory partition value.", __FUNCTION__);
ian@0 2637 return -EINVAL;
ian@0 2638 }
ian@0 2639
ian@0 2640 /* Rx BD lengths */
ian@0 2641 for (i = 0; i < ug_info->numQueuesRx; i++) {
ian@0 2642 if ((ug_info->bdRingLenRx[i] < UCC_GETH_RX_BD_RING_SIZE_MIN) ||
ian@0 2643 (ug_info->bdRingLenRx[i] %
ian@0 2644 UCC_GETH_RX_BD_RING_SIZE_ALIGNMENT)) {
ian@0 2645 ugeth_err
ian@0 2646 ("%s: Rx BD ring length must be multiple of 4,"
ian@0 2647 " no smaller than 8.", __FUNCTION__);
ian@0 2648 return -EINVAL;
ian@0 2649 }
ian@0 2650 }
ian@0 2651
ian@0 2652 /* Tx BD lengths */
ian@0 2653 for (i = 0; i < ug_info->numQueuesTx; i++) {
ian@0 2654 if (ug_info->bdRingLenTx[i] < UCC_GETH_TX_BD_RING_SIZE_MIN) {
ian@0 2655 ugeth_err
ian@0 2656 ("%s: Tx BD ring length must be no smaller than 2.",
ian@0 2657 __FUNCTION__);
ian@0 2658 return -EINVAL;
ian@0 2659 }
ian@0 2660 }
ian@0 2661
ian@0 2662 /* mrblr */
ian@0 2663 if ((uf_info->max_rx_buf_length == 0) ||
ian@0 2664 (uf_info->max_rx_buf_length % UCC_GETH_MRBLR_ALIGNMENT)) {
ian@0 2665 ugeth_err
ian@0 2666 ("%s: max_rx_buf_length must be non-zero multiple of 128.",
ian@0 2667 __FUNCTION__);
ian@0 2668 return -EINVAL;
ian@0 2669 }
ian@0 2670
ian@0 2671 /* num Tx queues */
ian@0 2672 if (ug_info->numQueuesTx > NUM_TX_QUEUES) {
ian@0 2673 ugeth_err("%s: number of tx queues too large.", __FUNCTION__);
ian@0 2674 return -EINVAL;
ian@0 2675 }
ian@0 2676
ian@0 2677 /* num Rx queues */
ian@0 2678 if (ug_info->numQueuesRx > NUM_RX_QUEUES) {
ian@0 2679 ugeth_err("%s: number of rx queues too large.", __FUNCTION__);
ian@0 2680 return -EINVAL;
ian@0 2681 }
ian@0 2682
ian@0 2683 /* l2qt */
ian@0 2684 for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++) {
ian@0 2685 if (ug_info->l2qt[i] >= ug_info->numQueuesRx) {
ian@0 2686 ugeth_err
ian@0 2687 ("%s: VLAN priority table entry must not be"
ian@0 2688 " larger than number of Rx queues.",
ian@0 2689 __FUNCTION__);
ian@0 2690 return -EINVAL;
ian@0 2691 }
ian@0 2692 }
ian@0 2693
ian@0 2694 /* l3qt */
ian@0 2695 for (i = 0; i < UCC_GETH_IP_PRIORITY_MAX; i++) {
ian@0 2696 if (ug_info->l3qt[i] >= ug_info->numQueuesRx) {
ian@0 2697 ugeth_err
ian@0 2698 ("%s: IP priority table entry must not be"
ian@0 2699 " larger than number of Rx queues.",
ian@0 2700 __FUNCTION__);
ian@0 2701 return -EINVAL;
ian@0 2702 }
ian@0 2703 }
ian@0 2704
ian@0 2705 if (ug_info->cam && !ug_info->ecamptr) {
ian@0 2706 ugeth_err("%s: If cam mode is chosen, must supply cam ptr.",
ian@0 2707 __FUNCTION__);
ian@0 2708 return -EINVAL;
ian@0 2709 }
ian@0 2710
ian@0 2711 if ((ug_info->numStationAddresses !=
ian@0 2712 UCC_GETH_NUM_OF_STATION_ADDRESSES_1)
ian@0 2713 && ug_info->rxExtendedFiltering) {
ian@0 2714 ugeth_err("%s: Number of station addresses greater than 1 "
ian@0 2715 "not allowed in extended parsing mode.",
ian@0 2716 __FUNCTION__);
ian@0 2717 return -EINVAL;
ian@0 2718 }
ian@0 2719
ian@0 2720 /* Generate uccm_mask for receive */
ian@0 2721 uf_info->uccm_mask = ug_info->eventRegMask & UCCE_OTHER;/* Errors */
ian@0 2722 for (i = 0; i < ug_info->numQueuesRx; i++)
ian@0 2723 uf_info->uccm_mask |= (UCCE_RXBF_SINGLE_MASK << i);
ian@0 2724
ian@0 2725 for (i = 0; i < ug_info->numQueuesTx; i++)
ian@0 2726 uf_info->uccm_mask |= (UCCE_TXBF_SINGLE_MASK << i);
ian@0 2727 /* Initialize the general fast UCC block. */
ian@0 2728 if (ucc_fast_init(uf_info, &uccf)) {
ian@0 2729 ugeth_err("%s: Failed to init uccf.", __FUNCTION__);
ian@0 2730 ucc_geth_memclean(ugeth);
ian@0 2731 return -ENOMEM;
ian@0 2732 }
ian@0 2733 ugeth->uccf = uccf;
ian@0 2734
ian@0 2735 switch (ug_info->numThreadsRx) {
ian@0 2736 case UCC_GETH_NUM_OF_THREADS_1:
ian@0 2737 numThreadsRxNumerical = 1;
ian@0 2738 break;
ian@0 2739 case UCC_GETH_NUM_OF_THREADS_2:
ian@0 2740 numThreadsRxNumerical = 2;
ian@0 2741 break;
ian@0 2742 case UCC_GETH_NUM_OF_THREADS_4:
ian@0 2743 numThreadsRxNumerical = 4;
ian@0 2744 break;
ian@0 2745 case UCC_GETH_NUM_OF_THREADS_6:
ian@0 2746 numThreadsRxNumerical = 6;
ian@0 2747 break;
ian@0 2748 case UCC_GETH_NUM_OF_THREADS_8:
ian@0 2749 numThreadsRxNumerical = 8;
ian@0 2750 break;
ian@0 2751 default:
ian@0 2752 ugeth_err("%s: Bad number of Rx threads value.", __FUNCTION__);
ian@0 2753 ucc_geth_memclean(ugeth);
ian@0 2754 return -EINVAL;
ian@0 2755 break;
ian@0 2756 }
ian@0 2757
ian@0 2758 switch (ug_info->numThreadsTx) {
ian@0 2759 case UCC_GETH_NUM_OF_THREADS_1:
ian@0 2760 numThreadsTxNumerical = 1;
ian@0 2761 break;
ian@0 2762 case UCC_GETH_NUM_OF_THREADS_2:
ian@0 2763 numThreadsTxNumerical = 2;
ian@0 2764 break;
ian@0 2765 case UCC_GETH_NUM_OF_THREADS_4:
ian@0 2766 numThreadsTxNumerical = 4;
ian@0 2767 break;
ian@0 2768 case UCC_GETH_NUM_OF_THREADS_6:
ian@0 2769 numThreadsTxNumerical = 6;
ian@0 2770 break;
ian@0 2771 case UCC_GETH_NUM_OF_THREADS_8:
ian@0 2772 numThreadsTxNumerical = 8;
ian@0 2773 break;
ian@0 2774 default:
ian@0 2775 ugeth_err("%s: Bad number of Tx threads value.", __FUNCTION__);
ian@0 2776 ucc_geth_memclean(ugeth);
ian@0 2777 return -EINVAL;
ian@0 2778 break;
ian@0 2779 }
ian@0 2780
ian@0 2781 /* Calculate rx_extended_features */
ian@0 2782 ugeth->rx_non_dynamic_extended_features = ug_info->ipCheckSumCheck ||
ian@0 2783 ug_info->ipAddressAlignment ||
ian@0 2784 (ug_info->numStationAddresses !=
ian@0 2785 UCC_GETH_NUM_OF_STATION_ADDRESSES_1);
ian@0 2786
ian@0 2787 ugeth->rx_extended_features = ugeth->rx_non_dynamic_extended_features ||
ian@0 2788 (ug_info->vlanOperationTagged != UCC_GETH_VLAN_OPERATION_TAGGED_NOP)
ian@0 2789 || (ug_info->vlanOperationNonTagged !=
ian@0 2790 UCC_GETH_VLAN_OPERATION_NON_TAGGED_NOP);
ian@0 2791
ian@0 2792 uf_regs = uccf->uf_regs;
ian@0 2793 ug_regs = (ucc_geth_t *) (uccf->uf_regs);
ian@0 2794 ugeth->ug_regs = ug_regs;
ian@0 2795
ian@0 2796 init_default_reg_vals(&uf_regs->upsmr,
ian@0 2797 &ug_regs->maccfg1, &ug_regs->maccfg2);
ian@0 2798
ian@0 2799 /* Set UPSMR */
ian@0 2800 /* For more details see the hardware spec. */
ian@0 2801 init_rx_parameters(ug_info->bro,
ian@0 2802 ug_info->rsh, ug_info->pro, &uf_regs->upsmr);
ian@0 2803
ian@0 2804 /* We're going to ignore other registers for now, */
ian@0 2805 /* except as needed to get up and running */
ian@0 2806
ian@0 2807 /* Set MACCFG1 */
ian@0 2808 /* For more details see the hardware spec. */
ian@0 2809 init_flow_control_params(ug_info->aufc,
ian@0 2810 ug_info->receiveFlowControl,
ian@0 2811 1,
ian@0 2812 ug_info->pausePeriod,
ian@0 2813 ug_info->extensionField,
ian@0 2814 &uf_regs->upsmr,
ian@0 2815 &ug_regs->uempr, &ug_regs->maccfg1);
ian@0 2816
ian@0 2817 maccfg1 = in_be32(&ug_regs->maccfg1);
ian@0 2818 maccfg1 |= MACCFG1_ENABLE_RX;
ian@0 2819 maccfg1 |= MACCFG1_ENABLE_TX;
ian@0 2820 out_be32(&ug_regs->maccfg1, maccfg1);
ian@0 2821
ian@0 2822 /* Set IPGIFG */
ian@0 2823 /* For more details see the hardware spec. */
ian@0 2824 ret_val = init_inter_frame_gap_params(ug_info->nonBackToBackIfgPart1,
ian@0 2825 ug_info->nonBackToBackIfgPart2,
ian@0 2826 ug_info->
ian@0 2827 miminumInterFrameGapEnforcement,
ian@0 2828 ug_info->backToBackInterFrameGap,
ian@0 2829 &ug_regs->ipgifg);
ian@0 2830 if (ret_val != 0) {
ian@0 2831 ugeth_err("%s: IPGIFG initialization parameter too large.",
ian@0 2832 __FUNCTION__);
ian@0 2833 ucc_geth_memclean(ugeth);
ian@0 2834 return ret_val;
ian@0 2835 }
ian@0 2836
ian@0 2837 /* Set HAFDUP */
ian@0 2838 /* For more details see the hardware spec. */
ian@0 2839 ret_val = init_half_duplex_params(ug_info->altBeb,
ian@0 2840 ug_info->backPressureNoBackoff,
ian@0 2841 ug_info->noBackoff,
ian@0 2842 ug_info->excessDefer,
ian@0 2843 ug_info->altBebTruncation,
ian@0 2844 ug_info->maxRetransmission,
ian@0 2845 ug_info->collisionWindow,
ian@0 2846 &ug_regs->hafdup);
ian@0 2847 if (ret_val != 0) {
ian@0 2848 ugeth_err("%s: Half Duplex initialization parameter too large.",
ian@0 2849 __FUNCTION__);
ian@0 2850 ucc_geth_memclean(ugeth);
ian@0 2851 return ret_val;
ian@0 2852 }
ian@0 2853
ian@0 2854 /* Set IFSTAT */
ian@0 2855 /* For more details see the hardware spec. */
ian@0 2856 /* Read only - resets upon read */
ian@0 2857 ifstat = in_be32(&ug_regs->ifstat);
ian@0 2858
ian@0 2859 /* Clear UEMPR */
ian@0 2860 /* For more details see the hardware spec. */
ian@0 2861 out_be32(&ug_regs->uempr, 0);
ian@0 2862
ian@0 2863 /* Set UESCR */
ian@0 2864 /* For more details see the hardware spec. */
ian@0 2865 init_hw_statistics_gathering_mode((ug_info->statisticsMode &
ian@0 2866 UCC_GETH_STATISTICS_GATHERING_MODE_HARDWARE),
ian@0 2867 0, &uf_regs->upsmr, &ug_regs->uescr);
ian@0 2868
ian@0 2869 /* Allocate Tx bds */
ian@0 2870 for (j = 0; j < ug_info->numQueuesTx; j++) {
ian@0 2871 /* Allocate in multiple of
ian@0 2872 UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT,
ian@0 2873 according to spec */
ian@0 2874 length = ((ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD)
ian@0 2875 / UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT)
ian@0 2876 * UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT;
ian@0 2877 if ((ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD) %
ian@0 2878 UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT)
ian@0 2879 length += UCC_GETH_TX_BD_RING_SIZE_MEMORY_ALIGNMENT;
ian@0 2880 if (uf_info->bd_mem_part == MEM_PART_SYSTEM) {
ian@0 2881 u32 align = 4;
ian@0 2882 if (UCC_GETH_TX_BD_RING_ALIGNMENT > 4)
ian@0 2883 align = UCC_GETH_TX_BD_RING_ALIGNMENT;
ian@0 2884 ugeth->tx_bd_ring_offset[j] =
ian@0 2885 (u32) (kmalloc((u32) (length + align),
ian@0 2886 GFP_KERNEL));
ian@0 2887 if (ugeth->tx_bd_ring_offset[j] != 0)
ian@0 2888 ugeth->p_tx_bd_ring[j] =
ian@0 2889 (void*)((ugeth->tx_bd_ring_offset[j] +
ian@0 2890 align) & ~(align - 1));
ian@0 2891 } else if (uf_info->bd_mem_part == MEM_PART_MURAM) {
ian@0 2892 ugeth->tx_bd_ring_offset[j] =
ian@0 2893 qe_muram_alloc(length,
ian@0 2894 UCC_GETH_TX_BD_RING_ALIGNMENT);
ian@0 2895 if (!IS_MURAM_ERR(ugeth->tx_bd_ring_offset[j]))
ian@0 2896 ugeth->p_tx_bd_ring[j] =
ian@0 2897 (u8 *) qe_muram_addr(ugeth->
ian@0 2898 tx_bd_ring_offset[j]);
ian@0 2899 }
ian@0 2900 if (!ugeth->p_tx_bd_ring[j]) {
ian@0 2901 ugeth_err
ian@0 2902 ("%s: Can not allocate memory for Tx bd rings.",
ian@0 2903 __FUNCTION__);
ian@0 2904 ucc_geth_memclean(ugeth);
ian@0 2905 return -ENOMEM;
ian@0 2906 }
ian@0 2907 /* Zero unused end of bd ring, according to spec */
ian@0 2908 memset(ugeth->p_tx_bd_ring[j] +
ian@0 2909 ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD, 0,
ian@0 2910 length - ug_info->bdRingLenTx[j] * UCC_GETH_SIZE_OF_BD);
ian@0 2911 }
ian@0 2912
ian@0 2913 /* Allocate Rx bds */
ian@0 2914 for (j = 0; j < ug_info->numQueuesRx; j++) {
ian@0 2915 length = ug_info->bdRingLenRx[j] * UCC_GETH_SIZE_OF_BD;
ian@0 2916 if (uf_info->bd_mem_part == MEM_PART_SYSTEM) {
ian@0 2917 u32 align = 4;
ian@0 2918 if (UCC_GETH_RX_BD_RING_ALIGNMENT > 4)
ian@0 2919 align = UCC_GETH_RX_BD_RING_ALIGNMENT;
ian@0 2920 ugeth->rx_bd_ring_offset[j] =
ian@0 2921 (u32) (kmalloc((u32) (length + align), GFP_KERNEL));
ian@0 2922 if (ugeth->rx_bd_ring_offset[j] != 0)
ian@0 2923 ugeth->p_rx_bd_ring[j] =
ian@0 2924 (void*)((ugeth->rx_bd_ring_offset[j] +
ian@0 2925 align) & ~(align - 1));
ian@0 2926 } else if (uf_info->bd_mem_part == MEM_PART_MURAM) {
ian@0 2927 ugeth->rx_bd_ring_offset[j] =
ian@0 2928 qe_muram_alloc(length,
ian@0 2929 UCC_GETH_RX_BD_RING_ALIGNMENT);
ian@0 2930 if (!IS_MURAM_ERR(ugeth->rx_bd_ring_offset[j]))
ian@0 2931 ugeth->p_rx_bd_ring[j] =
ian@0 2932 (u8 *) qe_muram_addr(ugeth->
ian@0 2933 rx_bd_ring_offset[j]);
ian@0 2934 }
ian@0 2935 if (!ugeth->p_rx_bd_ring[j]) {
ian@0 2936 ugeth_err
ian@0 2937 ("%s: Can not allocate memory for Rx bd rings.",
ian@0 2938 __FUNCTION__);
ian@0 2939 ucc_geth_memclean(ugeth);
ian@0 2940 return -ENOMEM;
ian@0 2941 }
ian@0 2942 }
ian@0 2943
ian@0 2944 /* Init Tx bds */
ian@0 2945 for (j = 0; j < ug_info->numQueuesTx; j++) {
ian@0 2946 /* Setup the skbuff rings */
ian@0 2947 ugeth->tx_skbuff[j] =
ian@0 2948 (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) *
ian@0 2949 ugeth->ug_info->bdRingLenTx[j],
ian@0 2950 GFP_KERNEL);
ian@0 2951
ian@0 2952 if (ugeth->tx_skbuff[j] == NULL) {
ian@0 2953 ugeth_err("%s: Could not allocate tx_skbuff",
ian@0 2954 __FUNCTION__);
ian@0 2955 ucc_geth_memclean(ugeth);
ian@0 2956 return -ENOMEM;
ian@0 2957 }
ian@0 2958
ian@0 2959 for (i = 0; i < ugeth->ug_info->bdRingLenTx[j]; i++)
ian@0 2960 ugeth->tx_skbuff[j][i] = NULL;
ian@0 2961
ian@0 2962 ugeth->skb_curtx[j] = ugeth->skb_dirtytx[j] = 0;
ian@0 2963 bd = ugeth->confBd[j] = ugeth->txBd[j] = ugeth->p_tx_bd_ring[j];
ian@0 2964 for (i = 0; i < ug_info->bdRingLenTx[j]; i++) {
ian@0 2965 BD_BUFFER_CLEAR(bd);
ian@0 2966 BD_STATUS_AND_LENGTH_SET(bd, 0);
ian@0 2967 bd += UCC_GETH_SIZE_OF_BD;
ian@0 2968 }
ian@0 2969 bd -= UCC_GETH_SIZE_OF_BD;
ian@0 2970 BD_STATUS_AND_LENGTH_SET(bd, T_W);/* for last BD set Wrap bit */
ian@0 2971 }
ian@0 2972
ian@0 2973 /* Init Rx bds */
ian@0 2974 for (j = 0; j < ug_info->numQueuesRx; j++) {
ian@0 2975 /* Setup the skbuff rings */
ian@0 2976 ugeth->rx_skbuff[j] =
ian@0 2977 (struct sk_buff **)kmalloc(sizeof(struct sk_buff *) *
ian@0 2978 ugeth->ug_info->bdRingLenRx[j],
ian@0 2979 GFP_KERNEL);
ian@0 2980
ian@0 2981 if (ugeth->rx_skbuff[j] == NULL) {
ian@0 2982 ugeth_err("%s: Could not allocate rx_skbuff",
ian@0 2983 __FUNCTION__);
ian@0 2984 ucc_geth_memclean(ugeth);
ian@0 2985 return -ENOMEM;
ian@0 2986 }
ian@0 2987
ian@0 2988 for (i = 0; i < ugeth->ug_info->bdRingLenRx[j]; i++)
ian@0 2989 ugeth->rx_skbuff[j][i] = NULL;
ian@0 2990
ian@0 2991 ugeth->skb_currx[j] = 0;
ian@0 2992 bd = ugeth->rxBd[j] = ugeth->p_rx_bd_ring[j];
ian@0 2993 for (i = 0; i < ug_info->bdRingLenRx[j]; i++) {
ian@0 2994 BD_STATUS_AND_LENGTH_SET(bd, R_I);
ian@0 2995 BD_BUFFER_CLEAR(bd);
ian@0 2996 bd += UCC_GETH_SIZE_OF_BD;
ian@0 2997 }
ian@0 2998 bd -= UCC_GETH_SIZE_OF_BD;
ian@0 2999 BD_STATUS_AND_LENGTH_SET(bd, R_W);/* for last BD set Wrap bit */
ian@0 3000 }
ian@0 3001
ian@0 3002 /*
ian@0 3003 * Global PRAM
ian@0 3004 */
ian@0 3005 /* Tx global PRAM */
ian@0 3006 /* Allocate global tx parameter RAM page */
ian@0 3007 ugeth->tx_glbl_pram_offset =
ian@0 3008 qe_muram_alloc(sizeof(ucc_geth_tx_global_pram_t),
ian@0 3009 UCC_GETH_TX_GLOBAL_PRAM_ALIGNMENT);
ian@0 3010 if (IS_MURAM_ERR(ugeth->tx_glbl_pram_offset)) {
ian@0 3011 ugeth_err
ian@0 3012 ("%s: Can not allocate DPRAM memory for p_tx_glbl_pram.",
ian@0 3013 __FUNCTION__);
ian@0 3014 ucc_geth_memclean(ugeth);
ian@0 3015 return -ENOMEM;
ian@0 3016 }
ian@0 3017 ugeth->p_tx_glbl_pram =
ian@0 3018 (ucc_geth_tx_global_pram_t *) qe_muram_addr(ugeth->
ian@0 3019 tx_glbl_pram_offset);
ian@0 3020 /* Zero out p_tx_glbl_pram */
ian@0 3021 memset(ugeth->p_tx_glbl_pram, 0, sizeof(ucc_geth_tx_global_pram_t));
ian@0 3022
ian@0 3023 /* Fill global PRAM */
ian@0 3024
ian@0 3025 /* TQPTR */
ian@0 3026 /* Size varies with number of Tx threads */
ian@0 3027 ugeth->thread_dat_tx_offset =
ian@0 3028 qe_muram_alloc(numThreadsTxNumerical *
ian@0 3029 sizeof(ucc_geth_thread_data_tx_t) +
ian@0 3030 32 * (numThreadsTxNumerical == 1),
ian@0 3031 UCC_GETH_THREAD_DATA_ALIGNMENT);
ian@0 3032 if (IS_MURAM_ERR(ugeth->thread_dat_tx_offset)) {
ian@0 3033 ugeth_err
ian@0 3034 ("%s: Can not allocate DPRAM memory for p_thread_data_tx.",
ian@0 3035 __FUNCTION__);
ian@0 3036 ucc_geth_memclean(ugeth);
ian@0 3037 return -ENOMEM;
ian@0 3038 }
ian@0 3039
ian@0 3040 ugeth->p_thread_data_tx =
ian@0 3041 (ucc_geth_thread_data_tx_t *) qe_muram_addr(ugeth->
ian@0 3042 thread_dat_tx_offset);
ian@0 3043 out_be32(&ugeth->p_tx_glbl_pram->tqptr, ugeth->thread_dat_tx_offset);
ian@0 3044
ian@0 3045 /* vtagtable */
ian@0 3046 for (i = 0; i < UCC_GETH_TX_VTAG_TABLE_ENTRY_MAX; i++)
ian@0 3047 out_be32(&ugeth->p_tx_glbl_pram->vtagtable[i],
ian@0 3048 ug_info->vtagtable[i]);
ian@0 3049
ian@0 3050 /* iphoffset */
ian@0 3051 for (i = 0; i < TX_IP_OFFSET_ENTRY_MAX; i++)
ian@0 3052 ugeth->p_tx_glbl_pram->iphoffset[i] = ug_info->iphoffset[i];
ian@0 3053
ian@0 3054 /* SQPTR */
ian@0 3055 /* Size varies with number of Tx queues */
ian@0 3056 ugeth->send_q_mem_reg_offset =
ian@0 3057 qe_muram_alloc(ug_info->numQueuesTx *
ian@0 3058 sizeof(ucc_geth_send_queue_qd_t),
ian@0 3059 UCC_GETH_SEND_QUEUE_QUEUE_DESCRIPTOR_ALIGNMENT);
ian@0 3060 if (IS_MURAM_ERR(ugeth->send_q_mem_reg_offset)) {
ian@0 3061 ugeth_err
ian@0 3062 ("%s: Can not allocate DPRAM memory for p_send_q_mem_reg.",
ian@0 3063 __FUNCTION__);
ian@0 3064 ucc_geth_memclean(ugeth);
ian@0 3065 return -ENOMEM;
ian@0 3066 }
ian@0 3067
ian@0 3068 ugeth->p_send_q_mem_reg =
ian@0 3069 (ucc_geth_send_queue_mem_region_t *) qe_muram_addr(ugeth->
ian@0 3070 send_q_mem_reg_offset);
ian@0 3071 out_be32(&ugeth->p_tx_glbl_pram->sqptr, ugeth->send_q_mem_reg_offset);
ian@0 3072
ian@0 3073 /* Setup the table */
ian@0 3074 /* Assume BD rings are already established */
ian@0 3075 for (i = 0; i < ug_info->numQueuesTx; i++) {
ian@0 3076 endOfRing =
ian@0 3077 ugeth->p_tx_bd_ring[i] + (ug_info->bdRingLenTx[i] -
ian@0 3078 1) * UCC_GETH_SIZE_OF_BD;
ian@0 3079 if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) {
ian@0 3080 out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base,
ian@0 3081 (u32) virt_to_phys(ugeth->p_tx_bd_ring[i]));
ian@0 3082 out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].
ian@0 3083 last_bd_completed_address,
ian@0 3084 (u32) virt_to_phys(endOfRing));
ian@0 3085 } else if (ugeth->ug_info->uf_info.bd_mem_part ==
ian@0 3086 MEM_PART_MURAM) {
ian@0 3087 out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base,
ian@0 3088 (u32) immrbar_virt_to_phys(ugeth->
ian@0 3089 p_tx_bd_ring[i]));
ian@0 3090 out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].
ian@0 3091 last_bd_completed_address,
ian@0 3092 (u32) immrbar_virt_to_phys(endOfRing));
ian@0 3093 }
ian@0 3094 }
ian@0 3095
ian@0 3096 /* schedulerbasepointer */
ian@0 3097
ian@0 3098 if (ug_info->numQueuesTx > 1) {
ian@0 3099 /* scheduler exists only if more than 1 tx queue */
ian@0 3100 ugeth->scheduler_offset =
ian@0 3101 qe_muram_alloc(sizeof(ucc_geth_scheduler_t),
ian@0 3102 UCC_GETH_SCHEDULER_ALIGNMENT);
ian@0 3103 if (IS_MURAM_ERR(ugeth->scheduler_offset)) {
ian@0 3104 ugeth_err
ian@0 3105 ("%s: Can not allocate DPRAM memory for p_scheduler.",
ian@0 3106 __FUNCTION__);
ian@0 3107 ucc_geth_memclean(ugeth);
ian@0 3108 return -ENOMEM;
ian@0 3109 }
ian@0 3110
ian@0 3111 ugeth->p_scheduler =
ian@0 3112 (ucc_geth_scheduler_t *) qe_muram_addr(ugeth->
ian@0 3113 scheduler_offset);
ian@0 3114 out_be32(&ugeth->p_tx_glbl_pram->schedulerbasepointer,
ian@0 3115 ugeth->scheduler_offset);
ian@0 3116 /* Zero out p_scheduler */
ian@0 3117 memset(ugeth->p_scheduler, 0, sizeof(ucc_geth_scheduler_t));
ian@0 3118
ian@0 3119 /* Set values in scheduler */
ian@0 3120 out_be32(&ugeth->p_scheduler->mblinterval,
ian@0 3121 ug_info->mblinterval);
ian@0 3122 out_be16(&ugeth->p_scheduler->nortsrbytetime,
ian@0 3123 ug_info->nortsrbytetime);
ian@0 3124 ugeth->p_scheduler->fracsiz = ug_info->fracsiz;
ian@0 3125 ugeth->p_scheduler->strictpriorityq = ug_info->strictpriorityq;
ian@0 3126 ugeth->p_scheduler->txasap = ug_info->txasap;
ian@0 3127 ugeth->p_scheduler->extrabw = ug_info->extrabw;
ian@0 3128 for (i = 0; i < NUM_TX_QUEUES; i++)
ian@0 3129 ugeth->p_scheduler->weightfactor[i] =
ian@0 3130 ug_info->weightfactor[i];
ian@0 3131
ian@0 3132 /* Set pointers to cpucount registers in scheduler */
ian@0 3133 ugeth->p_cpucount[0] = &(ugeth->p_scheduler->cpucount0);
ian@0 3134 ugeth->p_cpucount[1] = &(ugeth->p_scheduler->cpucount1);
ian@0 3135 ugeth->p_cpucount[2] = &(ugeth->p_scheduler->cpucount2);
ian@0 3136 ugeth->p_cpucount[3] = &(ugeth->p_scheduler->cpucount3);
ian@0 3137 ugeth->p_cpucount[4] = &(ugeth->p_scheduler->cpucount4);
ian@0 3138 ugeth->p_cpucount[5] = &(ugeth->p_scheduler->cpucount5);
ian@0 3139 ugeth->p_cpucount[6] = &(ugeth->p_scheduler->cpucount6);
ian@0 3140 ugeth->p_cpucount[7] = &(ugeth->p_scheduler->cpucount7);
ian@0 3141 }
ian@0 3142
ian@0 3143 /* schedulerbasepointer */
ian@0 3144 /* TxRMON_PTR (statistics) */
ian@0 3145 if (ug_info->
ian@0 3146 statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_TX) {
ian@0 3147 ugeth->tx_fw_statistics_pram_offset =
ian@0 3148 qe_muram_alloc(sizeof
ian@0 3149 (ucc_geth_tx_firmware_statistics_pram_t),
ian@0 3150 UCC_GETH_TX_STATISTICS_ALIGNMENT);
ian@0 3151 if (IS_MURAM_ERR(ugeth->tx_fw_statistics_pram_offset)) {
ian@0 3152 ugeth_err
ian@0 3153 ("%s: Can not allocate DPRAM memory for"
ian@0 3154 " p_tx_fw_statistics_pram.", __FUNCTION__);
ian@0 3155 ucc_geth_memclean(ugeth);
ian@0 3156 return -ENOMEM;
ian@0 3157 }
ian@0 3158 ugeth->p_tx_fw_statistics_pram =
ian@0 3159 (ucc_geth_tx_firmware_statistics_pram_t *)
ian@0 3160 qe_muram_addr(ugeth->tx_fw_statistics_pram_offset);
ian@0 3161 /* Zero out p_tx_fw_statistics_pram */
ian@0 3162 memset(ugeth->p_tx_fw_statistics_pram,
ian@0 3163 0, sizeof(ucc_geth_tx_firmware_statistics_pram_t));
ian@0 3164 }
ian@0 3165
ian@0 3166 /* temoder */
ian@0 3167 /* Already has speed set */
ian@0 3168
ian@0 3169 if (ug_info->numQueuesTx > 1)
ian@0 3170 temoder |= TEMODER_SCHEDULER_ENABLE;
ian@0 3171 if (ug_info->ipCheckSumGenerate)
ian@0 3172 temoder |= TEMODER_IP_CHECKSUM_GENERATE;
ian@0 3173 temoder |= ((ug_info->numQueuesTx - 1) << TEMODER_NUM_OF_QUEUES_SHIFT);
ian@0 3174 out_be16(&ugeth->p_tx_glbl_pram->temoder, temoder);
ian@0 3175
ian@0 3176 test = in_be16(&ugeth->p_tx_glbl_pram->temoder);
ian@0 3177
ian@0 3178 /* Function code register value to be used later */
ian@0 3179 function_code = QE_BMR_BYTE_ORDER_BO_MOT | UCC_FAST_FUNCTION_CODE_GBL;
ian@0 3180 /* Required for QE */
ian@0 3181
ian@0 3182 /* function code register */
ian@0 3183 out_be32(&ugeth->p_tx_glbl_pram->tstate, ((u32) function_code) << 24);
ian@0 3184
ian@0 3185 /* Rx global PRAM */
ian@0 3186 /* Allocate global rx parameter RAM page */
ian@0 3187 ugeth->rx_glbl_pram_offset =
ian@0 3188 qe_muram_alloc(sizeof(ucc_geth_rx_global_pram_t),
ian@0 3189 UCC_GETH_RX_GLOBAL_PRAM_ALIGNMENT);
ian@0 3190 if (IS_MURAM_ERR(ugeth->rx_glbl_pram_offset)) {
ian@0 3191 ugeth_err
ian@0 3192 ("%s: Can not allocate DPRAM memory for p_rx_glbl_pram.",
ian@0 3193 __FUNCTION__);
ian@0 3194 ucc_geth_memclean(ugeth);
ian@0 3195 return -ENOMEM;
ian@0 3196 }
ian@0 3197 ugeth->p_rx_glbl_pram =
ian@0 3198 (ucc_geth_rx_global_pram_t *) qe_muram_addr(ugeth->
ian@0 3199 rx_glbl_pram_offset);
ian@0 3200 /* Zero out p_rx_glbl_pram */
ian@0 3201 memset(ugeth->p_rx_glbl_pram, 0, sizeof(ucc_geth_rx_global_pram_t));
ian@0 3202
ian@0 3203 /* Fill global PRAM */
ian@0 3204
ian@0 3205 /* RQPTR */
ian@0 3206 /* Size varies with number of Rx threads */
ian@0 3207 ugeth->thread_dat_rx_offset =
ian@0 3208 qe_muram_alloc(numThreadsRxNumerical *
ian@0 3209 sizeof(ucc_geth_thread_data_rx_t),
ian@0 3210 UCC_GETH_THREAD_DATA_ALIGNMENT);
ian@0 3211 if (IS_MURAM_ERR(ugeth->thread_dat_rx_offset)) {
ian@0 3212 ugeth_err
ian@0 3213 ("%s: Can not allocate DPRAM memory for p_thread_data_rx.",
ian@0 3214 __FUNCTION__);
ian@0 3215 ucc_geth_memclean(ugeth);
ian@0 3216 return -ENOMEM;
ian@0 3217 }
ian@0 3218
ian@0 3219 ugeth->p_thread_data_rx =
ian@0 3220 (ucc_geth_thread_data_rx_t *) qe_muram_addr(ugeth->
ian@0 3221 thread_dat_rx_offset);
ian@0 3222 out_be32(&ugeth->p_rx_glbl_pram->rqptr, ugeth->thread_dat_rx_offset);
ian@0 3223
ian@0 3224 /* typeorlen */
ian@0 3225 out_be16(&ugeth->p_rx_glbl_pram->typeorlen, ug_info->typeorlen);
ian@0 3226
ian@0 3227 /* rxrmonbaseptr (statistics) */
ian@0 3228 if (ug_info->
ian@0 3229 statisticsMode & UCC_GETH_STATISTICS_GATHERING_MODE_FIRMWARE_RX) {
ian@0 3230 ugeth->rx_fw_statistics_pram_offset =
ian@0 3231 qe_muram_alloc(sizeof
ian@0 3232 (ucc_geth_rx_firmware_statistics_pram_t),
ian@0 3233 UCC_GETH_RX_STATISTICS_ALIGNMENT);
ian@0 3234 if (IS_MURAM_ERR(ugeth->rx_fw_statistics_pram_offset)) {
ian@0 3235 ugeth_err
ian@0 3236 ("%s: Can not allocate DPRAM memory for"
ian@0 3237 " p_rx_fw_statistics_pram.", __FUNCTION__);
ian@0 3238 ucc_geth_memclean(ugeth);
ian@0 3239 return -ENOMEM;
ian@0 3240 }
ian@0 3241 ugeth->p_rx_fw_statistics_pram =
ian@0 3242 (ucc_geth_rx_firmware_statistics_pram_t *)
ian@0 3243 qe_muram_addr(ugeth->rx_fw_statistics_pram_offset);
ian@0 3244 /* Zero out p_rx_fw_statistics_pram */
ian@0 3245 memset(ugeth->p_rx_fw_statistics_pram, 0,
ian@0 3246 sizeof(ucc_geth_rx_firmware_statistics_pram_t));
ian@0 3247 }
ian@0 3248
ian@0 3249 /* intCoalescingPtr */
ian@0 3250
ian@0 3251 /* Size varies with number of Rx queues */
ian@0 3252 ugeth->rx_irq_coalescing_tbl_offset =
ian@0 3253 qe_muram_alloc(ug_info->numQueuesRx *
ian@0 3254 sizeof(ucc_geth_rx_interrupt_coalescing_entry_t),
ian@0 3255 UCC_GETH_RX_INTERRUPT_COALESCING_ALIGNMENT);
ian@0 3256 if (IS_MURAM_ERR(ugeth->rx_irq_coalescing_tbl_offset)) {
ian@0 3257 ugeth_err
ian@0 3258 ("%s: Can not allocate DPRAM memory for"
ian@0 3259 " p_rx_irq_coalescing_tbl.", __FUNCTION__);
ian@0 3260 ucc_geth_memclean(ugeth);
ian@0 3261 return -ENOMEM;
ian@0 3262 }
ian@0 3263
ian@0 3264 ugeth->p_rx_irq_coalescing_tbl =
ian@0 3265 (ucc_geth_rx_interrupt_coalescing_table_t *)
ian@0 3266 qe_muram_addr(ugeth->rx_irq_coalescing_tbl_offset);
ian@0 3267 out_be32(&ugeth->p_rx_glbl_pram->intcoalescingptr,
ian@0 3268 ugeth->rx_irq_coalescing_tbl_offset);
ian@0 3269
ian@0 3270 /* Fill interrupt coalescing table */
ian@0 3271 for (i = 0; i < ug_info->numQueuesRx; i++) {
ian@0 3272 out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i].
ian@0 3273 interruptcoalescingmaxvalue,
ian@0 3274 ug_info->interruptcoalescingmaxvalue[i]);
ian@0 3275 out_be32(&ugeth->p_rx_irq_coalescing_tbl->coalescingentry[i].
ian@0 3276 interruptcoalescingcounter,
ian@0 3277 ug_info->interruptcoalescingmaxvalue[i]);
ian@0 3278 }
ian@0 3279
ian@0 3280 /* MRBLR */
ian@0 3281 init_max_rx_buff_len(uf_info->max_rx_buf_length,
ian@0 3282 &ugeth->p_rx_glbl_pram->mrblr);
ian@0 3283 /* MFLR */
ian@0 3284 out_be16(&ugeth->p_rx_glbl_pram->mflr, ug_info->maxFrameLength);
ian@0 3285 /* MINFLR */
ian@0 3286 init_min_frame_len(ug_info->minFrameLength,
ian@0 3287 &ugeth->p_rx_glbl_pram->minflr,
ian@0 3288 &ugeth->p_rx_glbl_pram->mrblr);
ian@0 3289 /* MAXD1 */
ian@0 3290 out_be16(&ugeth->p_rx_glbl_pram->maxd1, ug_info->maxD1Length);
ian@0 3291 /* MAXD2 */
ian@0 3292 out_be16(&ugeth->p_rx_glbl_pram->maxd2, ug_info->maxD2Length);
ian@0 3293
ian@0 3294 /* l2qt */
ian@0 3295 l2qt = 0;
ian@0 3296 for (i = 0; i < UCC_GETH_VLAN_PRIORITY_MAX; i++)
ian@0 3297 l2qt |= (ug_info->l2qt[i] << (28 - 4 * i));
ian@0 3298 out_be32(&ugeth->p_rx_glbl_pram->l2qt, l2qt);
ian@0 3299
ian@0 3300 /* l3qt */
ian@0 3301 for (j = 0; j < UCC_GETH_IP_PRIORITY_MAX; j += 8) {
ian@0 3302 l3qt = 0;
ian@0 3303 for (i = 0; i < 8; i++)
ian@0 3304 l3qt |= (ug_info->l3qt[j + i] << (28 - 4 * i));
ian@0 3305 out_be32(&ugeth->p_rx_glbl_pram->l3qt[j], l3qt);
ian@0 3306 }
ian@0 3307
ian@0 3308 /* vlantype */
ian@0 3309 out_be16(&ugeth->p_rx_glbl_pram->vlantype, ug_info->vlantype);
ian@0 3310
ian@0 3311 /* vlantci */
ian@0 3312 out_be16(&ugeth->p_rx_glbl_pram->vlantci, ug_info->vlantci);
ian@0 3313
ian@0 3314 /* ecamptr */
ian@0 3315 out_be32(&ugeth->p_rx_glbl_pram->ecamptr, ug_info->ecamptr);
ian@0 3316
ian@0 3317 /* RBDQPTR */
ian@0 3318 /* Size varies with number of Rx queues */
ian@0 3319 ugeth->rx_bd_qs_tbl_offset =
ian@0 3320 qe_muram_alloc(ug_info->numQueuesRx *
ian@0 3321 (sizeof(ucc_geth_rx_bd_queues_entry_t) +
ian@0 3322 sizeof(ucc_geth_rx_prefetched_bds_t)),
ian@0 3323 UCC_GETH_RX_BD_QUEUES_ALIGNMENT);
ian@0 3324 if (IS_MURAM_ERR(ugeth->rx_bd_qs_tbl_offset)) {
ian@0 3325 ugeth_err
ian@0 3326 ("%s: Can not allocate DPRAM memory for p_rx_bd_qs_tbl.",
ian@0 3327 __FUNCTION__);
ian@0 3328 ucc_geth_memclean(ugeth);
ian@0 3329 return -ENOMEM;
ian@0 3330 }
ian@0 3331
ian@0 3332 ugeth->p_rx_bd_qs_tbl =
ian@0 3333 (ucc_geth_rx_bd_queues_entry_t *) qe_muram_addr(ugeth->
ian@0 3334 rx_bd_qs_tbl_offset);
ian@0 3335 out_be32(&ugeth->p_rx_glbl_pram->rbdqptr, ugeth->rx_bd_qs_tbl_offset);
ian@0 3336 /* Zero out p_rx_bd_qs_tbl */
ian@0 3337 memset(ugeth->p_rx_bd_qs_tbl,
ian@0 3338 0,
ian@0 3339 ug_info->numQueuesRx * (sizeof(ucc_geth_rx_bd_queues_entry_t) +
ian@0 3340 sizeof(ucc_geth_rx_prefetched_bds_t)));
ian@0 3341
ian@0 3342 /* Setup the table */
ian@0 3343 /* Assume BD rings are already established */
ian@0 3344 for (i = 0; i < ug_info->numQueuesRx; i++) {
ian@0 3345 if (ugeth->ug_info->uf_info.bd_mem_part == MEM_PART_SYSTEM) {
ian@0 3346 out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,
ian@0 3347 (u32) virt_to_phys(ugeth->p_rx_bd_ring[i]));
ian@0 3348 } else if (ugeth->ug_info->uf_info.bd_mem_part ==
ian@0 3349 MEM_PART_MURAM) {
ian@0 3350 out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,