| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_wm.c,v 1.353 2015/10/13 07:53:02 knakahara Exp $ */ | | 1 | /* $NetBSD: if_wm.c,v 1.354 2015/10/13 08:00:15 knakahara Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. | | 4 | * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Written by Jason R. Thorpe for Wasabi Systems, Inc. | | 7 | * Written by Jason R. Thorpe for Wasabi Systems, Inc. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
| @@ -73,27 +73,27 @@ | | | @@ -73,27 +73,27 @@ |
73 | * TODO (in order of importance): | | 73 | * TODO (in order of importance): |
74 | * | | 74 | * |
75 | * - Check XXX'ed comments | | 75 | * - Check XXX'ed comments |
76 | * - EEE (Energy Efficiency Ethernet) | | 76 | * - EEE (Energy Efficiency Ethernet) |
77 | * - Multi queue | | 77 | * - Multi queue |
78 | * - Image Unique ID | | 78 | * - Image Unique ID |
79 | * - LPLU other than PCH* | | 79 | * - LPLU other than PCH* |
80 | * - Virtual Function | | 80 | * - Virtual Function |
81 | * - Set LED correctly (based on contents in EEPROM) | | 81 | * - Set LED correctly (based on contents in EEPROM) |
82 | * - Rework how parameters are loaded from the EEPROM. | | 82 | * - Rework how parameters are loaded from the EEPROM. |
83 | */ | | 83 | */ |
84 | | | 84 | |
85 | #include <sys/cdefs.h> | | 85 | #include <sys/cdefs.h> |
86 | __KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.353 2015/10/13 07:53:02 knakahara Exp $"); | | 86 | __KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.354 2015/10/13 08:00:15 knakahara Exp $"); |
87 | | | 87 | |
88 | #ifdef _KERNEL_OPT | | 88 | #ifdef _KERNEL_OPT |
89 | #include "opt_net_mpsafe.h" | | 89 | #include "opt_net_mpsafe.h" |
90 | #endif | | 90 | #endif |
91 | | | 91 | |
92 | #include <sys/param.h> | | 92 | #include <sys/param.h> |
93 | #include <sys/systm.h> | | 93 | #include <sys/systm.h> |
94 | #include <sys/callout.h> | | 94 | #include <sys/callout.h> |
95 | #include <sys/mbuf.h> | | 95 | #include <sys/mbuf.h> |
96 | #include <sys/malloc.h> | | 96 | #include <sys/malloc.h> |
97 | #include <sys/kernel.h> | | 97 | #include <sys/kernel.h> |
98 | #include <sys/socket.h> | | 98 | #include <sys/socket.h> |
99 | #include <sys/ioctl.h> | | 99 | #include <sys/ioctl.h> |
| @@ -209,55 +209,33 @@ int wm_debug = WM_DEBUG_TX | WM_DEBUG_RX | | | @@ -209,55 +209,33 @@ int wm_debug = WM_DEBUG_TX | WM_DEBUG_RX |
209 | #define WM_MAXTXDMA (2 * round_page(IP_MAXPACKET)) /* for TSO */ | | 209 | #define WM_MAXTXDMA (2 * round_page(IP_MAXPACKET)) /* for TSO */ |
210 | | | 210 | |
211 | /* | | 211 | /* |
212 | * Receive descriptor list size. We have one Rx buffer for normal | | 212 | * Receive descriptor list size. We have one Rx buffer for normal |
213 | * sized packets. Jumbo packets consume 5 Rx buffers for a full-sized | | 213 | * sized packets. Jumbo packets consume 5 Rx buffers for a full-sized |
214 | * packet. We allocate 256 receive descriptors, each with a 2k | | 214 | * packet. We allocate 256 receive descriptors, each with a 2k |
215 | * buffer (MCLBYTES), which gives us room for 50 jumbo packets. | | 215 | * buffer (MCLBYTES), which gives us room for 50 jumbo packets. |
216 | */ | | 216 | */ |
217 | #define WM_NRXDESC 256 | | 217 | #define WM_NRXDESC 256 |
218 | #define WM_NRXDESC_MASK (WM_NRXDESC - 1) | | 218 | #define WM_NRXDESC_MASK (WM_NRXDESC - 1) |
219 | #define WM_NEXTRX(x) (((x) + 1) & WM_NRXDESC_MASK) | | 219 | #define WM_NEXTRX(x) (((x) + 1) & WM_NRXDESC_MASK) |
220 | #define WM_PREVRX(x) (((x) - 1) & WM_NRXDESC_MASK) | | 220 | #define WM_PREVRX(x) (((x) - 1) & WM_NRXDESC_MASK) |
221 | | | 221 | |
222 | /* | | 222 | typedef union txdescs { |
223 | * Control structures are DMA'd to the i82542 chip. We allocate them in | | 223 | wiseman_txdesc_t sctxu_txdescs[WM_NTXDESC_82544]; |
224 | * a single clump that maps to a single DMA segment to make several things | | 224 | nq_txdesc_t sctxu_nq_txdescs[WM_NTXDESC_82544]; |
225 | * easier. | | 225 | } txdescs_t; |
226 | */ | | | |
227 | struct wm_control_data_82544 { | | | |
228 | /* | | | |
229 | * The receive descriptors. | | | |
230 | */ | | | |
231 | wiseman_rxdesc_t wcd_rxdescs[WM_NRXDESC]; | | | |
232 | | | 226 | |
233 | /* | | 227 | #define WM_CDTXOFF(x) (sizeof(wiseman_txdesc_t) * x) |
234 | * The transmit descriptors. Put these at the end, because | | 228 | #define WM_CDRXOFF(x) (sizeof(wiseman_rxdesc_t) * x) |
235 | * we might use a smaller number of them. | | | |
236 | */ | | | |
237 | union { | | | |
238 | wiseman_txdesc_t wcdu_txdescs[WM_NTXDESC_82544]; | | | |
239 | nq_txdesc_t wcdu_nq_txdescs[WM_NTXDESC_82544]; | | | |
240 | } wdc_u; | | | |
241 | }; | | | |
242 | | | | |
243 | struct wm_control_data_82542 { | | | |
244 | wiseman_rxdesc_t wcd_rxdescs[WM_NRXDESC]; | | | |
245 | wiseman_txdesc_t wcd_txdescs[WM_NTXDESC_82542]; | | | |
246 | }; | | | |
247 | | | | |
248 | #define WM_CDOFF(x) offsetof(struct wm_control_data_82544, x) | | | |
249 | #define WM_CDTXOFF(x) WM_CDOFF(wdc_u.wcdu_txdescs[(x)]) | | | |
250 | #define WM_CDRXOFF(x) WM_CDOFF(wcd_rxdescs[(x)]) | | | |
251 | | | 229 | |
252 | /* | | 230 | /* |
253 | * Software state for transmit jobs. | | 231 | * Software state for transmit jobs. |
254 | */ | | 232 | */ |
255 | struct wm_txsoft { | | 233 | struct wm_txsoft { |
256 | struct mbuf *txs_mbuf; /* head of our mbuf chain */ | | 234 | struct mbuf *txs_mbuf; /* head of our mbuf chain */ |
257 | bus_dmamap_t txs_dmamap; /* our DMA map */ | | 235 | bus_dmamap_t txs_dmamap; /* our DMA map */ |
258 | int txs_firstdesc; /* first descriptor in packet */ | | 236 | int txs_firstdesc; /* first descriptor in packet */ |
259 | int txs_lastdesc; /* last descriptor in packet */ | | 237 | int txs_lastdesc; /* last descriptor in packet */ |
260 | int txs_ndesc; /* # of descriptors used */ | | 238 | int txs_ndesc; /* # of descriptors used */ |
261 | }; | | 239 | }; |
262 | | | 240 | |
263 | /* | | 241 | /* |
| @@ -336,37 +314,44 @@ struct wm_softc { | | | @@ -336,37 +314,44 @@ struct wm_softc { |
336 | int sc_nvm_ver_minor; | | 314 | int sc_nvm_ver_minor; |
337 | int sc_nvm_ver_build; | | 315 | int sc_nvm_ver_build; |
338 | int sc_nvm_addrbits; /* NVM address bits */ | | 316 | int sc_nvm_addrbits; /* NVM address bits */ |
339 | unsigned int sc_nvm_wordsize; /* NVM word size */ | | 317 | unsigned int sc_nvm_wordsize; /* NVM word size */ |
340 | int sc_ich8_flash_base; | | 318 | int sc_ich8_flash_base; |
341 | int sc_ich8_flash_bank_size; | | 319 | int sc_ich8_flash_bank_size; |
342 | int sc_nvm_k1_enabled; | | 320 | int sc_nvm_k1_enabled; |
343 | | | 321 | |
344 | /* Software state for the transmit and receive descriptors. */ | | 322 | /* Software state for the transmit and receive descriptors. */ |
345 | int sc_txnum; /* must be a power of two */ | | 323 | int sc_txnum; /* must be a power of two */ |
346 | struct wm_txsoft sc_txsoft[WM_TXQUEUELEN_MAX]; | | 324 | struct wm_txsoft sc_txsoft[WM_TXQUEUELEN_MAX]; |
347 | struct wm_rxsoft sc_rxsoft[WM_NRXDESC]; | | 325 | struct wm_rxsoft sc_rxsoft[WM_NRXDESC]; |
348 | | | 326 | |
349 | /* Control data structures. */ | | 327 | /* TX control data structures. */ |
350 | int sc_ntxdesc; /* must be a power of two */ | | 328 | int sc_ntxdesc; /* must be a power of two */ |
351 | struct wm_control_data_82544 *sc_control_data; | | 329 | txdescs_t *sc_txdescs_u; |
352 | bus_dmamap_t sc_cddmamap; /* control data DMA map */ | | 330 | bus_dmamap_t sc_txdesc_dmamap; /* control data DMA map */ |
353 | bus_dma_segment_t sc_cd_seg; /* control data segment */ | | 331 | bus_dma_segment_t sc_txdesc_seg;/* control data segment */ |
354 | int sc_cd_rseg; /* real number of control segment */ | | 332 | int sc_txdesc_rseg; /* real number of control segment */ |
355 | size_t sc_cd_size; /* control data size */ | | 333 | size_t sc_txdesc_size; /* control data size */ |
356 | #define sc_cddma sc_cddmamap->dm_segs[0].ds_addr | | 334 | #define sc_txdesc_dma sc_txdesc_dmamap->dm_segs[0].ds_addr |
357 | #define sc_txdescs sc_control_data->wdc_u.wcdu_txdescs | | 335 | #define sc_txdescs sc_txdescs_u->sctxu_txdescs |
358 | #define sc_nq_txdescs sc_control_data->wdc_u.wcdu_nq_txdescs | | 336 | #define sc_nq_txdescs sc_txdescs_u->sctxu_nq_txdescs |
359 | #define sc_rxdescs sc_control_data->wcd_rxdescs | | 337 | |
| | | 338 | /* RX control data structures. */ |
| | | 339 | wiseman_rxdesc_t *sc_rxdescs; |
| | | 340 | bus_dmamap_t sc_rxdesc_dmamap; /* control data DMA map */ |
| | | 341 | bus_dma_segment_t sc_rxdesc_seg;/* control data segment */ |
| | | 342 | int sc_rxdesc_rseg; /* real number of control segment */ |
| | | 343 | size_t sc_rxdesc_size; /* control data size */ |
| | | 344 | #define sc_rxdesc_dma sc_rxdesc_dmamap->dm_segs[0].ds_addr |
360 | | | 345 | |
361 | #ifdef WM_EVENT_COUNTERS | | 346 | #ifdef WM_EVENT_COUNTERS |
362 | /* Event counters. */ | | 347 | /* Event counters. */ |
363 | struct evcnt sc_ev_txsstall; /* Tx stalled due to no txs */ | | 348 | struct evcnt sc_ev_txsstall; /* Tx stalled due to no txs */ |
364 | struct evcnt sc_ev_txdstall; /* Tx stalled due to no txd */ | | 349 | struct evcnt sc_ev_txdstall; /* Tx stalled due to no txd */ |
365 | struct evcnt sc_ev_txfifo_stall;/* Tx FIFO stalls (82547) */ | | 350 | struct evcnt sc_ev_txfifo_stall;/* Tx FIFO stalls (82547) */ |
366 | struct evcnt sc_ev_txdw; /* Tx descriptor interrupts */ | | 351 | struct evcnt sc_ev_txdw; /* Tx descriptor interrupts */ |
367 | struct evcnt sc_ev_txqe; /* Tx queue empty interrupts */ | | 352 | struct evcnt sc_ev_txqe; /* Tx queue empty interrupts */ |
368 | struct evcnt sc_ev_rxintr; /* Rx interrupts */ | | 353 | struct evcnt sc_ev_rxintr; /* Rx interrupts */ |
369 | struct evcnt sc_ev_linkintr; /* Link interrupts */ | | 354 | struct evcnt sc_ev_linkintr; /* Link interrupts */ |
370 | | | 355 | |
371 | struct evcnt sc_ev_rxipsum; /* IP checksums checked in-bound */ | | 356 | struct evcnt sc_ev_rxipsum; /* IP checksums checked in-bound */ |
372 | struct evcnt sc_ev_rxtusum; /* TCP/UDP cksums checked in-bound */ | | 357 | struct evcnt sc_ev_rxtusum; /* TCP/UDP cksums checked in-bound */ |
| @@ -483,28 +468,28 @@ do { \ | | | @@ -483,28 +468,28 @@ do { \ |
483 | #define CSR_WRITE_FLUSH(sc) \ | | 468 | #define CSR_WRITE_FLUSH(sc) \ |
484 | (void) CSR_READ((sc), WMREG_STATUS) | | 469 | (void) CSR_READ((sc), WMREG_STATUS) |
485 | | | 470 | |
486 | #define ICH8_FLASH_READ32(sc, reg) \ | | 471 | #define ICH8_FLASH_READ32(sc, reg) \ |
487 | bus_space_read_4((sc)->sc_flasht, (sc)->sc_flashh, (reg)) | | 472 | bus_space_read_4((sc)->sc_flasht, (sc)->sc_flashh, (reg)) |
488 | #define ICH8_FLASH_WRITE32(sc, reg, data) \ | | 473 | #define ICH8_FLASH_WRITE32(sc, reg, data) \ |
489 | bus_space_write_4((sc)->sc_flasht, (sc)->sc_flashh, (reg), (data)) | | 474 | bus_space_write_4((sc)->sc_flasht, (sc)->sc_flashh, (reg), (data)) |
490 | | | 475 | |
491 | #define ICH8_FLASH_READ16(sc, reg) \ | | 476 | #define ICH8_FLASH_READ16(sc, reg) \ |
492 | bus_space_read_2((sc)->sc_flasht, (sc)->sc_flashh, (reg)) | | 477 | bus_space_read_2((sc)->sc_flasht, (sc)->sc_flashh, (reg)) |
493 | #define ICH8_FLASH_WRITE16(sc, reg, data) \ | | 478 | #define ICH8_FLASH_WRITE16(sc, reg, data) \ |
494 | bus_space_write_2((sc)->sc_flasht, (sc)->sc_flashh, (reg), (data)) | | 479 | bus_space_write_2((sc)->sc_flasht, (sc)->sc_flashh, (reg), (data)) |
495 | | | 480 | |
496 | #define WM_CDTXADDR(sc, x) ((sc)->sc_cddma + WM_CDTXOFF((x))) | | 481 | #define WM_CDTXADDR(sc, x) ((sc)->sc_txdesc_dma + WM_CDTXOFF((x))) |
497 | #define WM_CDRXADDR(sc, x) ((sc)->sc_cddma + WM_CDRXOFF((x))) | | 482 | #define WM_CDRXADDR(sc, x) ((sc)->sc_rxdesc_dma + WM_CDRXOFF((x))) |
498 | | | 483 | |
499 | #define WM_CDTXADDR_LO(sc, x) (WM_CDTXADDR((sc), (x)) & 0xffffffffU) | | 484 | #define WM_CDTXADDR_LO(sc, x) (WM_CDTXADDR((sc), (x)) & 0xffffffffU) |
500 | #define WM_CDTXADDR_HI(sc, x) \ | | 485 | #define WM_CDTXADDR_HI(sc, x) \ |
501 | (sizeof(bus_addr_t) == 8 ? \ | | 486 | (sizeof(bus_addr_t) == 8 ? \ |
502 | (uint64_t)WM_CDTXADDR((sc), (x)) >> 32 : 0) | | 487 | (uint64_t)WM_CDTXADDR((sc), (x)) >> 32 : 0) |
503 | | | 488 | |
504 | #define WM_CDRXADDR_LO(sc, x) (WM_CDRXADDR((sc), (x)) & 0xffffffffU) | | 489 | #define WM_CDRXADDR_LO(sc, x) (WM_CDRXADDR((sc), (x)) & 0xffffffffU) |
505 | #define WM_CDRXADDR_HI(sc, x) \ | | 490 | #define WM_CDRXADDR_HI(sc, x) \ |
506 | (sizeof(bus_addr_t) == 8 ? \ | | 491 | (sizeof(bus_addr_t) == 8 ? \ |
507 | (uint64_t)WM_CDRXADDR((sc), (x)) >> 32 : 0) | | 492 | (uint64_t)WM_CDRXADDR((sc), (x)) >> 32 : 0) |
508 | | | 493 | |
509 | /* | | 494 | /* |
510 | * Register read/write functions. | | 495 | * Register read/write functions. |
| @@ -556,28 +541,30 @@ static uint32_t wm_rxpbs_adjust_82580(ui | | | @@ -556,28 +541,30 @@ static uint32_t wm_rxpbs_adjust_82580(ui |
556 | static void wm_reset(struct wm_softc *); | | 541 | static void wm_reset(struct wm_softc *); |
557 | static int wm_add_rxbuf(struct wm_softc *, int); | | 542 | static int wm_add_rxbuf(struct wm_softc *, int); |
558 | static void wm_rxdrain(struct wm_softc *); | | 543 | static void wm_rxdrain(struct wm_softc *); |
559 | static int wm_init(struct ifnet *); | | 544 | static int wm_init(struct ifnet *); |
560 | static int wm_init_locked(struct ifnet *); | | 545 | static int wm_init_locked(struct ifnet *); |
561 | static void wm_stop(struct ifnet *, int); | | 546 | static void wm_stop(struct ifnet *, int); |
562 | static void wm_stop_locked(struct ifnet *, int); | | 547 | static void wm_stop_locked(struct ifnet *, int); |
563 | static int wm_tx_offload(struct wm_softc *, struct wm_txsoft *, | | 548 | static int wm_tx_offload(struct wm_softc *, struct wm_txsoft *, |
564 | uint32_t *, uint8_t *); | | 549 | uint32_t *, uint8_t *); |
565 | static void wm_dump_mbuf_chain(struct wm_softc *, struct mbuf *); | | 550 | static void wm_dump_mbuf_chain(struct wm_softc *, struct mbuf *); |
566 | static void wm_82547_txfifo_stall(void *); | | 551 | static void wm_82547_txfifo_stall(void *); |
567 | static int wm_82547_txfifo_bugchk(struct wm_softc *, struct mbuf *); | | 552 | static int wm_82547_txfifo_bugchk(struct wm_softc *, struct mbuf *); |
568 | /* DMA related */ | | 553 | /* DMA related */ |
569 | static int wm_alloc_descs(struct wm_softc *); | | 554 | static int wm_alloc_tx_descs(struct wm_softc *); |
570 | static void wm_free_descs(struct wm_softc *); | | 555 | static void wm_free_tx_descs(struct wm_softc *); |
| | | 556 | static int wm_alloc_rx_descs(struct wm_softc *); |
| | | 557 | static void wm_free_rx_descs(struct wm_softc *); |
571 | static int wm_alloc_tx_buffer(struct wm_softc *); | | 558 | static int wm_alloc_tx_buffer(struct wm_softc *); |
572 | static void wm_free_tx_buffer(struct wm_softc *); | | 559 | static void wm_free_tx_buffer(struct wm_softc *); |
573 | static int wm_alloc_rx_buffer(struct wm_softc *); | | 560 | static int wm_alloc_rx_buffer(struct wm_softc *); |
574 | static void wm_free_rx_buffer(struct wm_softc *); | | 561 | static void wm_free_rx_buffer(struct wm_softc *); |
575 | static int wm_alloc_txrx_queues(struct wm_softc *); | | 562 | static int wm_alloc_txrx_queues(struct wm_softc *); |
576 | static void wm_free_txrx_queues(struct wm_softc *); | | 563 | static void wm_free_txrx_queues(struct wm_softc *); |
577 | /* Start */ | | 564 | /* Start */ |
578 | static void wm_start(struct ifnet *); | | 565 | static void wm_start(struct ifnet *); |
579 | static void wm_start_locked(struct ifnet *); | | 566 | static void wm_start_locked(struct ifnet *); |
580 | static int wm_nq_tx_offload(struct wm_softc *, struct wm_txsoft *, | | 567 | static int wm_nq_tx_offload(struct wm_softc *, struct wm_txsoft *, |
581 | uint32_t *, uint32_t *, bool *); | | 568 | uint32_t *, uint32_t *, bool *); |
582 | static void wm_nq_start(struct ifnet *); | | 569 | static void wm_nq_start(struct ifnet *); |
583 | static void wm_nq_start_locked(struct ifnet *); | | 570 | static void wm_nq_start_locked(struct ifnet *); |
| @@ -1336,43 +1323,43 @@ wm_set_dma_addr(volatile wiseman_addr_t | | | @@ -1336,43 +1323,43 @@ wm_set_dma_addr(volatile wiseman_addr_t |
1336 | else | | 1323 | else |
1337 | wa->wa_high = 0; | | 1324 | wa->wa_high = 0; |
1338 | } | | 1325 | } |
1339 | | | 1326 | |
1340 | /* | | 1327 | /* |
1341 | * Descriptor sync/init functions. | | 1328 | * Descriptor sync/init functions. |
1342 | */ | | 1329 | */ |
1343 | static inline void | | 1330 | static inline void |
1344 | wm_cdtxsync(struct wm_softc *sc, int start, int num, int ops) | | 1331 | wm_cdtxsync(struct wm_softc *sc, int start, int num, int ops) |
1345 | { | | 1332 | { |
1346 | | | 1333 | |
1347 | /* If it will wrap around, sync to the end of the ring. */ | | 1334 | /* If it will wrap around, sync to the end of the ring. */ |
1348 | if ((start + num) > WM_NTXDESC(sc)) { | | 1335 | if ((start + num) > WM_NTXDESC(sc)) { |
1349 | bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap, | | 1336 | bus_dmamap_sync(sc->sc_dmat, sc->sc_txdesc_dmamap, |
1350 | WM_CDTXOFF(start), sizeof(wiseman_txdesc_t) * | | 1337 | WM_CDTXOFF(start), sizeof(wiseman_txdesc_t) * |
1351 | (WM_NTXDESC(sc) - start), ops); | | 1338 | (WM_NTXDESC(sc) - start), ops); |
1352 | num -= (WM_NTXDESC(sc) - start); | | 1339 | num -= (WM_NTXDESC(sc) - start); |
1353 | start = 0; | | 1340 | start = 0; |
1354 | } | | 1341 | } |
1355 | | | 1342 | |
1356 | /* Now sync whatever is left. */ | | 1343 | /* Now sync whatever is left. */ |
1357 | bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap, | | 1344 | bus_dmamap_sync(sc->sc_dmat, sc->sc_txdesc_dmamap, |
1358 | WM_CDTXOFF(start), sizeof(wiseman_txdesc_t) * num, ops); | | 1345 | WM_CDTXOFF(start), sizeof(wiseman_txdesc_t) * num, ops); |
1359 | } | | 1346 | } |
1360 | | | 1347 | |
1361 | static inline void | | 1348 | static inline void |
1362 | wm_cdrxsync(struct wm_softc *sc, int start, int ops) | | 1349 | wm_cdrxsync(struct wm_softc *sc, int start, int ops) |
1363 | { | | 1350 | { |
1364 | | | 1351 | |
1365 | bus_dmamap_sync(sc->sc_dmat, sc->sc_cddmamap, | | 1352 | bus_dmamap_sync(sc->sc_dmat, sc->sc_rxdesc_dmamap, |
1366 | WM_CDRXOFF(start), sizeof(wiseman_rxdesc_t), ops); | | 1353 | WM_CDRXOFF(start), sizeof(wiseman_rxdesc_t), ops); |
1367 | } | | 1354 | } |
1368 | | | 1355 | |
1369 | static inline void | | 1356 | static inline void |
1370 | wm_init_rxdesc(struct wm_softc *sc, int start) | | 1357 | wm_init_rxdesc(struct wm_softc *sc, int start) |
1371 | { | | 1358 | { |
1372 | struct wm_rxsoft *rxs = &sc->sc_rxsoft[start]; | | 1359 | struct wm_rxsoft *rxs = &sc->sc_rxsoft[start]; |
1373 | wiseman_rxdesc_t *rxd = &sc->sc_rxdescs[start]; | | 1360 | wiseman_rxdesc_t *rxd = &sc->sc_rxdescs[start]; |
1374 | struct mbuf *m = rxs->rxs_mbuf; | | 1361 | struct mbuf *m = rxs->rxs_mbuf; |
1375 | | | 1362 | |
1376 | /* | | 1363 | /* |
1377 | * Note: We scoot the packet forward 2 bytes in the buffer | | 1364 | * Note: We scoot the packet forward 2 bytes in the buffer |
1378 | * so that the payload after the Ethernet header is aligned | | 1365 | * so that the payload after the Ethernet header is aligned |
| @@ -5086,100 +5073,175 @@ wm_82547_txfifo_bugchk(struct wm_softc * | | | @@ -5086,100 +5073,175 @@ wm_82547_txfifo_bugchk(struct wm_softc * |
5086 | callout_schedule(&sc->sc_txfifo_ch, 1); | | 5073 | callout_schedule(&sc->sc_txfifo_ch, 1); |
5087 | return 1; | | 5074 | return 1; |
5088 | } | | 5075 | } |
5089 | | | 5076 | |
5090 | send_packet: | | 5077 | send_packet: |
5091 | sc->sc_txfifo_head += len; | | 5078 | sc->sc_txfifo_head += len; |
5092 | if (sc->sc_txfifo_head >= sc->sc_txfifo_size) | | 5079 | if (sc->sc_txfifo_head >= sc->sc_txfifo_size) |
5093 | sc->sc_txfifo_head -= sc->sc_txfifo_size; | | 5080 | sc->sc_txfifo_head -= sc->sc_txfifo_size; |
5094 | | | 5081 | |
5095 | return 0; | | 5082 | return 0; |
5096 | } | | 5083 | } |
5097 | | | 5084 | |
5098 | static int | | 5085 | static int |
5099 | wm_alloc_descs(struct wm_softc *sc) | | 5086 | wm_alloc_tx_descs(struct wm_softc *sc) |
| | | 5087 | { |
| | | 5088 | int error; |
| | | 5089 | |
| | | 5090 | /* |
| | | 5091 | * Allocate the control data structures, and create and load the |
| | | 5092 | * DMA map for it. |
| | | 5093 | * |
| | | 5094 | * NOTE: All Tx descriptors must be in the same 4G segment of |
| | | 5095 | * memory. So must Rx descriptors. We simplify by allocating |
| | | 5096 | * both sets within the same 4G segment. |
| | | 5097 | */ |
| | | 5098 | if (sc->sc_type < WM_T_82544) { |
| | | 5099 | WM_NTXDESC(sc) = WM_NTXDESC_82542; |
| | | 5100 | sc->sc_txdesc_size = sizeof(wiseman_txdesc_t) * WM_NTXDESC(sc); |
| | | 5101 | } else { |
| | | 5102 | WM_NTXDESC(sc) = WM_NTXDESC_82544; |
| | | 5103 | sc->sc_txdesc_size = sizeof(txdescs_t); |
| | | 5104 | } |
| | | 5105 | |
| | | 5106 | if ((error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_txdesc_size, PAGE_SIZE, |
| | | 5107 | (bus_size_t) 0x100000000ULL, &sc->sc_txdesc_seg, 1, |
| | | 5108 | &sc->sc_txdesc_rseg, 0)) != 0) { |
| | | 5109 | aprint_error_dev(sc->sc_dev, |
| | | 5110 | "unable to allocate TX control data, error = %d\n", |
| | | 5111 | error); |
| | | 5112 | goto fail_0; |
| | | 5113 | } |
| | | 5114 | |
| | | 5115 | if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_txdesc_seg, |
| | | 5116 | sc->sc_txdesc_rseg, sc->sc_txdesc_size, |
| | | 5117 | (void **)&sc->sc_txdescs_u, BUS_DMA_COHERENT)) != 0) { |
| | | 5118 | aprint_error_dev(sc->sc_dev, |
| | | 5119 | "unable to map TX control data, error = %d\n", error); |
| | | 5120 | goto fail_1; |
| | | 5121 | } |
| | | 5122 | |
| | | 5123 | if ((error = bus_dmamap_create(sc->sc_dmat, sc->sc_txdesc_size, 1, |
| | | 5124 | sc->sc_txdesc_size, 0, 0, &sc->sc_txdesc_dmamap)) != 0) { |
| | | 5125 | aprint_error_dev(sc->sc_dev, |
| | | 5126 | "unable to create TX control data DMA map, error = %d\n", |
| | | 5127 | error); |
| | | 5128 | goto fail_2; |
| | | 5129 | } |
| | | 5130 | |
| | | 5131 | if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_txdesc_dmamap, |
| | | 5132 | sc->sc_txdescs_u, sc->sc_txdesc_size, NULL, 0)) != 0) { |
| | | 5133 | aprint_error_dev(sc->sc_dev, |
| | | 5134 | "unable to load TX control data DMA map, error = %d\n", |
| | | 5135 | error); |
| | | 5136 | goto fail_3; |
| | | 5137 | } |
| | | 5138 | |
| | | 5139 | return 0; |
| | | 5140 | |
| | | 5141 | fail_3: |
| | | 5142 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_txdesc_dmamap); |
| | | 5143 | fail_2: |
| | | 5144 | bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_txdescs_u, |
| | | 5145 | sc->sc_txdesc_size); |
| | | 5146 | fail_1: |
| | | 5147 | bus_dmamem_free(sc->sc_dmat, &sc->sc_txdesc_seg, sc->sc_txdesc_rseg); |
| | | 5148 | fail_0: |
| | | 5149 | return error; |
| | | 5150 | } |
| | | 5151 | |
| | | 5152 | static void |
| | | 5153 | wm_free_tx_descs(struct wm_softc *sc) |
| | | 5154 | { |
| | | 5155 | |
| | | 5156 | bus_dmamap_unload(sc->sc_dmat, sc->sc_txdesc_dmamap); |
| | | 5157 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_txdesc_dmamap); |
| | | 5158 | bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_txdescs_u, |
| | | 5159 | sc->sc_txdesc_size); |
| | | 5160 | bus_dmamem_free(sc->sc_dmat, &sc->sc_txdesc_seg, sc->sc_txdesc_rseg); |
| | | 5161 | } |
| | | 5162 | |
| | | 5163 | static int |
| | | 5164 | wm_alloc_rx_descs(struct wm_softc *sc) |
5100 | { | | 5165 | { |
5101 | int error; | | 5166 | int error; |
5102 | | | 5167 | |
5103 | /* | | 5168 | /* |
5104 | * Allocate the control data structures, and create and load the | | 5169 | * Allocate the control data structures, and create and load the |
5105 | * DMA map for it. | | 5170 | * DMA map for it. |
5106 | * | | 5171 | * |
5107 | * NOTE: All Tx descriptors must be in the same 4G segment of | | 5172 | * NOTE: All Tx descriptors must be in the same 4G segment of |
5108 | * memory. So must Rx descriptors. We simplify by allocating | | 5173 | * memory. So must Rx descriptors. We simplify by allocating |
5109 | * both sets within the same 4G segment. | | 5174 | * both sets within the same 4G segment. |
5110 | */ | | 5175 | */ |
5111 | WM_NTXDESC(sc) = sc->sc_type < WM_T_82544 ? | | 5176 | sc->sc_rxdesc_size = sizeof(wiseman_rxdesc_t) * WM_NRXDESC; |
5112 | WM_NTXDESC_82542 : WM_NTXDESC_82544; | | 5177 | if ((error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_rxdesc_size, PAGE_SIZE, |
5113 | sc->sc_cd_size = sc->sc_type < WM_T_82544 ? | | 5178 | (bus_size_t) 0x100000000ULL, &sc->sc_rxdesc_seg, 1, |
5114 | sizeof(struct wm_control_data_82542) : | | 5179 | &sc->sc_rxdesc_rseg, 0)) != 0) { |
5115 | sizeof(struct wm_control_data_82544); | | | |
5116 | if ((error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_cd_size, PAGE_SIZE, | | | |
5117 | (bus_size_t) 0x100000000ULL, &sc->sc_cd_seg, 1, | | | |
5118 | &sc->sc_cd_rseg, 0)) != 0) { | | | |
5119 | aprint_error_dev(sc->sc_dev, | | 5180 | aprint_error_dev(sc->sc_dev, |
5120 | "unable to allocate control data, error = %d\n", | | 5181 | "unable to allocate RX control data, error = %d\n", |
5121 | error); | | 5182 | error); |
5122 | goto fail_0; | | 5183 | goto fail_0; |
5123 | } | | 5184 | } |
5124 | | | 5185 | |
5125 | if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_cd_seg, | | 5186 | if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_rxdesc_seg, |
5126 | sc->sc_cd_rseg, sc->sc_cd_size, | | 5187 | sc->sc_rxdesc_rseg, sc->sc_rxdesc_size, |
5127 | (void **)&sc->sc_control_data, BUS_DMA_COHERENT)) != 0) { | | 5188 | (void **)&sc->sc_rxdescs, BUS_DMA_COHERENT)) != 0) { |
5128 | aprint_error_dev(sc->sc_dev, | | 5189 | aprint_error_dev(sc->sc_dev, |
5129 | "unable to map control data, error = %d\n", error); | | 5190 | "unable to map RX control data, error = %d\n", error); |
5130 | goto fail_1; | | 5191 | goto fail_1; |
5131 | } | | 5192 | } |
5132 | | | 5193 | |
5133 | if ((error = bus_dmamap_create(sc->sc_dmat, sc->sc_cd_size, 1, | | 5194 | if ((error = bus_dmamap_create(sc->sc_dmat, sc->sc_rxdesc_size, 1, |
5134 | sc->sc_cd_size, 0, 0, &sc->sc_cddmamap)) != 0) { | | 5195 | sc->sc_rxdesc_size, 0, 0, &sc->sc_rxdesc_dmamap)) != 0) { |
5135 | aprint_error_dev(sc->sc_dev, | | 5196 | aprint_error_dev(sc->sc_dev, |
5136 | "unable to create control data DMA map, error = %d\n", | | 5197 | "unable to create RX control data DMA map, error = %d\n", |
5137 | error); | | 5198 | error); |
5138 | goto fail_2; | | 5199 | goto fail_2; |
5139 | } | | 5200 | } |
5140 | | | 5201 | |
5141 | if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_cddmamap, | | 5202 | if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_rxdesc_dmamap, |
5142 | sc->sc_control_data, sc->sc_cd_size, NULL, 0)) != 0) { | | 5203 | sc->sc_rxdescs, sc->sc_rxdesc_size, NULL, 0)) != 0) { |
5143 | aprint_error_dev(sc->sc_dev, | | 5204 | aprint_error_dev(sc->sc_dev, |
5144 | "unable to load control data DMA map, error = %d\n", | | 5205 | "unable to load RX control data DMA map, error = %d\n", |
5145 | error); | | 5206 | error); |
5146 | goto fail_3; | | 5207 | goto fail_3; |
5147 | } | | 5208 | } |
5148 | | | 5209 | |
5149 | return 0; | | 5210 | return 0; |
5150 | | | 5211 | |
5151 | fail_3: | | 5212 | fail_3: |
5152 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); | | 5213 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_rxdesc_dmamap); |
5153 | fail_2: | | 5214 | fail_2: |
5154 | bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data, | | 5215 | bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_rxdescs, |
5155 | sc->sc_cd_size); | | 5216 | sc->sc_rxdesc_size); |
5156 | fail_1: | | 5217 | fail_1: |
5157 | bus_dmamem_free(sc->sc_dmat, &sc->sc_cd_seg, sc->sc_cd_rseg); | | 5218 | bus_dmamem_free(sc->sc_dmat, &sc->sc_rxdesc_seg, sc->sc_rxdesc_rseg); |
5158 | fail_0: | | 5219 | fail_0: |
5159 | return error; | | 5220 | return error; |
5160 | } | | 5221 | } |
5161 | | | 5222 | |
5162 | static void | | 5223 | static void |
5163 | wm_free_descs(struct wm_softc *sc) | | 5224 | wm_free_rx_descs(struct wm_softc *sc) |
5164 | { | | 5225 | { |
5165 | | | 5226 | |
5166 | bus_dmamap_unload(sc->sc_dmat, sc->sc_cddmamap); | | 5227 | bus_dmamap_unload(sc->sc_dmat, sc->sc_rxdesc_dmamap); |
5167 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_cddmamap); | | 5228 | bus_dmamap_destroy(sc->sc_dmat, sc->sc_rxdesc_dmamap); |
5168 | bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_control_data, | | 5229 | bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_rxdescs, |
5169 | sc->sc_cd_size); | | 5230 | sc->sc_rxdesc_size); |
5170 | bus_dmamem_free(sc->sc_dmat, &sc->sc_cd_seg, sc->sc_cd_rseg); | | 5231 | bus_dmamem_free(sc->sc_dmat, &sc->sc_rxdesc_seg, sc->sc_rxdesc_rseg); |
5171 | } | | 5232 | } |
5172 | | | 5233 | |
| | | 5234 | |
5173 | static int | | 5235 | static int |
5174 | wm_alloc_tx_buffer(struct wm_softc *sc) | | 5236 | wm_alloc_tx_buffer(struct wm_softc *sc) |
5175 | { | | 5237 | { |
5176 | int i, error; | | 5238 | int i, error; |
5177 | | | 5239 | |
5178 | /* Create the transmit buffer DMA maps. */ | | 5240 | /* Create the transmit buffer DMA maps. */ |
5179 | WM_TXQUEUELEN(sc) = | | 5241 | WM_TXQUEUELEN(sc) = |
5180 | (sc->sc_type == WM_T_82547 || sc->sc_type == WM_T_82547_2) ? | | 5242 | (sc->sc_type == WM_T_82547 || sc->sc_type == WM_T_82547_2) ? |
5181 | WM_TXQUEUELEN_MAX_82547 : WM_TXQUEUELEN_MAX; | | 5243 | WM_TXQUEUELEN_MAX_82547 : WM_TXQUEUELEN_MAX; |
5182 | for (i = 0; i < WM_TXQUEUELEN(sc); i++) { | | 5244 | for (i = 0; i < WM_TXQUEUELEN(sc); i++) { |
5183 | if ((error = bus_dmamap_create(sc->sc_dmat, WM_MAXTXDMA, | | 5245 | if ((error = bus_dmamap_create(sc->sc_dmat, WM_MAXTXDMA, |
5184 | WM_NTXSEGS, WTX_MAX_LEN, 0, 0, | | 5246 | WM_NTXSEGS, WTX_MAX_LEN, 0, 0, |
5185 | &sc->sc_txsoft[i].txs_dmamap)) != 0) { | | 5247 | &sc->sc_txsoft[i].txs_dmamap)) != 0) { |
| @@ -5253,59 +5315,72 @@ wm_free_rx_buffer(struct wm_softc *sc) | | | @@ -5253,59 +5315,72 @@ wm_free_rx_buffer(struct wm_softc *sc) |
5253 | sc->sc_rxsoft[i].rxs_dmamap); | | 5315 | sc->sc_rxsoft[i].rxs_dmamap); |
5254 | } | | 5316 | } |
5255 | } | | 5317 | } |
5256 | | | 5318 | |
5257 | /* | | 5319 | /* |
5258 | * wm_alloc_quques: | | 5320 | * wm_alloc_quques: |
5259 | * Allocate {tx,rx}descs and {tx,rx} buffers | | 5321 | * Allocate {tx,rx}descs and {tx,rx} buffers |
5260 | */ | | 5322 | */ |
5261 | static int | | 5323 | static int |
5262 | wm_alloc_txrx_queues(struct wm_softc *sc) | | 5324 | wm_alloc_txrx_queues(struct wm_softc *sc) |
5263 | { | | 5325 | { |
5264 | int error; | | 5326 | int error; |
5265 | | | 5327 | |
5266 | error = wm_alloc_descs(sc); | | 5328 | /* |
| | | 5329 | * For transmission |
| | | 5330 | */ |
| | | 5331 | error = wm_alloc_tx_descs(sc); |
5267 | if (error) | | 5332 | if (error) |
5268 | goto fail_0; | | 5333 | goto fail_0; |
5269 | | | 5334 | |
5270 | error = wm_alloc_tx_buffer(sc); | | 5335 | error = wm_alloc_tx_buffer(sc); |
5271 | if (error) | | 5336 | if (error) |
5272 | goto fail_1; | | 5337 | goto fail_1; |
5273 | | | 5338 | |
5274 | error = wm_alloc_rx_buffer(sc); | | 5339 | /* |
| | | 5340 | * For recieve |
| | | 5341 | */ |
| | | 5342 | error = wm_alloc_rx_descs(sc); |
5275 | if (error) | | 5343 | if (error) |
5276 | goto fail_2; | | 5344 | goto fail_2; |
5277 | | | 5345 | |
| | | 5346 | error = wm_alloc_rx_buffer(sc); |
| | | 5347 | if (error) |
| | | 5348 | goto fail_3; |
| | | 5349 | |
5278 | return 0; | | 5350 | return 0; |
5279 | | | 5351 | |
| | | 5352 | fail_3: |
| | | 5353 | wm_free_rx_descs(sc); |
5280 | fail_2: | | 5354 | fail_2: |
5281 | wm_free_tx_buffer(sc); | | 5355 | wm_free_tx_buffer(sc); |
5282 | fail_1: | | 5356 | fail_1: |
5283 | wm_free_descs(sc); | | 5357 | wm_free_tx_descs(sc); |
5284 | fail_0: | | 5358 | fail_0: |
5285 | return error; | | 5359 | return error; |
5286 | } | | 5360 | } |
5287 | | | 5361 | |
5288 | /* | | 5362 | /* |
5289 | * wm_free_quques: | | 5363 | * wm_free_quques: |
5290 | * Free {tx,rx}descs and {tx,rx} buffers | | 5364 | * Free {tx,rx}descs and {tx,rx} buffers |
5291 | */ | | 5365 | */ |
5292 | static void | | 5366 | static void |
5293 | wm_free_txrx_queues(struct wm_softc *sc) | | 5367 | wm_free_txrx_queues(struct wm_softc *sc) |
5294 | { | | 5368 | { |
5295 | | | 5369 | |
5296 | wm_free_rx_buffer(sc); | | 5370 | wm_free_rx_buffer(sc); |
| | | 5371 | wm_free_rx_descs(sc); |
5297 | wm_free_tx_buffer(sc); | | 5372 | wm_free_tx_buffer(sc); |
5298 | wm_free_descs(sc); | | 5373 | wm_free_tx_descs(sc); |
5299 | } | | 5374 | } |
5300 | | | 5375 | |
5301 | /* | | 5376 | /* |
5302 | * wm_start: [ifnet interface function] | | 5377 | * wm_start: [ifnet interface function] |
5303 | * | | 5378 | * |
5304 | * Start packet transmission on the interface. | | 5379 | * Start packet transmission on the interface. |
5305 | */ | | 5380 | */ |
5306 | static void | | 5381 | static void |
5307 | wm_start(struct ifnet *ifp) | | 5382 | wm_start(struct ifnet *ifp) |
5308 | { | | 5383 | { |
5309 | struct wm_softc *sc = ifp->if_softc; | | 5384 | struct wm_softc *sc = ifp->if_softc; |
5310 | | | 5385 | |
5311 | WM_TX_LOCK(sc); | | 5386 | WM_TX_LOCK(sc); |