2005-01-06 01:43:34 +00:00
|
|
|
/*-
|
2002-02-27 17:41:06 +00:00
|
|
|
* Copyright (C) 2001 Eduardo Horvath.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*
|
2002-07-10 10:24:23 +00:00
|
|
|
* from: NetBSD: gemvar.h,v 1.8 2002/05/15 02:36:12 matt Exp
|
2002-02-27 17:41:06 +00:00
|
|
|
*
|
|
|
|
* $FreeBSD$
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _IF_GEMVAR_H
|
|
|
|
#define _IF_GEMVAR_H
|
|
|
|
|
|
|
|
#include <sys/queue.h>
|
|
|
|
#include <sys/callout.h>
|
|
|
|
|
|
|
|
/*
|
2009-06-23 20:36:59 +00:00
|
|
|
* Transmit descriptor ring size - this is arbitrary, but allocate
|
2002-02-27 17:41:06 +00:00
|
|
|
* enough descriptors for 64 pending transmissions and 16 segments
|
2007-12-30 01:32:03 +00:00
|
|
|
* per packet. This limit is not actually enforced (packets with
|
|
|
|
* more segments can be sent, depending on the busdma backend); it
|
|
|
|
* is however used as an estimate for the TX window size.
|
2002-02-27 17:41:06 +00:00
|
|
|
*/
|
|
|
|
#define GEM_NTXSEGS 16
|
|
|
|
|
|
|
|
#define GEM_TXQUEUELEN 64
|
|
|
|
#define GEM_NTXDESC (GEM_TXQUEUELEN * GEM_NTXSEGS)
|
2003-01-06 22:09:01 +00:00
|
|
|
#define GEM_MAXTXFREE (GEM_NTXDESC - 1)
|
2002-02-27 17:41:06 +00:00
|
|
|
#define GEM_NTXDESC_MASK (GEM_NTXDESC - 1)
|
|
|
|
#define GEM_NEXTTX(x) ((x + 1) & GEM_NTXDESC_MASK)
|
|
|
|
|
|
|
|
/*
|
2009-06-23 20:36:59 +00:00
|
|
|
* Receive descriptor ring size - we have one RX buffer per incoming
|
2002-02-27 17:41:06 +00:00
|
|
|
* packet, so this logic is a little simpler.
|
|
|
|
*/
|
o Revert the part of if_gem.c rev. 1.35 which added a call to gem_stop()
to gem_attach() as the former access softc members not yet initialized
at that time and gem_reset() actually is enough to stop the chip. [1]
o Revise the use of gem_bitwait(); add bus_barrier() calls before calling
gem_bitwait() to ensure the respective bit has been written before we
starting polling on it and poll for the right bits to change, f.e. even
though we only reset RX we have to actually wait for both GEM_RESET_RX
and GEM_RESET_TX to clear. Add some additional gem_bitwait() calls in
places we've been missing them according to the GEM documentation.
Along with this some excessive DELAYs, which probably only were added
because of bugs in gem_bitwait() and its use in the first place, as
well as as have of an gem_bitwait() reimplementation in gem_reset_tx()
were removed.
o Add gem_reset_rxdma() and use it to deal with GEM_MAC_RX_OVERFLOW errors
more gracefully as unlike gem_init_locked() it resets the RX DMA engine
only, causing no link loss and the FIFOs not to be cleared. Also use it
deal with GEM_INTR_RX_TAG_ERR errors, with previously were unhandled.
This was based on information obtained from the Linux GEM and OpenSolaris
ERI drivers.
o Turn on workarounds for silicon bugs in the Apple GMAC variants.
This was based on information obtained from the Darwin GMAC and Linux GEM
drivers.
o Turn on "infinite" (i.e. maximum 31 * 64 bytes in length) DMA bursts.
This greatly improves especially RX performance.
o Optimize the RX path, this consists of:
- kicking the receiver as soon as we've a spare descriptor in gem_rint()
again instead of just once after all the ready ones have been handled;
- kicking the receiver the right way, i.e. as outlined in the GEM
documentation in batches of 4 and by pointing it to the descriptor
after the last valid one;
- calling gem_rint() before gem_tint() in gem_intr() as gem_tint() may
take quite a while;
- doubling the size of the RX ring to 256 descriptors.
Overall the RX performance of a GEM in a 1GHz Sun Fire V210 was improved
from ~100Mbit/s to ~850Mbit/s.
o In gem_add_rxbuf() don't assign the newly allocated mbuf to rxs_mbuf
before calling bus_dmamap_load_mbuf_sg(), if bus_dmamap_load_mbuf_sg()
fails we'll free the newly allocated mbuf, unable to recycle the
previous one but a NULL pointer dereference instead.
o In gem_init_locked() honor the return value of gem_meminit().
o Simplify gem_ringsize() and dont' return garbage in the default case.
Based on OpenBSD.
o Don't turn on MAC control, MIF and PCS interrupts unless GEM_DEBUG is
defined as we don't need/use these interrupts for operation.
o In gem_start_locked() sync the DMA maps of the descriptor rings before
every kick of the transmitter and not just once after enqueuing all
packets as the NIC might instantly start transmitting after we kicked
it the first time.
o Keep state of the link state and use it to enable or disable the MAC
in gem_mii_statchg() accordingly as well as to return early from
gem_start_locked() in case the link is down. [3]
o Initialize the maximum frame size to a sane value.
o In gem_mii_statchg() enable carrier extension if appropriate.
o Increment if_ierrors in case of an GEM_MAC_RX_OVERFLOW error and in
gem_eint(). [3]
o Handle IFF_ALLMULTI correctly; don't set it if we've turned promiscuous
group mode on and don't clear the flag if we've disabled promiscuous
group mode (these were mostly NOPs though). [2]
o Let gem_eint() also report GEM_INTR_PERR errors.
o Move setting sc_variant from gem_pci_probe() to gem_pci_attach() as
device probe methods are not supposed to touch the softc.
o Collapse sc_inited and sc_pci into bits for sc_flags.
o Add CTASSERTs ensuring that GEM_NRXDESC and GEM_NTXDESC are set to
legal values.
o Correctly set up for 802.3x flow control, though #ifdef out the code
that actually enables it as this needs more testing and mainly a proper
framework to support it.
o Correct and add some conversions from hard-coded functions names to
__func__ which were borked or forgotten in if_gem.c rev. 1.42.
o Use PCIR_BAR instead of a homegrown macro.
o Replace sc_enaddr[6] with sc_enaddr[ETHER_ADDR_LEN].
o In gem_pci_attach() in case attaching fails release the resources in
the opposite order they were allocated.
o Make gem_reset() static to if_gem.c as it's not needed outside that
module.
o Remove the GEM_GIGABIT flag and the associated code; GEM_GIGABIT was
never set and the associated code was in the wrong place.
o Remove sc_mif_config; it was only used to cache the contents of the
respective register within gem_attach().
o Remove the #ifdef'ed out NetBSD/OpenBSD code for establishing a suspend
hook as it will never be used on FreeBSD.
o Also probe Apple Intrepid 2 GMAC and Apple Shasta GMAC, add support for
Apple K2 GMAC. Based on OpenBSD.
o Add support for Sun GBE/P cards, or in other words actually add support
for cards based on GEM to gem(4). This mainly consists of adding support
for the TBI of these chips. Along with this the PHY selection code was
rewritten to hardcode the PHY number for certain configurations as for
example the PHY of the on-board ERI of Blade 1000 shows up twice causing
no link as the second incarnation is isolated.
These changes were ported from OpenBSD with some additional improvements
and modulo some bugs.
o Add code to if_gem_pci.c allowing to read the MAC-address from the VPD on
systems without Open Firmware.
This is an improved version of my variant of the respective code in
if_hme_pci.c
o Now that gem(4) is MI enable it for all archs.
Pointed out by: yongari [1]
Suggested by: rwatson [2], yongari [3]
Tested on: i386 (GEM), powerpc (GMACs by marcel and yongari),
sparc64 (ERI and GEM)
Reviewed by: yongari
Approved by: re (kensmith)
2007-09-26 21:14:18 +00:00
|
|
|
#define GEM_NRXDESC 256
|
2002-02-27 17:41:06 +00:00
|
|
|
#define GEM_NRXDESC_MASK (GEM_NRXDESC - 1)
|
|
|
|
#define GEM_NEXTRX(x) ((x + 1) & GEM_NRXDESC_MASK)
|
|
|
|
|
2002-03-23 19:43:15 +00:00
|
|
|
/*
|
2007-12-30 01:32:03 +00:00
|
|
|
* How many ticks to wait until to retry on a RX descriptor that is
|
|
|
|
* still owned by the hardware.
|
2002-03-23 19:43:15 +00:00
|
|
|
*/
|
|
|
|
#define GEM_RXOWN_TICKS (hz / 50)
|
|
|
|
|
2002-02-27 17:41:06 +00:00
|
|
|
/*
|
2009-06-23 20:36:59 +00:00
|
|
|
* Control structures are DMA'd to the chip. We allocate them
|
2007-12-30 01:32:03 +00:00
|
|
|
* in a single clump that maps to a single DMA segment to make
|
|
|
|
* several things easier.
|
2002-02-27 17:41:06 +00:00
|
|
|
*/
|
|
|
|
struct gem_control_data {
|
2007-12-30 01:32:03 +00:00
|
|
|
struct gem_desc gcd_txdescs[GEM_NTXDESC]; /* TX descriptors */
|
|
|
|
struct gem_desc gcd_rxdescs[GEM_NRXDESC]; /* RX descriptors */
|
2002-02-27 17:41:06 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define GEM_CDOFF(x) offsetof(struct gem_control_data, x)
|
|
|
|
#define GEM_CDTXOFF(x) GEM_CDOFF(gcd_txdescs[(x)])
|
|
|
|
#define GEM_CDRXOFF(x) GEM_CDOFF(gcd_rxdescs[(x)])
|
|
|
|
|
|
|
|
/*
|
2007-12-30 01:32:03 +00:00
|
|
|
* software state for transmit job mbufs (may be elements of mbuf chains)
|
2002-02-27 17:41:06 +00:00
|
|
|
*/
|
|
|
|
struct gem_txsoft {
|
|
|
|
struct mbuf *txs_mbuf; /* head of our mbuf chain */
|
|
|
|
bus_dmamap_t txs_dmamap; /* our DMA map */
|
2009-06-23 20:36:59 +00:00
|
|
|
u_int txs_firstdesc; /* first descriptor in packet */
|
|
|
|
u_int txs_lastdesc; /* last descriptor in packet */
|
|
|
|
u_int txs_ndescs; /* number of descriptors */
|
2002-02-27 17:41:06 +00:00
|
|
|
STAILQ_ENTRY(gem_txsoft) txs_q;
|
|
|
|
};
|
|
|
|
|
|
|
|
STAILQ_HEAD(gem_txsq, gem_txsoft);
|
|
|
|
|
|
|
|
/*
|
2007-12-30 01:32:03 +00:00
|
|
|
* software state for receive jobs
|
2002-02-27 17:41:06 +00:00
|
|
|
*/
|
|
|
|
struct gem_rxsoft {
|
|
|
|
struct mbuf *rxs_mbuf; /* head of our mbuf chain */
|
|
|
|
bus_dmamap_t rxs_dmamap; /* our DMA map */
|
|
|
|
bus_addr_t rxs_paddr; /* physical address of the segment */
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
2007-12-30 01:32:03 +00:00
|
|
|
* software state per device
|
2002-02-27 17:41:06 +00:00
|
|
|
*/
|
|
|
|
struct gem_softc {
|
2005-06-10 16:49:24 +00:00
|
|
|
struct ifnet *sc_ifp;
|
o Revert the part of if_gem.c rev. 1.35 which added a call to gem_stop()
to gem_attach() as the former access softc members not yet initialized
at that time and gem_reset() actually is enough to stop the chip. [1]
o Revise the use of gem_bitwait(); add bus_barrier() calls before calling
gem_bitwait() to ensure the respective bit has been written before we
starting polling on it and poll for the right bits to change, f.e. even
though we only reset RX we have to actually wait for both GEM_RESET_RX
and GEM_RESET_TX to clear. Add some additional gem_bitwait() calls in
places we've been missing them according to the GEM documentation.
Along with this some excessive DELAYs, which probably only were added
because of bugs in gem_bitwait() and its use in the first place, as
well as as have of an gem_bitwait() reimplementation in gem_reset_tx()
were removed.
o Add gem_reset_rxdma() and use it to deal with GEM_MAC_RX_OVERFLOW errors
more gracefully as unlike gem_init_locked() it resets the RX DMA engine
only, causing no link loss and the FIFOs not to be cleared. Also use it
deal with GEM_INTR_RX_TAG_ERR errors, with previously were unhandled.
This was based on information obtained from the Linux GEM and OpenSolaris
ERI drivers.
o Turn on workarounds for silicon bugs in the Apple GMAC variants.
This was based on information obtained from the Darwin GMAC and Linux GEM
drivers.
o Turn on "infinite" (i.e. maximum 31 * 64 bytes in length) DMA bursts.
This greatly improves especially RX performance.
o Optimize the RX path, this consists of:
- kicking the receiver as soon as we've a spare descriptor in gem_rint()
again instead of just once after all the ready ones have been handled;
- kicking the receiver the right way, i.e. as outlined in the GEM
documentation in batches of 4 and by pointing it to the descriptor
after the last valid one;
- calling gem_rint() before gem_tint() in gem_intr() as gem_tint() may
take quite a while;
- doubling the size of the RX ring to 256 descriptors.
Overall the RX performance of a GEM in a 1GHz Sun Fire V210 was improved
from ~100Mbit/s to ~850Mbit/s.
o In gem_add_rxbuf() don't assign the newly allocated mbuf to rxs_mbuf
before calling bus_dmamap_load_mbuf_sg(), if bus_dmamap_load_mbuf_sg()
fails we'll free the newly allocated mbuf, unable to recycle the
previous one but a NULL pointer dereference instead.
o In gem_init_locked() honor the return value of gem_meminit().
o Simplify gem_ringsize() and dont' return garbage in the default case.
Based on OpenBSD.
o Don't turn on MAC control, MIF and PCS interrupts unless GEM_DEBUG is
defined as we don't need/use these interrupts for operation.
o In gem_start_locked() sync the DMA maps of the descriptor rings before
every kick of the transmitter and not just once after enqueuing all
packets as the NIC might instantly start transmitting after we kicked
it the first time.
o Keep state of the link state and use it to enable or disable the MAC
in gem_mii_statchg() accordingly as well as to return early from
gem_start_locked() in case the link is down. [3]
o Initialize the maximum frame size to a sane value.
o In gem_mii_statchg() enable carrier extension if appropriate.
o Increment if_ierrors in case of an GEM_MAC_RX_OVERFLOW error and in
gem_eint(). [3]
o Handle IFF_ALLMULTI correctly; don't set it if we've turned promiscuous
group mode on and don't clear the flag if we've disabled promiscuous
group mode (these were mostly NOPs though). [2]
o Let gem_eint() also report GEM_INTR_PERR errors.
o Move setting sc_variant from gem_pci_probe() to gem_pci_attach() as
device probe methods are not supposed to touch the softc.
o Collapse sc_inited and sc_pci into bits for sc_flags.
o Add CTASSERTs ensuring that GEM_NRXDESC and GEM_NTXDESC are set to
legal values.
o Correctly set up for 802.3x flow control, though #ifdef out the code
that actually enables it as this needs more testing and mainly a proper
framework to support it.
o Correct and add some conversions from hard-coded functions names to
__func__ which were borked or forgotten in if_gem.c rev. 1.42.
o Use PCIR_BAR instead of a homegrown macro.
o Replace sc_enaddr[6] with sc_enaddr[ETHER_ADDR_LEN].
o In gem_pci_attach() in case attaching fails release the resources in
the opposite order they were allocated.
o Make gem_reset() static to if_gem.c as it's not needed outside that
module.
o Remove the GEM_GIGABIT flag and the associated code; GEM_GIGABIT was
never set and the associated code was in the wrong place.
o Remove sc_mif_config; it was only used to cache the contents of the
respective register within gem_attach().
o Remove the #ifdef'ed out NetBSD/OpenBSD code for establishing a suspend
hook as it will never be used on FreeBSD.
o Also probe Apple Intrepid 2 GMAC and Apple Shasta GMAC, add support for
Apple K2 GMAC. Based on OpenBSD.
o Add support for Sun GBE/P cards, or in other words actually add support
for cards based on GEM to gem(4). This mainly consists of adding support
for the TBI of these chips. Along with this the PHY selection code was
rewritten to hardcode the PHY number for certain configurations as for
example the PHY of the on-board ERI of Blade 1000 shows up twice causing
no link as the second incarnation is isolated.
These changes were ported from OpenBSD with some additional improvements
and modulo some bugs.
o Add code to if_gem_pci.c allowing to read the MAC-address from the VPD on
systems without Open Firmware.
This is an improved version of my variant of the respective code in
if_hme_pci.c
o Now that gem(4) is MI enable it for all archs.
Pointed out by: yongari [1]
Suggested by: rwatson [2], yongari [3]
Tested on: i386 (GEM), powerpc (GMACs by marcel and yongari),
sparc64 (ERI and GEM)
Reviewed by: yongari
Approved by: re (kensmith)
2007-09-26 21:14:18 +00:00
|
|
|
struct mtx sc_mtx;
|
2002-02-27 17:41:06 +00:00
|
|
|
device_t sc_miibus;
|
|
|
|
struct mii_data *sc_mii; /* MII media control */
|
|
|
|
device_t sc_dev; /* generic device information */
|
o Revert the part of if_gem.c rev. 1.35 which added a call to gem_stop()
to gem_attach() as the former access softc members not yet initialized
at that time and gem_reset() actually is enough to stop the chip. [1]
o Revise the use of gem_bitwait(); add bus_barrier() calls before calling
gem_bitwait() to ensure the respective bit has been written before we
starting polling on it and poll for the right bits to change, f.e. even
though we only reset RX we have to actually wait for both GEM_RESET_RX
and GEM_RESET_TX to clear. Add some additional gem_bitwait() calls in
places we've been missing them according to the GEM documentation.
Along with this some excessive DELAYs, which probably only were added
because of bugs in gem_bitwait() and its use in the first place, as
well as as have of an gem_bitwait() reimplementation in gem_reset_tx()
were removed.
o Add gem_reset_rxdma() and use it to deal with GEM_MAC_RX_OVERFLOW errors
more gracefully as unlike gem_init_locked() it resets the RX DMA engine
only, causing no link loss and the FIFOs not to be cleared. Also use it
deal with GEM_INTR_RX_TAG_ERR errors, with previously were unhandled.
This was based on information obtained from the Linux GEM and OpenSolaris
ERI drivers.
o Turn on workarounds for silicon bugs in the Apple GMAC variants.
This was based on information obtained from the Darwin GMAC and Linux GEM
drivers.
o Turn on "infinite" (i.e. maximum 31 * 64 bytes in length) DMA bursts.
This greatly improves especially RX performance.
o Optimize the RX path, this consists of:
- kicking the receiver as soon as we've a spare descriptor in gem_rint()
again instead of just once after all the ready ones have been handled;
- kicking the receiver the right way, i.e. as outlined in the GEM
documentation in batches of 4 and by pointing it to the descriptor
after the last valid one;
- calling gem_rint() before gem_tint() in gem_intr() as gem_tint() may
take quite a while;
- doubling the size of the RX ring to 256 descriptors.
Overall the RX performance of a GEM in a 1GHz Sun Fire V210 was improved
from ~100Mbit/s to ~850Mbit/s.
o In gem_add_rxbuf() don't assign the newly allocated mbuf to rxs_mbuf
before calling bus_dmamap_load_mbuf_sg(), if bus_dmamap_load_mbuf_sg()
fails we'll free the newly allocated mbuf, unable to recycle the
previous one but a NULL pointer dereference instead.
o In gem_init_locked() honor the return value of gem_meminit().
o Simplify gem_ringsize() and dont' return garbage in the default case.
Based on OpenBSD.
o Don't turn on MAC control, MIF and PCS interrupts unless GEM_DEBUG is
defined as we don't need/use these interrupts for operation.
o In gem_start_locked() sync the DMA maps of the descriptor rings before
every kick of the transmitter and not just once after enqueuing all
packets as the NIC might instantly start transmitting after we kicked
it the first time.
o Keep state of the link state and use it to enable or disable the MAC
in gem_mii_statchg() accordingly as well as to return early from
gem_start_locked() in case the link is down. [3]
o Initialize the maximum frame size to a sane value.
o In gem_mii_statchg() enable carrier extension if appropriate.
o Increment if_ierrors in case of an GEM_MAC_RX_OVERFLOW error and in
gem_eint(). [3]
o Handle IFF_ALLMULTI correctly; don't set it if we've turned promiscuous
group mode on and don't clear the flag if we've disabled promiscuous
group mode (these were mostly NOPs though). [2]
o Let gem_eint() also report GEM_INTR_PERR errors.
o Move setting sc_variant from gem_pci_probe() to gem_pci_attach() as
device probe methods are not supposed to touch the softc.
o Collapse sc_inited and sc_pci into bits for sc_flags.
o Add CTASSERTs ensuring that GEM_NRXDESC and GEM_NTXDESC are set to
legal values.
o Correctly set up for 802.3x flow control, though #ifdef out the code
that actually enables it as this needs more testing and mainly a proper
framework to support it.
o Correct and add some conversions from hard-coded functions names to
__func__ which were borked or forgotten in if_gem.c rev. 1.42.
o Use PCIR_BAR instead of a homegrown macro.
o Replace sc_enaddr[6] with sc_enaddr[ETHER_ADDR_LEN].
o In gem_pci_attach() in case attaching fails release the resources in
the opposite order they were allocated.
o Make gem_reset() static to if_gem.c as it's not needed outside that
module.
o Remove the GEM_GIGABIT flag and the associated code; GEM_GIGABIT was
never set and the associated code was in the wrong place.
o Remove sc_mif_config; it was only used to cache the contents of the
respective register within gem_attach().
o Remove the #ifdef'ed out NetBSD/OpenBSD code for establishing a suspend
hook as it will never be used on FreeBSD.
o Also probe Apple Intrepid 2 GMAC and Apple Shasta GMAC, add support for
Apple K2 GMAC. Based on OpenBSD.
o Add support for Sun GBE/P cards, or in other words actually add support
for cards based on GEM to gem(4). This mainly consists of adding support
for the TBI of these chips. Along with this the PHY selection code was
rewritten to hardcode the PHY number for certain configurations as for
example the PHY of the on-board ERI of Blade 1000 shows up twice causing
no link as the second incarnation is isolated.
These changes were ported from OpenBSD with some additional improvements
and modulo some bugs.
o Add code to if_gem_pci.c allowing to read the MAC-address from the VPD on
systems without Open Firmware.
This is an improved version of my variant of the respective code in
if_hme_pci.c
o Now that gem(4) is MI enable it for all archs.
Pointed out by: yongari [1]
Suggested by: rwatson [2], yongari [3]
Tested on: i386 (GEM), powerpc (GMACs by marcel and yongari),
sparc64 (ERI and GEM)
Reviewed by: yongari
Approved by: re (kensmith)
2007-09-26 21:14:18 +00:00
|
|
|
u_char sc_enaddr[ETHER_ADDR_LEN];
|
2002-02-27 17:41:06 +00:00
|
|
|
struct callout sc_tick_ch; /* tick callout */
|
2007-12-30 01:32:03 +00:00
|
|
|
struct callout sc_rx_ch; /* delayed RX callout */
|
2009-06-23 20:36:59 +00:00
|
|
|
u_int sc_wdog_timer; /* watchdog timer */
|
2002-02-27 17:41:06 +00:00
|
|
|
|
2007-05-04 19:15:28 +00:00
|
|
|
void *sc_ih;
|
2008-03-24 17:23:53 +00:00
|
|
|
struct resource *sc_res[3];
|
|
|
|
#define GEM_RES_INTR 0
|
|
|
|
#define GEM_RES_BANK1 1
|
|
|
|
#define GEM_RES_BANK2 2
|
|
|
|
|
2007-12-30 01:32:03 +00:00
|
|
|
bus_dma_tag_t sc_pdmatag; /* parent bus DMA tag */
|
|
|
|
bus_dma_tag_t sc_rdmatag; /* RX bus DMA tag */
|
|
|
|
bus_dma_tag_t sc_tdmatag; /* TX bus DMA tag */
|
|
|
|
bus_dma_tag_t sc_cdmatag; /* control data bus DMA tag */
|
|
|
|
bus_dmamap_t sc_dmamap; /* bus DMA handle */
|
2002-02-27 17:41:06 +00:00
|
|
|
|
2007-12-30 01:32:03 +00:00
|
|
|
u_int sc_variant;
|
2002-07-10 10:24:23 +00:00
|
|
|
#define GEM_UNKNOWN 0 /* don't know */
|
o Revert the part of if_gem.c rev. 1.35 which added a call to gem_stop()
to gem_attach() as the former access softc members not yet initialized
at that time and gem_reset() actually is enough to stop the chip. [1]
o Revise the use of gem_bitwait(); add bus_barrier() calls before calling
gem_bitwait() to ensure the respective bit has been written before we
starting polling on it and poll for the right bits to change, f.e. even
though we only reset RX we have to actually wait for both GEM_RESET_RX
and GEM_RESET_TX to clear. Add some additional gem_bitwait() calls in
places we've been missing them according to the GEM documentation.
Along with this some excessive DELAYs, which probably only were added
because of bugs in gem_bitwait() and its use in the first place, as
well as as have of an gem_bitwait() reimplementation in gem_reset_tx()
were removed.
o Add gem_reset_rxdma() and use it to deal with GEM_MAC_RX_OVERFLOW errors
more gracefully as unlike gem_init_locked() it resets the RX DMA engine
only, causing no link loss and the FIFOs not to be cleared. Also use it
deal with GEM_INTR_RX_TAG_ERR errors, with previously were unhandled.
This was based on information obtained from the Linux GEM and OpenSolaris
ERI drivers.
o Turn on workarounds for silicon bugs in the Apple GMAC variants.
This was based on information obtained from the Darwin GMAC and Linux GEM
drivers.
o Turn on "infinite" (i.e. maximum 31 * 64 bytes in length) DMA bursts.
This greatly improves especially RX performance.
o Optimize the RX path, this consists of:
- kicking the receiver as soon as we've a spare descriptor in gem_rint()
again instead of just once after all the ready ones have been handled;
- kicking the receiver the right way, i.e. as outlined in the GEM
documentation in batches of 4 and by pointing it to the descriptor
after the last valid one;
- calling gem_rint() before gem_tint() in gem_intr() as gem_tint() may
take quite a while;
- doubling the size of the RX ring to 256 descriptors.
Overall the RX performance of a GEM in a 1GHz Sun Fire V210 was improved
from ~100Mbit/s to ~850Mbit/s.
o In gem_add_rxbuf() don't assign the newly allocated mbuf to rxs_mbuf
before calling bus_dmamap_load_mbuf_sg(), if bus_dmamap_load_mbuf_sg()
fails we'll free the newly allocated mbuf, unable to recycle the
previous one but a NULL pointer dereference instead.
o In gem_init_locked() honor the return value of gem_meminit().
o Simplify gem_ringsize() and dont' return garbage in the default case.
Based on OpenBSD.
o Don't turn on MAC control, MIF and PCS interrupts unless GEM_DEBUG is
defined as we don't need/use these interrupts for operation.
o In gem_start_locked() sync the DMA maps of the descriptor rings before
every kick of the transmitter and not just once after enqueuing all
packets as the NIC might instantly start transmitting after we kicked
it the first time.
o Keep state of the link state and use it to enable or disable the MAC
in gem_mii_statchg() accordingly as well as to return early from
gem_start_locked() in case the link is down. [3]
o Initialize the maximum frame size to a sane value.
o In gem_mii_statchg() enable carrier extension if appropriate.
o Increment if_ierrors in case of an GEM_MAC_RX_OVERFLOW error and in
gem_eint(). [3]
o Handle IFF_ALLMULTI correctly; don't set it if we've turned promiscuous
group mode on and don't clear the flag if we've disabled promiscuous
group mode (these were mostly NOPs though). [2]
o Let gem_eint() also report GEM_INTR_PERR errors.
o Move setting sc_variant from gem_pci_probe() to gem_pci_attach() as
device probe methods are not supposed to touch the softc.
o Collapse sc_inited and sc_pci into bits for sc_flags.
o Add CTASSERTs ensuring that GEM_NRXDESC and GEM_NTXDESC are set to
legal values.
o Correctly set up for 802.3x flow control, though #ifdef out the code
that actually enables it as this needs more testing and mainly a proper
framework to support it.
o Correct and add some conversions from hard-coded functions names to
__func__ which were borked or forgotten in if_gem.c rev. 1.42.
o Use PCIR_BAR instead of a homegrown macro.
o Replace sc_enaddr[6] with sc_enaddr[ETHER_ADDR_LEN].
o In gem_pci_attach() in case attaching fails release the resources in
the opposite order they were allocated.
o Make gem_reset() static to if_gem.c as it's not needed outside that
module.
o Remove the GEM_GIGABIT flag and the associated code; GEM_GIGABIT was
never set and the associated code was in the wrong place.
o Remove sc_mif_config; it was only used to cache the contents of the
respective register within gem_attach().
o Remove the #ifdef'ed out NetBSD/OpenBSD code for establishing a suspend
hook as it will never be used on FreeBSD.
o Also probe Apple Intrepid 2 GMAC and Apple Shasta GMAC, add support for
Apple K2 GMAC. Based on OpenBSD.
o Add support for Sun GBE/P cards, or in other words actually add support
for cards based on GEM to gem(4). This mainly consists of adding support
for the TBI of these chips. Along with this the PHY selection code was
rewritten to hardcode the PHY number for certain configurations as for
example the PHY of the on-board ERI of Blade 1000 shows up twice causing
no link as the second incarnation is isolated.
These changes were ported from OpenBSD with some additional improvements
and modulo some bugs.
o Add code to if_gem_pci.c allowing to read the MAC-address from the VPD on
systems without Open Firmware.
This is an improved version of my variant of the respective code in
if_hme_pci.c
o Now that gem(4) is MI enable it for all archs.
Pointed out by: yongari [1]
Suggested by: rwatson [2], yongari [3]
Tested on: i386 (GEM), powerpc (GMACs by marcel and yongari),
sparc64 (ERI and GEM)
Reviewed by: yongari
Approved by: re (kensmith)
2007-09-26 21:14:18 +00:00
|
|
|
#define GEM_SUN_GEM 1 /* Sun GEM */
|
|
|
|
#define GEM_SUN_ERI 2 /* Sun ERI */
|
|
|
|
#define GEM_APPLE_GMAC 3 /* Apple GMAC */
|
|
|
|
#define GEM_APPLE_K2_GMAC 4 /* Apple K2 GMAC */
|
|
|
|
|
|
|
|
#define GEM_IS_APPLE(sc) \
|
|
|
|
((sc)->sc_variant == GEM_APPLE_GMAC || \
|
|
|
|
(sc)->sc_variant == GEM_APPLE_K2_GMAC)
|
2002-07-10 10:24:23 +00:00
|
|
|
|
2007-12-30 01:32:03 +00:00
|
|
|
u_int sc_flags;
|
|
|
|
#define GEM_INITED (1 << 0) /* reset persistent regs init'ed */
|
2009-06-24 19:04:08 +00:00
|
|
|
#define GEM_LINK (1 << 1) /* link is up */
|
|
|
|
#define GEM_PCI (1 << 2) /* PCI busses are little-endian */
|
|
|
|
#define GEM_PCI66 (1 << 3) /* PCI bus runs at 66MHz */
|
|
|
|
#define GEM_SERDES (1 << 4) /* use the SERDES */
|
2002-02-27 17:41:06 +00:00
|
|
|
|
|
|
|
/*
|
2007-12-30 01:32:03 +00:00
|
|
|
* ring buffer DMA stuff
|
2002-02-27 17:41:06 +00:00
|
|
|
*/
|
|
|
|
bus_dmamap_t sc_cddmamap; /* control data DMA map */
|
|
|
|
bus_addr_t sc_cddma;
|
|
|
|
|
|
|
|
/*
|
2007-12-30 01:32:03 +00:00
|
|
|
* software state for transmit and receive descriptors
|
2002-02-27 17:41:06 +00:00
|
|
|
*/
|
|
|
|
struct gem_txsoft sc_txsoft[GEM_TXQUEUELEN];
|
|
|
|
struct gem_rxsoft sc_rxsoft[GEM_NRXDESC];
|
|
|
|
|
|
|
|
/*
|
2007-12-30 01:32:03 +00:00
|
|
|
* control data structures
|
2002-02-27 17:41:06 +00:00
|
|
|
*/
|
|
|
|
struct gem_control_data *sc_control_data;
|
|
|
|
#define sc_txdescs sc_control_data->gcd_txdescs
|
|
|
|
#define sc_rxdescs sc_control_data->gcd_rxdescs
|
|
|
|
|
2009-06-23 20:36:59 +00:00
|
|
|
u_int sc_txfree; /* number of free TX descriptors */
|
|
|
|
u_int sc_txnext; /* next ready TX descriptor */
|
|
|
|
u_int sc_txwin; /* TX desc. since last TX intr. */
|
2002-02-27 17:41:06 +00:00
|
|
|
|
2007-12-30 01:32:03 +00:00
|
|
|
struct gem_txsq sc_txfreeq; /* free TX descsofts */
|
|
|
|
struct gem_txsq sc_txdirtyq; /* dirty TX descsofts */
|
2002-02-27 17:41:06 +00:00
|
|
|
|
2009-06-23 20:36:59 +00:00
|
|
|
u_int sc_rxptr; /* next ready RX descriptor/state */
|
|
|
|
u_int sc_rxfifosize; /* RX FIFO size (bytes) */
|
2002-02-27 17:41:06 +00:00
|
|
|
|
2011-06-28 16:16:43 +00:00
|
|
|
uint32_t sc_mac_rxcfg; /* RX MAC conf. % GEM_MAC_RX_ENABLE */
|
|
|
|
|
2002-07-10 10:24:23 +00:00
|
|
|
int sc_ifflags;
|
2009-06-23 20:36:59 +00:00
|
|
|
u_long sc_csum_features;
|
2002-02-27 17:41:06 +00:00
|
|
|
};
|
|
|
|
|
2008-03-24 17:23:53 +00:00
|
|
|
#define GEM_BANKN_BARRIER(n, sc, offs, len, flags) \
|
|
|
|
bus_barrier((sc)->sc_res[(n)], (offs), (len), (flags))
|
|
|
|
#define GEM_BANK1_BARRIER(sc, offs, len, flags) \
|
|
|
|
GEM_BANKN_BARRIER(GEM_RES_BANK1, (sc), (offs), (len), (flags))
|
|
|
|
#define GEM_BANK2_BARRIER(sc, offs, len, flags) \
|
|
|
|
GEM_BANKN_BARRIER(GEM_RES_BANK2, (sc), (offs), (len), (flags))
|
|
|
|
|
|
|
|
#define GEM_BANKN_READ_M(n, m, sc, offs) \
|
|
|
|
bus_read_ ## m((sc)->sc_res[(n)], (offs))
|
|
|
|
#define GEM_BANK1_READ_1(sc, offs) \
|
|
|
|
GEM_BANKN_READ_M(GEM_RES_BANK1, 1, (sc), (offs))
|
|
|
|
#define GEM_BANK1_READ_2(sc, offs) \
|
|
|
|
GEM_BANKN_READ_M(GEM_RES_BANK1, 2, (sc), (offs))
|
|
|
|
#define GEM_BANK1_READ_4(sc, offs) \
|
|
|
|
GEM_BANKN_READ_M(GEM_RES_BANK1, 4, (sc), (offs))
|
|
|
|
#define GEM_BANK2_READ_1(sc, offs) \
|
|
|
|
GEM_BANKN_READ_M(GEM_RES_BANK2, 1, (sc), (offs))
|
|
|
|
#define GEM_BANK2_READ_2(sc, offs) \
|
|
|
|
GEM_BANKN_READ_M(GEM_RES_BANK2, 2, (sc), (offs))
|
|
|
|
#define GEM_BANK2_READ_4(sc, offs) \
|
|
|
|
GEM_BANKN_READ_M(GEM_RES_BANK2, 4, (sc), (offs))
|
|
|
|
|
|
|
|
#define GEM_BANKN_WRITE_M(n, m, sc, offs, v) \
|
|
|
|
bus_write_ ## m((sc)->sc_res[n], (offs), (v))
|
|
|
|
#define GEM_BANK1_WRITE_1(sc, offs, v) \
|
|
|
|
GEM_BANKN_WRITE_M(GEM_RES_BANK1, 1, (sc), (offs), (v))
|
|
|
|
#define GEM_BANK1_WRITE_2(sc, offs, v) \
|
|
|
|
GEM_BANKN_WRITE_M(GEM_RES_BANK1, 2, (sc), (offs), (v))
|
|
|
|
#define GEM_BANK1_WRITE_4(sc, offs, v) \
|
|
|
|
GEM_BANKN_WRITE_M(GEM_RES_BANK1, 4, (sc), (offs), (v))
|
|
|
|
#define GEM_BANK2_WRITE_1(sc, offs, v) \
|
|
|
|
GEM_BANKN_WRITE_M(GEM_RES_BANK2, 1, (sc), (offs), (v))
|
|
|
|
#define GEM_BANK2_WRITE_2(sc, offs, v) \
|
|
|
|
GEM_BANKN_WRITE_M(GEM_RES_BANK2, 2, (sc), (offs), (v))
|
|
|
|
#define GEM_BANK2_WRITE_4(sc, offs, v) \
|
|
|
|
GEM_BANKN_WRITE_M(GEM_RES_BANK2, 4, (sc), (offs), (v))
|
|
|
|
|
2007-12-30 01:32:03 +00:00
|
|
|
/* XXX this should be handled by bus_dma(9). */
|
o Revert the part of if_gem.c rev. 1.35 which added a call to gem_stop()
to gem_attach() as the former access softc members not yet initialized
at that time and gem_reset() actually is enough to stop the chip. [1]
o Revise the use of gem_bitwait(); add bus_barrier() calls before calling
gem_bitwait() to ensure the respective bit has been written before we
starting polling on it and poll for the right bits to change, f.e. even
though we only reset RX we have to actually wait for both GEM_RESET_RX
and GEM_RESET_TX to clear. Add some additional gem_bitwait() calls in
places we've been missing them according to the GEM documentation.
Along with this some excessive DELAYs, which probably only were added
because of bugs in gem_bitwait() and its use in the first place, as
well as as have of an gem_bitwait() reimplementation in gem_reset_tx()
were removed.
o Add gem_reset_rxdma() and use it to deal with GEM_MAC_RX_OVERFLOW errors
more gracefully as unlike gem_init_locked() it resets the RX DMA engine
only, causing no link loss and the FIFOs not to be cleared. Also use it
deal with GEM_INTR_RX_TAG_ERR errors, with previously were unhandled.
This was based on information obtained from the Linux GEM and OpenSolaris
ERI drivers.
o Turn on workarounds for silicon bugs in the Apple GMAC variants.
This was based on information obtained from the Darwin GMAC and Linux GEM
drivers.
o Turn on "infinite" (i.e. maximum 31 * 64 bytes in length) DMA bursts.
This greatly improves especially RX performance.
o Optimize the RX path, this consists of:
- kicking the receiver as soon as we've a spare descriptor in gem_rint()
again instead of just once after all the ready ones have been handled;
- kicking the receiver the right way, i.e. as outlined in the GEM
documentation in batches of 4 and by pointing it to the descriptor
after the last valid one;
- calling gem_rint() before gem_tint() in gem_intr() as gem_tint() may
take quite a while;
- doubling the size of the RX ring to 256 descriptors.
Overall the RX performance of a GEM in a 1GHz Sun Fire V210 was improved
from ~100Mbit/s to ~850Mbit/s.
o In gem_add_rxbuf() don't assign the newly allocated mbuf to rxs_mbuf
before calling bus_dmamap_load_mbuf_sg(), if bus_dmamap_load_mbuf_sg()
fails we'll free the newly allocated mbuf, unable to recycle the
previous one but a NULL pointer dereference instead.
o In gem_init_locked() honor the return value of gem_meminit().
o Simplify gem_ringsize() and dont' return garbage in the default case.
Based on OpenBSD.
o Don't turn on MAC control, MIF and PCS interrupts unless GEM_DEBUG is
defined as we don't need/use these interrupts for operation.
o In gem_start_locked() sync the DMA maps of the descriptor rings before
every kick of the transmitter and not just once after enqueuing all
packets as the NIC might instantly start transmitting after we kicked
it the first time.
o Keep state of the link state and use it to enable or disable the MAC
in gem_mii_statchg() accordingly as well as to return early from
gem_start_locked() in case the link is down. [3]
o Initialize the maximum frame size to a sane value.
o In gem_mii_statchg() enable carrier extension if appropriate.
o Increment if_ierrors in case of an GEM_MAC_RX_OVERFLOW error and in
gem_eint(). [3]
o Handle IFF_ALLMULTI correctly; don't set it if we've turned promiscuous
group mode on and don't clear the flag if we've disabled promiscuous
group mode (these were mostly NOPs though). [2]
o Let gem_eint() also report GEM_INTR_PERR errors.
o Move setting sc_variant from gem_pci_probe() to gem_pci_attach() as
device probe methods are not supposed to touch the softc.
o Collapse sc_inited and sc_pci into bits for sc_flags.
o Add CTASSERTs ensuring that GEM_NRXDESC and GEM_NTXDESC are set to
legal values.
o Correctly set up for 802.3x flow control, though #ifdef out the code
that actually enables it as this needs more testing and mainly a proper
framework to support it.
o Correct and add some conversions from hard-coded functions names to
__func__ which were borked or forgotten in if_gem.c rev. 1.42.
o Use PCIR_BAR instead of a homegrown macro.
o Replace sc_enaddr[6] with sc_enaddr[ETHER_ADDR_LEN].
o In gem_pci_attach() in case attaching fails release the resources in
the opposite order they were allocated.
o Make gem_reset() static to if_gem.c as it's not needed outside that
module.
o Remove the GEM_GIGABIT flag and the associated code; GEM_GIGABIT was
never set and the associated code was in the wrong place.
o Remove sc_mif_config; it was only used to cache the contents of the
respective register within gem_attach().
o Remove the #ifdef'ed out NetBSD/OpenBSD code for establishing a suspend
hook as it will never be used on FreeBSD.
o Also probe Apple Intrepid 2 GMAC and Apple Shasta GMAC, add support for
Apple K2 GMAC. Based on OpenBSD.
o Add support for Sun GBE/P cards, or in other words actually add support
for cards based on GEM to gem(4). This mainly consists of adding support
for the TBI of these chips. Along with this the PHY selection code was
rewritten to hardcode the PHY number for certain configurations as for
example the PHY of the on-board ERI of Blade 1000 shows up twice causing
no link as the second incarnation is isolated.
These changes were ported from OpenBSD with some additional improvements
and modulo some bugs.
o Add code to if_gem_pci.c allowing to read the MAC-address from the VPD on
systems without Open Firmware.
This is an improved version of my variant of the respective code in
if_hme_pci.c
o Now that gem(4) is MI enable it for all archs.
Pointed out by: yongari [1]
Suggested by: rwatson [2], yongari [3]
Tested on: i386 (GEM), powerpc (GMACs by marcel and yongari),
sparc64 (ERI and GEM)
Reviewed by: yongari
Approved by: re (kensmith)
2007-09-26 21:14:18 +00:00
|
|
|
#define GEM_DMA_READ(sc, v) \
|
|
|
|
((((sc)->sc_flags & GEM_PCI) != 0) ? le64toh(v) : be64toh(v))
|
|
|
|
#define GEM_DMA_WRITE(sc, v) \
|
|
|
|
((((sc)->sc_flags & GEM_PCI) != 0) ? htole64(v) : htobe64(v))
|
2002-02-27 17:41:06 +00:00
|
|
|
|
|
|
|
#define GEM_CDTXADDR(sc, x) ((sc)->sc_cddma + GEM_CDTXOFF((x)))
|
|
|
|
#define GEM_CDRXADDR(sc, x) ((sc)->sc_cddma + GEM_CDRXOFF((x)))
|
|
|
|
|
2003-01-21 17:17:01 +00:00
|
|
|
#define GEM_CDSYNC(sc, ops) \
|
o Revert the part of if_gem.c rev. 1.35 which added a call to gem_stop()
to gem_attach() as the former access softc members not yet initialized
at that time and gem_reset() actually is enough to stop the chip. [1]
o Revise the use of gem_bitwait(); add bus_barrier() calls before calling
gem_bitwait() to ensure the respective bit has been written before we
starting polling on it and poll for the right bits to change, f.e. even
though we only reset RX we have to actually wait for both GEM_RESET_RX
and GEM_RESET_TX to clear. Add some additional gem_bitwait() calls in
places we've been missing them according to the GEM documentation.
Along with this some excessive DELAYs, which probably only were added
because of bugs in gem_bitwait() and its use in the first place, as
well as as have of an gem_bitwait() reimplementation in gem_reset_tx()
were removed.
o Add gem_reset_rxdma() and use it to deal with GEM_MAC_RX_OVERFLOW errors
more gracefully as unlike gem_init_locked() it resets the RX DMA engine
only, causing no link loss and the FIFOs not to be cleared. Also use it
deal with GEM_INTR_RX_TAG_ERR errors, with previously were unhandled.
This was based on information obtained from the Linux GEM and OpenSolaris
ERI drivers.
o Turn on workarounds for silicon bugs in the Apple GMAC variants.
This was based on information obtained from the Darwin GMAC and Linux GEM
drivers.
o Turn on "infinite" (i.e. maximum 31 * 64 bytes in length) DMA bursts.
This greatly improves especially RX performance.
o Optimize the RX path, this consists of:
- kicking the receiver as soon as we've a spare descriptor in gem_rint()
again instead of just once after all the ready ones have been handled;
- kicking the receiver the right way, i.e. as outlined in the GEM
documentation in batches of 4 and by pointing it to the descriptor
after the last valid one;
- calling gem_rint() before gem_tint() in gem_intr() as gem_tint() may
take quite a while;
- doubling the size of the RX ring to 256 descriptors.
Overall the RX performance of a GEM in a 1GHz Sun Fire V210 was improved
from ~100Mbit/s to ~850Mbit/s.
o In gem_add_rxbuf() don't assign the newly allocated mbuf to rxs_mbuf
before calling bus_dmamap_load_mbuf_sg(), if bus_dmamap_load_mbuf_sg()
fails we'll free the newly allocated mbuf, unable to recycle the
previous one but a NULL pointer dereference instead.
o In gem_init_locked() honor the return value of gem_meminit().
o Simplify gem_ringsize() and dont' return garbage in the default case.
Based on OpenBSD.
o Don't turn on MAC control, MIF and PCS interrupts unless GEM_DEBUG is
defined as we don't need/use these interrupts for operation.
o In gem_start_locked() sync the DMA maps of the descriptor rings before
every kick of the transmitter and not just once after enqueuing all
packets as the NIC might instantly start transmitting after we kicked
it the first time.
o Keep state of the link state and use it to enable or disable the MAC
in gem_mii_statchg() accordingly as well as to return early from
gem_start_locked() in case the link is down. [3]
o Initialize the maximum frame size to a sane value.
o In gem_mii_statchg() enable carrier extension if appropriate.
o Increment if_ierrors in case of an GEM_MAC_RX_OVERFLOW error and in
gem_eint(). [3]
o Handle IFF_ALLMULTI correctly; don't set it if we've turned promiscuous
group mode on and don't clear the flag if we've disabled promiscuous
group mode (these were mostly NOPs though). [2]
o Let gem_eint() also report GEM_INTR_PERR errors.
o Move setting sc_variant from gem_pci_probe() to gem_pci_attach() as
device probe methods are not supposed to touch the softc.
o Collapse sc_inited and sc_pci into bits for sc_flags.
o Add CTASSERTs ensuring that GEM_NRXDESC and GEM_NTXDESC are set to
legal values.
o Correctly set up for 802.3x flow control, though #ifdef out the code
that actually enables it as this needs more testing and mainly a proper
framework to support it.
o Correct and add some conversions from hard-coded functions names to
__func__ which were borked or forgotten in if_gem.c rev. 1.42.
o Use PCIR_BAR instead of a homegrown macro.
o Replace sc_enaddr[6] with sc_enaddr[ETHER_ADDR_LEN].
o In gem_pci_attach() in case attaching fails release the resources in
the opposite order they were allocated.
o Make gem_reset() static to if_gem.c as it's not needed outside that
module.
o Remove the GEM_GIGABIT flag and the associated code; GEM_GIGABIT was
never set and the associated code was in the wrong place.
o Remove sc_mif_config; it was only used to cache the contents of the
respective register within gem_attach().
o Remove the #ifdef'ed out NetBSD/OpenBSD code for establishing a suspend
hook as it will never be used on FreeBSD.
o Also probe Apple Intrepid 2 GMAC and Apple Shasta GMAC, add support for
Apple K2 GMAC. Based on OpenBSD.
o Add support for Sun GBE/P cards, or in other words actually add support
for cards based on GEM to gem(4). This mainly consists of adding support
for the TBI of these chips. Along with this the PHY selection code was
rewritten to hardcode the PHY number for certain configurations as for
example the PHY of the on-board ERI of Blade 1000 shows up twice causing
no link as the second incarnation is isolated.
These changes were ported from OpenBSD with some additional improvements
and modulo some bugs.
o Add code to if_gem_pci.c allowing to read the MAC-address from the VPD on
systems without Open Firmware.
This is an improved version of my variant of the respective code in
if_hme_pci.c
o Now that gem(4) is MI enable it for all archs.
Pointed out by: yongari [1]
Suggested by: rwatson [2], yongari [3]
Tested on: i386 (GEM), powerpc (GMACs by marcel and yongari),
sparc64 (ERI and GEM)
Reviewed by: yongari
Approved by: re (kensmith)
2007-09-26 21:14:18 +00:00
|
|
|
bus_dmamap_sync((sc)->sc_cdmatag, (sc)->sc_cddmamap, (ops));
|
2002-02-27 17:41:06 +00:00
|
|
|
|
|
|
|
#define GEM_INIT_RXDESC(sc, x) \
|
|
|
|
do { \
|
|
|
|
struct gem_rxsoft *__rxs = &sc->sc_rxsoft[(x)]; \
|
|
|
|
struct gem_desc *__rxd = &sc->sc_rxdescs[(x)]; \
|
|
|
|
struct mbuf *__m = __rxs->rxs_mbuf; \
|
|
|
|
\
|
|
|
|
__m->m_data = __m->m_ext.ext_buf; \
|
|
|
|
__rxd->gd_addr = \
|
|
|
|
GEM_DMA_WRITE((sc), __rxs->rxs_paddr); \
|
2009-06-23 20:36:59 +00:00
|
|
|
__rxd->gd_flags = GEM_DMA_WRITE((sc), \
|
|
|
|
(((__m->m_ext.ext_size) << GEM_RD_BUFSHIFT) & \
|
|
|
|
GEM_RD_BUFSIZE) | GEM_RD_OWN); \
|
o Revert the part of if_gem.c rev. 1.35 which added a call to gem_stop()
to gem_attach() as the former access softc members not yet initialized
at that time and gem_reset() actually is enough to stop the chip. [1]
o Revise the use of gem_bitwait(); add bus_barrier() calls before calling
gem_bitwait() to ensure the respective bit has been written before we
starting polling on it and poll for the right bits to change, f.e. even
though we only reset RX we have to actually wait for both GEM_RESET_RX
and GEM_RESET_TX to clear. Add some additional gem_bitwait() calls in
places we've been missing them according to the GEM documentation.
Along with this some excessive DELAYs, which probably only were added
because of bugs in gem_bitwait() and its use in the first place, as
well as as have of an gem_bitwait() reimplementation in gem_reset_tx()
were removed.
o Add gem_reset_rxdma() and use it to deal with GEM_MAC_RX_OVERFLOW errors
more gracefully as unlike gem_init_locked() it resets the RX DMA engine
only, causing no link loss and the FIFOs not to be cleared. Also use it
deal with GEM_INTR_RX_TAG_ERR errors, with previously were unhandled.
This was based on information obtained from the Linux GEM and OpenSolaris
ERI drivers.
o Turn on workarounds for silicon bugs in the Apple GMAC variants.
This was based on information obtained from the Darwin GMAC and Linux GEM
drivers.
o Turn on "infinite" (i.e. maximum 31 * 64 bytes in length) DMA bursts.
This greatly improves especially RX performance.
o Optimize the RX path, this consists of:
- kicking the receiver as soon as we've a spare descriptor in gem_rint()
again instead of just once after all the ready ones have been handled;
- kicking the receiver the right way, i.e. as outlined in the GEM
documentation in batches of 4 and by pointing it to the descriptor
after the last valid one;
- calling gem_rint() before gem_tint() in gem_intr() as gem_tint() may
take quite a while;
- doubling the size of the RX ring to 256 descriptors.
Overall the RX performance of a GEM in a 1GHz Sun Fire V210 was improved
from ~100Mbit/s to ~850Mbit/s.
o In gem_add_rxbuf() don't assign the newly allocated mbuf to rxs_mbuf
before calling bus_dmamap_load_mbuf_sg(), if bus_dmamap_load_mbuf_sg()
fails we'll free the newly allocated mbuf, unable to recycle the
previous one but a NULL pointer dereference instead.
o In gem_init_locked() honor the return value of gem_meminit().
o Simplify gem_ringsize() and dont' return garbage in the default case.
Based on OpenBSD.
o Don't turn on MAC control, MIF and PCS interrupts unless GEM_DEBUG is
defined as we don't need/use these interrupts for operation.
o In gem_start_locked() sync the DMA maps of the descriptor rings before
every kick of the transmitter and not just once after enqueuing all
packets as the NIC might instantly start transmitting after we kicked
it the first time.
o Keep state of the link state and use it to enable or disable the MAC
in gem_mii_statchg() accordingly as well as to return early from
gem_start_locked() in case the link is down. [3]
o Initialize the maximum frame size to a sane value.
o In gem_mii_statchg() enable carrier extension if appropriate.
o Increment if_ierrors in case of an GEM_MAC_RX_OVERFLOW error and in
gem_eint(). [3]
o Handle IFF_ALLMULTI correctly; don't set it if we've turned promiscuous
group mode on and don't clear the flag if we've disabled promiscuous
group mode (these were mostly NOPs though). [2]
o Let gem_eint() also report GEM_INTR_PERR errors.
o Move setting sc_variant from gem_pci_probe() to gem_pci_attach() as
device probe methods are not supposed to touch the softc.
o Collapse sc_inited and sc_pci into bits for sc_flags.
o Add CTASSERTs ensuring that GEM_NRXDESC and GEM_NTXDESC are set to
legal values.
o Correctly set up for 802.3x flow control, though #ifdef out the code
that actually enables it as this needs more testing and mainly a proper
framework to support it.
o Correct and add some conversions from hard-coded functions names to
__func__ which were borked or forgotten in if_gem.c rev. 1.42.
o Use PCIR_BAR instead of a homegrown macro.
o Replace sc_enaddr[6] with sc_enaddr[ETHER_ADDR_LEN].
o In gem_pci_attach() in case attaching fails release the resources in
the opposite order they were allocated.
o Make gem_reset() static to if_gem.c as it's not needed outside that
module.
o Remove the GEM_GIGABIT flag and the associated code; GEM_GIGABIT was
never set and the associated code was in the wrong place.
o Remove sc_mif_config; it was only used to cache the contents of the
respective register within gem_attach().
o Remove the #ifdef'ed out NetBSD/OpenBSD code for establishing a suspend
hook as it will never be used on FreeBSD.
o Also probe Apple Intrepid 2 GMAC and Apple Shasta GMAC, add support for
Apple K2 GMAC. Based on OpenBSD.
o Add support for Sun GBE/P cards, or in other words actually add support
for cards based on GEM to gem(4). This mainly consists of adding support
for the TBI of these chips. Along with this the PHY selection code was
rewritten to hardcode the PHY number for certain configurations as for
example the PHY of the on-board ERI of Blade 1000 shows up twice causing
no link as the second incarnation is isolated.
These changes were ported from OpenBSD with some additional improvements
and modulo some bugs.
o Add code to if_gem_pci.c allowing to read the MAC-address from the VPD on
systems without Open Firmware.
This is an improved version of my variant of the respective code in
if_hme_pci.c
o Now that gem(4) is MI enable it for all archs.
Pointed out by: yongari [1]
Suggested by: rwatson [2], yongari [3]
Tested on: i386 (GEM), powerpc (GMACs by marcel and yongari),
sparc64 (ERI and GEM)
Reviewed by: yongari
Approved by: re (kensmith)
2007-09-26 21:14:18 +00:00
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define GEM_UPDATE_RXDESC(sc, x) \
|
|
|
|
do { \
|
|
|
|
struct gem_rxsoft *__rxs = &sc->sc_rxsoft[(x)]; \
|
|
|
|
struct gem_desc *__rxd = &sc->sc_rxdescs[(x)]; \
|
|
|
|
struct mbuf *__m = __rxs->rxs_mbuf; \
|
|
|
|
\
|
2009-06-23 20:36:59 +00:00
|
|
|
__rxd->gd_flags = GEM_DMA_WRITE((sc), \
|
|
|
|
(((__m->m_ext.ext_size) << GEM_RD_BUFSHIFT) & \
|
|
|
|
GEM_RD_BUFSIZE) | GEM_RD_OWN); \
|
2002-02-27 17:41:06 +00:00
|
|
|
} while (0)
|
|
|
|
|
2005-07-24 18:45:15 +00:00
|
|
|
#define GEM_LOCK_INIT(_sc, _name) \
|
|
|
|
mtx_init(&(_sc)->sc_mtx, _name, MTX_NETWORK_LOCK, MTX_DEF)
|
|
|
|
#define GEM_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
|
|
|
|
#define GEM_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
|
|
|
|
#define GEM_LOCK_ASSERT(_sc, _what) mtx_assert(&(_sc)->sc_mtx, (_what))
|
|
|
|
#define GEM_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx)
|
|
|
|
|
2002-02-27 17:41:06 +00:00
|
|
|
#ifdef _KERNEL
|
|
|
|
extern devclass_t gem_devclass;
|
|
|
|
|
2007-12-30 01:32:03 +00:00
|
|
|
int gem_attach(struct gem_softc *sc);
|
|
|
|
void gem_detach(struct gem_softc *sc);
|
|
|
|
void gem_intr(void *v);
|
|
|
|
void gem_resume(struct gem_softc *sc);
|
|
|
|
void gem_suspend(struct gem_softc *sc);
|
2002-02-27 17:41:06 +00:00
|
|
|
|
2007-12-30 01:32:03 +00:00
|
|
|
int gem_mediachange(struct ifnet *ifp);
|
|
|
|
void gem_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr);
|
2002-02-27 17:41:06 +00:00
|
|
|
|
|
|
|
/* MII methods & callbacks */
|
2007-12-30 01:32:03 +00:00
|
|
|
int gem_mii_readreg(device_t dev, int phy, int reg);
|
|
|
|
void gem_mii_statchg(device_t dev);
|
|
|
|
int gem_mii_writereg(device_t dev, int phy, int reg, int val);
|
2002-02-27 17:41:06 +00:00
|
|
|
|
|
|
|
#endif /* _KERNEL */
|
|
|
|
|
|
|
|
#endif
|