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