comparison usr/src/uts/common/io/atge/atge_l1c.c @ 13768:ed21ea5d20cf

212 Atheros AR8132 / L1c Gigabit Ethernet Adapter Reviewed by: Garrett D'Amore <garrett@damore.org> Reviewed by: Milan Jurik <milan.jurik@xylab.cz> Approved by: Dan McDonald <danmcd@nexenta.com>
author Gary Mills <gary_mills@fastmail.fm>
date Fri, 10 Aug 2012 10:52:49 -0400
parents
children
comparison
equal deleted inserted replaced
13767:8c906b14afbd 13768:ed21ea5d20cf
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 (c) 2012 Gary Mills
24 *
25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
27 */
28 /*
29 * Copyright (c) 2009, Pyun YongHyeon <yongari@FreeBSD.org>
30 * All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice unmodified, this list of conditions, and the following
37 * disclaimer.
38 * 2. Redistributions in binary form must reproduce the above copyright
39 * notice, this list of conditions and the following disclaimer in the
40 * documentation and/or other materials provided with the distribution.
41 *
42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * SUCH DAMAGE.
53 */
54
55 #include <sys/types.h>
56 #include <sys/stream.h>
57 #include <sys/strsun.h>
58 #include <sys/stat.h>
59 #include <sys/modctl.h>
60 #include <sys/ethernet.h>
61 #include <sys/debug.h>
62 #include <sys/conf.h>
63 #include <sys/mii.h>
64 #include <sys/miiregs.h>
65 #include <sys/sysmacros.h>
66 #include <sys/dditypes.h>
67 #include <sys/ddi.h>
68 #include <sys/sunddi.h>
69 #include <sys/byteorder.h>
70 #include <sys/note.h>
71 #include <sys/vlan.h>
72 #include <sys/stream.h>
73
74 #include "atge.h"
75 #include "atge_l1c_reg.h"
76 #include "atge_cmn_reg.h"
77
78 static ddi_dma_attr_t atge_l1c_dma_attr_tx_desc = {
79 DMA_ATTR_V0, /* dma_attr_version */
80 0, /* dma_attr_addr_lo */
81 0x0000ffffffffull, /* dma_attr_addr_hi */
82 0x0000ffffffffull, /* dma_attr_count_max */
83 L1C_TX_RING_ALIGN, /* dma_attr_align */
84 0x0000fffc, /* dma_attr_burstsizes */
85 1, /* dma_attr_minxfer */
86 0x0000ffffffffull, /* dma_attr_maxxfer */
87 0x0000ffffffffull, /* dma_attr_seg */
88 1, /* dma_attr_sgllen */
89 1, /* dma_attr_granular */
90 0 /* dma_attr_flags */
91 };
92
93 static ddi_dma_attr_t atge_l1c_dma_attr_rx_desc = {
94 DMA_ATTR_V0, /* dma_attr_version */
95 0, /* dma_attr_addr_lo */
96 0x0000ffffffffull, /* dma_attr_addr_hi */
97 0x0000ffffffffull, /* dma_attr_count_max */
98 L1C_RX_RING_ALIGN, /* dma_attr_align */
99 0x0000fffc, /* dma_attr_burstsizes */
100 1, /* dma_attr_minxfer */
101 0x0000ffffffffull, /* dma_attr_maxxfer */
102 0x0000ffffffffull, /* dma_attr_seg */
103 1, /* dma_attr_sgllen */
104 1, /* dma_attr_granular */
105 0 /* dma_attr_flags */
106 };
107
108 static ddi_dma_attr_t atge_l1c_dma_attr_cmb = {
109 DMA_ATTR_V0, /* dma_attr_version */
110 0, /* dma_attr_addr_lo */
111 0x0000ffffffffull, /* dma_attr_addr_hi */
112 0x0000ffffffffull, /* dma_attr_count_max */
113 L1C_CMB_ALIGN, /* dma_attr_align */
114 0x0000fffc, /* dma_attr_burstsizes */
115 1, /* dma_attr_minxfer */
116 0x0000ffffffffull, /* dma_attr_maxxfer */
117 0x0000ffffffffull, /* dma_attr_seg */
118 1, /* dma_attr_sgllen */
119 1, /* dma_attr_granular */
120 0 /* dma_attr_flags */
121 };
122
123 static ddi_dma_attr_t atge_l1c_dma_attr_smb = {
124 DMA_ATTR_V0, /* dma_attr_version */
125 0, /* dma_attr_addr_lo */
126 0x0000ffffffffull, /* dma_attr_addr_hi */
127 0x0000ffffffffull, /* dma_attr_count_max */
128 L1C_SMB_ALIGN, /* dma_attr_align */
129 0x0000fffc, /* dma_attr_burstsizes */
130 1, /* dma_attr_minxfer */
131 0x0000ffffffffull, /* dma_attr_maxxfer */
132 0x0000ffffffffull, /* dma_attr_seg */
133 1, /* dma_attr_sgllen */
134 1, /* dma_attr_granular */
135 0 /* dma_attr_flags */
136 };
137
138 static ddi_dma_attr_t atge_l1c_dma_attr_rr = {
139 DMA_ATTR_V0, /* dma_attr_version */
140 0, /* dma_attr_addr_lo */
141 0x0000ffffffffull, /* dma_attr_addr_hi */
142 0x0000ffffffffull, /* dma_attr_count_max */
143 L1C_RR_RING_ALIGN, /* dma_attr_align */
144 0x0000fffc, /* dma_attr_burstsizes */
145 1, /* dma_attr_minxfer */
146 0x0000ffffffffull, /* dma_attr_maxxfer */
147 0x0000ffffffffull, /* dma_attr_seg */
148 1, /* dma_attr_sgllen */
149 1, /* dma_attr_granular */
150 0 /* dma_attr_flags */
151 };
152
153 int
154 atge_l1c_alloc_dma(atge_t *atgep)
155 {
156 atge_l1c_data_t *l1c;
157 atge_dma_t *dma;
158 int err;
159
160 l1c = kmem_zalloc(sizeof (atge_l1c_data_t), KM_SLEEP);
161 atgep->atge_private_data = l1c;
162
163 /*
164 * Allocate TX ring descriptor.
165 */
166 atgep->atge_tx_buf_len = atgep->atge_mtu +
167 sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL;
168 atgep->atge_tx_ring = kmem_alloc(sizeof (atge_ring_t), KM_SLEEP);
169 atgep->atge_tx_ring->r_atge = atgep;
170 atgep->atge_tx_ring->r_desc_ring = NULL;
171 dma = atge_alloc_a_dma_blk(atgep, &atge_l1c_dma_attr_tx_desc,
172 ATGE_TX_RING_SZ, DDI_DMA_RDWR);
173 if (dma == NULL) {
174 atge_error(atgep->atge_dip, "DMA allocation failed for TX"
175 " desc ring");
176 return (DDI_FAILURE);
177 }
178 atgep->atge_tx_ring->r_desc_ring = dma;
179
180 /*
181 * Allocate DMA buffers for TX ring.
182 */
183 err = atge_alloc_buffers(atgep->atge_tx_ring, ATGE_TX_RING_CNT,
184 atgep->atge_tx_buf_len, DDI_DMA_WRITE);
185 if (err != DDI_SUCCESS) {
186 atge_error(atgep->atge_dip, "DMA allocation failed for"
187 " TX Ring");
188 return (err);
189 }
190
191 /*
192 * Allocate RX ring.
193 */
194 atgep->atge_rx_buf_len = atgep->atge_mtu +
195 sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL;
196 l1c->atge_rx_ring = kmem_alloc(sizeof (atge_ring_t), KM_SLEEP);
197 l1c->atge_rx_ring->r_atge = atgep;
198 l1c->atge_rx_ring->r_desc_ring = NULL;
199 dma = atge_alloc_a_dma_blk(atgep, &atge_l1c_dma_attr_rx_desc,
200 L1C_RX_RING_SZ, DDI_DMA_RDWR);
201 if (dma == NULL) {
202 atge_error(atgep->atge_dip, "DMA allocation failed"
203 " for RX Ring");
204 return (DDI_FAILURE);
205 }
206 l1c->atge_rx_ring->r_desc_ring = dma;
207
208 /*
209 * Allocate DMA buffers for RX ring.
210 */
211 err = atge_alloc_buffers(l1c->atge_rx_ring, L1C_RX_RING_CNT,
212 atgep->atge_rx_buf_len, DDI_DMA_READ);
213 if (err != DDI_SUCCESS) {
214 atge_error(atgep->atge_dip, "DMA allocation failed for"
215 " RX buffers");
216 return (err);
217 }
218
219 /*
220 * Allocate CMB used for fetching interrupt status data.
221 */
222 ATGE_DB(("%s: %s() L1C_CMB_BLOCK_SZ : 0x%x", atgep->atge_name,
223 __func__, L1C_CMB_BLOCK_SZ));
224
225 dma = atge_alloc_a_dma_blk(atgep, &atge_l1c_dma_attr_cmb,
226 L1C_CMB_BLOCK_SZ, DDI_DMA_RDWR);
227 l1c->atge_l1c_cmb = dma;
228 if (dma == NULL) {
229 atge_error(atgep->atge_dip, "DMA allocation failed for CMB");
230 return (DDI_FAILURE);
231 }
232
233 /*
234 * RR ring (Return Ring for RX and TX).
235 */
236 ATGE_DB(("%s: %s() L1C_RR_RING_SZ : 0x%x", atgep->atge_name,
237 __func__, L1C_RR_RING_SZ));
238
239 dma = atge_alloc_a_dma_blk(atgep, &atge_l1c_dma_attr_rr,
240 L1C_RR_RING_SZ, DDI_DMA_RDWR);
241 l1c->atge_l1c_rr = dma;
242 if (dma == NULL) {
243 atge_error(atgep->atge_dip, "DMA allocation failed"
244 " for RX RR ring");
245 return (DDI_FAILURE);
246 }
247
248 /*
249 * SMB for statistics.
250 */
251 ATGE_DB(("%s: %s() L1C_SMB_BLOCK_SZ : 0x%x", atgep->atge_name,
252 __func__, L1C_SMB_BLOCK_SZ));
253
254 dma = atge_alloc_a_dma_blk(atgep, &atge_l1c_dma_attr_smb,
255 L1C_SMB_BLOCK_SZ, DDI_DMA_RDWR);
256 l1c->atge_l1c_smb = dma;
257 if (dma == NULL) {
258 atge_error(atgep->atge_dip, "DMA allocation failed for SMB");
259 return (DDI_FAILURE);
260 }
261
262 atgep->atge_hw_stats = kmem_zalloc(sizeof (atge_l1c_smb_t), KM_SLEEP);
263
264 return (DDI_SUCCESS);
265 }
266
267 void
268 atge_l1c_free_dma(atge_t *atgep)
269 {
270 atge_l1c_data_t *l1c;
271
272 l1c = atgep->atge_private_data;
273
274 /*
275 * Free TX ring.
276 */
277 if (atgep->atge_tx_ring != NULL) {
278 atge_free_buffers(atgep->atge_tx_ring, ATGE_TX_RING_CNT);
279
280 if (atgep->atge_tx_ring->r_desc_ring != NULL) {
281 atge_free_a_dma_blk(atgep->atge_tx_ring->r_desc_ring);
282 }
283
284 kmem_free(atgep->atge_tx_ring, sizeof (atge_ring_t));
285 atgep->atge_tx_ring = NULL;
286 }
287
288 if (l1c && l1c->atge_l1c_cmb != NULL) {
289 atge_free_a_dma_blk(l1c->atge_l1c_cmb);
290 l1c->atge_l1c_cmb = NULL;
291 }
292
293 if (l1c && l1c->atge_l1c_rr != NULL) {
294 atge_free_a_dma_blk(l1c->atge_l1c_rr);
295 l1c->atge_l1c_rr = NULL;
296 }
297
298 if (l1c && l1c->atge_l1c_smb != NULL) {
299 atge_free_a_dma_blk(l1c->atge_l1c_smb);
300 l1c->atge_l1c_smb = NULL;
301 }
302
303 /*
304 * Free RX ring.
305 */
306 if (l1c && l1c->atge_rx_ring != NULL) {
307 atge_free_buffers(l1c->atge_rx_ring, L1C_RX_RING_CNT);
308
309 if (l1c->atge_rx_ring->r_desc_ring != NULL) {
310 atge_free_a_dma_blk(l1c->atge_rx_ring->r_desc_ring);
311 }
312
313 kmem_free(l1c->atge_rx_ring, sizeof (atge_ring_t));
314 l1c->atge_rx_ring = NULL;
315 }
316
317 /*
318 * Free the memory allocated for gathering hw stats.
319 */
320 if (atgep->atge_hw_stats != NULL) {
321 kmem_free(atgep->atge_hw_stats, sizeof (atge_l1c_smb_t));
322 atgep->atge_hw_stats = NULL;
323 }
324
325 /*
326 * Free the private area.
327 */
328 if (l1c != NULL) {
329 kmem_free(l1c, sizeof (atge_l1c_data_t));
330 atgep->atge_private_data = NULL;
331 }
332 }
333
334 void
335 atge_l1c_init_rx_ring(atge_t *atgep)
336 {
337 atge_l1c_data_t *l1c;
338 atge_dma_t *dma;
339 l1c_rx_desc_t *rx;
340 int i;
341
342 l1c = atgep->atge_private_data;
343 l1c->atge_rx_ring->r_consumer = L1C_RX_RING_CNT - 1;
344 dma = l1c->atge_rx_ring->r_desc_ring;
345 bzero(dma->addr, L1C_RX_RING_SZ);
346
347 for (i = 0; i < L1C_RX_RING_CNT; i++) {
348 rx = (l1c_rx_desc_t *)(dma->addr +
349 (i * sizeof (l1c_rx_desc_t)));
350
351 ATGE_PUT64(dma, &rx->addr,
352 l1c->atge_rx_ring->r_buf_tbl[i]->cookie.dmac_laddress);
353 /* No length field. */
354 }
355
356 DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORDEV);
357 /* Let controller know availability of new Rx buffers. */
358 OUTL(atgep, ATGE_MBOX_RD0_PROD_IDX, l1c->atge_rx_ring->r_consumer);
359 }
360
361 void
362 atge_l1c_init_tx_ring(atge_t *atgep)
363 {
364 atgep->atge_tx_ring->r_producer = 0;
365 atgep->atge_tx_ring->r_consumer = 0;
366 atgep->atge_tx_ring->r_avail_desc = ATGE_TX_RING_CNT;
367
368 bzero(atgep->atge_tx_ring->r_desc_ring->addr, ATGE_TX_RING_SZ);
369 DMA_SYNC(atgep->atge_tx_ring->r_desc_ring, 0, 0, DDI_DMA_SYNC_FORDEV);
370 }
371
372 void
373 atge_l1c_init_rr_ring(atge_t *atgep)
374 {
375 atge_l1c_data_t *l1c;
376 atge_dma_t *dma;
377
378 l1c = atgep->atge_private_data;
379 l1c->atge_l1c_rr_consumers = 0;
380
381 dma = l1c->atge_l1c_rr;
382 bzero(dma->addr, L1C_RR_RING_SZ);
383 DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORDEV);
384 }
385
386 void
387 atge_l1c_init_smb(atge_t *atgep)
388 {
389 atge_l1c_data_t *l1c;
390 atge_dma_t *dma;
391
392 l1c = atgep->atge_private_data;
393 dma = l1c->atge_l1c_smb;
394 bzero(dma->addr, L1C_SMB_BLOCK_SZ);
395 DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORDEV);
396 }
397
398 void
399 atge_l1c_init_cmb(atge_t *atgep)
400 {
401 atge_l1c_data_t *l1c;
402 atge_dma_t *dma;
403
404 l1c = atgep->atge_private_data;
405 dma = l1c->atge_l1c_cmb;
406 bzero(dma->addr, L1C_CMB_BLOCK_SZ);
407 DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORDEV);
408 }
409
410 void
411 atge_l1c_program_dma(atge_t *atgep)
412 {
413 atge_l1c_data_t *l1c;
414 atge_ring_t *r;
415 uint32_t reg;
416
417 l1c = atgep->atge_private_data;
418
419 /*
420 * Clear WOL status and disable all WOL feature as WOL
421 * would interfere Rx operation under normal environments.
422 */
423 (void) INL(atgep, ATGE_WOL_CFG);
424 OUTL(atgep, ATGE_WOL_CFG, 0);
425
426 /* TX */
427 r = atgep->atge_tx_ring;
428 OUTL(atgep, L1C_TX_BASE_ADDR_HI,
429 ATGE_ADDR_HI(r->r_desc_ring->cookie.dmac_laddress));
430 OUTL(atgep, L1C_TDL_HEAD_ADDR_LO,
431 ATGE_ADDR_LO(r->r_desc_ring->cookie.dmac_laddress));
432 /* We don't use high priority ring. */
433 OUTL(atgep, L1C_TDH_HEAD_ADDR_LO, 0);
434
435 /* RX */
436 r = l1c->atge_rx_ring;
437 OUTL(atgep, L1C_RX_BASE_ADDR_HI,
438 ATGE_ADDR_HI(r->r_desc_ring->cookie.dmac_laddress));
439 OUTL(atgep, L1C_RD0_HEAD_ADDR_LO,
440 ATGE_ADDR_LO(r->r_desc_ring->cookie.dmac_laddress));
441 /* We use one Rx ring. */
442 OUTL(atgep, L1C_RD1_HEAD_ADDR_LO, 0);
443 OUTL(atgep, L1C_RD2_HEAD_ADDR_LO, 0);
444 OUTL(atgep, L1C_RD3_HEAD_ADDR_LO, 0);
445
446 /* RR Ring */
447 /*
448 * Let hardware split jumbo frames into alc_max_buf_sized chunks.
449 * if it do not fit the buffer size. Rx return descriptor holds
450 * a counter that indicates how many fragments were made by the
451 * hardware. The buffer size should be multiple of 8 bytes.
452 * Since hardware has limit on the size of buffer size, always
453 * use the maximum value.
454 * For strict-alignment architectures make sure to reduce buffer
455 * size by 8 bytes to make room for alignment fixup.
456 */
457 OUTL(atgep, L1C_RX_BUF_SIZE, RX_BUF_SIZE_MAX); /* XXX */
458
459 /* Set Rx return descriptor base addresses. */
460 OUTL(atgep, L1C_RRD0_HEAD_ADDR_LO,
461 ATGE_ADDR_LO(l1c->atge_l1c_rr->cookie.dmac_laddress));
462 /* We use one Rx return ring. */
463 OUTL(atgep, L1C_RRD1_HEAD_ADDR_LO, 0);
464 OUTL(atgep, L1C_RRD2_HEAD_ADDR_LO, 0);
465 OUTL(atgep, L1C_RRD3_HEAD_ADDR_LO, 0);
466
467 /* CMB */
468 OUTL(atgep, L1C_CMB_BASE_ADDR_LO,
469 ATGE_ADDR_LO(l1c->atge_l1c_cmb->cookie.dmac_laddress));
470
471 /* SMB */
472 OUTL(atgep, L1C_SMB_BASE_ADDR_HI,
473 ATGE_ADDR_HI(l1c->atge_l1c_smb->cookie.dmac_laddress));
474 OUTL(atgep, L1C_SMB_BASE_ADDR_LO,
475 ATGE_ADDR_LO(l1c->atge_l1c_smb->cookie.dmac_laddress));
476
477 /*
478 * Set RX return ring (RR) counter.
479 */
480 /* Set Rx descriptor counter. */
481 OUTL(atgep, L1C_RD_RING_CNT,
482 (L1C_RX_RING_CNT << RD_RING_CNT_SHIFT) & RD_RING_CNT_MASK);
483 /* Set Rx return descriptor counter. */
484 OUTL(atgep, L1C_RRD_RING_CNT,
485 (L1C_RR_RING_CNT << RRD_RING_CNT_SHIFT) & RRD_RING_CNT_MASK);
486
487 /*
488 * Set TX descriptor counter.
489 */
490 OUTL(atgep, L1C_TD_RING_CNT,
491 (ATGE_TX_RING_CNT << TD_RING_CNT_SHIFT) & TD_RING_CNT_MASK);
492
493 switch (ATGE_DID(atgep)) {
494 case ATGE_CHIP_AR8152V1_DEV_ID:
495 /* Reconfigure SRAM - Vendor magic. */
496 OUTL(atgep, L1C_SRAM_RX_FIFO_LEN, 0x000002A0);
497 OUTL(atgep, L1C_SRAM_TX_FIFO_LEN, 0x00000100);
498 OUTL(atgep, L1C_SRAM_RX_FIFO_ADDR, 0x029F0000);
499 OUTL(atgep, L1C_SRAM_RD_ADDR, 0x02BF02A0);
500 OUTL(atgep, L1C_SRAM_TX_FIFO_ADDR, 0x03BF02C0);
501 OUTL(atgep, L1C_SRAM_TRD_ADDR, 0x03DF03C0);
502 OUTL(atgep, L1C_TXF_WATER_MARK, 0x00000000);
503 OUTL(atgep, L1C_RD_DMA_CFG, 0x00000000);
504 break;
505 }
506
507 /*
508 * Inform hardware that we have loaded DMA registers.
509 */
510 OUTL(atgep, ATGE_DMA_BLOCK, DMA_BLOCK_LOAD);
511
512 /* Configure interrupt moderation timer. */
513 reg = ATGE_USECS(atgep->atge_int_rx_mod) << IM_TIMER_RX_SHIFT;
514 reg |= ATGE_USECS(atgep->atge_int_tx_mod) << IM_TIMER_TX_SHIFT;
515 OUTL(atgep, ATGE_IM_TIMER, reg);
516 /*
517 * We don't want to automatic interrupt clear as task queue
518 * for the interrupt should know interrupt status.
519 */
520 reg = 0;
521 if (ATGE_USECS(atgep->atge_int_rx_mod) != 0)
522 reg |= MASTER_IM_RX_TIMER_ENB;
523 if (ATGE_USECS(atgep->atge_int_tx_mod) != 0)
524 reg |= MASTER_IM_TX_TIMER_ENB;
525 OUTL(atgep, ATGE_MASTER_CFG, reg);
526 }
527
528 void
529 atge_l1c_clear_stats(atge_t *atgep)
530 {
531 atge_l1c_smb_t smb;
532 uint32_t *reg;
533 int i;
534
535 /*
536 * Clear RX stats first.
537 */
538 i = 0;
539 reg = &smb.rx_frames;
540 while (reg++ <= &smb.rx_pkts_filtered) {
541 (void) INL(atgep, ATGE_RX_MIB_BASE + i);
542 i += sizeof (uint32_t);
543 }
544
545 /*
546 * Clear TX stats.
547 */
548 i = 0;
549 reg = &smb.tx_frames;
550 while (reg++ <= &smb.tx_mcast_bytes) {
551 (void) INL(atgep, ATGE_TX_MIB_BASE + i);
552 i += sizeof (uint32_t);
553 }
554 }
555
556 void
557 atge_l1c_gather_stats(atge_t *atgep)
558 {
559 atge_l1c_data_t *l1c;
560 atge_dma_t *dma;
561 atge_l1c_smb_t *stat;
562 atge_l1c_smb_t *smb;
563
564 ASSERT(atgep != NULL);
565
566 l1c = atgep->atge_private_data;
567 dma = l1c->atge_l1c_smb;
568 DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORKERNEL);
569 stat = (atge_l1c_smb_t *)atgep->atge_hw_stats;
570 smb = (atge_l1c_smb_t *)dma->addr;
571
572 /* Rx stats. */
573 stat->rx_frames += smb->rx_frames;
574 stat->rx_bcast_frames += smb->rx_bcast_frames;
575 stat->rx_mcast_frames += smb->rx_mcast_frames;
576 stat->rx_pause_frames += smb->rx_pause_frames;
577 stat->rx_control_frames += smb->rx_control_frames;
578 stat->rx_crcerrs += smb->rx_crcerrs;
579 stat->rx_lenerrs += smb->rx_lenerrs;
580 stat->rx_bytes += smb->rx_bytes;
581 stat->rx_runts += smb->rx_runts;
582 stat->rx_fragments += smb->rx_fragments;
583 stat->rx_pkts_64 += smb->rx_pkts_64;
584 stat->rx_pkts_65_127 += smb->rx_pkts_65_127;
585 stat->rx_pkts_128_255 += smb->rx_pkts_128_255;
586 stat->rx_pkts_256_511 += smb->rx_pkts_256_511;
587 stat->rx_pkts_512_1023 += smb->rx_pkts_512_1023;
588 stat->rx_pkts_1024_1518 += smb->rx_pkts_1024_1518;
589 stat->rx_pkts_1519_max += smb->rx_pkts_1519_max;
590 stat->rx_pkts_truncated += smb->rx_pkts_truncated;
591 stat->rx_fifo_oflows += smb->rx_fifo_oflows;
592 stat->rx_alignerrs += smb->rx_alignerrs;
593 stat->rx_bcast_bytes += smb->rx_bcast_bytes;
594 stat->rx_mcast_bytes += smb->rx_mcast_bytes;
595 stat->rx_pkts_filtered += smb->rx_pkts_filtered;
596
597 /* Tx stats. */
598 stat->tx_frames += smb->tx_frames;
599 stat->tx_bcast_frames += smb->tx_bcast_frames;
600 stat->tx_mcast_frames += smb->tx_mcast_frames;
601 stat->tx_pause_frames += smb->tx_pause_frames;
602 stat->tx_excess_defer += smb->tx_excess_defer;
603 stat->tx_control_frames += smb->tx_control_frames;
604 stat->tx_deferred += smb->tx_deferred;
605 stat->tx_bytes += smb->tx_bytes;
606 stat->tx_pkts_64 += smb->tx_pkts_64;
607 stat->tx_pkts_65_127 += smb->tx_pkts_65_127;
608 stat->tx_pkts_128_255 += smb->tx_pkts_128_255;
609 stat->tx_pkts_256_511 += smb->tx_pkts_256_511;
610 stat->tx_pkts_512_1023 += smb->tx_pkts_512_1023;
611 stat->tx_pkts_1024_1518 += smb->tx_pkts_1024_1518;
612 stat->tx_pkts_1519_max += smb->tx_pkts_1519_max;
613 stat->tx_single_colls += smb->tx_single_colls;
614 stat->tx_multi_colls += smb->tx_multi_colls;
615 stat->tx_late_colls += smb->tx_late_colls;
616 stat->tx_excess_colls += smb->tx_excess_colls;
617 stat->tx_underrun += smb->tx_underrun;
618 stat->tx_desc_underrun += smb->tx_desc_underrun;
619 stat->tx_lenerrs += smb->tx_lenerrs;
620 stat->tx_pkts_truncated += smb->tx_pkts_truncated;
621 stat->tx_bcast_bytes += smb->tx_bcast_bytes;
622 stat->tx_mcast_bytes += smb->tx_mcast_bytes;
623
624 /*
625 * Update global counters in atge_t.
626 */
627 atgep->atge_brdcstrcv += smb->rx_bcast_frames;
628 atgep->atge_multircv += smb->rx_mcast_frames;
629 atgep->atge_multixmt += smb->tx_mcast_frames;
630 atgep->atge_brdcstxmt += smb->tx_bcast_frames;
631
632 atgep->atge_align_errors += smb->rx_alignerrs;
633 atgep->atge_fcs_errors += smb->rx_crcerrs;
634 atgep->atge_defer_xmts += smb->tx_deferred;
635 atgep->atge_first_collisions += smb->tx_single_colls;
636 atgep->atge_multi_collisions += smb->tx_multi_colls * 2;
637 atgep->atge_tx_late_collisions += smb->tx_late_colls;
638 atgep->atge_ex_collisions += smb->tx_excess_colls;
639 atgep->atge_toolong_errors += smb->rx_lenerrs;
640 atgep->atge_overflow += smb->rx_fifo_oflows;
641 atgep->atge_underflow += (smb->tx_underrun + smb->tx_desc_underrun);
642 atgep->atge_runt += smb->rx_runts;
643
644
645 atgep->atge_collisions += smb->tx_single_colls +
646 smb->tx_multi_colls * 2 + smb->tx_late_colls;
647
648 /*
649 * tx_pkts_truncated counter looks suspicious. It constantly
650 * increments with no sign of Tx errors. Hence we don't factor it.
651 */
652 atgep->atge_macxmt_errors += smb->tx_late_colls + smb->tx_underrun;
653
654 atgep->atge_macrcv_errors += smb->rx_crcerrs + smb->rx_lenerrs +
655 smb->rx_runts + smb->rx_pkts_truncated +
656 smb->rx_alignerrs;
657
658 smb->updated = 0;
659 DMA_SYNC(dma, 0, 0, DDI_DMA_SYNC_FORDEV);
660 }
661
662 void
663 atge_l1c_stop_tx_mac(atge_t *atgep)
664 {
665 uint32_t reg;
666 int t;
667
668 ATGE_DB(("%s: %s() called", atgep->atge_name, __func__));
669
670 reg = INL(atgep, ATGE_MAC_CFG);
671 if ((reg & ATGE_CFG_TX_ENB) != 0) {
672 reg &= ~ATGE_CFG_TX_ENB;
673 OUTL(atgep, ATGE_MAC_CFG, reg);
674 }
675
676 /* Stop TX DMA engine. */
677 reg = INL(atgep, ATGE_DMA_CFG);
678 if ((reg & DMA_CFG_RD_ENB) != 0) {
679 reg &= ~DMA_CFG_RD_ENB;
680 OUTL(atgep, ATGE_DMA_CFG, reg);
681 }
682
683 for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
684 if ((INL(atgep, ATGE_IDLE_STATUS) &
685 (IDLE_STATUS_TXMAC | IDLE_STATUS_DMARD)) == 0)
686 break;
687
688 drv_usecwait(10);
689 }
690
691 if (t == 0) {
692 /* This should be an FMA event. */
693 atge_error(atgep->atge_dip, "stopping TX DMA Engine timeout");
694 }
695 }
696
697 void
698 atge_l1c_stop_rx_mac(atge_t *atgep)
699 {
700 uint32_t reg;
701 int t;
702
703 ATGE_DB(("%s: %s() called", atgep->atge_name, __func__));
704
705 reg = INL(atgep, ATGE_MAC_CFG);
706 if ((reg & ATGE_CFG_RX_ENB) != 0) {
707 reg &= ~ATGE_CFG_RX_ENB;
708 OUTL(atgep, ATGE_MAC_CFG, reg);
709 }
710
711 /* Stop RX DMA engine. */
712 reg = INL(atgep, ATGE_DMA_CFG);
713 if ((reg & DMA_CFG_WR_ENB) != 0) {
714 reg &= ~DMA_CFG_WR_ENB;
715 OUTL(atgep, ATGE_DMA_CFG, reg);
716 }
717
718 for (t = ATGE_RESET_TIMEOUT; t > 0; t--) {
719 if ((INL(atgep, ATGE_IDLE_STATUS) &
720 (IDLE_STATUS_RXMAC | IDLE_STATUS_DMAWR)) == 0)
721 break;
722 drv_usecwait(10);
723 }
724
725 if (t == 0) {
726 /* This should be an FMA event. */
727 atge_error(atgep->atge_dip, " stopping RX DMA Engine timeout");
728 }
729 }
730
731 /*
732 * Receives (consumes) packets.
733 */
734 static mblk_t *
735 atge_l1c_rx(atge_t *atgep)
736 {
737 atge_l1c_data_t *l1c;
738 mblk_t *mp = NULL, *rx_head = NULL, *rx_tail = NULL;
739 l1c_rx_rdesc_t *rx_rr;
740 uint32_t rdinfo, status, totlen, pktlen, slotlen;
741 int nsegs, rx_cons = 0, cnt;
742 atge_dma_t *buf;
743 uchar_t *bufp;
744 int sync = 0;
745
746 l1c = atgep->atge_private_data;
747 ASSERT(l1c != NULL);
748
749 DMA_SYNC(l1c->atge_l1c_rr, 0, 0, DDI_DMA_SYNC_FORKERNEL);
750 for (;;) {
751 rx_rr = (l1c_rx_rdesc_t *)(l1c->atge_l1c_rr->addr +
752 (l1c->atge_l1c_rr_consumers * sizeof (l1c_rx_rdesc_t)));
753
754 rdinfo = ATGE_GET32(l1c->atge_l1c_rr, &rx_rr->rdinfo);
755 status = ATGE_GET32(l1c->atge_l1c_rr, &rx_rr->status);
756
757 rx_cons = L1C_RRD_RD_IDX(rdinfo);
758 nsegs = L1C_RRD_RD_CNT(rdinfo);
759 totlen = L1C_RRD_BYTES(status);
760
761 ATGE_DB(("%s: %s() PKT -- rdinfo : 0x%x,"
762 "status : 0x%x, totlen : %d,"
763 " rx_cons : %d, nsegs : %d", atgep->atge_name, __func__,
764 rdinfo, status, totlen, rx_cons, nsegs));
765
766 if ((status & L1C_RRD_VALID) == 0) {
767 break;
768 }
769
770 if ((status & (L1C_RRD_ERR_CRC | L1C_RRD_ERR_ALIGN |
771 L1C_RRD_ERR_TRUNC | L1C_RRD_ERR_RUNT |
772 L1C_RRD_ERR_ICMP | L1C_RRD_ERR_LENGTH)) != 0) {
773 atge_error(atgep->atge_dip, "errored pkt");
774
775 l1c->atge_rx_ring->r_consumer += nsegs;
776 l1c->atge_rx_ring->r_consumer %= L1C_RX_RING_CNT;
777 break;
778 }
779
780 ASSERT(rx_cons >= 0 && rx_cons <= L1C_RX_RING_CNT);
781
782 mp = allocb(totlen + L1C_HEADROOM, BPRI_MED);
783 if (mp != NULL) {
784 mp->b_rptr += L1C_HEADROOM;
785 bufp = mp->b_rptr;
786 mp->b_wptr = bufp + totlen;
787 mp->b_next = NULL;
788
789 atgep->atge_ipackets++;
790 atgep->atge_rbytes += totlen;
791
792 /*
793 * If there are more than one segments, then the first
794 * segment should be of size MTU. We couldn't verify
795 * this as our driver does not support changing MTU
796 * or Jumbo Frames.
797 */
798 if (nsegs > 1) {
799 slotlen = atgep->atge_mtu;
800 } else {
801 slotlen = totlen;
802 }
803 } else {
804 ATGE_DB(("%s: %s() PKT mp == NULL totlen : %d",
805 atgep->atge_name, __func__, totlen));
806
807 if (slotlen > atgep->atge_rx_buf_len) {
808 atgep->atge_toolong_errors++;
809 } else if (mp == NULL) {
810 atgep->atge_norcvbuf++;
811 }
812
813 rx_rr->status = 0;
814 break;
815 }
816
817 for (cnt = 0, pktlen = 0; cnt < nsegs; cnt++) {
818 buf = l1c->atge_rx_ring->r_buf_tbl[rx_cons];
819
820 slotlen = min(atgep->atge_max_frame_size, totlen);
821
822 bcopy(buf->addr, (bufp + pktlen), slotlen);
823 pktlen += slotlen;
824 totlen -= slotlen;
825
826 ATGE_DB(("%s: %s() len : %d, rxcons : %d, pktlen : %d",
827 atgep->atge_name, __func__, slotlen, rx_cons,
828 pktlen));
829
830 ATGE_INC_SLOT(rx_cons, L1C_RX_RING_CNT);
831 }
832
833 if (rx_tail == NULL) {
834 rx_head = rx_tail = mp;
835 } else {
836 rx_tail->b_next = mp;
837 rx_tail = mp;
838 }
839
840 if (cnt != nsegs) {
841 l1c->atge_rx_ring->r_consumer += nsegs;
842 l1c->atge_rx_ring->r_consumer %= L1C_RX_RING_CNT;
843 } else {
844 l1c->atge_rx_ring->r_consumer = rx_cons;
845 }
846
847 /*
848 * Tell the chip that this RR can be reused.
849 */
850 rx_rr->status = 0;
851
852 ATGE_INC_SLOT(l1c->atge_l1c_rr_consumers, L1C_RR_RING_CNT);
853 sync++;
854 }
855
856 if (sync) {
857 DMA_SYNC(l1c->atge_rx_ring->r_desc_ring, 0, 0,
858 DDI_DMA_SYNC_FORDEV);
859
860 DMA_SYNC(l1c->atge_l1c_rr, 0, 0, DDI_DMA_SYNC_FORDEV);
861 /*
862 * Let controller know availability of new Rx buffers.
863 */
864 OUTL(atgep, ATGE_MBOX_RD0_PROD_IDX,
865 l1c->atge_rx_ring->r_consumer);
866
867 ATGE_DB(("%s: %s() PKT Recved -> r_consumer : %d, rx_cons : %d"
868 " atge_l1c_rr_consumers : %d",
869 atgep->atge_name, __func__, l1c->atge_rx_ring->r_consumer,
870 rx_cons, l1c->atge_l1c_rr_consumers));
871 }
872
873
874 return (rx_head);
875 }
876
877 /*
878 * The interrupt handler for L1C chip.
879 */
880 /*ARGSUSED*/
881 uint_t
882 atge_l1c_interrupt(caddr_t arg1, caddr_t arg2)
883 {
884 atge_t *atgep = (void *)arg1;
885 mblk_t *rx_head = NULL;
886 uint32_t status;
887 int resched = 0;
888
889 ASSERT(atgep != NULL);
890
891 mutex_enter(&atgep->atge_intr_lock);
892
893 if (atgep->atge_chip_state & ATGE_CHIP_SUSPENDED) {
894 mutex_exit(&atgep->atge_intr_lock);
895 return (DDI_INTR_UNCLAIMED);
896 }
897
898 status = INL(atgep, ATGE_INTR_STATUS);
899 if (status == 0 || (status & atgep->atge_intrs) == 0) {
900 mutex_exit(&atgep->atge_intr_lock);
901
902 if (atgep->atge_flags & ATGE_FIXED_TYPE)
903 return (DDI_INTR_UNCLAIMED);
904
905 return (DDI_INTR_CLAIMED);
906 }
907
908 ATGE_DB(("%s: %s() entry status : %x",
909 atgep->atge_name, __func__, status));
910
911 /*
912 * Disable interrupts.
913 */
914 if (status & L1C_INTR_GPHY) {
915 /* clear PHY interrupt source before we ack interrupts */
916 (void) atge_mii_read(atgep,
917 atgep->atge_phyaddr, ATGE_ISR_ACK_GPHY);
918 }
919
920 OUTL(atgep, ATGE_INTR_STATUS, status | L1C_INTR_DIS_INT);
921 FLUSH(atgep, ATGE_INTR_STATUS);
922
923 /*
924 * Check if chip is running, only then do the work.
925 */
926 if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) {
927 atge_l1c_data_t *l1c;
928
929 l1c = atgep->atge_private_data;
930
931 ATGE_DB(("%s: %s() atge_l1c_intr_status : %x, "
932 "atge_l1c_rx_prod_cons : %d, atge_l1c_tx_prod_cons : %d"
933 " atge_l1c_rr_consumers : %d",
934 atgep->atge_name, __func__, l1c->atge_l1c_intr_status,
935 l1c->atge_l1c_rx_prod_cons, l1c->atge_l1c_tx_prod_cons,
936 l1c->atge_l1c_rr_consumers));
937
938 if (status & L1C_INTR_SMB)
939 atge_l1c_gather_stats(atgep);
940
941 /*
942 * Check for errors.
943 */
944 if (status & (L1C_INTR_DMA_RD_TO_RST |
945 L1C_INTR_DMA_WR_TO_RST | L1C_INTR_TXQ_TO_RST)) {
946 /* This should be an FMA event. */
947 atge_error(atgep->atge_dip,
948 "L1C chip detected a fatal error, "
949 "interrupt status: %x", status);
950
951 if (status & L1C_INTR_DMA_RD_TO_RST) {
952 atge_error(atgep->atge_dip,
953 "DMA read error");
954 }
955 if (status & L1C_INTR_DMA_WR_TO_RST) {
956 atge_error(atgep->atge_dip,
957 "DMA write error");
958 }
959 if (status & L1C_INTR_TXQ_TO_RST) {
960 atge_error(atgep->atge_dip,
961 "Transmit queue error");
962 }
963
964 /* This should be an FMA event. */
965 atge_device_stop(atgep);
966 /*
967 * Device has failed fatally.
968 * It will not be restarted by the driver.
969 */
970 goto done;
971
972 }
973
974 rx_head = atge_l1c_rx(atgep);
975 if (status & L1C_INTR_TX_PKT) {
976 int cons;
977
978 mutex_enter(&atgep->atge_tx_lock);
979 cons = INL(atgep, ATGE_MBOX_TD_CONS_IDX) >> 16;
980 atge_tx_reclaim(atgep, cons);
981 if (atgep->atge_tx_resched) {
982 atgep->atge_tx_resched = 0;
983 resched = 1;
984 }
985
986 mutex_exit(&atgep->atge_tx_lock);
987 }
988 }
989
990 /* Re-enable interrupts. */
991 OUTL(atgep, ATGE_INTR_STATUS, 0);
992
993 done:
994 mutex_exit(&atgep->atge_intr_lock);
995
996 if (status & L1C_INTR_GPHY) {
997 /* link down */
998 ATGE_DB(("%s: %s() MII_CHECK Performed",
999 atgep->atge_name, __func__));
1000 mii_check(atgep->atge_mii);
1001 }
1002
1003 /*
1004 * Pass the list of packets received from chip to MAC layer.
1005 */
1006 if (rx_head) {
1007 mac_rx(atgep->atge_mh, 0, rx_head);
1008 }
1009
1010 /*
1011 * Let MAC start sending pkts if the downstream was asked to pause.
1012 */
1013 if (resched)
1014 mac_tx_update(atgep->atge_mh);
1015
1016 return (DDI_INTR_CLAIMED);
1017 }
1018
1019 void
1020 atge_l1c_send_packet(atge_ring_t *r)
1021 {
1022 atge_t *atgep;
1023
1024 atgep = r->r_atge;
1025
1026 mutex_enter(&atgep->atge_mbox_lock);
1027 /* Sync descriptors. */
1028 DMA_SYNC(atgep->atge_tx_ring->r_desc_ring, 0, 0, DDI_DMA_SYNC_FORDEV);
1029 /* Kick. Assume we're using normal Tx priority queue. */
1030 OUTL(atgep, ATGE_MBOX_TD_PROD_IDX,
1031 (atgep->atge_tx_ring->r_producer << MBOX_TD_PROD_LO_IDX_SHIFT) &
1032 MBOX_TD_PROD_LO_IDX_MASK);
1033 mutex_exit(&atgep->atge_mbox_lock);
1034 }