1*0eb090a7SSaurabh Misra /*
2*0eb090a7SSaurabh Misra * CDDL HEADER START
3*0eb090a7SSaurabh Misra *
4*0eb090a7SSaurabh Misra * The contents of this file are subject to the terms of the
5*0eb090a7SSaurabh Misra * Common Development and Distribution License (the "License").
6*0eb090a7SSaurabh Misra * You may not use this file except in compliance with the License.
7*0eb090a7SSaurabh Misra *
8*0eb090a7SSaurabh Misra * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*0eb090a7SSaurabh Misra * or http://www.opensolaris.org/os/licensing.
10*0eb090a7SSaurabh Misra * See the License for the specific language governing permissions
11*0eb090a7SSaurabh Misra * and limitations under the License.
12*0eb090a7SSaurabh Misra *
13*0eb090a7SSaurabh Misra * When distributing Covered Code, include this CDDL HEADER in each
14*0eb090a7SSaurabh Misra * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*0eb090a7SSaurabh Misra * If applicable, add the following below this CDDL HEADER, with the
16*0eb090a7SSaurabh Misra * fields enclosed by brackets "[]" replaced with your own identifying
17*0eb090a7SSaurabh Misra * information: Portions Copyright [yyyy] [name of copyright owner]
18*0eb090a7SSaurabh Misra *
19*0eb090a7SSaurabh Misra * CDDL HEADER END
20*0eb090a7SSaurabh Misra */
21*0eb090a7SSaurabh Misra
22*0eb090a7SSaurabh Misra /*
23*0eb090a7SSaurabh Misra * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24*0eb090a7SSaurabh Misra * Use is subject to license terms.
25*0eb090a7SSaurabh Misra */
26*0eb090a7SSaurabh Misra
27*0eb090a7SSaurabh Misra #include <sys/types.h>
28*0eb090a7SSaurabh Misra #include <sys/stream.h>
29*0eb090a7SSaurabh Misra #include <sys/strsun.h>
30*0eb090a7SSaurabh Misra #include <sys/stat.h>
31*0eb090a7SSaurabh Misra #include <sys/modctl.h>
32*0eb090a7SSaurabh Misra #include <sys/ethernet.h>
33*0eb090a7SSaurabh Misra #include <sys/debug.h>
34*0eb090a7SSaurabh Misra #include <sys/conf.h>
35*0eb090a7SSaurabh Misra #include <sys/mii.h>
36*0eb090a7SSaurabh Misra #include <sys/miiregs.h>
37*0eb090a7SSaurabh Misra #include <sys/sysmacros.h>
38*0eb090a7SSaurabh Misra #include <sys/dditypes.h>
39*0eb090a7SSaurabh Misra #include <sys/ddi.h>
40*0eb090a7SSaurabh Misra #include <sys/sunddi.h>
41*0eb090a7SSaurabh Misra #include <sys/byteorder.h>
42*0eb090a7SSaurabh Misra #include <sys/note.h>
43*0eb090a7SSaurabh Misra #include <sys/vlan.h>
44*0eb090a7SSaurabh Misra #include <sys/stream.h>
45*0eb090a7SSaurabh Misra
46*0eb090a7SSaurabh Misra #include "atge.h"
47*0eb090a7SSaurabh Misra #include "atge_l1_reg.h"
48*0eb090a7SSaurabh Misra #include "atge_cmn_reg.h"
49*0eb090a7SSaurabh Misra
50*0eb090a7SSaurabh Misra static ddi_dma_attr_t atge_l1_dma_attr_tx_desc = {
51*0eb090a7SSaurabh Misra DMA_ATTR_V0, /* dma_attr_version */
52*0eb090a7SSaurabh Misra 0, /* dma_attr_addr_lo */
53*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_addr_hi */
54*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_count_max */
55*0eb090a7SSaurabh Misra L1_TX_RING_ALIGN, /* dma_attr_align */
56*0eb090a7SSaurabh Misra 0x0000fffc, /* dma_attr_burstsizes */
57*0eb090a7SSaurabh Misra 1, /* dma_attr_minxfer */
58*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_maxxfer */
59*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_seg */
60*0eb090a7SSaurabh Misra 1, /* dma_attr_sgllen */
61*0eb090a7SSaurabh Misra 1, /* dma_attr_granular */
62*0eb090a7SSaurabh Misra 0 /* dma_attr_flags */
63*0eb090a7SSaurabh Misra };
64*0eb090a7SSaurabh Misra
65*0eb090a7SSaurabh Misra static ddi_dma_attr_t atge_l1_dma_attr_rx_desc = {
66*0eb090a7SSaurabh Misra DMA_ATTR_V0, /* dma_attr_version */
67*0eb090a7SSaurabh Misra 0, /* dma_attr_addr_lo */
68*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_addr_hi */
69*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_count_max */
70*0eb090a7SSaurabh Misra L1_RX_RING_ALIGN, /* dma_attr_align */
71*0eb090a7SSaurabh Misra 0x0000fffc, /* dma_attr_burstsizes */
72*0eb090a7SSaurabh Misra 1, /* dma_attr_minxfer */
73*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_maxxfer */
74*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_seg */
75*0eb090a7SSaurabh Misra 1, /* dma_attr_sgllen */
76*0eb090a7SSaurabh Misra 1, /* dma_attr_granular */
77*0eb090a7SSaurabh Misra 0 /* dma_attr_flags */
78*0eb090a7SSaurabh Misra };
79*0eb090a7SSaurabh Misra
80*0eb090a7SSaurabh Misra static ddi_dma_attr_t atge_l1_dma_attr_cmb = {
81*0eb090a7SSaurabh Misra DMA_ATTR_V0, /* dma_attr_version */
82*0eb090a7SSaurabh Misra 0, /* dma_attr_addr_lo */
83*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_addr_hi */
84*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_count_max */
85*0eb090a7SSaurabh Misra L1_CMB_ALIGN, /* dma_attr_align */
86*0eb090a7SSaurabh Misra 0x0000fffc, /* dma_attr_burstsizes */
87*0eb090a7SSaurabh Misra 1, /* dma_attr_minxfer */
88*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_maxxfer */
89*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_seg */
90*0eb090a7SSaurabh Misra 1, /* dma_attr_sgllen */
91*0eb090a7SSaurabh Misra 1, /* dma_attr_granular */
92*0eb090a7SSaurabh Misra 0 /* dma_attr_flags */
93*0eb090a7SSaurabh Misra };
94*0eb090a7SSaurabh Misra
95*0eb090a7SSaurabh Misra static ddi_dma_attr_t atge_l1_dma_attr_smb = {
96*0eb090a7SSaurabh Misra DMA_ATTR_V0, /* dma_attr_version */
97*0eb090a7SSaurabh Misra 0, /* dma_attr_addr_lo */
98*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_addr_hi */
99*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_count_max */
100*0eb090a7SSaurabh Misra L1_SMB_ALIGN, /* dma_attr_align */
101*0eb090a7SSaurabh Misra 0x0000fffc, /* dma_attr_burstsizes */
102*0eb090a7SSaurabh Misra 1, /* dma_attr_minxfer */
103*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_maxxfer */
104*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_seg */
105*0eb090a7SSaurabh Misra 1, /* dma_attr_sgllen */
106*0eb090a7SSaurabh Misra 1, /* dma_attr_granular */
107*0eb090a7SSaurabh Misra 0 /* dma_attr_flags */
108*0eb090a7SSaurabh Misra };
109*0eb090a7SSaurabh Misra
110*0eb090a7SSaurabh Misra static ddi_dma_attr_t atge_l1_dma_attr_rr = {
111*0eb090a7SSaurabh Misra DMA_ATTR_V0, /* dma_attr_version */
112*0eb090a7SSaurabh Misra 0, /* dma_attr_addr_lo */
113*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_addr_hi */
114*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_count_max */
115*0eb090a7SSaurabh Misra L1_RR_RING_ALIGN, /* dma_attr_align */
116*0eb090a7SSaurabh Misra 0x0000fffc, /* dma_attr_burstsizes */
117*0eb090a7SSaurabh Misra 1, /* dma_attr_minxfer */
118*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_maxxfer */
119*0eb090a7SSaurabh Misra 0x0000ffffffffull, /* dma_attr_seg */
120*0eb090a7SSaurabh Misra 1, /* dma_attr_sgllen */
121*0eb090a7SSaurabh Misra 1, /* dma_attr_granular */
122*0eb090a7SSaurabh Misra 0 /* dma_attr_flags */
123*0eb090a7SSaurabh Misra };
124*0eb090a7SSaurabh Misra
125*0eb090a7SSaurabh Misra int
atge_l1_alloc_dma(atge_t * atgep)126*0eb090a7SSaurabh Misra atge_l1_alloc_dma(atge_t *atgep)
127*0eb090a7SSaurabh Misra {
128*0eb090a7SSaurabh Misra atge_l1_data_t *l1;
129*0eb090a7SSaurabh Misra atge_dma_t *dma;
130*0eb090a7SSaurabh Misra int err;
131*0eb090a7SSaurabh Misra
132*0eb090a7SSaurabh Misra l1 = kmem_zalloc(sizeof (atge_l1_data_t), KM_SLEEP);
133*0eb090a7SSaurabh Misra atgep->atge_private_data = l1;
134*0eb090a7SSaurabh Misra
135*0eb090a7SSaurabh Misra /*
136*0eb090a7SSaurabh Misra * Allocate TX ring descriptor.
137*0eb090a7SSaurabh Misra */
138*0eb090a7SSaurabh Misra atgep->atge_tx_buf_len = atgep->atge_mtu +
139*0eb090a7SSaurabh Misra sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL;
140*0eb090a7SSaurabh Misra atgep->atge_tx_ring = kmem_alloc(sizeof (atge_ring_t), KM_SLEEP);
141*0eb090a7SSaurabh Misra atgep->atge_tx_ring->r_atge = atgep;
142*0eb090a7SSaurabh Misra atgep->atge_tx_ring->r_desc_ring = NULL;
143*0eb090a7SSaurabh Misra dma = atge_alloc_a_dma_blk(atgep, &atge_l1_dma_attr_tx_desc,
144*0eb090a7SSaurabh Misra ATGE_TX_RING_SZ, DDI_DMA_RDWR);
145*0eb090a7SSaurabh Misra if (dma == NULL) {
146*0eb090a7SSaurabh Misra atge_error(atgep->atge_dip, "DMA allocation failed for TX"
147*0eb090a7SSaurabh Misra " desc ring");
148*0eb090a7SSaurabh Misra return (DDI_FAILURE);
149*0eb090a7SSaurabh Misra }
150*0eb090a7SSaurabh Misra atgep->atge_tx_ring->r_desc_ring = dma;
151*0eb090a7SSaurabh Misra
152*0eb090a7SSaurabh Misra /*
153*0eb090a7SSaurabh Misra * Allocate DMA buffers for TX ring.
154*0eb090a7SSaurabh Misra */
155*0eb090a7SSaurabh Misra err = atge_alloc_buffers(atgep->atge_tx_ring, ATGE_TX_RING_CNT,
156*0eb090a7SSaurabh Misra atgep->atge_tx_buf_len, DDI_DMA_WRITE);
157*0eb090a7SSaurabh Misra if (err != DDI_SUCCESS) {
158*0eb090a7SSaurabh Misra atge_error(atgep->atge_dip, "DMA allocation failed for"
159*0eb090a7SSaurabh Misra " TX Ring");
160*0eb090a7SSaurabh Misra return (err);
161*0eb090a7SSaurabh Misra }
162*0eb090a7SSaurabh Misra
163*0eb090a7SSaurabh Misra /*
164*0eb090a7SSaurabh Misra * Allocate RX ring.
165*0eb090a7SSaurabh Misra */
166*0eb090a7SSaurabh Misra atgep->atge_rx_buf_len = atgep->atge_mtu +
167*0eb090a7SSaurabh Misra sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL;
168*0eb090a7SSaurabh Misra l1->atge_rx_ring = kmem_alloc(sizeof (atge_ring_t), KM_SLEEP);
169*0eb090a7SSaurabh Misra l1->atge_rx_ring->r_atge = atgep;
170*0eb090a7SSaurabh Misra l1->atge_rx_ring->r_desc_ring = NULL;
171*0eb090a7SSaurabh Misra dma = atge_alloc_a_dma_blk(atgep, &atge_l1_dma_attr_rx_desc,
172*0eb090a7SSaurabh Misra L1_RX_RING_SZ, DDI_DMA_RDWR);
173*0eb090a7SSaurabh Misra if (dma == NULL) {
174*0eb090a7SSaurabh Misra atge_error(atgep->atge_dip, "DMA allocation failed"
175*0eb090a7SSaurabh Misra " for RX Ring");
176*0eb090a7SSaurabh Misra return (DDI_FAILURE);
177*0eb090a7SSaurabh Misra }
178*0eb090a7SSaurabh Misra l1->atge_rx_ring->r_desc_ring = dma;
179*0eb090a7SSaurabh Misra
180*0eb090a7SSaurabh Misra /*
181*0eb090a7SSaurabh Misra * Allocate DMA buffers for RX ring.
182*0eb090a7SSaurabh Misra */
183*0eb090a7SSaurabh Misra err = atge_alloc_buffers(l1->atge_rx_ring, L1_RX_RING_CNT,
184*0eb090a7SSaurabh Misra atgep->atge_rx_buf_len, DDI_DMA_WRITE);
185*0eb090a7SSaurabh Misra if (err != DDI_SUCCESS) {
186*0eb090a7SSaurabh Misra atge_error(atgep->atge_dip, "DMA allocation failed for"
187*0eb090a7SSaurabh Misra " RX buffers");
188*0eb090a7SSaurabh Misra return (err);
189*0eb090a7SSaurabh Misra }
190*0eb090a7SSaurabh Misra
191*0eb090a7SSaurabh Misra /*
192*0eb090a7SSaurabh Misra * Allocate CMB used for fetching interrupt status data.
193*0eb090a7SSaurabh Misra */
194*0eb090a7SSaurabh Misra ATGE_DB(("%s: %s() L1_CMB_BLOCK_SZ : %x", atgep->atge_name,
195*0eb090a7SSaurabh Misra __func__, L1_CMB_BLOCK_SZ));
196*0eb090a7SSaurabh Misra
197*0eb090a7SSaurabh Misra dma = atge_alloc_a_dma_blk(atgep, &atge_l1_dma_attr_cmb,
198*0eb090a7SSaurabh Misra L1_CMB_BLOCK_SZ, DDI_DMA_RDWR);
199*0eb090a7SSaurabh Misra l1->atge_l1_cmb = dma;
200*0eb090a7SSaurabh Misra if (dma == NULL) {
201*0eb090a7SSaurabh Misra atge_error(atgep->atge_dip, "DMA allocation failed for CMB");
202*0eb090a7SSaurabh Misra return (DDI_FAILURE);
203*0eb090a7SSaurabh Misra }
204*0eb090a7SSaurabh Misra
205*0eb090a7SSaurabh Misra /*
206*0eb090a7SSaurabh Misra * RR ring (Return Ring for RX and TX).
207*0eb090a7SSaurabh Misra */
208*0eb090a7SSaurabh Misra ATGE_DB(("%s: %s() L1_RR_RING_SZ : %x", atgep->atge_name,
209*0eb090a7SSaurabh Misra __func__, L1_RR_RING_SZ));
210*0eb090a7SSaurabh Misra
211*0eb090a7SSaurabh Misra dma = atge_alloc_a_dma_blk(atgep, &atge_l1_dma_attr_rr,
212*0eb090a7SSaurabh Misra L1_RR_RING_SZ, DDI_DMA_RDWR);
213*0eb090a7SSaurabh Misra l1->atge_l1_rr = dma;
214*0eb090a7SSaurabh Misra if (dma == NULL) {
215*0eb090a7SSaurabh Misra atge_error(atgep->atge_dip, "DMA allocation failed"
216*0eb090a7SSaurabh Misra " for RX RR ring");
217*0eb090a7SSaurabh Misra return (DDI_FAILURE);
218*0eb090a7SSaurabh Misra }
219*0eb090a7SSaurabh Misra
220*0eb090a7SSaurabh Misra /*
221*0eb090a7SSaurabh Misra * SMB for statistics.
222*0eb090a7SSaurabh Misra */
223*0eb090a7SSaurabh Misra ATGE_DB(("%s: %s() L1_SMB_BLOCK_SZ : %x", atgep->atge_name,
224*0eb090a7SSaurabh Misra __func__, L1_SMB_BLOCK_SZ));
225*0eb090a7SSaurabh Misra
226*0eb090a7SSaurabh Misra dma = atge_alloc_a_dma_blk(atgep, &atge_l1_dma_attr_smb,
227*0eb090a7SSaurabh Misra L1_SMB_BLOCK_SZ, DDI_DMA_RDWR);
228*0eb090a7SSaurabh Misra l1->atge_l1_smb = dma;
229*0eb090a7SSaurabh Misra if (dma == NULL) {
230*0eb090a7SSaurabh Misra atge_error(atgep->atge_dip, "DMA allocation failed for SMB");
231*0eb090a7SSaurabh Misra return (DDI_FAILURE);
232*0eb090a7SSaurabh Misra }
233*0eb090a7SSaurabh Misra
234*0eb090a7SSaurabh Misra atgep->atge_hw_stats = kmem_zalloc(sizeof (atge_l1_smb_t), KM_SLEEP);
235*0eb090a7SSaurabh Misra
236*0eb090a7SSaurabh Misra return (DDI_SUCCESS);
237*0eb090a7SSaurabh Misra }
238*0eb090a7SSaurabh Misra
239*0eb090a7SSaurabh Misra void
atge_l1_free_dma(atge_t * atgep)240*0eb090a7SSaurabh Misra atge_l1_free_dma(atge_t *atgep)
241*0eb090a7SSaurabh Misra {
242*0eb090a7SSaurabh Misra atge_l1_data_t *l1;
243*0eb090a7SSaurabh Misra
244*0eb090a7SSaurabh Misra l1 = atgep->atge_private_data;
245*0eb090a7SSaurabh Misra
246*0eb090a7SSaurabh Misra /*
247*0eb090a7SSaurabh Misra * Free TX ring.
248*0eb090a7SSaurabh Misra */
249*0eb090a7SSaurabh Misra if (atgep->atge_tx_ring != NULL) {
250*0eb090a7SSaurabh Misra atge_free_buffers(atgep->atge_tx_ring, ATGE_TX_RING_CNT);
251*0eb090a7SSaurabh Misra
252*0eb090a7SSaurabh Misra if (atgep->atge_tx_ring->r_desc_ring != NULL) {
253*0eb090a7SSaurabh Misra atge_free_a_dma_blk(atgep->atge_tx_ring->r_desc_ring);
254*0eb090a7SSaurabh Misra }
255*0eb090a7SSaurabh Misra
256*0eb090a7SSaurabh Misra kmem_free(atgep->atge_tx_ring, sizeof (atge_ring_t));
257*0eb090a7SSaurabh Misra atgep->atge_tx_ring = NULL;
258*0eb090a7SSaurabh Misra }
259*0eb090a7SSaurabh Misra
260*0eb090a7SSaurabh Misra if (l1 && l1->atge_l1_cmb != NULL) {
261*0eb090a7SSaurabh Misra atge_free_a_dma_blk(l1->atge_l1_cmb);
262*0eb090a7SSaurabh Misra l1->atge_l1_cmb = NULL;
263*0eb090a7SSaurabh Misra }
264*0eb090a7SSaurabh Misra
265*0eb090a7SSaurabh Misra if (l1 && l1->atge_l1_rr != NULL) {
266*0eb090a7SSaurabh Misra atge_free_a_dma_blk(l1->atge_l1_rr);
267*0eb090a7SSaurabh Misra l1->atge_l1_rr = NULL;
268*0eb090a7SSaurabh Misra }
269*0eb090a7SSaurabh Misra
270*0eb090a7SSaurabh Misra if (l1 && l1->atge_l1_smb != NULL) {
271*0eb090a7SSaurabh Misra atge_free_a_dma_blk(l1->atge_l1_smb);
272*0eb090a7SSaurabh Misra l1->atge_l1_smb = NULL;
273*0eb090a7SSaurabh Misra }
274*0eb090a7SSaurabh Misra
275*0eb090a7SSaurabh Misra /*
276*0eb090a7SSaurabh Misra * Free RX ring.
277*0eb090a7SSaurabh Misra */
278*0eb090a7SSaurabh Misra if (l1 && l1->atge_rx_ring != NULL) {
279*0eb090a7SSaurabh Misra atge_free_buffers(l1->atge_rx_ring, L1_RX_RING_CNT);
280*0eb090a7SSaurabh Misra
281*0eb090a7SSaurabh Misra if (l1->atge_rx_ring->r_desc_ring != NULL) {
282*0eb090a7SSaurabh Misra atge_free_a_dma_blk(l1->atge_rx_ring->r_desc_ring);
283*0eb090a7SSaurabh Misra }
284*0eb090a7SSaurabh Misra
285*0eb090a7SSaurabh Misra kmem_free(l1->atge_rx_ring, sizeof (atge_ring_t));
286*0eb090a7SSaurabh Misra l1->atge_rx_ring = NULL;
287*0eb090a7SSaurabh Misra }
288*0eb090a7SSaurabh Misra
289*0eb090a7SSaurabh Misra /*
290*0eb090a7SSaurabh Misra * Free the memory allocated for gathering hw stats.
291*0eb090a7SSaurabh Misra */
292*0eb090a7SSaurabh Misra if (atgep->atge_hw_stats != NULL) {
293*0eb090a7SSaurabh Misra kmem_free(atgep->atge_hw_stats, sizeof (atge_l1_smb_t));
294*0eb090a7SSaurabh Misra atgep->atge_hw_stats = NULL;
295*0eb090a7SSaurabh Misra }
296*0eb090a7SSaurabh Misra }
297*0eb090a7SSaurabh Misra
298*0eb090a7SSaurabh Misra void
atge_l1_init_rx_ring(atge_t * atgep)299*0eb090a7SSaurabh Misra atge_l1_init_rx_ring(atge_t *atgep)
300*0eb090a7SSaurabh Misra {
301*0eb090a7SSaurabh Misra atge_l1_data_t *l1;
302*0eb090a7SSaurabh Misra atge_dma_t *dma;
303*0eb090a7SSaurabh Misra l1_rx_desc_t *rx;
304*0eb090a7SSaurabh Misra int i;
305*0eb090a7SSaurabh Misra
306*0eb090a7SSaurabh Misra l1 = atgep->atge_private_data;
307*0eb090a7SSaurabh Misra l1->atge_rx_ring->r_consumer = L1_RX_RING_CNT - 1;
308*0eb090a7SSaurabh Misra dma = l1->atge_rx_ring->r_desc_ring;
309*0eb090a7SSaurabh Misra bzero(dma->addr, L1_RX_RING_SZ);
310*0eb090a7SSaurabh Misra
311*0eb090a7SSaurabh Misra for (i = 0; i < L1_RX_RING_CNT; i++) {
312*0eb090a7SSaurabh Misra rx = (l1_rx_desc_t *)(dma->addr + (i * sizeof (l1_rx_desc_t)));
313*0eb090a7SSaurabh Misra
314*0eb090a7SSaurabh Misra ATGE_PUT64(dma, &rx->addr,
315*0eb090a7SSaurabh Misra l1->atge_rx_ring->r_buf_tbl[i]->cookie.dmac_laddress);
316*0eb090a7SSaurabh Misra ATGE_PUT32(dma, &rx->len,
317*0eb090a7SSaurabh Misra (l1->atge_rx_ring->r_buf_tbl[i]->len & L1_RD_LEN_MASK) <<
318*0eb090a7SSaurabh Misra L1_RD_LEN_SHIFT);
319*0eb090a7SSaurabh Misra }
320*0eb090a7SSaurabh Misra
321*0eb090a7SSaurabh Misra DMA_SYNC(dma, 0, L1_RX_RING_SZ, DDI_DMA_SYNC_FORDEV);
322*0eb090a7SSaurabh Misra }
323*0eb090a7SSaurabh Misra
324*0eb090a7SSaurabh Misra void
atge_l1_init_tx_ring(atge_t * atgep)325*0eb090a7SSaurabh Misra atge_l1_init_tx_ring(atge_t *atgep)
326*0eb090a7SSaurabh Misra {
327*0eb090a7SSaurabh Misra atgep->atge_tx_ring->r_producer = 0;
328*0eb090a7SSaurabh Misra atgep->atge_tx_ring->r_consumer = 0;
329*0eb090a7SSaurabh Misra atgep->atge_tx_ring->r_avail_desc = ATGE_TX_RING_CNT;
330*0eb090a7SSaurabh Misra
331*0eb090a7SSaurabh Misra bzero(atgep->atge_tx_ring->r_desc_ring->addr, ATGE_TX_RING_SZ);
332*0eb090a7SSaurabh Misra DMA_SYNC(atgep->atge_tx_ring->r_desc_ring, 0, ATGE_TX_RING_SZ,
333*0eb090a7SSaurabh Misra DDI_DMA_SYNC_FORDEV);
334*0eb090a7SSaurabh Misra }
335*0eb090a7SSaurabh Misra
336*0eb090a7SSaurabh Misra void
atge_l1_init_rr_ring(atge_t * atgep)337*0eb090a7SSaurabh Misra atge_l1_init_rr_ring(atge_t *atgep)
338*0eb090a7SSaurabh Misra {
339*0eb090a7SSaurabh Misra atge_l1_data_t *l1;
340*0eb090a7SSaurabh Misra atge_dma_t *dma;
341*0eb090a7SSaurabh Misra
342*0eb090a7SSaurabh Misra l1 = atgep->atge_private_data;
343*0eb090a7SSaurabh Misra l1->atge_l1_rr_consumers = 0;
344*0eb090a7SSaurabh Misra
345*0eb090a7SSaurabh Misra dma = l1->atge_l1_rr;
346*0eb090a7SSaurabh Misra bzero(dma->addr, L1_RR_RING_SZ);
347*0eb090a7SSaurabh Misra DMA_SYNC(dma, 0, L1_RR_RING_SZ, DDI_DMA_SYNC_FORDEV);
348*0eb090a7SSaurabh Misra }
349*0eb090a7SSaurabh Misra
350*0eb090a7SSaurabh Misra void
atge_l1_init_smb(atge_t * atgep)351*0eb090a7SSaurabh Misra atge_l1_init_smb(atge_t *atgep)
352*0eb090a7SSaurabh Misra {
353*0eb090a7SSaurabh Misra atge_l1_data_t *l1;
354*0eb090a7SSaurabh Misra atge_dma_t *dma;
355*0eb090a7SSaurabh Misra
356*0eb090a7SSaurabh Misra l1 = atgep->atge_private_data;
357*0eb090a7SSaurabh Misra dma = l1->atge_l1_smb;
358*0eb090a7SSaurabh Misra bzero(dma->addr, L1_SMB_BLOCK_SZ);
359*0eb090a7SSaurabh Misra DMA_SYNC(dma, 0, L1_SMB_BLOCK_SZ, DDI_DMA_SYNC_FORDEV);
360*0eb090a7SSaurabh Misra }
361*0eb090a7SSaurabh Misra
362*0eb090a7SSaurabh Misra void
atge_l1_init_cmb(atge_t * atgep)363*0eb090a7SSaurabh Misra atge_l1_init_cmb(atge_t *atgep)
364*0eb090a7SSaurabh Misra {
365*0eb090a7SSaurabh Misra atge_l1_data_t *l1;
366*0eb090a7SSaurabh Misra atge_dma_t *dma;
367*0eb090a7SSaurabh Misra
368*0eb090a7SSaurabh Misra l1 = atgep->atge_private_data;
369*0eb090a7SSaurabh Misra dma = l1->atge_l1_cmb;
370*0eb090a7SSaurabh Misra bzero(dma->addr, L1_CMB_BLOCK_SZ);
371*0eb090a7SSaurabh Misra DMA_SYNC(dma, 0, L1_CMB_BLOCK_SZ, DDI_DMA_SYNC_FORDEV);
372*0eb090a7SSaurabh Misra }
373*0eb090a7SSaurabh Misra
374*0eb090a7SSaurabh Misra void
atge_l1_sync_mbox(atge_t * atgep)375*0eb090a7SSaurabh Misra atge_l1_sync_mbox(atge_t *atgep)
376*0eb090a7SSaurabh Misra {
377*0eb090a7SSaurabh Misra atge_l1_data_t *l1;
378*0eb090a7SSaurabh Misra
379*0eb090a7SSaurabh Misra l1 = atgep->atge_private_data;
380*0eb090a7SSaurabh Misra
381*0eb090a7SSaurabh Misra mutex_enter(&atgep->atge_mbox_lock);
382*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_MBOX,
383*0eb090a7SSaurabh Misra ((l1->atge_rx_ring->r_consumer << MBOX_RD_PROD_IDX_SHIFT) &
384*0eb090a7SSaurabh Misra MBOX_RD_PROD_IDX_MASK) |
385*0eb090a7SSaurabh Misra ((l1->atge_l1_rr_consumers <<
386*0eb090a7SSaurabh Misra MBOX_RRD_CONS_IDX_SHIFT) & MBOX_RRD_CONS_IDX_MASK) |
387*0eb090a7SSaurabh Misra ((atgep->atge_tx_ring->r_producer << MBOX_TD_PROD_IDX_SHIFT) &
388*0eb090a7SSaurabh Misra MBOX_TD_PROD_IDX_MASK));
389*0eb090a7SSaurabh Misra mutex_exit(&atgep->atge_mbox_lock);
390*0eb090a7SSaurabh Misra }
391*0eb090a7SSaurabh Misra
392*0eb090a7SSaurabh Misra void
atge_l1_program_dma(atge_t * atgep)393*0eb090a7SSaurabh Misra atge_l1_program_dma(atge_t *atgep)
394*0eb090a7SSaurabh Misra {
395*0eb090a7SSaurabh Misra atge_l1_data_t *l1;
396*0eb090a7SSaurabh Misra atge_ring_t *r;
397*0eb090a7SSaurabh Misra
398*0eb090a7SSaurabh Misra l1 = atgep->atge_private_data;
399*0eb090a7SSaurabh Misra
400*0eb090a7SSaurabh Misra /* TX */
401*0eb090a7SSaurabh Misra r = atgep->atge_tx_ring;
402*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_DESC_ADDR_HI,
403*0eb090a7SSaurabh Misra ATGE_ADDR_HI(r->r_desc_ring->cookie.dmac_laddress));
404*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_DESC_TPD_ADDR_LO,
405*0eb090a7SSaurabh Misra ATGE_ADDR_LO(r->r_desc_ring->cookie.dmac_laddress));
406*0eb090a7SSaurabh Misra
407*0eb090a7SSaurabh Misra /* RX */
408*0eb090a7SSaurabh Misra r = l1->atge_rx_ring;
409*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_DESC_RD_ADDR_LO,
410*0eb090a7SSaurabh Misra ATGE_ADDR_LO(r->r_desc_ring->cookie.dmac_laddress));
411*0eb090a7SSaurabh Misra
412*0eb090a7SSaurabh Misra /* RR Ring */
413*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_DESC_RRD_ADDR_LO,
414*0eb090a7SSaurabh Misra ATGE_ADDR_LO(l1->atge_l1_rr->cookie.dmac_laddress));
415*0eb090a7SSaurabh Misra
416*0eb090a7SSaurabh Misra /* CMB */
417*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_DESC_CMB_ADDR_LO,
418*0eb090a7SSaurabh Misra ATGE_ADDR_LO(l1->atge_l1_cmb->cookie.dmac_laddress));
419*0eb090a7SSaurabh Misra
420*0eb090a7SSaurabh Misra /* SMB */
421*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_DESC_SMB_ADDR_LO,
422*0eb090a7SSaurabh Misra ATGE_ADDR_LO(l1->atge_l1_smb->cookie.dmac_laddress));
423*0eb090a7SSaurabh Misra
424*0eb090a7SSaurabh Misra /*
425*0eb090a7SSaurabh Misra * Set RX return ring (RR) counter.
426*0eb090a7SSaurabh Misra */
427*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_DESC_RRD_RD_CNT,
428*0eb090a7SSaurabh Misra ((L1_RR_RING_CNT << DESC_RRD_CNT_SHIFT) &
429*0eb090a7SSaurabh Misra DESC_RRD_CNT_MASK) |
430*0eb090a7SSaurabh Misra ((L1_RX_RING_CNT << DESC_RD_CNT_SHIFT) & DESC_RD_CNT_MASK));
431*0eb090a7SSaurabh Misra
432*0eb090a7SSaurabh Misra /*
433*0eb090a7SSaurabh Misra * Set TX descriptor counter.
434*0eb090a7SSaurabh Misra */
435*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_DESC_TPD_CNT,
436*0eb090a7SSaurabh Misra (ATGE_TX_RING_CNT << DESC_TPD_CNT_SHIFT) & DESC_TPD_CNT_MASK);
437*0eb090a7SSaurabh Misra
438*0eb090a7SSaurabh Misra /*
439*0eb090a7SSaurabh Misra * Inform hardware that we have loaded DMA registers.
440*0eb090a7SSaurabh Misra */
441*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_DMA_BLOCK, DMA_BLOCK_LOAD);
442*0eb090a7SSaurabh Misra
443*0eb090a7SSaurabh Misra /*
444*0eb090a7SSaurabh Misra * Initialize mailbox register (mbox).
445*0eb090a7SSaurabh Misra */
446*0eb090a7SSaurabh Misra atge_l1_sync_mbox(atgep);
447*0eb090a7SSaurabh Misra }
448*0eb090a7SSaurabh Misra
449*0eb090a7SSaurabh Misra void
atge_l1_gather_stats(atge_t * atgep)450*0eb090a7SSaurabh Misra atge_l1_gather_stats(atge_t *atgep)
451*0eb090a7SSaurabh Misra {
452*0eb090a7SSaurabh Misra atge_l1_data_t *l1;
453*0eb090a7SSaurabh Misra atge_dma_t *dma;
454*0eb090a7SSaurabh Misra atge_l1_smb_t *stat;
455*0eb090a7SSaurabh Misra atge_l1_smb_t *smb;
456*0eb090a7SSaurabh Misra
457*0eb090a7SSaurabh Misra ASSERT(atgep != NULL);
458*0eb090a7SSaurabh Misra
459*0eb090a7SSaurabh Misra l1 = atgep->atge_private_data;
460*0eb090a7SSaurabh Misra dma = l1->atge_l1_smb;
461*0eb090a7SSaurabh Misra DMA_SYNC(dma, 0, L1_SMB_BLOCK_SZ, DDI_DMA_SYNC_FORKERNEL);
462*0eb090a7SSaurabh Misra stat = (atge_l1_smb_t *)atgep->atge_hw_stats;
463*0eb090a7SSaurabh Misra smb = (atge_l1_smb_t *)dma->addr;
464*0eb090a7SSaurabh Misra
465*0eb090a7SSaurabh Misra /* Rx stats. */
466*0eb090a7SSaurabh Misra stat->rx_frames += smb->rx_frames;
467*0eb090a7SSaurabh Misra stat->rx_bcast_frames += smb->rx_bcast_frames;
468*0eb090a7SSaurabh Misra stat->rx_mcast_frames += smb->rx_mcast_frames;
469*0eb090a7SSaurabh Misra stat->rx_pause_frames += smb->rx_pause_frames;
470*0eb090a7SSaurabh Misra stat->rx_control_frames += smb->rx_control_frames;
471*0eb090a7SSaurabh Misra stat->rx_crcerrs += smb->rx_crcerrs;
472*0eb090a7SSaurabh Misra stat->rx_lenerrs += smb->rx_lenerrs;
473*0eb090a7SSaurabh Misra stat->rx_bytes += smb->rx_bytes;
474*0eb090a7SSaurabh Misra stat->rx_runts += smb->rx_runts;
475*0eb090a7SSaurabh Misra stat->rx_fragments += smb->rx_fragments;
476*0eb090a7SSaurabh Misra stat->rx_pkts_64 += smb->rx_pkts_64;
477*0eb090a7SSaurabh Misra stat->rx_pkts_65_127 += smb->rx_pkts_65_127;
478*0eb090a7SSaurabh Misra stat->rx_pkts_128_255 += smb->rx_pkts_128_255;
479*0eb090a7SSaurabh Misra stat->rx_pkts_256_511 += smb->rx_pkts_256_511;
480*0eb090a7SSaurabh Misra stat->rx_pkts_512_1023 += smb->rx_pkts_512_1023;
481*0eb090a7SSaurabh Misra stat->rx_pkts_1024_1518 += smb->rx_pkts_1024_1518;
482*0eb090a7SSaurabh Misra stat->rx_pkts_1519_max += smb->rx_pkts_1519_max;
483*0eb090a7SSaurabh Misra stat->rx_pkts_truncated += smb->rx_pkts_truncated;
484*0eb090a7SSaurabh Misra stat->rx_fifo_oflows += smb->rx_fifo_oflows;
485*0eb090a7SSaurabh Misra stat->rx_alignerrs += smb->rx_alignerrs;
486*0eb090a7SSaurabh Misra stat->rx_bcast_bytes += smb->rx_bcast_bytes;
487*0eb090a7SSaurabh Misra stat->rx_mcast_bytes += smb->rx_mcast_bytes;
488*0eb090a7SSaurabh Misra stat->rx_pkts_filtered += smb->rx_pkts_filtered;
489*0eb090a7SSaurabh Misra
490*0eb090a7SSaurabh Misra /* Tx stats. */
491*0eb090a7SSaurabh Misra stat->tx_frames += smb->tx_frames;
492*0eb090a7SSaurabh Misra stat->tx_bcast_frames += smb->tx_bcast_frames;
493*0eb090a7SSaurabh Misra stat->tx_mcast_frames += smb->tx_mcast_frames;
494*0eb090a7SSaurabh Misra stat->tx_pause_frames += smb->tx_pause_frames;
495*0eb090a7SSaurabh Misra stat->tx_excess_defer += smb->tx_excess_defer;
496*0eb090a7SSaurabh Misra stat->tx_control_frames += smb->tx_control_frames;
497*0eb090a7SSaurabh Misra stat->tx_deferred += smb->tx_deferred;
498*0eb090a7SSaurabh Misra stat->tx_bytes += smb->tx_bytes;
499*0eb090a7SSaurabh Misra stat->tx_pkts_64 += smb->tx_pkts_64;
500*0eb090a7SSaurabh Misra stat->tx_pkts_65_127 += smb->tx_pkts_65_127;
501*0eb090a7SSaurabh Misra stat->tx_pkts_128_255 += smb->tx_pkts_128_255;
502*0eb090a7SSaurabh Misra stat->tx_pkts_256_511 += smb->tx_pkts_256_511;
503*0eb090a7SSaurabh Misra stat->tx_pkts_512_1023 += smb->tx_pkts_512_1023;
504*0eb090a7SSaurabh Misra stat->tx_pkts_1024_1518 += smb->tx_pkts_1024_1518;
505*0eb090a7SSaurabh Misra stat->tx_pkts_1519_max += smb->tx_pkts_1519_max;
506*0eb090a7SSaurabh Misra stat->tx_single_colls += smb->tx_single_colls;
507*0eb090a7SSaurabh Misra stat->tx_multi_colls += smb->tx_multi_colls;
508*0eb090a7SSaurabh Misra stat->tx_late_colls += smb->tx_late_colls;
509*0eb090a7SSaurabh Misra stat->tx_excess_colls += smb->tx_excess_colls;
510*0eb090a7SSaurabh Misra stat->tx_underrun += smb->tx_underrun;
511*0eb090a7SSaurabh Misra stat->tx_desc_underrun += smb->tx_desc_underrun;
512*0eb090a7SSaurabh Misra stat->tx_lenerrs += smb->tx_lenerrs;
513*0eb090a7SSaurabh Misra stat->tx_pkts_truncated += smb->tx_pkts_truncated;
514*0eb090a7SSaurabh Misra stat->tx_bcast_bytes += smb->tx_bcast_bytes;
515*0eb090a7SSaurabh Misra stat->tx_mcast_bytes += smb->tx_mcast_bytes;
516*0eb090a7SSaurabh Misra
517*0eb090a7SSaurabh Misra /*
518*0eb090a7SSaurabh Misra * Update global counters in atge_t.
519*0eb090a7SSaurabh Misra */
520*0eb090a7SSaurabh Misra atgep->atge_brdcstrcv += smb->rx_bcast_frames;
521*0eb090a7SSaurabh Misra atgep->atge_multircv += smb->rx_mcast_frames;
522*0eb090a7SSaurabh Misra atgep->atge_multixmt += smb->tx_mcast_frames;
523*0eb090a7SSaurabh Misra atgep->atge_brdcstxmt += smb->tx_bcast_frames;
524*0eb090a7SSaurabh Misra
525*0eb090a7SSaurabh Misra atgep->atge_align_errors += smb->rx_alignerrs;
526*0eb090a7SSaurabh Misra atgep->atge_fcs_errors += smb->rx_crcerrs;
527*0eb090a7SSaurabh Misra atgep->atge_defer_xmts += smb->tx_deferred;
528*0eb090a7SSaurabh Misra atgep->atge_first_collisions += smb->tx_single_colls;
529*0eb090a7SSaurabh Misra atgep->atge_multi_collisions += smb->tx_multi_colls * 2;
530*0eb090a7SSaurabh Misra atgep->atge_tx_late_collisions += smb->tx_late_colls;
531*0eb090a7SSaurabh Misra atgep->atge_ex_collisions += smb->tx_excess_colls;
532*0eb090a7SSaurabh Misra atgep->atge_toolong_errors += smb->rx_lenerrs;
533*0eb090a7SSaurabh Misra atgep->atge_overflow += smb->rx_fifo_oflows;
534*0eb090a7SSaurabh Misra atgep->atge_underflow += (smb->tx_underrun + smb->tx_desc_underrun);
535*0eb090a7SSaurabh Misra atgep->atge_runt += smb->rx_runts;
536*0eb090a7SSaurabh Misra
537*0eb090a7SSaurabh Misra
538*0eb090a7SSaurabh Misra atgep->atge_collisions += smb->tx_single_colls +
539*0eb090a7SSaurabh Misra smb->tx_multi_colls * 2 + smb->tx_late_colls;
540*0eb090a7SSaurabh Misra
541*0eb090a7SSaurabh Misra /*
542*0eb090a7SSaurabh Misra * tx_pkts_truncated counter looks suspicious. It constantly
543*0eb090a7SSaurabh Misra * increments with no sign of Tx errors. Hence we don't factor it.
544*0eb090a7SSaurabh Misra */
545*0eb090a7SSaurabh Misra atgep->atge_macxmt_errors += smb->tx_late_colls + smb->tx_underrun;
546*0eb090a7SSaurabh Misra
547*0eb090a7SSaurabh Misra atgep->atge_macrcv_errors += smb->rx_crcerrs + smb->rx_lenerrs +
548*0eb090a7SSaurabh Misra smb->rx_runts + smb->rx_pkts_truncated +
549*0eb090a7SSaurabh Misra smb->rx_alignerrs;
550*0eb090a7SSaurabh Misra
551*0eb090a7SSaurabh Misra smb->updated = 0;
552*0eb090a7SSaurabh Misra DMA_SYNC(dma, 0, L1_SMB_BLOCK_SZ, DDI_DMA_SYNC_FORDEV);
553*0eb090a7SSaurabh Misra }
554*0eb090a7SSaurabh Misra
555*0eb090a7SSaurabh Misra void
atge_l1_stop_tx_mac(atge_t * atgep)556*0eb090a7SSaurabh Misra atge_l1_stop_tx_mac(atge_t *atgep)
557*0eb090a7SSaurabh Misra {
558*0eb090a7SSaurabh Misra uint32_t reg;
559*0eb090a7SSaurabh Misra int t;
560*0eb090a7SSaurabh Misra
561*0eb090a7SSaurabh Misra ATGE_DB(("%s: %s() called", atgep->atge_name, __func__));
562*0eb090a7SSaurabh Misra
563*0eb090a7SSaurabh Misra reg = INL(atgep, ATGE_MAC_CFG);
564*0eb090a7SSaurabh Misra if ((reg & ATGE_CFG_TX_ENB) != 0) {
565*0eb090a7SSaurabh Misra reg &= ~ATGE_CFG_TX_ENB;
566*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_MAC_CFG, reg);
567*0eb090a7SSaurabh Misra }
568*0eb090a7SSaurabh Misra
569*0eb090a7SSaurabh Misra /* Stop TX DMA engine. */
570*0eb090a7SSaurabh Misra reg = INL(atgep, ATGE_DMA_CFG);
571*0eb090a7SSaurabh Misra if ((reg & DMA_CFG_RD_ENB) != 0) {
572*0eb090a7SSaurabh Misra reg &= ~DMA_CFG_RD_ENB;
573*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_DMA_CFG, reg);
574*0eb090a7SSaurabh Misra }
575*0eb090a7SSaurabh Misra
576*0eb090a7SSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
577*0eb090a7SSaurabh Misra if ((INL(atgep, ATGE_IDLE_STATUS) &
578*0eb090a7SSaurabh Misra (IDLE_STATUS_TXMAC | IDLE_STATUS_DMARD)) == 0)
579*0eb090a7SSaurabh Misra break;
580*0eb090a7SSaurabh Misra
581*0eb090a7SSaurabh Misra drv_usecwait(10);
582*0eb090a7SSaurabh Misra }
583*0eb090a7SSaurabh Misra
584*0eb090a7SSaurabh Misra if (t == 0) {
585*0eb090a7SSaurabh Misra atge_error(atgep->atge_dip, "stopping TX DMA Engine timeout");
586*0eb090a7SSaurabh Misra }
587*0eb090a7SSaurabh Misra }
588*0eb090a7SSaurabh Misra
589*0eb090a7SSaurabh Misra void
atge_l1_stop_rx_mac(atge_t * atgep)590*0eb090a7SSaurabh Misra atge_l1_stop_rx_mac(atge_t *atgep)
591*0eb090a7SSaurabh Misra {
592*0eb090a7SSaurabh Misra uint32_t reg;
593*0eb090a7SSaurabh Misra int t;
594*0eb090a7SSaurabh Misra
595*0eb090a7SSaurabh Misra ATGE_DB(("%s: %s() called", atgep->atge_name, __func__));
596*0eb090a7SSaurabh Misra
597*0eb090a7SSaurabh Misra reg = INL(atgep, ATGE_MAC_CFG);
598*0eb090a7SSaurabh Misra if ((reg & ATGE_CFG_RX_ENB) != 0) {
599*0eb090a7SSaurabh Misra reg &= ~ATGE_CFG_RX_ENB;
600*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_MAC_CFG, reg);
601*0eb090a7SSaurabh Misra }
602*0eb090a7SSaurabh Misra
603*0eb090a7SSaurabh Misra /* Stop RX DMA engine. */
604*0eb090a7SSaurabh Misra reg = INL(atgep, ATGE_DMA_CFG);
605*0eb090a7SSaurabh Misra if ((reg & DMA_CFG_WR_ENB) != 0) {
606*0eb090a7SSaurabh Misra reg &= ~DMA_CFG_WR_ENB;
607*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_DMA_CFG, reg);
608*0eb090a7SSaurabh Misra }
609*0eb090a7SSaurabh Misra
610*0eb090a7SSaurabh Misra for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
611*0eb090a7SSaurabh Misra if ((INL(atgep, ATGE_IDLE_STATUS) &
612*0eb090a7SSaurabh Misra (IDLE_STATUS_RXMAC | IDLE_STATUS_DMAWR)) == 0)
613*0eb090a7SSaurabh Misra break;
614*0eb090a7SSaurabh Misra drv_usecwait(10);
615*0eb090a7SSaurabh Misra }
616*0eb090a7SSaurabh Misra
617*0eb090a7SSaurabh Misra if (t == 0) {
618*0eb090a7SSaurabh Misra atge_error(atgep->atge_dip, " stopping RX DMA Engine timeout");
619*0eb090a7SSaurabh Misra }
620*0eb090a7SSaurabh Misra }
621*0eb090a7SSaurabh Misra
622*0eb090a7SSaurabh Misra /*
623*0eb090a7SSaurabh Misra * Receives (consumes) packets.
624*0eb090a7SSaurabh Misra */
625*0eb090a7SSaurabh Misra static mblk_t *
atge_l1_rx(atge_t * atgep)626*0eb090a7SSaurabh Misra atge_l1_rx(atge_t *atgep)
627*0eb090a7SSaurabh Misra {
628*0eb090a7SSaurabh Misra atge_l1_data_t *l1;
629*0eb090a7SSaurabh Misra mblk_t *mp = NULL, *rx_head = NULL, *rx_tail = NULL;
630*0eb090a7SSaurabh Misra l1_rx_rdesc_t *rx_rr;
631*0eb090a7SSaurabh Misra l1_rx_desc_t *rxd;
632*0eb090a7SSaurabh Misra uint32_t index, flags, totlen, pktlen, slotlen;
633*0eb090a7SSaurabh Misra int nsegs, rx_cons = 0, cnt;
634*0eb090a7SSaurabh Misra atge_dma_t *buf;
635*0eb090a7SSaurabh Misra uchar_t *bufp;
636*0eb090a7SSaurabh Misra int sync = 0;
637*0eb090a7SSaurabh Misra
638*0eb090a7SSaurabh Misra l1 = atgep->atge_private_data;
639*0eb090a7SSaurabh Misra ASSERT(l1 != NULL);
640*0eb090a7SSaurabh Misra
641*0eb090a7SSaurabh Misra DMA_SYNC(l1->atge_l1_rr, 0, L1_RR_RING_SZ, DDI_DMA_SYNC_FORKERNEL);
642*0eb090a7SSaurabh Misra
643*0eb090a7SSaurabh Misra while (l1->atge_l1_rr_consumers != l1->atge_l1_rx_prod_cons) {
644*0eb090a7SSaurabh Misra rx_rr = (l1_rx_rdesc_t *)(l1->atge_l1_rr->addr +
645*0eb090a7SSaurabh Misra (l1->atge_l1_rr_consumers * sizeof (l1_rx_rdesc_t)));
646*0eb090a7SSaurabh Misra
647*0eb090a7SSaurabh Misra index = ATGE_GET32(l1->atge_l1_rr, &rx_rr->index);
648*0eb090a7SSaurabh Misra flags = ATGE_GET32(l1->atge_l1_rr, &rx_rr->flags);
649*0eb090a7SSaurabh Misra totlen = L1_RX_BYTES(ATGE_GET32(l1->atge_l1_rr, &rx_rr->len));
650*0eb090a7SSaurabh Misra
651*0eb090a7SSaurabh Misra rx_cons = L1_RX_CONS(index);
652*0eb090a7SSaurabh Misra nsegs = L1_RX_NSEGS(index);
653*0eb090a7SSaurabh Misra
654*0eb090a7SSaurabh Misra ATGE_DB(("%s: %s() PKT -- index : %d, flags : %x, totlen : %d,"
655*0eb090a7SSaurabh Misra " rx_cons : %d, nsegs : %d", atgep->atge_name, __func__,
656*0eb090a7SSaurabh Misra index, flags, totlen, rx_cons, nsegs));
657*0eb090a7SSaurabh Misra
658*0eb090a7SSaurabh Misra if (nsegs == 0)
659*0eb090a7SSaurabh Misra break;
660*0eb090a7SSaurabh Misra
661*0eb090a7SSaurabh Misra if ((flags & L1_RRD_ERROR) &&
662*0eb090a7SSaurabh Misra (flags & (L1_RRD_CRC | L1_RRD_CODE | L1_RRD_DRIBBLE |
663*0eb090a7SSaurabh Misra L1_RRD_RUNT | L1_RRD_OFLOW | L1_RRD_TRUNC)) != 0) {
664*0eb090a7SSaurabh Misra atge_error(atgep->atge_dip, "errored pkt");
665*0eb090a7SSaurabh Misra
666*0eb090a7SSaurabh Misra l1->atge_rx_ring->r_consumer += nsegs;
667*0eb090a7SSaurabh Misra l1->atge_rx_ring->r_consumer %= L1_RX_RING_CNT;
668*0eb090a7SSaurabh Misra break;
669*0eb090a7SSaurabh Misra }
670*0eb090a7SSaurabh Misra
671*0eb090a7SSaurabh Misra ASSERT(rx_cons >= 0 && rx_cons <= L1_RX_RING_CNT);
672*0eb090a7SSaurabh Misra
673*0eb090a7SSaurabh Misra mp = allocb(totlen + VLAN_TAGSZ, BPRI_MED);
674*0eb090a7SSaurabh Misra if (mp != NULL) {
675*0eb090a7SSaurabh Misra mp->b_rptr += VLAN_TAGSZ;
676*0eb090a7SSaurabh Misra bufp = mp->b_rptr;
677*0eb090a7SSaurabh Misra mp->b_wptr = bufp + totlen;
678*0eb090a7SSaurabh Misra mp->b_next = NULL;
679*0eb090a7SSaurabh Misra
680*0eb090a7SSaurabh Misra atgep->atge_ipackets++;
681*0eb090a7SSaurabh Misra atgep->atge_rbytes += totlen;
682*0eb090a7SSaurabh Misra
683*0eb090a7SSaurabh Misra /*
684*0eb090a7SSaurabh Misra * If there are more than one segments, then the first
685*0eb090a7SSaurabh Misra * segment should be of size MTU. We couldn't verify
686*0eb090a7SSaurabh Misra * this as our driver does not support changing MTU
687*0eb090a7SSaurabh Misra * or Jumbo Frames.
688*0eb090a7SSaurabh Misra */
689*0eb090a7SSaurabh Misra if (nsegs > 1) {
690*0eb090a7SSaurabh Misra slotlen = atgep->atge_mtu;
691*0eb090a7SSaurabh Misra } else {
692*0eb090a7SSaurabh Misra slotlen = totlen;
693*0eb090a7SSaurabh Misra }
694*0eb090a7SSaurabh Misra } else {
695*0eb090a7SSaurabh Misra ATGE_DB(("%s: %s() PKT mp == NULL totlen : %d",
696*0eb090a7SSaurabh Misra atgep->atge_name, __func__, totlen));
697*0eb090a7SSaurabh Misra
698*0eb090a7SSaurabh Misra if (slotlen > atgep->atge_rx_buf_len) {
699*0eb090a7SSaurabh Misra atgep->atge_toolong_errors++;
700*0eb090a7SSaurabh Misra } else if (mp == NULL) {
701*0eb090a7SSaurabh Misra atgep->atge_norcvbuf++;
702*0eb090a7SSaurabh Misra }
703*0eb090a7SSaurabh Misra
704*0eb090a7SSaurabh Misra rx_rr->index = 0;
705*0eb090a7SSaurabh Misra break;
706*0eb090a7SSaurabh Misra }
707*0eb090a7SSaurabh Misra
708*0eb090a7SSaurabh Misra for (cnt = 0, pktlen = 0; cnt < nsegs; cnt++) {
709*0eb090a7SSaurabh Misra buf = l1->atge_rx_ring->r_buf_tbl[rx_cons];
710*0eb090a7SSaurabh Misra rxd = (l1_rx_desc_t *)(
711*0eb090a7SSaurabh Misra l1->atge_rx_ring->r_desc_ring->addr +
712*0eb090a7SSaurabh Misra (rx_cons * sizeof (l1_rx_desc_t)));
713*0eb090a7SSaurabh Misra
714*0eb090a7SSaurabh Misra if (cnt != 0) {
715*0eb090a7SSaurabh Misra slotlen = L1_RX_BYTES(ATGE_GET32(
716*0eb090a7SSaurabh Misra l1->atge_rx_ring->r_desc_ring, &rxd->len));
717*0eb090a7SSaurabh Misra }
718*0eb090a7SSaurabh Misra
719*0eb090a7SSaurabh Misra bcopy(buf->addr, (bufp + pktlen), slotlen);
720*0eb090a7SSaurabh Misra pktlen += slotlen;
721*0eb090a7SSaurabh Misra
722*0eb090a7SSaurabh Misra ATGE_DB(("%s: %s() len : %d, rxcons : %d, pktlen : %d",
723*0eb090a7SSaurabh Misra atgep->atge_name, __func__, slotlen, rx_cons,
724*0eb090a7SSaurabh Misra pktlen));
725*0eb090a7SSaurabh Misra
726*0eb090a7SSaurabh Misra ATGE_INC_SLOT(rx_cons, L1_RX_RING_CNT);
727*0eb090a7SSaurabh Misra }
728*0eb090a7SSaurabh Misra
729*0eb090a7SSaurabh Misra if (rx_tail == NULL) {
730*0eb090a7SSaurabh Misra rx_head = rx_tail = mp;
731*0eb090a7SSaurabh Misra } else {
732*0eb090a7SSaurabh Misra rx_tail->b_next = mp;
733*0eb090a7SSaurabh Misra rx_tail = mp;
734*0eb090a7SSaurabh Misra }
735*0eb090a7SSaurabh Misra
736*0eb090a7SSaurabh Misra if (cnt != nsegs) {
737*0eb090a7SSaurabh Misra l1->atge_rx_ring->r_consumer += nsegs;
738*0eb090a7SSaurabh Misra l1->atge_rx_ring->r_consumer %= L1_RX_RING_CNT;
739*0eb090a7SSaurabh Misra } else {
740*0eb090a7SSaurabh Misra l1->atge_rx_ring->r_consumer = rx_cons;
741*0eb090a7SSaurabh Misra }
742*0eb090a7SSaurabh Misra
743*0eb090a7SSaurabh Misra /*
744*0eb090a7SSaurabh Misra * Tell the chip that this RR can be reused.
745*0eb090a7SSaurabh Misra */
746*0eb090a7SSaurabh Misra rx_rr->index = 0;
747*0eb090a7SSaurabh Misra
748*0eb090a7SSaurabh Misra ATGE_INC_SLOT(l1->atge_l1_rr_consumers, L1_RR_RING_CNT);
749*0eb090a7SSaurabh Misra sync++;
750*0eb090a7SSaurabh Misra }
751*0eb090a7SSaurabh Misra
752*0eb090a7SSaurabh Misra if (sync) {
753*0eb090a7SSaurabh Misra DMA_SYNC(l1->atge_rx_ring->r_desc_ring, 0, L1_RX_RING_SZ,
754*0eb090a7SSaurabh Misra DDI_DMA_SYNC_FORDEV);
755*0eb090a7SSaurabh Misra
756*0eb090a7SSaurabh Misra DMA_SYNC(l1->atge_l1_rr, 0, L1_RR_RING_SZ, DDI_DMA_SYNC_FORDEV);
757*0eb090a7SSaurabh Misra atge_l1_sync_mbox(atgep);
758*0eb090a7SSaurabh Misra
759*0eb090a7SSaurabh Misra ATGE_DB(("%s: %s() PKT Recved -> r_consumer : %d, rx_cons : %d"
760*0eb090a7SSaurabh Misra " atge_l1_rr_consumers : %d",
761*0eb090a7SSaurabh Misra atgep->atge_name, __func__, l1->atge_rx_ring->r_consumer,
762*0eb090a7SSaurabh Misra rx_cons, l1->atge_l1_rr_consumers));
763*0eb090a7SSaurabh Misra }
764*0eb090a7SSaurabh Misra
765*0eb090a7SSaurabh Misra
766*0eb090a7SSaurabh Misra return (rx_head);
767*0eb090a7SSaurabh Misra }
768*0eb090a7SSaurabh Misra
769*0eb090a7SSaurabh Misra /*
770*0eb090a7SSaurabh Misra * The interrupt handler for L1 chip.
771*0eb090a7SSaurabh Misra */
772*0eb090a7SSaurabh Misra /*ARGSUSED*/
773*0eb090a7SSaurabh Misra uint_t
atge_l1_interrupt(caddr_t arg1,caddr_t arg2)774*0eb090a7SSaurabh Misra atge_l1_interrupt(caddr_t arg1, caddr_t arg2)
775*0eb090a7SSaurabh Misra {
776*0eb090a7SSaurabh Misra atge_t *atgep = (void *)arg1;
777*0eb090a7SSaurabh Misra mblk_t *rx_head = NULL, *rx_head1 = NULL;
778*0eb090a7SSaurabh Misra uint32_t status;
779*0eb090a7SSaurabh Misra int resched = 0;
780*0eb090a7SSaurabh Misra
781*0eb090a7SSaurabh Misra ASSERT(atgep != NULL);
782*0eb090a7SSaurabh Misra
783*0eb090a7SSaurabh Misra mutex_enter(&atgep->atge_intr_lock);
784*0eb090a7SSaurabh Misra
785*0eb090a7SSaurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_SUSPENDED) {
786*0eb090a7SSaurabh Misra mutex_exit(&atgep->atge_intr_lock);
787*0eb090a7SSaurabh Misra return (DDI_INTR_UNCLAIMED);
788*0eb090a7SSaurabh Misra }
789*0eb090a7SSaurabh Misra
790*0eb090a7SSaurabh Misra status = INL(atgep, ATGE_INTR_STATUS);
791*0eb090a7SSaurabh Misra if (status == 0 || (status & atgep->atge_intrs) == 0) {
792*0eb090a7SSaurabh Misra mutex_exit(&atgep->atge_intr_lock);
793*0eb090a7SSaurabh Misra
794*0eb090a7SSaurabh Misra if (atgep->atge_flags & ATGE_FIXED_TYPE)
795*0eb090a7SSaurabh Misra return (DDI_INTR_UNCLAIMED);
796*0eb090a7SSaurabh Misra
797*0eb090a7SSaurabh Misra return (DDI_INTR_CLAIMED);
798*0eb090a7SSaurabh Misra }
799*0eb090a7SSaurabh Misra
800*0eb090a7SSaurabh Misra ATGE_DB(("%s: %s() entry status : %x",
801*0eb090a7SSaurabh Misra atgep->atge_name, __func__, status));
802*0eb090a7SSaurabh Misra
803*0eb090a7SSaurabh Misra /*
804*0eb090a7SSaurabh Misra * Disable interrupts.
805*0eb090a7SSaurabh Misra */
806*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, status | INTR_DIS_INT);
807*0eb090a7SSaurabh Misra FLUSH(atgep, ATGE_INTR_STATUS);
808*0eb090a7SSaurabh Misra
809*0eb090a7SSaurabh Misra /*
810*0eb090a7SSaurabh Misra * Check if chip is running, only then do the work.
811*0eb090a7SSaurabh Misra */
812*0eb090a7SSaurabh Misra if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) {
813*0eb090a7SSaurabh Misra atge_l1_data_t *l1;
814*0eb090a7SSaurabh Misra l1_cmb_t *cmb;
815*0eb090a7SSaurabh Misra
816*0eb090a7SSaurabh Misra l1 = atgep->atge_private_data;
817*0eb090a7SSaurabh Misra
818*0eb090a7SSaurabh Misra DMA_SYNC(l1->atge_l1_cmb, 0, L1_CMB_BLOCK_SZ,
819*0eb090a7SSaurabh Misra DDI_DMA_SYNC_FORKERNEL);
820*0eb090a7SSaurabh Misra
821*0eb090a7SSaurabh Misra cmb = (l1_cmb_t *)l1->atge_l1_cmb->addr;
822*0eb090a7SSaurabh Misra l1->atge_l1_intr_status =
823*0eb090a7SSaurabh Misra ATGE_GET32(l1->atge_l1_cmb, &cmb->intr_status);
824*0eb090a7SSaurabh Misra l1->atge_l1_rx_prod_cons =
825*0eb090a7SSaurabh Misra (ATGE_GET32(l1->atge_l1_cmb, &cmb->rx_prod_cons) &
826*0eb090a7SSaurabh Misra RRD_PROD_MASK) >> RRD_PROD_SHIFT;
827*0eb090a7SSaurabh Misra l1->atge_l1_tx_prod_cons =
828*0eb090a7SSaurabh Misra (ATGE_GET32(l1->atge_l1_cmb, &cmb->tx_prod_cons) &
829*0eb090a7SSaurabh Misra TPD_CONS_MASK) >> TPD_CONS_SHIFT;
830*0eb090a7SSaurabh Misra
831*0eb090a7SSaurabh Misra ATGE_DB(("%s: %s() atge_l1_intr_status : %x, "
832*0eb090a7SSaurabh Misra "atge_l1_rx_prod_cons : %d, atge_l1_tx_prod_cons : %d"
833*0eb090a7SSaurabh Misra " atge_l1_rr_consumers : %d",
834*0eb090a7SSaurabh Misra atgep->atge_name, __func__, l1->atge_l1_intr_status,
835*0eb090a7SSaurabh Misra l1->atge_l1_rx_prod_cons, l1->atge_l1_tx_prod_cons,
836*0eb090a7SSaurabh Misra l1->atge_l1_rr_consumers));
837*0eb090a7SSaurabh Misra
838*0eb090a7SSaurabh Misra /*
839*0eb090a7SSaurabh Misra * Inform the hardware that CMB was served.
840*0eb090a7SSaurabh Misra */
841*0eb090a7SSaurabh Misra cmb->intr_status = 0;
842*0eb090a7SSaurabh Misra DMA_SYNC(l1->atge_l1_cmb, 0, L1_CMB_BLOCK_SZ,
843*0eb090a7SSaurabh Misra DDI_DMA_SYNC_FORDEV);
844*0eb090a7SSaurabh Misra
845*0eb090a7SSaurabh Misra /*
846*0eb090a7SSaurabh Misra * We must check for RX Overflow condition and restart the
847*0eb090a7SSaurabh Misra * chip. This needs to be done only when producer and consumer
848*0eb090a7SSaurabh Misra * counters are same for the RR ring (Return RX).
849*0eb090a7SSaurabh Misra */
850*0eb090a7SSaurabh Misra if ((l1->atge_l1_intr_status & (INTR_CMB_RX | INTR_MAC_RX)) &&
851*0eb090a7SSaurabh Misra (l1->atge_l1_intr_status &
852*0eb090a7SSaurabh Misra (INTR_RX_FIFO_OFLOW | INTR_RRD_OFLOW) &&
853*0eb090a7SSaurabh Misra (l1->atge_l1_rr_consumers == l1->atge_l1_rx_prod_cons))) {
854*0eb090a7SSaurabh Misra
855*0eb090a7SSaurabh Misra ATGE_DB(("%s: %s() RX OVERFLOW :"
856*0eb090a7SSaurabh Misra " atge_l1_rx_prod_cons : %d,"
857*0eb090a7SSaurabh Misra " l1->atge_l1_rr_consumers : %d",
858*0eb090a7SSaurabh Misra atgep->atge_name, __func__,
859*0eb090a7SSaurabh Misra l1->atge_l1_rx_prod_cons,
860*0eb090a7SSaurabh Misra l1->atge_l1_rr_consumers));
861*0eb090a7SSaurabh Misra
862*0eb090a7SSaurabh Misra mutex_enter(&atgep->atge_tx_lock);
863*0eb090a7SSaurabh Misra atge_device_restart(atgep);
864*0eb090a7SSaurabh Misra mutex_exit(&atgep->atge_tx_lock);
865*0eb090a7SSaurabh Misra goto done;
866*0eb090a7SSaurabh Misra }
867*0eb090a7SSaurabh Misra
868*0eb090a7SSaurabh Misra rx_head = atge_l1_rx(atgep);
869*0eb090a7SSaurabh Misra
870*0eb090a7SSaurabh Misra if (l1->atge_l1_intr_status & INTR_SMB)
871*0eb090a7SSaurabh Misra atge_l1_gather_stats(atgep);
872*0eb090a7SSaurabh Misra
873*0eb090a7SSaurabh Misra if (l1->atge_l1_intr_status & (INTR_CMB_TX | INTR_MAC_TX)) {
874*0eb090a7SSaurabh Misra mutex_enter(&atgep->atge_tx_lock);
875*0eb090a7SSaurabh Misra atge_tx_reclaim(atgep, l1->atge_l1_tx_prod_cons);
876*0eb090a7SSaurabh Misra if (atgep->atge_tx_resched) {
877*0eb090a7SSaurabh Misra atgep->atge_tx_resched = 0;
878*0eb090a7SSaurabh Misra resched = 1;
879*0eb090a7SSaurabh Misra }
880*0eb090a7SSaurabh Misra
881*0eb090a7SSaurabh Misra mutex_exit(&atgep->atge_tx_lock);
882*0eb090a7SSaurabh Misra }
883*0eb090a7SSaurabh Misra
884*0eb090a7SSaurabh Misra if ((status & (INTR_DMA_RD_TO_RST | INTR_DMA_WR_TO_RST)) != 0) {
885*0eb090a7SSaurabh Misra atge_error(atgep->atge_dip,
886*0eb090a7SSaurabh Misra "DMA transfer error");
887*0eb090a7SSaurabh Misra
888*0eb090a7SSaurabh Misra ATGE_DB(("%s: %s() DMA transfer error",
889*0eb090a7SSaurabh Misra atgep->atge_name, __func__));
890*0eb090a7SSaurabh Misra
891*0eb090a7SSaurabh Misra atge_device_stop(atgep);
892*0eb090a7SSaurabh Misra goto done;
893*0eb090a7SSaurabh Misra }
894*0eb090a7SSaurabh Misra }
895*0eb090a7SSaurabh Misra
896*0eb090a7SSaurabh Misra done:
897*0eb090a7SSaurabh Misra
898*0eb090a7SSaurabh Misra OUTL(atgep, ATGE_INTR_STATUS, INTR_DIS_DMA | INTR_DIS_SM);
899*0eb090a7SSaurabh Misra mutex_exit(&atgep->atge_intr_lock);
900*0eb090a7SSaurabh Misra
901*0eb090a7SSaurabh Misra if (status & INTR_GPHY || atgep->atge_flags & ATGE_MII_CHECK) {
902*0eb090a7SSaurabh Misra ATGE_DB(("%s: %s() MII_CHECK Requested",
903*0eb090a7SSaurabh Misra atgep->atge_name, __func__));
904*0eb090a7SSaurabh Misra
905*0eb090a7SSaurabh Misra if (status & INTR_GPHY) {
906*0eb090a7SSaurabh Misra (void) atge_mii_read(atgep,
907*0eb090a7SSaurabh Misra atgep->atge_phyaddr, ATGE_ISR_ACK_GPHY);
908*0eb090a7SSaurabh Misra }
909*0eb090a7SSaurabh Misra
910*0eb090a7SSaurabh Misra atgep->atge_flags &= ~ATGE_MII_CHECK;
911*0eb090a7SSaurabh Misra mii_reset(atgep->atge_mii);
912*0eb090a7SSaurabh Misra }
913*0eb090a7SSaurabh Misra
914*0eb090a7SSaurabh Misra /*
915*0eb090a7SSaurabh Misra * Pass the list of packets received from chip to MAC layer.
916*0eb090a7SSaurabh Misra */
917*0eb090a7SSaurabh Misra if (rx_head) {
918*0eb090a7SSaurabh Misra mac_rx(atgep->atge_mh, 0, rx_head);
919*0eb090a7SSaurabh Misra }
920*0eb090a7SSaurabh Misra
921*0eb090a7SSaurabh Misra if (rx_head1) {
922*0eb090a7SSaurabh Misra mac_rx(atgep->atge_mh, 0, rx_head1);
923*0eb090a7SSaurabh Misra }
924*0eb090a7SSaurabh Misra
925*0eb090a7SSaurabh Misra /*
926*0eb090a7SSaurabh Misra * Let MAC start sending pkts if the downstream was asked to pause.
927*0eb090a7SSaurabh Misra */
928*0eb090a7SSaurabh Misra if (resched)
929*0eb090a7SSaurabh Misra mac_tx_update(atgep->atge_mh);
930*0eb090a7SSaurabh Misra
931*0eb090a7SSaurabh Misra return (DDI_INTR_CLAIMED);
932*0eb090a7SSaurabh Misra }
933*0eb090a7SSaurabh Misra
934*0eb090a7SSaurabh Misra void
atge_l1_send_packet(atge_ring_t * r)935*0eb090a7SSaurabh Misra atge_l1_send_packet(atge_ring_t *r)
936*0eb090a7SSaurabh Misra {
937*0eb090a7SSaurabh Misra atge_l1_sync_mbox(r->r_atge);
938*0eb090a7SSaurabh Misra }
939