| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: if_wm.c,v 1.357 2015/10/13 08:11:31 knakahara Exp $ */ | | 1 | /* $NetBSD: if_wm.c,v 1.358 2015/10/13 08:14:27 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.357 2015/10/13 08:11:31 knakahara Exp $"); | | 86 | __KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.358 2015/10/13 08:14:27 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/kmem.h> | | 97 | #include <sys/kmem.h> |
98 | #include <sys/kernel.h> | | 98 | #include <sys/kernel.h> |
99 | #include <sys/socket.h> | | 99 | #include <sys/socket.h> |
| @@ -572,29 +572,30 @@ static void wm_rxdrain(struct wm_softc * | | | @@ -572,29 +572,30 @@ static void wm_rxdrain(struct wm_softc * |
572 | static int wm_init(struct ifnet *); | | 572 | static int wm_init(struct ifnet *); |
573 | static int wm_init_locked(struct ifnet *); | | 573 | static int wm_init_locked(struct ifnet *); |
574 | static void wm_stop(struct ifnet *, int); | | 574 | static void wm_stop(struct ifnet *, int); |
575 | static void wm_stop_locked(struct ifnet *, int); | | 575 | static void wm_stop_locked(struct ifnet *, int); |
576 | static int wm_tx_offload(struct wm_softc *, struct wm_txsoft *, | | 576 | static int wm_tx_offload(struct wm_softc *, struct wm_txsoft *, |
577 | uint32_t *, uint8_t *); | | 577 | uint32_t *, uint8_t *); |
578 | static void wm_dump_mbuf_chain(struct wm_softc *, struct mbuf *); | | 578 | static void wm_dump_mbuf_chain(struct wm_softc *, struct mbuf *); |
579 | static void wm_82547_txfifo_stall(void *); | | 579 | static void wm_82547_txfifo_stall(void *); |
580 | static int wm_82547_txfifo_bugchk(struct wm_softc *, struct mbuf *); | | 580 | static int wm_82547_txfifo_bugchk(struct wm_softc *, struct mbuf *); |
581 | /* DMA related */ | | 581 | /* DMA related */ |
582 | static int wm_alloc_tx_descs(struct wm_softc *); | | 582 | static int wm_alloc_tx_descs(struct wm_softc *); |
583 | static void wm_free_tx_descs(struct wm_softc *); | | 583 | static void wm_free_tx_descs(struct wm_softc *); |
584 | static void wm_init_tx_descs(struct wm_softc *); | | 584 | static void wm_init_tx_descs(struct wm_softc *); |
| | | 585 | static void wm_init_tx_regs(struct wm_softc *); |
585 | static int wm_alloc_rx_descs(struct wm_softc *); | | 586 | static int wm_alloc_rx_descs(struct wm_softc *); |
586 | static void wm_free_rx_descs(struct wm_softc *); | | 587 | static void wm_free_rx_descs(struct wm_softc *); |
587 | static void wm_init_rx_descs(struct wm_softc *); | | 588 | static void wm_init_rx_regs(struct wm_softc *); |
588 | static int wm_alloc_tx_buffer(struct wm_softc *); | | 589 | static int wm_alloc_tx_buffer(struct wm_softc *); |
589 | static void wm_free_tx_buffer(struct wm_softc *); | | 590 | static void wm_free_tx_buffer(struct wm_softc *); |
590 | static void wm_init_tx_buffer(struct wm_softc *); | | 591 | static void wm_init_tx_buffer(struct wm_softc *); |
591 | static int wm_alloc_rx_buffer(struct wm_softc *); | | 592 | static int wm_alloc_rx_buffer(struct wm_softc *); |
592 | static void wm_free_rx_buffer(struct wm_softc *); | | 593 | static void wm_free_rx_buffer(struct wm_softc *); |
593 | static int wm_init_rx_buffer(struct wm_softc *); | | 594 | static int wm_init_rx_buffer(struct wm_softc *); |
594 | static void wm_init_tx_queue(struct wm_softc *); | | 595 | static void wm_init_tx_queue(struct wm_softc *); |
595 | static int wm_init_rx_queue(struct wm_softc *); | | 596 | static int wm_init_rx_queue(struct wm_softc *); |
596 | static int wm_alloc_txrx_queues(struct wm_softc *); | | 597 | static int wm_alloc_txrx_queues(struct wm_softc *); |
597 | static void wm_free_txrx_queues(struct wm_softc *); | | 598 | static void wm_free_txrx_queues(struct wm_softc *); |
598 | static int wm_init_txrx_queues(struct wm_softc *); | | 599 | static int wm_init_txrx_queues(struct wm_softc *); |
599 | /* Start */ | | 600 | /* Start */ |
600 | static void wm_start(struct ifnet *); | | 601 | static void wm_start(struct ifnet *); |
| @@ -5355,26 +5356,34 @@ wm_free_txrx_queues(struct wm_softc *sc) | | | @@ -5355,26 +5356,34 @@ wm_free_txrx_queues(struct wm_softc *sc) |
5355 | static void | | 5356 | static void |
5356 | wm_init_tx_descs(struct wm_softc *sc) | | 5357 | wm_init_tx_descs(struct wm_softc *sc) |
5357 | { | | 5358 | { |
5358 | struct wm_txqueue *txq = sc->sc_txq; | | 5359 | struct wm_txqueue *txq = sc->sc_txq; |
5359 | | | 5360 | |
5360 | KASSERT(WM_TX_LOCKED(txq)); | | 5361 | KASSERT(WM_TX_LOCKED(txq)); |
5361 | | | 5362 | |
5362 | /* Initialize the transmit descriptor ring. */ | | 5363 | /* Initialize the transmit descriptor ring. */ |
5363 | memset(txq->txq_descs, 0, WM_TXDESCSIZE(txq)); | | 5364 | memset(txq->txq_descs, 0, WM_TXDESCSIZE(txq)); |
5364 | wm_cdtxsync(sc, 0, WM_NTXDESC(txq), | | 5365 | wm_cdtxsync(sc, 0, WM_NTXDESC(txq), |
5365 | BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); | | 5366 | BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); |
5366 | txq->txq_free = WM_NTXDESC(txq); | | 5367 | txq->txq_free = WM_NTXDESC(txq); |
5367 | txq->txq_next = 0; | | 5368 | txq->txq_next = 0; |
| | | 5369 | } |
| | | 5370 | |
| | | 5371 | static void |
| | | 5372 | wm_init_tx_regs(struct wm_softc *sc) |
| | | 5373 | { |
| | | 5374 | struct wm_txqueue *txq = sc->sc_txq; |
| | | 5375 | |
| | | 5376 | KASSERT(WM_TX_LOCKED(txq)); |
5368 | | | 5377 | |
5369 | if (sc->sc_type < WM_T_82543) { | | 5378 | if (sc->sc_type < WM_T_82543) { |
5370 | CSR_WRITE(sc, WMREG_OLD_TDBAH, WM_CDTXADDR_HI(txq, 0)); | | 5379 | CSR_WRITE(sc, WMREG_OLD_TDBAH, WM_CDTXADDR_HI(txq, 0)); |
5371 | CSR_WRITE(sc, WMREG_OLD_TDBAL, WM_CDTXADDR_LO(txq, 0)); | | 5380 | CSR_WRITE(sc, WMREG_OLD_TDBAL, WM_CDTXADDR_LO(txq, 0)); |
5372 | CSR_WRITE(sc, WMREG_OLD_TDLEN, WM_TXDESCSIZE(txq)); | | 5381 | CSR_WRITE(sc, WMREG_OLD_TDLEN, WM_TXDESCSIZE(txq)); |
5373 | CSR_WRITE(sc, WMREG_OLD_TDH, 0); | | 5382 | CSR_WRITE(sc, WMREG_OLD_TDH, 0); |
5374 | CSR_WRITE(sc, WMREG_OLD_TDT, 0); | | 5383 | CSR_WRITE(sc, WMREG_OLD_TDT, 0); |
5375 | CSR_WRITE(sc, WMREG_OLD_TIDV, 128); | | 5384 | CSR_WRITE(sc, WMREG_OLD_TIDV, 128); |
5376 | } else { | | 5385 | } else { |
5377 | CSR_WRITE(sc, WMREG_TDBAH, WM_CDTXADDR_HI(txq, 0)); | | 5386 | CSR_WRITE(sc, WMREG_TDBAH, WM_CDTXADDR_HI(txq, 0)); |
5378 | CSR_WRITE(sc, WMREG_TDBAL, WM_CDTXADDR_LO(txq, 0)); | | 5387 | CSR_WRITE(sc, WMREG_TDBAL, WM_CDTXADDR_LO(txq, 0)); |
5379 | CSR_WRITE(sc, WMREG_TDLEN, WM_TXDESCSIZE(txq)); | | 5388 | CSR_WRITE(sc, WMREG_TDLEN, WM_TXDESCSIZE(txq)); |
5380 | CSR_WRITE(sc, WMREG_TDH, 0); | | 5389 | CSR_WRITE(sc, WMREG_TDH, 0); |
| @@ -5388,28 +5397,26 @@ wm_init_tx_descs(struct wm_softc *sc) | | | @@ -5388,28 +5397,26 @@ wm_init_tx_descs(struct wm_softc *sc) |
5388 | | TXDCTL_PTHRESH(0) | TXDCTL_HTHRESH(0) | | 5397 | | TXDCTL_PTHRESH(0) | TXDCTL_HTHRESH(0) |
5389 | | TXDCTL_WTHRESH(0)); | | 5398 | | TXDCTL_WTHRESH(0)); |
5390 | else { | | 5399 | else { |
5391 | /* ITR / 4 */ | | 5400 | /* ITR / 4 */ |
5392 | CSR_WRITE(sc, WMREG_TIDV, sc->sc_itr / 4); | | 5401 | CSR_WRITE(sc, WMREG_TIDV, sc->sc_itr / 4); |
5393 | if (sc->sc_type >= WM_T_82540) { | | 5402 | if (sc->sc_type >= WM_T_82540) { |
5394 | /* should be same */ | | 5403 | /* should be same */ |
5395 | CSR_WRITE(sc, WMREG_TADV, sc->sc_itr / 4); | | 5404 | CSR_WRITE(sc, WMREG_TADV, sc->sc_itr / 4); |
5396 | } | | 5405 | } |
5397 | | | 5406 | |
5398 | CSR_WRITE(sc, WMREG_TDT, 0); | | 5407 | CSR_WRITE(sc, WMREG_TDT, 0); |
5399 | CSR_WRITE(sc, WMREG_TXDCTL(0), TXDCTL_PTHRESH(0) | | | 5408 | CSR_WRITE(sc, WMREG_TXDCTL(0), TXDCTL_PTHRESH(0) | |
5400 | TXDCTL_HTHRESH(0) | TXDCTL_WTHRESH(0)); | | 5409 | TXDCTL_HTHRESH(0) | TXDCTL_WTHRESH(0)); |
5401 | CSR_WRITE(sc, WMREG_RXDCTL, RXDCTL_PTHRESH(0) | | | | |
5402 | RXDCTL_HTHRESH(0) | RXDCTL_WTHRESH(1)); | | | |
5403 | } | | 5410 | } |
5404 | } | | 5411 | } |
5405 | } | | 5412 | } |
5406 | | | 5413 | |
5407 | static void | | 5414 | static void |
5408 | wm_init_tx_buffer(struct wm_softc *sc) | | 5415 | wm_init_tx_buffer(struct wm_softc *sc) |
5409 | { | | 5416 | { |
5410 | struct wm_txqueue *txq = sc->sc_txq; | | 5417 | struct wm_txqueue *txq = sc->sc_txq; |
5411 | int i; | | 5418 | int i; |
5412 | | | 5419 | |
5413 | KASSERT(WM_TX_LOCKED(txq)); | | 5420 | KASSERT(WM_TX_LOCKED(txq)); |
5414 | | | 5421 | |
5415 | /* Initialize the transmit job descriptors. */ | | 5422 | /* Initialize the transmit job descriptors. */ |
| @@ -5428,31 +5435,32 @@ wm_init_tx_queue(struct wm_softc *sc) | | | @@ -5428,31 +5435,32 @@ wm_init_tx_queue(struct wm_softc *sc) |
5428 | KASSERT(WM_TX_LOCKED(txq)); | | 5435 | KASSERT(WM_TX_LOCKED(txq)); |
5429 | | | 5436 | |
5430 | /* | | 5437 | /* |
5431 | * Set up some register offsets that are different between | | 5438 | * Set up some register offsets that are different between |
5432 | * the i82542 and the i82543 and later chips. | | 5439 | * the i82542 and the i82543 and later chips. |
5433 | */ | | 5440 | */ |
5434 | if (sc->sc_type < WM_T_82543) { | | 5441 | if (sc->sc_type < WM_T_82543) { |
5435 | txq->txq_tdt_reg = WMREG_OLD_TDT; | | 5442 | txq->txq_tdt_reg = WMREG_OLD_TDT; |
5436 | } else { | | 5443 | } else { |
5437 | txq->txq_tdt_reg = WMREG_TDT; | | 5444 | txq->txq_tdt_reg = WMREG_TDT; |
5438 | } | | 5445 | } |
5439 | | | 5446 | |
5440 | wm_init_tx_descs(sc); | | 5447 | wm_init_tx_descs(sc); |
| | | 5448 | wm_init_tx_regs(sc); |
5441 | wm_init_tx_buffer(sc); | | 5449 | wm_init_tx_buffer(sc); |
5442 | } | | 5450 | } |
5443 | | | 5451 | |
5444 | static void | | 5452 | static void |
5445 | wm_init_rx_descs(struct wm_softc *sc) | | 5453 | wm_init_rx_regs(struct wm_softc *sc) |
5446 | { | | 5454 | { |
5447 | struct wm_rxqueue *rxq = sc->sc_rxq; | | 5455 | struct wm_rxqueue *rxq = sc->sc_rxq; |
5448 | | | 5456 | |
5449 | KASSERT(WM_RX_LOCKED(rxq)); | | 5457 | KASSERT(WM_RX_LOCKED(rxq)); |
5450 | | | 5458 | |
5451 | /* | | 5459 | /* |
5452 | * Initialize the receive descriptor and receive job | | 5460 | * Initialize the receive descriptor and receive job |
5453 | * descriptor rings. | | 5461 | * descriptor rings. |
5454 | */ | | 5462 | */ |
5455 | if (sc->sc_type < WM_T_82543) { | | 5463 | if (sc->sc_type < WM_T_82543) { |
5456 | CSR_WRITE(sc, WMREG_OLD_RDBAH0, WM_CDRXADDR_HI(rxq, 0)); | | 5464 | CSR_WRITE(sc, WMREG_OLD_RDBAH0, WM_CDRXADDR_HI(rxq, 0)); |
5457 | CSR_WRITE(sc, WMREG_OLD_RDBAL0, WM_CDRXADDR_LO(rxq, 0)); | | 5465 | CSR_WRITE(sc, WMREG_OLD_RDBAL0, WM_CDRXADDR_LO(rxq, 0)); |
5458 | CSR_WRITE(sc, WMREG_OLD_RDLEN0, | | 5466 | CSR_WRITE(sc, WMREG_OLD_RDLEN0, |
| @@ -5476,26 +5484,28 @@ wm_init_rx_descs(struct wm_softc *sc) | | | @@ -5476,26 +5484,28 @@ wm_init_rx_descs(struct wm_softc *sc) |
5476 | if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) { | | 5484 | if ((sc->sc_flags & WM_F_NEWQUEUE) != 0) { |
5477 | if (MCLBYTES & ((1 << SRRCTL_BSIZEPKT_SHIFT) - 1)) | | 5485 | if (MCLBYTES & ((1 << SRRCTL_BSIZEPKT_SHIFT) - 1)) |
5478 | panic("%s: MCLBYTES %d unsupported for i2575 or higher\n", __func__, MCLBYTES); | | 5486 | panic("%s: MCLBYTES %d unsupported for i2575 or higher\n", __func__, MCLBYTES); |
5479 | CSR_WRITE(sc, WMREG_SRRCTL, SRRCTL_DESCTYPE_LEGACY | | 5487 | CSR_WRITE(sc, WMREG_SRRCTL, SRRCTL_DESCTYPE_LEGACY |
5480 | | (MCLBYTES >> SRRCTL_BSIZEPKT_SHIFT)); | | 5488 | | (MCLBYTES >> SRRCTL_BSIZEPKT_SHIFT)); |
5481 | CSR_WRITE(sc, WMREG_RXDCTL, RXDCTL_QUEUE_ENABLE | | 5489 | CSR_WRITE(sc, WMREG_RXDCTL, RXDCTL_QUEUE_ENABLE |
5482 | | RXDCTL_PTHRESH(16) | RXDCTL_HTHRESH(8) | | 5490 | | RXDCTL_PTHRESH(16) | RXDCTL_HTHRESH(8) |
5483 | | RXDCTL_WTHRESH(1)); | | 5491 | | RXDCTL_WTHRESH(1)); |
5484 | } else { | | 5492 | } else { |
5485 | CSR_WRITE(sc, WMREG_RDH, 0); | | 5493 | CSR_WRITE(sc, WMREG_RDH, 0); |
5486 | CSR_WRITE(sc, WMREG_RDT, 0); | | 5494 | CSR_WRITE(sc, WMREG_RDT, 0); |
5487 | CSR_WRITE(sc, WMREG_RDTR, 375 | RDTR_FPD); /* ITR/4 */ | | 5495 | CSR_WRITE(sc, WMREG_RDTR, 375 | RDTR_FPD); /* ITR/4 */ |
5488 | CSR_WRITE(sc, WMREG_RADV, 375); /* MUST be same */ | | 5496 | CSR_WRITE(sc, WMREG_RADV, 375); /* MUST be same */ |
| | | 5497 | CSR_WRITE(sc, WMREG_RXDCTL, RXDCTL_PTHRESH(0) | |
| | | 5498 | RXDCTL_HTHRESH(0) | RXDCTL_WTHRESH(1)); |
5489 | } | | 5499 | } |
5490 | } | | 5500 | } |
5491 | } | | 5501 | } |
5492 | | | 5502 | |
5493 | static int | | 5503 | static int |
5494 | wm_init_rx_buffer(struct wm_softc *sc) | | 5504 | wm_init_rx_buffer(struct wm_softc *sc) |
5495 | { | | 5505 | { |
5496 | struct wm_rxqueue *rxq = sc->sc_rxq; | | 5506 | struct wm_rxqueue *rxq = sc->sc_rxq; |
5497 | struct wm_rxsoft *rxs; | | 5507 | struct wm_rxsoft *rxs; |
5498 | int error, i; | | 5508 | int error, i; |
5499 | | | 5509 | |
5500 | KASSERT(WM_RX_LOCKED(rxq)); | | 5510 | KASSERT(WM_RX_LOCKED(rxq)); |
5501 | | | 5511 | |
| @@ -5537,27 +5547,27 @@ wm_init_rx_queue(struct wm_softc *sc) | | | @@ -5537,27 +5547,27 @@ wm_init_rx_queue(struct wm_softc *sc) |
5537 | | | 5547 | |
5538 | KASSERT(WM_RX_LOCKED(rxq)); | | 5548 | KASSERT(WM_RX_LOCKED(rxq)); |
5539 | | | 5549 | |
5540 | /* | | 5550 | /* |
5541 | * Set up some register offsets that are different between | | 5551 | * Set up some register offsets that are different between |
5542 | * the i82542 and the i82543 and later chips. | | 5552 | * the i82542 and the i82543 and later chips. |
5543 | */ | | 5553 | */ |
5544 | if (sc->sc_type < WM_T_82543) { | | 5554 | if (sc->sc_type < WM_T_82543) { |
5545 | rxq->rxq_rdt_reg = WMREG_OLD_RDT0; | | 5555 | rxq->rxq_rdt_reg = WMREG_OLD_RDT0; |
5546 | } else { | | 5556 | } else { |
5547 | rxq->rxq_rdt_reg = WMREG_RDT; | | 5557 | rxq->rxq_rdt_reg = WMREG_RDT; |
5548 | } | | 5558 | } |
5549 | | | 5559 | |
5550 | wm_init_rx_descs(sc); | | 5560 | wm_init_rx_regs(sc); |
5551 | return wm_init_rx_buffer(sc); | | 5561 | return wm_init_rx_buffer(sc); |
5552 | } | | 5562 | } |
5553 | | | 5563 | |
5554 | /* | | 5564 | /* |
5555 | * wm_init_quques: | | 5565 | * wm_init_quques: |
5556 | * Initialize {tx,rx}descs and {tx,rx} buffers | | 5566 | * Initialize {tx,rx}descs and {tx,rx} buffers |
5557 | */ | | 5567 | */ |
5558 | static int | | 5568 | static int |
5559 | wm_init_txrx_queues(struct wm_softc *sc) | | 5569 | wm_init_txrx_queues(struct wm_softc *sc) |
5560 | { | | 5570 | { |
5561 | struct wm_txqueue *txq = sc->sc_txq; | | 5571 | struct wm_txqueue *txq = sc->sc_txq; |
5562 | struct wm_rxqueue *rxq = sc->sc_rxq; | | 5572 | struct wm_rxqueue *rxq = sc->sc_rxq; |
5563 | int error; | | 5573 | int error; |