015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * CDDL HEADER START
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * The contents of this file are subject to the terms of the
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Common Development and Distribution License (the "License").
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * You may not use this file except in compliance with the License.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * See the License for the specific language governing permissions
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * and limitations under the License.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * When distributing Covered Code, include this CDDL HEADER in each
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * If applicable, add the following below this CDDL HEADER, with the
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * fields enclosed by brackets "[]" replaced with your own identifying
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * information: Portions Copyright [yyyy] [name of copyright owner]
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * CDDL HEADER END
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills * Copyright (c) 2012 Gary Mills
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Use is subject to license terms.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * L1E specfic functions.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrastatic ddi_dma_attr_t atge_l1e_dma_attr_tx_desc = {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra 0, /* dma_attr_addr_lo */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra 0 /* dma_attr_flags */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrastatic ddi_dma_attr_t atge_l1e_dma_attr_rx_desc = {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra 0, /* dma_attr_addr_lo */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra 0 /* dma_attr_flags */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misrastatic ddi_dma_attr_t atge_l1e_dma_attr_cmb = {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra 0, /* dma_attr_addr_lo */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra 0 /* dma_attr_flags */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra l1e = (atge_l1e_data_t *)atgep->atge_private_data;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra for (pages = 0; pages < L1E_RX_PAGES; pages++) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra kmem_free(l1e->atge_l1e_rx_page, L1E_RX_PAGES * sizeof (atge_dma_t *));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra l1e = kmem_zalloc(sizeof (atge_l1e_data_t), KM_SLEEP);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Allocate TX ring descriptor.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_tx_ring = kmem_alloc(sizeof (atge_ring_t), KM_SLEEP);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra dma = atge_alloc_a_dma_blk(atgep, &atge_l1e_dma_attr_tx_desc,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Allocate DMA buffers for TX ring.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra err = atge_alloc_buffers(atgep->atge_tx_ring, ATGE_TX_RING_CNT,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Allocate RX pages.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra l1e->atge_l1e_pagesize = ROUNDUP(guard_size + L1E_RX_PAGE_SZ,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra kmem_zalloc(L1E_RX_PAGES * sizeof (atge_dma_t *), KM_SLEEP);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() atge_l1e_pagesize : %d, L1E_RX_PAGE_SZ : %d",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_name, __func__, l1e->atge_l1e_pagesize,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra for (pages = 0; pages < L1E_RX_PAGES; pages++) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra dma = atge_alloc_a_dma_blk(atgep, &atge_l1e_dma_attr_rx_desc,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Allocate CMB used for fetching interrupt status data.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() L1E_RX_CMB_SZ : %x", atgep->atge_name,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra dma = atge_alloc_a_dma_blk(atgep, &atge_l1e_dma_attr_cmb,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_hw_stats = kmem_zalloc(sizeof (atge_l1e_smb_t), KM_SLEEP);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Free TX ring.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra atge_free_buffers(atgep->atge_tx_ring, ATGE_TX_RING_CNT);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (atgep->atge_tx_ring->r_desc_ring != NULL) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atge_free_a_dma_blk(atgep->atge_tx_ring->r_desc_ring);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra kmem_free(atgep->atge_tx_ring, sizeof (atge_ring_t));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Free RX CMB.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Free RX buffers and RX ring.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Free the memory allocated for gathering hw stats.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra kmem_free(atgep->atge_hw_stats, sizeof (atge_l1e_smb_t));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra l1e->atge_l1e_proc_max = L1E_RX_PAGE_SZ / ETHERMIN;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra for (pages = 0; pages < L1E_RX_PAGES; pages++) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra DMA_SYNC(dma, 0, l1e->atge_l1e_pagesize, DDI_DMA_SYNC_FORDEV);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra bzero(dma->addr, L1E_RX_CMB_SZ * L1E_RX_PAGES);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra DMA_SYNC(dma, 0, L1E_RX_CMB_SZ * L1E_RX_PAGES, DDI_DMA_SYNC_FORDEV);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ASSERT(atgep->atge_tx_ring->r_desc_ring != NULL);
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra atgep->atge_tx_ring->r_avail_desc = ATGE_TX_RING_CNT;
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra bzero(atgep->atge_tx_ring->r_desc_ring->addr, ATGE_TX_RING_SZ);
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra DMA_SYNC(atgep->atge_tx_ring->r_desc_ring, 0, ATGE_TX_RING_SZ,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra l1e = (atge_l1e_data_t *)atgep->atge_private_data;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Clear WOL status and disable all WOL feature as WOL
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * would interfere Rx operation under normal environments.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Set Tx descriptor/RXF0/CMB base addresses. They share
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * the same high address part of DMAable region.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra paddr = atgep->atge_tx_ring->r_desc_ring->cookie.dmac_laddress;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra OUTL(atgep, ATGE_DESC_ADDR_HI, ATGE_ADDR_HI(paddr));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra OUTL(atgep, ATGE_DESC_TPD_ADDR_LO, ATGE_ADDR_LO(paddr));
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra (ATGE_TX_RING_CNT << DESC_TPD_CNT_SHIFT) & DESC_TPD_CNT_MASK);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra /* Set Rx page base address, note we use single queue. */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra paddr = l1e->atge_l1e_rx_page[0]->cookie.dmac_laddress;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra OUTL(atgep, L1E_RXF0_PAGE0_ADDR_LO, ATGE_ADDR_LO(paddr));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra paddr = l1e->atge_l1e_rx_page[1]->cookie.dmac_laddress;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra OUTL(atgep, L1E_RXF0_PAGE1_ADDR_LO, ATGE_ADDR_LO(paddr));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra /* Set Tx/Rx CMB addresses. */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra paddr = l1e->atge_l1e_rx_cmb->cookie.dmac_laddress;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra OUTL(atgep, L1E_RXF0_CMB0_ADDR_LO, ATGE_ADDR_LO(paddr));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra paddr = l1e->atge_l1e_rx_cmb->cookie.dmac_laddress + sizeof (uint32_t);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra OUTL(atgep, L1E_RXF0_CMB1_ADDR_LO, ATGE_ADDR_LO(paddr));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra /* Mark RXF0 valid. */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra OUTB(atgep, L1E_RXF0_PAGE0, RXF_VALID); /* 0 */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra OUTB(atgep, L1E_RXF0_PAGE1, RXF_VALID); /* 1 */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra /* Set Rx page size, excluding guard frame size. */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra OUTL(atgep, L1E_RXF_PAGE_SIZE, L1E_RX_PAGE_SZ);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra /* Tell hardware that we're ready to load DMA blocks. */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra /* Set Rx/Tx interrupt trigger threshold. */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra OUTL(atgep, L1E_INT_TRIG_THRESH, (1 << INT_TRIG_RX_THRESH_SHIFT) |
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Set interrupt trigger timer, its purpose and relation
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * with interrupt moderation mechanism is not clear yet.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ((ATGE_USECS(10) << INT_TRIG_RX_TIMER_SHIFT) |
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra (ATGE_USECS(1000) << INT_TRIG_TX_TIMER_SHIFT)));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra reg = ATGE_USECS(ATGE_IM_RX_TIMER_DEFAULT) << IM_TIMER_RX_SHIFT;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra reg |= ATGE_USECS(ATGE_IM_TX_TIMER_DEFAULT) << IM_TIMER_TX_SHIFT;
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills reg &= ~(L1E_MASTER_CHIP_REV_MASK | L1E_MASTER_CHIP_ID_MASK);
5e8715b93d1d651ab2805b5e6e98b17df49fa92fGary Mills reg &= ~(L1E_MASTER_IM_RX_TIMER_ENB | L1E_MASTER_IM_TX_TIMER_ENB);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra OUTW(atgep, TX_COALSC_TO_1e, 4000/2); /* 4mS */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra /* Sync CMB first */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra DMA_SYNC(dma_rx_cmb, 0, L1E_RX_CMB_SZ * L1E_RX_PAGES,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra dma_rx_page = l1e->atge_l1e_rx_page[current_page];
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Get the producer offset from CMB.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra /* Sync current RX Page as well */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra DMA_SYNC(dma_rx_page, l1e->atge_l1e_rx_page_cons,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra l1e->atge_l1e_rx_page_prods[current_page], DDI_DMA_SYNC_FORKERNEL);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() prod : %d, cons : %d, curr page : %d, gen : (%d)"
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra " cmb[0,1] : %d, %d",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra l1e->atge_l1e_rx_page_cons, l1e->atge_l1e_rx_curp, gen,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_GET32(dma_rx_cmb, ptr), ATGE_GET32(dma_rx_cmb, ptr + 1)));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra for (prog = 0; prog <= l1e->atge_l1e_proc_max; prog++) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (cons >= l1e->atge_l1e_rx_page_prods[l1e->atge_l1e_rx_curp])
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra dma_rx_page = l1e->atge_l1e_rx_page[l1e->atge_l1e_rx_curp];
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra seqno = ATGE_GET32(dma_rx_page, &(rs->seqno));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra flags = ATGE_GET32(dma_rx_page, &(rs->flags));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * We have not seen this happening but we
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * must restart the chip if that happens.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra " atge_l1e_rx_seqno : %d, length : %d, flags : %x",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Return all the pkts received before restarting
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * We will pass the pkt to upper layer provided it's clear
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * from any error.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * So we have received a frame/pkt.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (len == 0 || len > atgep->atge_rx_buf_len) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra bcopy(pageaddr + sizeof (rx_rs_t), bufp, len);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() seqno :%d, atge_l1e_rx_seqno :"
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra " %d, length : %d,"
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra " flags : %x, cons : %d, prod : %d",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra l1e->atge_l1e_rx_page_prods[l1e->atge_l1e_rx_curp]));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() receive completed (gen : %d) : cons : %d,"
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra " prod :%d, L1E_RX_PAGE_SZ : %d (prog:%d)",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra l1e->atge_l1e_rx_page_prods[l1e->atge_l1e_rx_curp],
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misraatge_l1e_rx_next_pkt(atge_t *atgep, uint32_t len)
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atge_l1e_data_t *l1e = atgep->atge_private_data;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Update consumer position.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ROUNDUP(len + sizeof (rx_rs_t), L1E_RX_PAGE_ALIGN);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * If we need to flip to the other page. Note that we use only two
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if (l1e->atge_l1e_rx_page_cons >= L1E_RX_PAGE_SZ) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() cons : %d, prod :%d, L1E_RX_PAGE_SZ : %d",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_name, __func__, l1e->atge_l1e_rx_page_cons,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra l1e->atge_l1e_rx_page_prods[curr], L1E_RX_PAGE_SZ));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Clear the producer.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Notify the NIC that the current RX page is available again.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra OUTB(atgep, L1E_RXF0_PAGE0 + curr, RXF_VALID);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * End of Rx page reached, let hardware reuse this page.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Switch to alternate Rx page.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Page flipped, sync CMB and then Rx page.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra DMA_SYNC(dma_rx_cmb, 0, L1E_RX_PAGES * L1E_RX_CMB_SZ,
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra DMA_SYNC(dma_rx_page, 0, l1e->atge_l1e_rx_page_prods[curr],
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() PAGE FLIPPED -> %d, producer[0,1]: %d, %d",
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_GET32(dma_rx_cmb, p), ATGE_GET32(dma_rx_cmb, p + 1)));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Ask chip to send the packet now.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Clear RX stats first.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra i += sizeof (uint32_t);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Clear TX stats.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra i += sizeof (uint32_t);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat = (atge_l1e_smb_t *)atgep->atge_hw_stats;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra /* Read Rx statistics. */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra i += sizeof (uint32_t);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra /* Read Tx statistics. */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra i += sizeof (uint32_t);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * SMB is cleared everytime we read; hence we always do '+='.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra /* Rx stats. */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->rx_bcast_frames += smb->rx_bcast_frames;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->rx_mcast_frames += smb->rx_mcast_frames;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->rx_pause_frames += smb->rx_pause_frames;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->rx_control_frames += smb->rx_control_frames;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->rx_pkts_128_255 += smb->rx_pkts_128_255;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->rx_pkts_256_511 += smb->rx_pkts_256_511;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->rx_pkts_512_1023 += smb->rx_pkts_512_1023;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->rx_pkts_1024_1518 += smb->rx_pkts_1024_1518;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->rx_pkts_1519_max += smb->rx_pkts_1519_max;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->rx_pkts_truncated += smb->rx_pkts_truncated;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->rx_pkts_filtered += smb->rx_pkts_filtered;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra /* Tx stats. */
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->tx_bcast_frames += smb->tx_bcast_frames;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->tx_mcast_frames += smb->tx_mcast_frames;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->tx_pause_frames += smb->tx_pause_frames;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->tx_excess_defer += smb->tx_excess_defer;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->tx_control_frames += smb->tx_control_frames;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->tx_pkts_128_255 += smb->tx_pkts_128_255;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->tx_pkts_256_511 += smb->tx_pkts_256_511;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->tx_pkts_512_1023 += smb->tx_pkts_512_1023;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->tx_pkts_1024_1518 += smb->tx_pkts_1024_1518;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->tx_pkts_1519_max += smb->tx_pkts_1519_max;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->tx_single_colls += smb->tx_single_colls;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->tx_excess_colls += smb->tx_excess_colls;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->tx_desc_underrun += smb->tx_desc_underrun;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra stat->tx_pkts_truncated += smb->tx_pkts_truncated;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * Update global counters in atge_t.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_brdcstrcv += smb->rx_bcast_frames;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_brdcstxmt += smb->tx_bcast_frames;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_align_errors += smb->rx_alignerrs;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_first_collisions += smb->tx_single_colls;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_multi_collisions += smb->tx_multi_colls * 2;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_tx_late_collisions += smb->tx_late_colls;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_ex_collisions += smb->tx_excess_colls;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_toolong_errors += smb->rx_lenerrs;
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_underflow += (smb->tx_underrun + smb->tx_desc_underrun);
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_collisions += smb->tx_single_colls +
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra smb->tx_multi_colls * 2 + smb->tx_late_colls +
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * tx_pkts_truncated counter looks suspicious. It constantly
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra * increments with no sign of Tx errors. Hence we don't factor it.
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_macxmt_errors += smb->tx_abort + smb->tx_late_colls +
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra atgep->atge_macrcv_errors += smb->rx_crcerrs + smb->rx_lenerrs +
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() reg : %x", atgep->atge_name, __func__, reg));
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra if ((reg & (ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB)) != 0) {
015a6ef6781cc3ceba8ad3bfbae98449b6002a1fSaurabh Misra ATGE_DB(("%s: %s() mac stopped", atgep->atge_name, __func__));
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * The interrupt handler for L1E/L2E
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_SUSPENDED) {
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra if (status == 0 || (status & atgep->atge_intrs) == 0) {
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * Disable interrupts.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra OUTL(atgep, ATGE_INTR_STATUS, status | INTR_DIS_INT);
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * Check if chip is running, only then do the work.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) {
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * Check for errors.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra "L1E chip found an error intr status : %x",
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra atge_error(atgep->atge_dip, "DMA transfer err");
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra atge_error(atgep->atge_dip, "TX FIFO underrun");
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * Enable interrupts.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * Ack interrupts from PHY
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * Pass the list of packets received from chip to MAC layer.
0eb090a7674ebcdcb1c35501097edeb5f2395459Saurabh Misra * Let MAC start sending pkts if the downstream was asked to pause.