Print this page
212 Atheros AR8132 / L1c Gigabit Ethernet Adapter
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/atge/atge_l1e.c
+++ new/usr/src/uts/common/io/atge/atge_l1e.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 + * Copyright (c) 2012 Gary Mills
24 + *
23 25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 26 * Use is subject to license terms.
25 27 */
26 28
27 29 #include <sys/types.h>
28 30 #include <sys/stream.h>
29 31 #include <sys/strsun.h>
30 32 #include <sys/stat.h>
31 33 #include <sys/modctl.h>
32 34 #include <sys/ethernet.h>
33 35 #include <sys/debug.h>
34 36 #include <sys/conf.h>
35 37 #include <sys/mii.h>
36 38 #include <sys/miiregs.h>
37 39 #include <sys/sysmacros.h>
38 40 #include <sys/dditypes.h>
39 41 #include <sys/ddi.h>
40 42 #include <sys/sunddi.h>
41 43 #include <sys/byteorder.h>
42 44 #include <sys/note.h>
43 45 #include <sys/vlan.h>
44 46 #include <sys/stream.h>
45 47
46 48 #include "atge.h"
47 49 #include "atge_l1e_reg.h"
48 50 #include "atge_cmn_reg.h"
49 51
50 52 /*
51 53 * L1E specfic functions.
52 54 */
53 55 void atge_l1e_device_reset(atge_t *);
54 56 void atge_l1e_stop_rx_mac(atge_t *);
55 57 void atge_l1e_stop_tx_mac(atge_t *);
56 58
57 59 static ddi_dma_attr_t atge_l1e_dma_attr_tx_desc = {
58 60 DMA_ATTR_V0, /* dma_attr_version */
59 61 0, /* dma_attr_addr_lo */
60 62 0x0000ffffffffull, /* dma_attr_addr_hi */
61 63 0x0000ffffffffull, /* dma_attr_count_max */
62 64 L1E_TX_RING_ALIGN, /* dma_attr_align */
63 65 0x0000fffc, /* dma_attr_burstsizes */
64 66 1, /* dma_attr_minxfer */
65 67 0x0000ffffffffull, /* dma_attr_maxxfer */
66 68 0x0000ffffffffull, /* dma_attr_seg */
67 69 1, /* dma_attr_sgllen */
68 70 1, /* dma_attr_granular */
69 71 0 /* dma_attr_flags */
70 72 };
71 73
72 74 static ddi_dma_attr_t atge_l1e_dma_attr_rx_desc = {
73 75 DMA_ATTR_V0, /* dma_attr_version */
74 76 0, /* dma_attr_addr_lo */
75 77 0x0000ffffffffull, /* dma_attr_addr_hi */
76 78 0x0000ffffffffull, /* dma_attr_count_max */
77 79 L1E_RX_PAGE_ALIGN, /* dma_attr_align */
78 80 0x0000fffc, /* dma_attr_burstsizes */
79 81 1, /* dma_attr_minxfer */
80 82 0x0000ffffffffull, /* dma_attr_maxxfer */
81 83 0x0000ffffffffull, /* dma_attr_seg */
82 84 1, /* dma_attr_sgllen */
83 85 1, /* dma_attr_granular */
84 86 0 /* dma_attr_flags */
85 87 };
86 88
87 89 static ddi_dma_attr_t atge_l1e_dma_attr_cmb = {
88 90 DMA_ATTR_V0, /* dma_attr_version */
89 91 0, /* dma_attr_addr_lo */
90 92 0x0000ffffffffull, /* dma_attr_addr_hi */
91 93 0x0000ffffffffull, /* dma_attr_count_max */
92 94 L1E_CMB_ALIGN, /* dma_attr_align */
93 95 0x0000fffc, /* dma_attr_burstsizes */
94 96 1, /* dma_attr_minxfer */
95 97 0x0000ffffffffull, /* dma_attr_maxxfer */
96 98 0x0000ffffffffull, /* dma_attr_seg */
97 99 1, /* dma_attr_sgllen */
98 100 1, /* dma_attr_granular */
99 101 0 /* dma_attr_flags */
100 102 };
101 103
102 104 void atge_l1e_rx_next_pkt(atge_t *, uint32_t);
103 105
104 106 void
105 107 atge_rx_desc_free(atge_t *atgep)
106 108 {
107 109 atge_l1e_data_t *l1e;
108 110 atge_dma_t *dma;
109 111 int pages;
110 112
111 113 l1e = (atge_l1e_data_t *)atgep->atge_private_data;
112 114 if (l1e == NULL)
113 115 return;
114 116
115 117 if (l1e->atge_l1e_rx_page == NULL)
116 118 return;
117 119
118 120 for (pages = 0; pages < L1E_RX_PAGES; pages++) {
119 121 dma = l1e->atge_l1e_rx_page[pages];
120 122 if (dma != NULL) {
121 123 (void) ddi_dma_unbind_handle(dma->hdl);
122 124 ddi_dma_mem_free(&dma->acchdl);
123 125 ddi_dma_free_handle(&dma->hdl);
124 126 kmem_free(dma, sizeof (atge_dma_t));
125 127 }
126 128 }
127 129
128 130 kmem_free(l1e->atge_l1e_rx_page, L1E_RX_PAGES * sizeof (atge_dma_t *));
129 131 l1e->atge_l1e_rx_page = NULL;
130 132 }
131 133
132 134 int
133 135 atge_l1e_alloc_dma(atge_t *atgep)
134 136 {
135 137 atge_dma_t *dma;
136 138 atge_l1e_data_t *l1e;
137 139 int err;
138 140 int pages;
139 141 int guard_size;
140 142
141 143 l1e = kmem_zalloc(sizeof (atge_l1e_data_t), KM_SLEEP);
142 144 atgep->atge_private_data = l1e;
143 145
144 146 /*
145 147 * Allocate TX ring descriptor.
146 148 */
147 149 atgep->atge_tx_buf_len = atgep->atge_mtu +
148 150 sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL;
149 151 atgep->atge_tx_ring = kmem_alloc(sizeof (atge_ring_t), KM_SLEEP);
150 152 atgep->atge_tx_ring->r_atge = atgep;
151 153 atgep->atge_tx_ring->r_desc_ring = NULL;
152 154 dma = atge_alloc_a_dma_blk(atgep, &atge_l1e_dma_attr_tx_desc,
153 155 ATGE_TX_RING_SZ, DDI_DMA_RDWR);
154 156 if (dma == NULL) {
155 157 ATGE_DB(("%s :%s failed",
156 158 atgep->atge_name, __func__));
157 159 return (DDI_FAILURE);
158 160 }
159 161 atgep->atge_tx_ring->r_desc_ring = dma;
160 162
161 163 /*
162 164 * Allocate DMA buffers for TX ring.
163 165 */
164 166 err = atge_alloc_buffers(atgep->atge_tx_ring, ATGE_TX_RING_CNT,
165 167 atgep->atge_tx_buf_len, DDI_DMA_WRITE);
166 168 if (err != DDI_SUCCESS) {
167 169 ATGE_DB(("%s :%s() TX buffers failed",
168 170 atgep->atge_name, __func__));
169 171 return (err);
170 172 }
171 173
172 174 /*
173 175 * Allocate RX pages.
174 176 */
175 177 atgep->atge_rx_buf_len = atgep->atge_mtu +
176 178 sizeof (struct ether_header) + VLAN_TAGSZ + ETHERFCSL;
177 179
178 180 if (atgep->atge_flags & ATGE_FLAG_JUMBO)
179 181 guard_size = L1E_JUMBO_FRAMELEN;
180 182 else
181 183 guard_size = L1E_MAX_FRAMELEN;
182 184
183 185 l1e->atge_l1e_pagesize = ROUNDUP(guard_size + L1E_RX_PAGE_SZ,
184 186 L1E_RX_PAGE_ALIGN);
185 187 l1e->atge_l1e_rx_page =
186 188 kmem_zalloc(L1E_RX_PAGES * sizeof (atge_dma_t *), KM_SLEEP);
187 189
188 190 ATGE_DB(("%s: %s() atge_l1e_pagesize : %d, L1E_RX_PAGE_SZ : %d",
189 191 atgep->atge_name, __func__, l1e->atge_l1e_pagesize,
190 192 L1E_RX_PAGE_SZ));
191 193
192 194 err = DDI_SUCCESS;
193 195 for (pages = 0; pages < L1E_RX_PAGES; pages++) {
194 196 dma = atge_alloc_a_dma_blk(atgep, &atge_l1e_dma_attr_rx_desc,
195 197 l1e->atge_l1e_pagesize, DDI_DMA_READ);
196 198
197 199 if (dma == NULL) {
198 200 err = DDI_FAILURE;
199 201 break;
200 202 }
201 203
202 204 l1e->atge_l1e_rx_page[pages] = dma;
203 205 }
204 206
205 207 if (err == DDI_FAILURE) {
206 208 ATGE_DB(("%s :%s RX pages failed",
207 209 atgep->atge_name, __func__));
208 210 return (DDI_FAILURE);
209 211 }
210 212
211 213 /*
212 214 * Allocate CMB used for fetching interrupt status data.
213 215 */
214 216 ATGE_DB(("%s: %s() L1E_RX_CMB_SZ : %x", atgep->atge_name,
215 217 __func__, L1E_RX_CMB_SZ));
216 218
217 219 err = DDI_SUCCESS;
218 220 dma = atge_alloc_a_dma_blk(atgep, &atge_l1e_dma_attr_cmb,
219 221 L1E_RX_CMB_SZ * L1E_RX_PAGES, DDI_DMA_RDWR);
220 222 if (dma == NULL) {
221 223 ATGE_DB(("%s :%s() RX CMB failed",
222 224 atgep->atge_name, __func__));
223 225 return (DDI_FAILURE);
224 226 }
225 227 l1e->atge_l1e_rx_cmb = dma;
226 228
227 229 if (err == DDI_FAILURE) {
228 230 ATGE_DB(("%s :%s() RX CMB failed",
229 231 atgep->atge_name, __func__));
230 232 return (DDI_FAILURE);
231 233 }
232 234
233 235 atgep->atge_hw_stats = kmem_zalloc(sizeof (atge_l1e_smb_t), KM_SLEEP);
234 236
235 237 return (DDI_SUCCESS);
236 238 }
237 239
238 240 void
239 241 atge_l1e_free_dma(atge_t *atgep)
240 242 {
241 243 atge_l1e_data_t *l1e;
242 244
243 245 /*
244 246 * Free TX ring.
245 247 */
246 248 if (atgep->atge_tx_ring != NULL) {
247 249 atge_free_buffers(atgep->atge_tx_ring, ATGE_TX_RING_CNT);
248 250
249 251 if (atgep->atge_tx_ring->r_desc_ring != NULL) {
250 252 atge_free_a_dma_blk(atgep->atge_tx_ring->r_desc_ring);
251 253 }
252 254
253 255 kmem_free(atgep->atge_tx_ring, sizeof (atge_ring_t));
254 256 atgep->atge_tx_ring = NULL;
255 257 }
256 258
257 259 l1e = atgep->atge_private_data;
258 260 if (l1e == NULL)
259 261 return;
260 262
261 263 /*
262 264 * Free RX CMB.
263 265 */
264 266 if (l1e->atge_l1e_rx_cmb != NULL) {
265 267 atge_free_a_dma_blk(l1e->atge_l1e_rx_cmb);
266 268 l1e->atge_l1e_rx_cmb = NULL;
267 269 }
268 270
269 271 /*
270 272 * Free RX buffers and RX ring.
271 273 */
272 274 atge_rx_desc_free(atgep);
273 275
274 276 /*
275 277 * Free the memory allocated for gathering hw stats.
276 278 */
277 279 if (atgep->atge_hw_stats != NULL) {
278 280 kmem_free(atgep->atge_hw_stats, sizeof (atge_l1e_smb_t));
279 281 atgep->atge_hw_stats = NULL;
280 282 }
281 283 }
282 284
283 285 void
284 286 atge_l1e_init_rx_pages(atge_t *atgep)
285 287 {
286 288 atge_l1e_data_t *l1e;
287 289 atge_dma_t *dma;
288 290 int pages;
289 291
290 292 ASSERT(atgep != NULL);
291 293 l1e = atgep->atge_private_data;
292 294
293 295 ASSERT(l1e != NULL);
294 296
295 297 l1e->atge_l1e_proc_max = L1E_RX_PAGE_SZ / ETHERMIN;
296 298 l1e->atge_l1e_rx_curp = 0;
297 299 l1e->atge_l1e_rx_seqno = 0;
298 300
299 301 for (pages = 0; pages < L1E_RX_PAGES; pages++) {
300 302 l1e->atge_l1e_rx_page_cons = 0;
301 303 l1e->atge_l1e_rx_page_prods[pages] = 0;
302 304
303 305
304 306 dma = l1e->atge_l1e_rx_page[pages];
305 307 ASSERT(dma != NULL);
306 308 bzero(dma->addr, l1e->atge_l1e_pagesize);
307 309 DMA_SYNC(dma, 0, l1e->atge_l1e_pagesize, DDI_DMA_SYNC_FORDEV);
308 310 }
309 311
310 312 dma = l1e->atge_l1e_rx_cmb;
311 313 ASSERT(dma != NULL);
312 314 bzero(dma->addr, L1E_RX_CMB_SZ * L1E_RX_PAGES);
313 315 DMA_SYNC(dma, 0, L1E_RX_CMB_SZ * L1E_RX_PAGES, DDI_DMA_SYNC_FORDEV);
314 316 }
315 317
316 318 void
317 319 atge_l1e_init_tx_ring(atge_t *atgep)
318 320 {
319 321 ASSERT(atgep != NULL);
320 322 ASSERT(atgep->atge_tx_ring != NULL);
321 323 ASSERT(atgep->atge_tx_ring->r_desc_ring != NULL);
322 324
323 325 atgep->atge_tx_ring->r_producer = 0;
324 326 atgep->atge_tx_ring->r_consumer = 0;
325 327 atgep->atge_tx_ring->r_avail_desc = ATGE_TX_RING_CNT;
326 328
327 329 bzero(atgep->atge_tx_ring->r_desc_ring->addr, ATGE_TX_RING_SZ);
328 330
329 331 DMA_SYNC(atgep->atge_tx_ring->r_desc_ring, 0, ATGE_TX_RING_SZ,
330 332 DDI_DMA_SYNC_FORDEV);
331 333 }
332 334
333 335 void
334 336 atge_l1e_program_dma(atge_t *atgep)
335 337 {
336 338 atge_l1e_data_t *l1e;
337 339 uint64_t paddr;
338 340 uint32_t reg;
339 341
340 342 l1e = (atge_l1e_data_t *)atgep->atge_private_data;
341 343
342 344 /*
343 345 * Clear WOL status and disable all WOL feature as WOL
344 346 * would interfere Rx operation under normal environments.
345 347 */
346 348 (void) INL(atgep, ATGE_WOL_CFG);
347 349 OUTL(atgep, ATGE_WOL_CFG, 0);
348 350
349 351 /*
350 352 * Set Tx descriptor/RXF0/CMB base addresses. They share
351 353 * the same high address part of DMAable region.
352 354 */
353 355 paddr = atgep->atge_tx_ring->r_desc_ring->cookie.dmac_laddress;
354 356 OUTL(atgep, ATGE_DESC_ADDR_HI, ATGE_ADDR_HI(paddr));
355 357 OUTL(atgep, ATGE_DESC_TPD_ADDR_LO, ATGE_ADDR_LO(paddr));
356 358 OUTL(atgep, ATGE_DESC_TPD_CNT,
357 359 (ATGE_TX_RING_CNT << DESC_TPD_CNT_SHIFT) & DESC_TPD_CNT_MASK);
358 360
359 361 /* Set Rx page base address, note we use single queue. */
360 362 paddr = l1e->atge_l1e_rx_page[0]->cookie.dmac_laddress;
361 363 OUTL(atgep, L1E_RXF0_PAGE0_ADDR_LO, ATGE_ADDR_LO(paddr));
362 364 paddr = l1e->atge_l1e_rx_page[1]->cookie.dmac_laddress;
363 365 OUTL(atgep, L1E_RXF0_PAGE1_ADDR_LO, ATGE_ADDR_LO(paddr));
364 366
365 367 /* Set Tx/Rx CMB addresses. */
366 368 paddr = l1e->atge_l1e_rx_cmb->cookie.dmac_laddress;
367 369 OUTL(atgep, L1E_RXF0_CMB0_ADDR_LO, ATGE_ADDR_LO(paddr));
368 370 paddr = l1e->atge_l1e_rx_cmb->cookie.dmac_laddress + sizeof (uint32_t);
369 371 OUTL(atgep, L1E_RXF0_CMB1_ADDR_LO, ATGE_ADDR_LO(paddr));
370 372
371 373 /* Mark RXF0 valid. */
372 374 OUTB(atgep, L1E_RXF0_PAGE0, RXF_VALID); /* 0 */
373 375 OUTB(atgep, L1E_RXF0_PAGE1, RXF_VALID); /* 1 */
374 376 OUTB(atgep, L1E_RXF0_PAGE0 + 2, 0);
375 377 OUTB(atgep, L1E_RXF0_PAGE0 + 3, 0);
376 378 OUTB(atgep, L1E_RXF0_PAGE0 + 4, 0);
377 379 OUTB(atgep, L1E_RXF0_PAGE0 + 5, 0);
378 380 OUTB(atgep, L1E_RXF0_PAGE0 + 6, 0);
379 381 OUTB(atgep, L1E_RXF0_PAGE0 + 6, 0);
380 382
381 383 /* Set Rx page size, excluding guard frame size. */
382 384 OUTL(atgep, L1E_RXF_PAGE_SIZE, L1E_RX_PAGE_SZ);
383 385
384 386 /* Tell hardware that we're ready to load DMA blocks. */
385 387 OUTL(atgep, ATGE_DMA_BLOCK, DMA_BLOCK_LOAD);
386 388
387 389 /* Set Rx/Tx interrupt trigger threshold. */
388 390 OUTL(atgep, L1E_INT_TRIG_THRESH, (1 << INT_TRIG_RX_THRESH_SHIFT) |
389 391 (4 << INT_TRIG_TX_THRESH_SHIFT));
390 392
391 393 /*
392 394 * Set interrupt trigger timer, its purpose and relation
393 395 * with interrupt moderation mechanism is not clear yet.
↓ open down ↓ |
361 lines elided |
↑ open up ↑ |
394 396 */
395 397 OUTL(atgep, L1E_INT_TRIG_TIMER,
396 398 ((ATGE_USECS(10) << INT_TRIG_RX_TIMER_SHIFT) |
397 399 (ATGE_USECS(1000) << INT_TRIG_TX_TIMER_SHIFT)));
398 400
399 401 reg = ATGE_USECS(ATGE_IM_RX_TIMER_DEFAULT) << IM_TIMER_RX_SHIFT;
400 402 reg |= ATGE_USECS(ATGE_IM_TX_TIMER_DEFAULT) << IM_TIMER_TX_SHIFT;
401 403 OUTL(atgep, ATGE_IM_TIMER, reg);
402 404
403 405 reg = INL(atgep, ATGE_MASTER_CFG);
404 - reg &= ~(MASTER_CHIP_REV_MASK | MASTER_CHIP_ID_MASK);
405 - reg &= ~(MASTER_IM_RX_TIMER_ENB | MASTER_IM_TX_TIMER_ENB);
406 - reg |= MASTER_IM_RX_TIMER_ENB;
407 - reg |= MASTER_IM_TX_TIMER_ENB;
406 + reg &= ~(L1E_MASTER_CHIP_REV_MASK | L1E_MASTER_CHIP_ID_MASK);
407 + reg &= ~(L1E_MASTER_IM_RX_TIMER_ENB | L1E_MASTER_IM_TX_TIMER_ENB);
408 + reg |= L1E_MASTER_IM_RX_TIMER_ENB;
409 + reg |= L1E_MASTER_IM_TX_TIMER_ENB;
408 410 OUTL(atgep, ATGE_MASTER_CFG, reg);
409 411
410 412 OUTW(atgep, RX_COALSC_PKT_1e, 0);
411 413 OUTW(atgep, RX_COALSC_TO_1e, 0);
412 414 OUTW(atgep, TX_COALSC_PKT_1e, 1);
413 415 OUTW(atgep, TX_COALSC_TO_1e, 4000/2); /* 4mS */
414 416 }
415 417
416 418 mblk_t *
417 419 atge_l1e_receive(atge_t *atgep)
418 420 {
419 421 atge_l1e_data_t *l1e;
420 422 atge_dma_t *dma_rx_page;
421 423 atge_dma_t *dma_rx_cmb;
422 424 uint32_t *ptr;
423 425 uint32_t cons, current_page;
424 426 uchar_t *pageaddr, *bufp;
425 427 rx_rs_t *rs;
426 428 int prog;
427 429 uint32_t seqno, len, flags;
428 430 mblk_t *mp = NULL, *rx_head, *rx_tail;
429 431 static uint32_t gen = 0;
430 432
431 433 l1e = atgep->atge_private_data;
432 434
433 435 ASSERT(MUTEX_HELD(&atgep->atge_intr_lock));
434 436 ASSERT(l1e != NULL);
435 437
436 438 rx_tail = NULL;
437 439 rx_head = NULL;
438 440
439 441 current_page = l1e->atge_l1e_rx_curp;
440 442
441 443 /* Sync CMB first */
442 444 dma_rx_cmb = l1e->atge_l1e_rx_cmb;
443 445 DMA_SYNC(dma_rx_cmb, 0, L1E_RX_CMB_SZ * L1E_RX_PAGES,
444 446 DDI_DMA_SYNC_FORKERNEL);
445 447
446 448 dma_rx_page = l1e->atge_l1e_rx_page[current_page];
447 449
448 450 /*
449 451 * Get the producer offset from CMB.
450 452 */
451 453 ptr = (void *)dma_rx_cmb->addr;
452 454
453 455 l1e->atge_l1e_rx_page_prods[current_page] =
454 456 ATGE_GET32(dma_rx_cmb, ptr + current_page);
455 457
456 458 /* Sync current RX Page as well */
457 459 DMA_SYNC(dma_rx_page, l1e->atge_l1e_rx_page_cons,
458 460 l1e->atge_l1e_rx_page_prods[current_page], DDI_DMA_SYNC_FORKERNEL);
459 461
460 462 ATGE_DB(("%s: %s() prod : %d, cons : %d, curr page : %d, gen : (%d)"
461 463 " cmb[0,1] : %d, %d",
462 464 atgep->atge_name, __func__,
463 465 l1e->atge_l1e_rx_page_prods[current_page],
464 466 l1e->atge_l1e_rx_page_cons, l1e->atge_l1e_rx_curp, gen,
465 467 ATGE_GET32(dma_rx_cmb, ptr), ATGE_GET32(dma_rx_cmb, ptr + 1)));
466 468
467 469 for (prog = 0; prog <= l1e->atge_l1e_proc_max; prog++) {
468 470 cons = l1e->atge_l1e_rx_page_cons;
469 471 if (cons >= l1e->atge_l1e_rx_page_prods[l1e->atge_l1e_rx_curp])
470 472 break;
471 473
472 474 dma_rx_page = l1e->atge_l1e_rx_page[l1e->atge_l1e_rx_curp];
473 475 pageaddr = (uchar_t *)dma_rx_page->addr;
474 476 pageaddr = pageaddr + cons;
475 477 rs = (rx_rs_t *)pageaddr;
476 478
477 479 seqno = ATGE_GET32(dma_rx_page, &(rs->seqno));
478 480 seqno = L1E_RX_SEQNO(seqno);
479 481
480 482 len = ATGE_GET32(dma_rx_page, &(rs->length));
481 483 len = L1E_RX_BYTES(len);
482 484
483 485 flags = ATGE_GET32(dma_rx_page, &(rs->flags));
484 486
485 487 if (seqno != l1e->atge_l1e_rx_seqno) {
486 488 /*
487 489 * We have not seen this happening but we
488 490 * must restart the chip if that happens.
489 491 */
490 492 ATGE_DB(("%s: %s() MISS-MATCH in seqno :%d,"
491 493 " atge_l1e_rx_seqno : %d, length : %d, flags : %x",
492 494 atgep->atge_name, __func__, seqno,
493 495 l1e->atge_l1e_rx_seqno, len, flags));
494 496
495 497 mutex_enter(&atgep->atge_tx_lock);
496 498 atge_device_restart(atgep);
497 499 mutex_exit(&atgep->atge_tx_lock);
498 500
499 501 /*
500 502 * Return all the pkts received before restarting
501 503 * the chip.
502 504 */
503 505 return (rx_head);
504 506 } else {
505 507 l1e->atge_l1e_rx_seqno++;
506 508 }
507 509
508 510 /*
509 511 * We will pass the pkt to upper layer provided it's clear
510 512 * from any error.
511 513 */
512 514 if ((flags & L1E_RD_ERROR) != 0) {
513 515 if ((flags & (L1E_RD_CRC | L1E_RD_CODE |
514 516 L1E_RD_DRIBBLE | L1E_RD_RUNT | L1E_RD_OFLOW |
515 517 L1E_RD_TRUNC)) != 0) {
516 518 ATGE_DB(("%s: %s() ERRORED PKT : %x",
517 519 atgep->atge_name, __func__, flags));
518 520 atge_l1e_rx_next_pkt(atgep, len);
519 521 atgep->atge_errrcv++;
520 522 continue;
521 523 }
522 524 }
523 525
524 526 /*
525 527 * So we have received a frame/pkt.
526 528 */
527 529 if (len == 0 || len > atgep->atge_rx_buf_len) {
528 530 ATGE_DB(("%s: %s() PKT len > error : %d",
529 531 atgep->atge_name, __func__, len));
530 532 atge_l1e_rx_next_pkt(atgep, len);
531 533 continue;
532 534 }
533 535
534 536 mp = allocb(len + VLAN_TAGSZ, BPRI_MED);
535 537 if (mp != NULL) {
536 538 mp->b_rptr += VLAN_TAGSZ;
537 539 bufp = mp->b_rptr;
538 540 mp->b_wptr = bufp + len;
539 541 mp->b_next = NULL;
540 542
541 543 bcopy(pageaddr + sizeof (rx_rs_t), bufp, len);
542 544
543 545 if (rx_tail == NULL)
544 546 rx_head = rx_tail = mp;
545 547 else {
546 548 rx_tail->b_next = mp;
547 549 rx_tail = mp;
548 550 }
549 551
550 552 atgep->atge_ipackets++;
551 553 atgep->atge_rbytes += len;
552 554 } else {
553 555 ATGE_DB(("%s: %s() PKT mp == NULL len : %d",
554 556 atgep->atge_name, __func__, len));
555 557
556 558 if (len > atgep->atge_rx_buf_len) {
557 559 atgep->atge_toolong_errors++;
558 560 } else if (mp == NULL) {
559 561 atgep->atge_norcvbuf++;
560 562 }
561 563 }
562 564
563 565 atge_l1e_rx_next_pkt(atgep, len);
564 566
565 567 ATGE_DB(("%s: %s() seqno :%d, atge_l1e_rx_seqno :"
566 568 " %d, length : %d,"
567 569 " flags : %x, cons : %d, prod : %d",
568 570 atgep->atge_name, __func__, seqno,
569 571 l1e->atge_l1e_rx_seqno, len, flags,
570 572 l1e->atge_l1e_rx_page_cons,
571 573 l1e->atge_l1e_rx_page_prods[l1e->atge_l1e_rx_curp]));
572 574 }
573 575
574 576 ATGE_DB(("%s: %s() receive completed (gen : %d) : cons : %d,"
575 577 " prod :%d, L1E_RX_PAGE_SZ : %d (prog:%d)",
576 578 atgep->atge_name, __func__, gen,
577 579 l1e->atge_l1e_rx_page_cons,
578 580 l1e->atge_l1e_rx_page_prods[l1e->atge_l1e_rx_curp],
579 581 L1E_RX_PAGE_SZ, prog));
580 582
581 583 gen++;
582 584 return (rx_head);
583 585 }
584 586
585 587 void
586 588 atge_l1e_rx_next_pkt(atge_t *atgep, uint32_t len)
587 589 {
588 590 atge_l1e_data_t *l1e = atgep->atge_private_data;
589 591 atge_dma_t *dma_rx_page;
590 592 atge_dma_t *dma_rx_cmb;
591 593 int curr = l1e->atge_l1e_rx_curp;
592 594 uint32_t *p;
593 595
594 596 /*
595 597 * Update consumer position.
596 598 */
597 599 l1e->atge_l1e_rx_page_cons +=
598 600 ROUNDUP(len + sizeof (rx_rs_t), L1E_RX_PAGE_ALIGN);
599 601
600 602 /*
601 603 * If we need to flip to the other page. Note that we use only two
602 604 * pages.
603 605 */
604 606 if (l1e->atge_l1e_rx_page_cons >= L1E_RX_PAGE_SZ) {
605 607 ATGE_DB(("%s: %s() cons : %d, prod :%d, L1E_RX_PAGE_SZ : %d",
606 608 atgep->atge_name, __func__, l1e->atge_l1e_rx_page_cons,
607 609 l1e->atge_l1e_rx_page_prods[curr], L1E_RX_PAGE_SZ));
608 610
609 611 /*
610 612 * Clear the producer.
611 613 */
612 614 dma_rx_cmb = l1e->atge_l1e_rx_cmb;
613 615 p = (void *)dma_rx_cmb->addr;
614 616 p = p + curr;
615 617 *p = 0;
616 618 DMA_SYNC(dma_rx_cmb, curr * L1E_RX_CMB_SZ,
617 619 L1E_RX_CMB_SZ, DDI_DMA_SYNC_FORDEV);
618 620
619 621 /*
620 622 * Notify the NIC that the current RX page is available again.
621 623 */
622 624 OUTB(atgep, L1E_RXF0_PAGE0 + curr, RXF_VALID);
623 625
624 626 /*
625 627 * End of Rx page reached, let hardware reuse this page.
626 628 */
627 629 l1e->atge_l1e_rx_page_cons = 0;
628 630 l1e->atge_l1e_rx_page_prods[curr] = 0;
629 631
630 632 /*
631 633 * Switch to alternate Rx page.
632 634 */
633 635 curr ^= 1;
634 636 l1e->atge_l1e_rx_curp = curr;
635 637
636 638 /*
637 639 * Page flipped, sync CMB and then Rx page.
638 640 */
639 641 DMA_SYNC(dma_rx_cmb, 0, L1E_RX_PAGES * L1E_RX_CMB_SZ,
640 642 DDI_DMA_SYNC_FORKERNEL);
641 643 p = (void *)dma_rx_cmb->addr;
642 644 l1e->atge_l1e_rx_page_prods[curr] =
643 645 ATGE_GET32(dma_rx_cmb, p + curr);
644 646
645 647 dma_rx_page = l1e->atge_l1e_rx_page[curr];
646 648 DMA_SYNC(dma_rx_page, 0, l1e->atge_l1e_rx_page_prods[curr],
647 649 DDI_DMA_SYNC_FORKERNEL);
648 650
649 651 ATGE_DB(("%s: %s() PAGE FLIPPED -> %d, producer[0,1]: %d, %d",
650 652 atgep->atge_name, __func__, curr,
651 653 ATGE_GET32(dma_rx_cmb, p), ATGE_GET32(dma_rx_cmb, p + 1)));
652 654 }
653 655 }
654 656
655 657 void
656 658 atge_l1e_send_packet(atge_ring_t *r)
657 659 {
658 660 /*
659 661 * Ask chip to send the packet now.
660 662 */
661 663 OUTL(r->r_atge, ATGE_MBOX, r->r_producer);
662 664 }
663 665
664 666 void
665 667 atge_l1e_clear_stats(atge_t *atgep)
666 668 {
667 669 atge_l1e_smb_t smb;
668 670 uint32_t *reg;
669 671 int i;
670 672
671 673 /*
672 674 * Clear RX stats first.
673 675 */
674 676 i = 0;
675 677 reg = &smb.rx_frames;
676 678 while (reg++ <= &smb.rx_pkts_filtered) {
677 679 (void) INL(atgep, L1E_RX_MIB_BASE + i);
678 680 i += sizeof (uint32_t);
679 681 }
680 682
681 683 /*
682 684 * Clear TX stats.
683 685 */
684 686 i = 0;
685 687 reg = &smb.tx_frames;
686 688 while (reg++ <= &smb.tx_mcast_bytes) {
687 689 (void) INL(atgep, L1E_TX_MIB_BASE + i);
688 690 i += sizeof (uint32_t);
689 691 }
690 692 }
691 693
692 694 void
693 695 atge_l1e_gather_stats(atge_t *atgep)
694 696 {
695 697 atge_l1e_smb_t *stat;
696 698 atge_l1e_smb_t *smb;
697 699 atge_l1e_smb_t local_smb;
698 700 uint32_t *reg;
699 701 int i;
700 702
701 703 ASSERT(atgep != NULL);
702 704
703 705 stat = (atge_l1e_smb_t *)atgep->atge_hw_stats;
704 706
705 707 bzero(&local_smb, sizeof (atge_l1e_smb_t));
706 708 smb = &local_smb;
707 709
708 710 /* Read Rx statistics. */
709 711 i = 0;
710 712 reg = &smb->rx_frames;
711 713 while (reg++ <= &smb->rx_pkts_filtered) {
712 714 *reg = INL(atgep, L1E_RX_MIB_BASE + i);
713 715 i += sizeof (uint32_t);
714 716 }
715 717
716 718 /* Read Tx statistics. */
717 719 i = 0;
718 720 reg = &smb->tx_frames;
719 721 while (reg++ <= &smb->tx_mcast_bytes) {
720 722 *reg = INL(atgep, L1E_TX_MIB_BASE + i);
721 723 i += sizeof (uint32_t);
722 724 }
723 725
724 726 /*
725 727 * SMB is cleared everytime we read; hence we always do '+='.
726 728 */
727 729
728 730 /* Rx stats. */
729 731 stat->rx_frames += smb->rx_frames;
730 732 stat->rx_bcast_frames += smb->rx_bcast_frames;
731 733 stat->rx_mcast_frames += smb->rx_mcast_frames;
732 734 stat->rx_pause_frames += smb->rx_pause_frames;
733 735 stat->rx_control_frames += smb->rx_control_frames;
734 736 stat->rx_crcerrs += smb->rx_crcerrs;
735 737 stat->rx_lenerrs += smb->rx_lenerrs;
736 738 stat->rx_bytes += smb->rx_bytes;
737 739 stat->rx_runts += smb->rx_runts;
738 740 stat->rx_fragments += smb->rx_fragments;
739 741 stat->rx_pkts_64 += smb->rx_pkts_64;
740 742 stat->rx_pkts_65_127 += smb->rx_pkts_65_127;
741 743 stat->rx_pkts_128_255 += smb->rx_pkts_128_255;
742 744 stat->rx_pkts_256_511 += smb->rx_pkts_256_511;
743 745 stat->rx_pkts_512_1023 += smb->rx_pkts_512_1023;
744 746 stat->rx_pkts_1024_1518 += smb->rx_pkts_1024_1518;
745 747 stat->rx_pkts_1519_max += smb->rx_pkts_1519_max;
746 748 stat->rx_pkts_truncated += smb->rx_pkts_truncated;
747 749 stat->rx_fifo_oflows += smb->rx_fifo_oflows;
748 750 stat->rx_rrs_errs += smb->rx_rrs_errs;
749 751 stat->rx_alignerrs += smb->rx_alignerrs;
750 752 stat->rx_bcast_bytes += smb->rx_bcast_bytes;
751 753 stat->rx_mcast_bytes += smb->rx_mcast_bytes;
752 754 stat->rx_pkts_filtered += smb->rx_pkts_filtered;
753 755
754 756 /* Tx stats. */
755 757 stat->tx_frames += smb->tx_frames;
756 758 stat->tx_bcast_frames += smb->tx_bcast_frames;
757 759 stat->tx_mcast_frames += smb->tx_mcast_frames;
758 760 stat->tx_pause_frames += smb->tx_pause_frames;
759 761 stat->tx_excess_defer += smb->tx_excess_defer;
760 762 stat->tx_control_frames += smb->tx_control_frames;
761 763 stat->tx_deferred += smb->tx_deferred;
762 764 stat->tx_bytes += smb->tx_bytes;
763 765 stat->tx_pkts_64 += smb->tx_pkts_64;
764 766 stat->tx_pkts_65_127 += smb->tx_pkts_65_127;
765 767 stat->tx_pkts_128_255 += smb->tx_pkts_128_255;
766 768 stat->tx_pkts_256_511 += smb->tx_pkts_256_511;
767 769 stat->tx_pkts_512_1023 += smb->tx_pkts_512_1023;
768 770 stat->tx_pkts_1024_1518 += smb->tx_pkts_1024_1518;
769 771 stat->tx_pkts_1519_max += smb->tx_pkts_1519_max;
770 772 stat->tx_single_colls += smb->tx_single_colls;
771 773 stat->tx_multi_colls += smb->tx_multi_colls;
772 774 stat->tx_late_colls += smb->tx_late_colls;
773 775 stat->tx_excess_colls += smb->tx_excess_colls;
774 776 stat->tx_abort += smb->tx_abort;
775 777 stat->tx_underrun += smb->tx_underrun;
776 778 stat->tx_desc_underrun += smb->tx_desc_underrun;
777 779 stat->tx_lenerrs += smb->tx_lenerrs;
778 780 stat->tx_pkts_truncated += smb->tx_pkts_truncated;
779 781 stat->tx_bcast_bytes += smb->tx_bcast_bytes;
780 782 stat->tx_mcast_bytes += smb->tx_mcast_bytes;
781 783
782 784 /*
783 785 * Update global counters in atge_t.
784 786 */
785 787 atgep->atge_brdcstrcv += smb->rx_bcast_frames;
786 788 atgep->atge_multircv += smb->rx_mcast_frames;
787 789 atgep->atge_multixmt += smb->tx_mcast_frames;
788 790 atgep->atge_brdcstxmt += smb->tx_bcast_frames;
789 791
790 792 atgep->atge_align_errors += smb->rx_alignerrs;
791 793 atgep->atge_fcs_errors += smb->rx_crcerrs;
792 794 atgep->atge_sqe_errors += smb->rx_rrs_errs;
793 795 atgep->atge_defer_xmts += smb->tx_deferred;
794 796 atgep->atge_first_collisions += smb->tx_single_colls;
795 797 atgep->atge_multi_collisions += smb->tx_multi_colls * 2;
796 798 atgep->atge_tx_late_collisions += smb->tx_late_colls;
797 799 atgep->atge_ex_collisions += smb->tx_excess_colls;
798 800 atgep->atge_macxmt_errors += smb->tx_abort;
799 801 atgep->atge_toolong_errors += smb->rx_lenerrs;
800 802 atgep->atge_overflow += smb->rx_fifo_oflows;
801 803 atgep->atge_underflow += (smb->tx_underrun + smb->tx_desc_underrun);
802 804 atgep->atge_runt += smb->rx_runts;
803 805
804 806
805 807 atgep->atge_collisions += smb->tx_single_colls +
806 808 smb->tx_multi_colls * 2 + smb->tx_late_colls +
807 809 smb->tx_abort * HDPX_CFG_RETRY_DEFAULT;
808 810
809 811 /*
810 812 * tx_pkts_truncated counter looks suspicious. It constantly
811 813 * increments with no sign of Tx errors. Hence we don't factor it.
812 814 */
813 815 atgep->atge_macxmt_errors += smb->tx_abort + smb->tx_late_colls +
814 816 smb->tx_underrun;
815 817
816 818 atgep->atge_macrcv_errors += smb->rx_crcerrs + smb->rx_lenerrs +
817 819 smb->rx_runts + smb->rx_pkts_truncated +
818 820 smb->rx_fifo_oflows + smb->rx_rrs_errs +
819 821 smb->rx_alignerrs;
820 822 }
821 823
822 824 void
823 825 atge_l1e_stop_mac(atge_t *atgep)
824 826 {
825 827 uint32_t reg;
826 828
827 829 reg = INL(atgep, ATGE_MAC_CFG);
828 830 ATGE_DB(("%s: %s() reg : %x", atgep->atge_name, __func__, reg));
829 831
830 832 if ((reg & (ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB)) != 0) {
831 833 reg &= ~ATGE_CFG_TX_ENB | ATGE_CFG_RX_ENB;
832 834 OUTL(atgep, ATGE_MAC_CFG, reg);
833 835 ATGE_DB(("%s: %s() mac stopped", atgep->atge_name, __func__));
834 836 }
835 837 }
836 838
837 839 /*
838 840 * The interrupt handler for L1E/L2E
839 841 */
840 842 /*ARGSUSED*/
841 843 uint_t
842 844 atge_l1e_interrupt(caddr_t arg1, caddr_t arg2)
843 845 {
844 846 atge_t *atgep = (void *)arg1;
845 847 mblk_t *rx_head = NULL;
846 848 uint32_t status;
847 849 int resched = 0;
848 850
849 851 ASSERT(atgep != NULL);
850 852
851 853 mutex_enter(&atgep->atge_intr_lock);
852 854
853 855 if (atgep->atge_chip_state & ATGE_CHIP_SUSPENDED) {
854 856 mutex_exit(&atgep->atge_intr_lock);
855 857 return (DDI_INTR_UNCLAIMED);
856 858 }
857 859
858 860 status = INL(atgep, ATGE_INTR_STATUS);
859 861 if (status == 0 || (status & atgep->atge_intrs) == 0) {
860 862 mutex_exit(&atgep->atge_intr_lock);
861 863
862 864 if (atgep->atge_flags & ATGE_FIXED_TYPE)
863 865 return (DDI_INTR_UNCLAIMED);
864 866
865 867 return (DDI_INTR_CLAIMED);
866 868 }
867 869
868 870 ATGE_DB(("%s: %s() entry status : %x",
869 871 atgep->atge_name, __func__, status));
870 872
871 873
872 874 /*
873 875 * Disable interrupts.
874 876 */
875 877 OUTL(atgep, ATGE_INTR_STATUS, status | INTR_DIS_INT);
876 878 FLUSH(atgep, ATGE_INTR_STATUS);
877 879
878 880 /*
879 881 * Check if chip is running, only then do the work.
880 882 */
881 883 if (atgep->atge_chip_state & ATGE_CHIP_RUNNING) {
882 884 if (status & INTR_SMB) {
883 885 atge_l1e_gather_stats(atgep);
884 886 }
885 887
886 888 /*
887 889 * Check for errors.
888 890 */
889 891 if (status & L1E_INTR_ERRORS) {
890 892 atge_error(atgep->atge_dip,
891 893 "L1E chip found an error intr status : %x",
892 894 status);
893 895
894 896 if (status &
895 897 (INTR_DMA_RD_TO_RST | INTR_DMA_WR_TO_RST)) {
896 898 atge_error(atgep->atge_dip, "DMA transfer err");
897 899
898 900 atge_device_stop(atgep);
899 901 goto done;
900 902 }
901 903
902 904 if (status & INTR_TX_FIFO_UNDERRUN) {
903 905 atge_error(atgep->atge_dip, "TX FIFO underrun");
904 906 }
905 907 }
906 908
907 909 rx_head = atge_l1e_receive(atgep);
908 910
909 911 if (status & INTR_TX_PKT) {
910 912 int cons;
911 913
912 914 mutex_enter(&atgep->atge_tx_lock);
913 915 cons = INW(atgep, L1E_TPD_CONS_IDX);
914 916 atge_tx_reclaim(atgep, cons);
915 917 if (atgep->atge_tx_resched) {
916 918 atgep->atge_tx_resched = 0;
917 919 resched = 1;
918 920 }
919 921
920 922 mutex_exit(&atgep->atge_tx_lock);
921 923 }
922 924 }
923 925
924 926 /*
925 927 * Enable interrupts.
926 928 */
927 929 OUTL(atgep, ATGE_INTR_STATUS, 0);
928 930
929 931 done:
930 932
931 933 mutex_exit(&atgep->atge_intr_lock);
932 934
933 935 if (status & INTR_GPHY) {
934 936 /*
935 937 * Ack interrupts from PHY
936 938 */
937 939 (void) atge_mii_read(atgep,
938 940 atgep->atge_phyaddr, ATGE_ISR_ACK_GPHY);
939 941
940 942 mii_check(atgep->atge_mii);
941 943 }
942 944
943 945 /*
944 946 * Pass the list of packets received from chip to MAC layer.
945 947 */
946 948 if (rx_head) {
947 949 mac_rx(atgep->atge_mh, 0, rx_head);
948 950 }
949 951
950 952 /*
951 953 * Let MAC start sending pkts if the downstream was asked to pause.
952 954 */
953 955 if (resched)
954 956 mac_tx_update(atgep->atge_mh);
955 957
956 958 return (DDI_INTR_CLAIMED);
957 959 }
↓ open down ↓ |
540 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX