Pull up following revision(s) (requested by msaitoh in ticket #375):

sys/dev/pci/if_alc.c: revision 1.40
	sys/dev/pci/if_alc.c: revision 1.41
	sys/dev/pci/if_alc.c: revision 1.42
	sys/dev/pci/if_alc.c: revision 1.39
	sys/dev/pci/if_alcreg.h: revision 1.8
	share/man/man4/alc.4: revision 1.6

Apply FreeBSD r218141:
 > alc_rev was used without initialization such that it failed to
 > apply AR8152 v1.0 specific initialization code. Fix this bug by
 > explicitly reading PCI device revision id via PCI accessor.
 >
 > Reported by:	Gabriel Linder ( linder.gabriel <> gmail dot com )

 Move PCIe initialization code from alc_attach() to alc_init_pcie().
No functional change.

Some alc(4) fixes:
- Apply FreeBSD r218141:
 > alc_rev was used without initialization such that it failed to
 > apply AR8152 v1.0 specific initialization code. Fix this bug by
 > explicitly reading PCI device revision id via PCI accessor.
 >
 > Reported by:	Gabriel Linder ( linder.gabriel <> gmail dot com )

- Apply FreeBSD r304574:
 > Correct DMA channel number selection on AR816x family of
 > controllers. For Gigabit Ethernet version of AR816x, AR813x/AR815x
 > except L1D controller, use vendor recommended ASPM parameters.
 > While here, increase alc_dma_burst array size.  Broken H/W can
 > return bogus value in theory.

- Use static.

- Whitespace fix. Remove extra backslash.

Add support for Killer E2400 and E2500.
This commit is contained in:
martin 2019-10-24 16:23:17 +00:00
parent 0d2c476a73
commit 57d057d10f
3 changed files with 120 additions and 91 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: alc.4,v 1.5 2015/01/19 11:53:59 wiz Exp $
.\" $NetBSD: alc.4,v 1.5.18.1 2019/10/24 16:23:17 martin Exp $
.\"
.\" Copyright (c) 2009 Kevin Lo <kevlo@openbsd.org>
.\"
@ -14,12 +14,12 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd January 18, 2015
.Dd October 16, 2019
.Dt ALC 4
.Os
.Sh NAME
.Nm alc
.Nd Atheros AR813x/AR815x/AR816x/AR817x Ethernet device
.Nd Atheros AR813x/AR815x/AR816x/AR817x Killer E2200/2400/2500 Ethernet device
.Sh SYNOPSIS
.Cd "alc* at pci?"
.Cd "atphy* at mii?"
@ -27,7 +27,8 @@
The
.Nm
driver provides support for Ethernet interfaces based on the
Atheros AR813x/AR815x/AR816x/AR817x Gigabit/Fast Ethernet chipsets.
Atheros AR813x/AR815x/AR816x/AR817x Gigabit/Fast Ethernet chipsets and
Killer E2200/2400/2500 Ethernet chipsets.
.Pp
The following
.Ar media

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_alc.c,v 1.38 2019/07/09 08:46:58 msaitoh Exp $ */
/* $NetBSD: if_alc.c,v 1.38.2.1 2019/10/24 16:23:17 martin Exp $ */
/* $OpenBSD: if_alc.c,v 1.1 2009/08/08 09:31:13 kevlo Exp $ */
/*-
* Copyright (c) 2009, Pyun YongHyeon <yongari@FreeBSD.org>
@ -101,6 +101,10 @@ static struct alc_ident alc_ident_table[] = {
"Atheros AR8172 PCIe Fast Ethernet" },
{ PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_E2200, 9 * 1024,
"Killer E2200 Gigabit Ethernet" },
{ PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_E2400, 9 * 1024,
"Killer E2400 Gigabit Ethernet" },
{ PCI_VENDOR_ATTANSIC, PCI_PRODUCT_ATTANSIC_E2500, 9 * 1024,
"Killer E2500 Gigabit Ethernet" },
{ 0, 0, 0, NULL },
};
@ -166,8 +170,9 @@ static void alc_stop_mac(struct alc_softc *);
static void alc_stop_queue(struct alc_softc *);
static void alc_tick(void *);
static void alc_txeof(struct alc_softc *);
static void alc_init_pcie(struct alc_softc *);
uint32_t alc_dma_burst[] = { 128, 256, 512, 1024, 2048, 4096, 0 };
static uint32_t alc_dma_burst[] = { 128, 256, 512, 1024, 2048, 4096, 0, 0 };
CFATTACH_DECL_NEW(alc, sizeof(struct alc_softc),
alc_match, alc_attach, alc_detach, NULL);
@ -763,7 +768,6 @@ alc_get_macaddr_816x(struct alc_softc *sc)
alc_get_macaddr_par(sc);
}
static void
alc_get_macaddr_par(struct alc_softc *sc)
{
@ -1002,6 +1006,8 @@ alc_phy_down(struct alc_softc *sc)
switch (sc->alc_ident->deviceid) {
case PCI_PRODUCT_ATTANSIC_AR8161:
case PCI_PRODUCT_ATTANSIC_E2200:
case PCI_PRODUCT_ATTANSIC_E2400:
case PCI_PRODUCT_ATTANSIC_E2500:
case PCI_PRODUCT_ATTANSIC_AR8162:
case PCI_PRODUCT_ATTANSIC_AR8171:
case PCI_PRODUCT_ATTANSIC_AR8172:
@ -1171,6 +1177,83 @@ alc_aspm_816x(struct alc_softc *sc, int init)
CSR_WRITE_4(sc, ALC_PM_CFG, pmcfg);
}
static void
alc_init_pcie(struct alc_softc *sc)
{
const char *aspm_state[] = { "L0s/L1", "L0s", "L1", "L0s/L1" };
uint32_t cap, ctl, val;
int state;
/* Clear data link and flow-control protocol error. */
val = CSR_READ_4(sc, ALC_PEX_UNC_ERR_SEV);
val &= ~(PEX_UNC_ERR_SEV_DLP | PEX_UNC_ERR_SEV_FCP);
CSR_WRITE_4(sc, ALC_PEX_UNC_ERR_SEV, val);
if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) == 0) {
CSR_WRITE_4(sc, ALC_LTSSM_ID_CFG,
CSR_READ_4(sc, ALC_LTSSM_ID_CFG) & ~LTSSM_ID_WRO_ENB);
CSR_WRITE_4(sc, ALC_PCIE_PHYMISC,
CSR_READ_4(sc, ALC_PCIE_PHYMISC) |
PCIE_PHYMISC_FORCE_RCV_DET);
if (sc->alc_ident->deviceid == PCI_PRODUCT_ATTANSIC_AR8152_B &&
sc->alc_rev == ATHEROS_AR8152_B_V10) {
val = CSR_READ_4(sc, ALC_PCIE_PHYMISC2);
val &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK |
PCIE_PHYMISC2_SERDES_TH_MASK);
val |= 3 << PCIE_PHYMISC2_SERDES_CDR_SHIFT;
val |= 3 << PCIE_PHYMISC2_SERDES_TH_SHIFT;
CSR_WRITE_4(sc, ALC_PCIE_PHYMISC2, val);
}
/* Disable ASPM L0S and L1. */
cap = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
sc->alc_expcap + PCIE_LCAP) >> 16;
if ((cap & PCIE_LCAP_ASPM) != 0) {
ctl = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
sc->alc_expcap + PCIE_LCSR) >> 16;
if ((ctl & 0x08) != 0)
sc->alc_rcb = DMA_CFG_RCB_128;
if (alcdebug)
printf("%s: RCB %u bytes\n",
device_xname(sc->sc_dev),
sc->alc_rcb == DMA_CFG_RCB_64 ? 64 : 128);
state = ctl & 0x03;
if (state & 0x01)
sc->alc_flags |= ALC_FLAG_L0S;
if (state & 0x02)
sc->alc_flags |= ALC_FLAG_L1S;
if (alcdebug)
printf("%s: ASPM %s %s\n",
device_xname(sc->sc_dev),
aspm_state[state],
state == 0 ? "disabled" : "enabled");
alc_disable_l0s_l1(sc);
} else {
aprint_debug_dev(sc->sc_dev, "no ASPM support\n");
}
} else {
val = CSR_READ_4(sc, ALC_PDLL_TRNS1);
val &= ~PDLL_TRNS1_D3PLLOFF_ENB;
CSR_WRITE_4(sc, ALC_PDLL_TRNS1, val);
val = CSR_READ_4(sc, ALC_MASTER_CFG);
if (AR816X_REV(sc->alc_rev) <= AR816X_REV_A1 &&
(sc->alc_rev & 0x01) != 0) {
if ((val & MASTER_WAKEN_25M) == 0 ||
(val & MASTER_CLK_SEL_DIS) == 0) {
val |= MASTER_WAKEN_25M | MASTER_CLK_SEL_DIS;
CSR_WRITE_4(sc, ALC_MASTER_CFG, val);
}
} else {
if ((val & MASTER_WAKEN_25M) == 0 ||
(val & MASTER_CLK_SEL_DIS) != 0) {
val |= MASTER_WAKEN_25M;
val &= ~MASTER_CLK_SEL_DIS;
CSR_WRITE_4(sc, ALC_MASTER_CFG, val);
}
}
}
alc_aspm(sc, 1, IFM_UNKNOWN);
}
static void
alc_attach(device_t parent, device_t self, void *aux)
{
@ -1183,13 +1266,12 @@ alc_attach(device_t parent, device_t self, void *aux)
struct ifnet *ifp;
struct mii_data * const mii = &sc->sc_miibus;
pcireg_t memtype;
const char *aspm_state[] = { "L0s/L1", "L0s", "L1", "L0s/L1" };
uint16_t burst;
int base, mii_flags, state, error = 0;
uint32_t cap, ctl, val;
int base, mii_flags, error = 0;
char intrbuf[PCI_INTRSTR_LEN];
sc->alc_ident = alc_find_ident(pa);
sc->alc_rev = PCI_REVISION(pa->pa_class);
aprint_naive("\n");
aprint_normal(": %s\n", sc->alc_ident->name);
@ -1266,75 +1348,14 @@ alc_attach(device_t parent, device_t self, void *aux)
sc->alc_dma_rd_burst = 3;
if (alc_dma_burst[sc->alc_dma_wr_burst] > 1024)
sc->alc_dma_wr_burst = 3;
/* Clear data link and flow-control protocol error. */
val = CSR_READ_4(sc, ALC_PEX_UNC_ERR_SEV);
val &= ~(PEX_UNC_ERR_SEV_DLP | PEX_UNC_ERR_SEV_FCP);
CSR_WRITE_4(sc, ALC_PEX_UNC_ERR_SEV, val);
if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) == 0) {
CSR_WRITE_4(sc, ALC_LTSSM_ID_CFG,
CSR_READ_4(sc, ALC_LTSSM_ID_CFG) & ~LTSSM_ID_WRO_ENB);
CSR_WRITE_4(sc, ALC_PCIE_PHYMISC,
CSR_READ_4(sc, ALC_PCIE_PHYMISC) |
PCIE_PHYMISC_FORCE_RCV_DET);
if (sc->alc_ident->deviceid == PCI_PRODUCT_ATTANSIC_AR8152_B &&
sc->alc_rev == ATHEROS_AR8152_B_V10) {
val = CSR_READ_4(sc, ALC_PCIE_PHYMISC2);
val &= ~(PCIE_PHYMISC2_SERDES_CDR_MASK |
PCIE_PHYMISC2_SERDES_TH_MASK);
val |= 3 << PCIE_PHYMISC2_SERDES_CDR_SHIFT;
val |= 3 << PCIE_PHYMISC2_SERDES_TH_SHIFT;
CSR_WRITE_4(sc, ALC_PCIE_PHYMISC2, val);
}
/* Disable ASPM L0S and L1. */
cap = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
base + PCIE_LCAP) >> 16;
if ((cap & PCIE_LCAP_ASPM) != 0) {
ctl = pci_conf_read(sc->sc_pct, sc->sc_pcitag,
base + PCIE_LCSR) >> 16;
if ((ctl & 0x08) != 0)
sc->alc_rcb = DMA_CFG_RCB_128;
if (alcdebug)
printf("%s: RCB %u bytes\n",
device_xname(sc->sc_dev),
sc->alc_rcb == DMA_CFG_RCB_64 ? 64 : 128);
state = ctl & 0x03;
if (state & 0x01)
sc->alc_flags |= ALC_FLAG_L0S;
if (state & 0x02)
sc->alc_flags |= ALC_FLAG_L1S;
if (alcdebug)
printf("%s: ASPM %s %s\n",
device_xname(sc->sc_dev),
aspm_state[state],
state == 0 ? "disabled" : "enabled");
alc_disable_l0s_l1(sc);
} else {
aprint_debug_dev(sc->sc_dev, "no ASPM support\n");
}
} else {
val = CSR_READ_4(sc, ALC_PDLL_TRNS1);
val &= ~PDLL_TRNS1_D3PLLOFF_ENB;
CSR_WRITE_4(sc, ALC_PDLL_TRNS1, val);
val = CSR_READ_4(sc, ALC_MASTER_CFG);
if (AR816X_REV(sc->alc_rev) <= AR816X_REV_A1 &&
(sc->alc_rev & 0x01) != 0) {
if ((val & MASTER_WAKEN_25M) == 0 ||
(val & MASTER_CLK_SEL_DIS) == 0) {
val |= MASTER_WAKEN_25M | MASTER_CLK_SEL_DIS;
CSR_WRITE_4(sc, ALC_MASTER_CFG, val);
}
} else {
if ((val & MASTER_WAKEN_25M) == 0 ||
(val & MASTER_CLK_SEL_DIS) != 0) {
val |= MASTER_WAKEN_25M;
val &= ~MASTER_CLK_SEL_DIS;
CSR_WRITE_4(sc, ALC_MASTER_CFG, val);
}
}
}
alc_aspm(sc, 1, IFM_UNKNOWN);
/*
* Force maximum payload size to 128 bytes for
* E2200/E2400/E2500.
* Otherwise it triggers DMA write error.
*/
if ((sc->alc_flags & ALC_FLAG_E2X00) != 0)
sc->alc_dma_wr_burst = 0;
alc_init_pcie(sc);
}
/* Reset PHY. */
@ -1352,13 +1373,17 @@ alc_attach(device_t parent, device_t self, void *aux)
* shows the same PHY model/revision number of AR8131.
*/
switch (sc->alc_ident->deviceid) {
case PCI_PRODUCT_ATTANSIC_E2200:
case PCI_PRODUCT_ATTANSIC_E2400:
case PCI_PRODUCT_ATTANSIC_E2500:
sc->alc_flags |= ALC_FLAG_E2X00;
/* FALLTHROUGH */
case PCI_PRODUCT_ATTANSIC_AR8161:
if (PCI_SUBSYS_ID(pci_conf_read(
sc->sc_pct, sc->sc_pcitag, PCI_SUBSYS_ID_REG)) == 0x0091 &&
sc->alc_rev == 0)
sc->alc_flags |= ALC_FLAG_LINK_WAR;
/* FALLTHROUGH */
case PCI_PRODUCT_ATTANSIC_E2200:
case PCI_PRODUCT_ATTANSIC_AR8171:
sc->alc_flags |= ALC_FLAG_AR816X_FAMILY;
break;
@ -1393,7 +1418,6 @@ alc_attach(device_t parent, device_t self, void *aux)
* Don't use Tx CMB. It is known to have silicon bug.
*/
sc->alc_flags |= ALC_FLAG_CMB_BUG;
sc->alc_rev = PCI_REVISION(pa->pa_class);
sc->alc_chip_rev = CSR_READ_4(sc, ALC_MASTER_CFG) >>
MASTER_CHIP_REV_SHIFT;
if (alcdebug) {
@ -1782,7 +1806,6 @@ alc_dma_alloc(struct alc_softc *sc)
return (0);
}
static void
alc_dma_free(struct alc_softc *sc)
{
@ -2847,7 +2870,7 @@ alc_init_backend(struct ifnet *ifp, bool init)
CSR_WRITE_4(sc, ALC_RRD1_HEAD_ADDR_LO, 0);
CSR_WRITE_4(sc, ALC_RRD2_HEAD_ADDR_LO, 0);
CSR_WRITE_4(sc, ALC_RRD3_HEAD_ADDR_LO, 0);
}\
}
/* Set Rx return descriptor counter. */
CSR_WRITE_4(sc, ALC_RRD_RING_CNT,
(ALC_RR_RING_CNT << RRD_RING_CNT_SHIFT) & RRD_RING_CNT_MASK);
@ -3044,13 +3067,17 @@ alc_init_backend(struct ifnet *ifp, bool init)
reg = (RXQ_CFG_RD_BURST_DEFAULT << RXQ_CFG_RD_BURST_SHIFT) &
RXQ_CFG_RD_BURST_MASK;
reg |= RXQ_CFG_RSS_MODE_DIS;
if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0) {
reg |= (RXQ_CFG_816X_IDT_TBL_SIZE_DEFAULT <<
RXQ_CFG_816X_IDT_TBL_SIZE_SHIFT) &
RXQ_CFG_816X_IDT_TBL_SIZE_MASK;
if ((sc->alc_flags & ALC_FLAG_FASTETHER) == 0 &&
sc->alc_ident->deviceid != PCI_PRODUCT_ATTANSIC_AR8151_V2)
reg |= RXQ_CFG_ASPM_THROUGHPUT_LIMIT_1M;
if ((sc->alc_flags & ALC_FLAG_FASTETHER) == 0)
reg |= RXQ_CFG_ASPM_THROUGHPUT_LIMIT_100M;
} else {
if ((sc->alc_flags & ALC_FLAG_FASTETHER) == 0 &&
sc->alc_ident->deviceid != PCI_PRODUCT_ATTANSIC_AR8151_V2)
reg |= RXQ_CFG_ASPM_THROUGHPUT_LIMIT_100M;
}
CSR_WRITE_4(sc, ALC_RXQ_CFG, reg);
/* Configure DMA parameters. */
@ -3074,12 +3101,12 @@ alc_init_backend(struct ifnet *ifp, bool init)
switch (AR816X_REV(sc->alc_rev)) {
case AR816X_REV_A0:
case AR816X_REV_A1:
reg |= DMA_CFG_RD_CHNL_SEL_1;
reg |= DMA_CFG_RD_CHNL_SEL_2;
break;
case AR816X_REV_B0:
/* FALLTHROUGH */
default:
reg |= DMA_CFG_RD_CHNL_SEL_3;
reg |= DMA_CFG_RD_CHNL_SEL_4;
break;
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_alcreg.h,v 1.6 2016/12/29 19:22:51 leot Exp $ */
/* $NetBSD: if_alcreg.h,v 1.6.22.1 2019/10/24 16:23:17 martin Exp $ */
/* $OpenBSD: if_alcreg.h,v 1.1 2009/08/08 09:31:13 kevlo Exp $ */
/*-
* Copyright (c) 2009, Pyun YongHyeon <yongari@FreeBSD.org>
@ -1475,7 +1475,8 @@ struct alc_softc {
#define ALC_FLAG_APS 0x1000
#define ALC_FLAG_AR816X_FAMILY 0x2000
#define ALC_FLAG_LINK_WAR 0x4000
#define ALC_FLAG_LINK 0x8000
#define ALC_FLAG_E2X00 0x8000
#define ALC_FLAG_LINK 0x10000
callout_t sc_tick_ch;
struct alc_hw_stats alc_stats;