svn commit: r273367 - stable/9/sys/dev/alc
Pyun YongHyeon
yongari at FreeBSD.org
Tue Oct 21 04:50:08 UTC 2014
Author: yongari
Date: Tue Oct 21 04:50:07 2014
New Revision: 273367
URL: https://svnweb.freebsd.org/changeset/base/273367
Log:
MFC r272730,273018:
Add support for QAC AR816x/AR817x Gigabit/Fast Ethernet controllers.
These controllers seem to have the same feature of AR813x/AR815x and
improved RSS support(4 TX queues and 8 RX queues). alc(4) supports
all hardware features except RSS. I didn't implement RX checksum
offloading for AR816x/AR817x just because I couldn't get
confirmation from the Vendor whether AR816x/AR817x corrected its
predecessor's RX checksum offloading bug on fragmented packets.
This change adds supports for the following controllers.
o AR8161 PCIe Gigabit Ethernet controller
o AR8162 PCIe Fast Ethernet controller
o AR8171 PCIe Gigabit Ethernet controller
o AR8172 PCIe Fast Ethernet controller
o Killer E2200 Gigabit Ethernet controller
Modified:
stable/9/sys/dev/alc/if_alc.c
stable/9/sys/dev/alc/if_alcreg.h
stable/9/sys/dev/alc/if_alcvar.h
Directory Properties:
stable/9/sys/ (props changed)
stable/9/sys/dev/ (props changed)
Modified: stable/9/sys/dev/alc/if_alc.c
==============================================================================
--- stable/9/sys/dev/alc/if_alc.c Tue Oct 21 04:48:49 2014 (r273366)
+++ stable/9/sys/dev/alc/if_alc.c Tue Oct 21 04:50:07 2014 (r273367)
@@ -110,17 +110,31 @@ static struct alc_ident alc_ident_table[
"Atheros AR8152 v1.1 PCIe Fast Ethernet" },
{ VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8152_B2, 6 * 1024,
"Atheros AR8152 v2.0 PCIe Fast Ethernet" },
+ { VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8161, 9 * 1024,
+ "Atheros AR8161 PCIe Gigabit Ethernet" },
+ { VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8162, 9 * 1024,
+ "Atheros AR8161 PCIe Fast Ethernet" },
+ { VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8171, 9 * 1024,
+ "Atheros AR8161 PCIe Gigabit Ethernet" },
+ { VENDORID_ATHEROS, DEVICEID_ATHEROS_AR8172, 9 * 1024,
+ "Atheros AR8161 PCIe Fast Ethernet" },
+ { VENDORID_ATHEROS, DEVICEID_ATHEROS_E2200, 9 * 1024,
+ "Killer E2200 Gigabit Ethernet" },
{ 0, 0, 0, NULL}
};
-static void alc_aspm(struct alc_softc *, int);
+static void alc_aspm(struct alc_softc *, int, int);
+static void alc_aspm_813x(struct alc_softc *, int);
+static void alc_aspm_816x(struct alc_softc *, int);
static int alc_attach(device_t);
static int alc_check_boundary(struct alc_softc *);
+static void alc_config_msi(struct alc_softc *);
static int alc_detach(device_t);
static void alc_disable_l0s_l1(struct alc_softc *);
static int alc_dma_alloc(struct alc_softc *);
static void alc_dma_free(struct alc_softc *);
static void alc_dmamap_cb(void *, bus_dma_segment_t *, int, int);
+static void alc_dsp_fixup(struct alc_softc *, int);
static int alc_encap(struct alc_softc *, struct mbuf **);
static struct alc_ident *
alc_find_ident(device_t);
@@ -129,6 +143,9 @@ static struct mbuf *
alc_fixup_rx(struct ifnet *, struct mbuf *);
#endif
static void alc_get_macaddr(struct alc_softc *);
+static void alc_get_macaddr_813x(struct alc_softc *);
+static void alc_get_macaddr_816x(struct alc_softc *);
+static void alc_get_macaddr_par(struct alc_softc *);
static void alc_init(void *);
static void alc_init_cmb(struct alc_softc *);
static void alc_init_locked(struct alc_softc *);
@@ -140,14 +157,26 @@ static void alc_int_task(void *, int);
static int alc_intr(void *);
static int alc_ioctl(struct ifnet *, u_long, caddr_t);
static void alc_mac_config(struct alc_softc *);
+static uint32_t alc_mii_readreg_813x(struct alc_softc *, int, int);
+static uint32_t alc_mii_readreg_816x(struct alc_softc *, int, int);
+static uint32_t alc_mii_writereg_813x(struct alc_softc *, int, int, int);
+static uint32_t alc_mii_writereg_816x(struct alc_softc *, int, int, int);
static int alc_miibus_readreg(device_t, int, int);
static void alc_miibus_statchg(device_t);
static int alc_miibus_writereg(device_t, int, int, int);
+static uint32_t alc_miidbg_readreg(struct alc_softc *, int);
+static uint32_t alc_miidbg_writereg(struct alc_softc *, int, int);
+static uint32_t alc_miiext_readreg(struct alc_softc *, int, int);
+static uint32_t alc_miiext_writereg(struct alc_softc *, int, int, int);
static int alc_mediachange(struct ifnet *);
+static int alc_mediachange_locked(struct alc_softc *);
static void alc_mediastatus(struct ifnet *, struct ifmediareq *);
static int alc_newbuf(struct alc_softc *, struct alc_rxdesc *);
+static void alc_osc_reset(struct alc_softc *);
static void alc_phy_down(struct alc_softc *);
static void alc_phy_reset(struct alc_softc *);
+static void alc_phy_reset_813x(struct alc_softc *);
+static void alc_phy_reset_816x(struct alc_softc *);
static int alc_probe(device_t);
static void alc_reset(struct alc_softc *);
static int alc_resume(device_t);
@@ -157,6 +186,8 @@ static void alc_rxfilter(struct alc_soft
static void alc_rxvlan(struct alc_softc *);
static void alc_setlinkspeed(struct alc_softc *);
static void alc_setwol(struct alc_softc *);
+static void alc_setwol_813x(struct alc_softc *);
+static void alc_setwol_816x(struct alc_softc *);
static int alc_shutdown(device_t);
static void alc_start(struct ifnet *);
static void alc_start_locked(struct ifnet *);
@@ -229,10 +260,21 @@ static int
alc_miibus_readreg(device_t dev, int phy, int reg)
{
struct alc_softc *sc;
- uint32_t v;
- int i;
+ int v;
sc = device_get_softc(dev);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ v = alc_mii_readreg_816x(sc, phy, reg);
+ else
+ v = alc_mii_readreg_813x(sc, phy, reg);
+ return (v);
+}
+
+static uint32_t
+alc_mii_readreg_813x(struct alc_softc *sc, int phy, int reg)
+{
+ uint32_t v;
+ int i;
/*
* For AR8132 fast ethernet controller, do not report 1000baseT
@@ -261,14 +303,52 @@ alc_miibus_readreg(device_t dev, int phy
return ((v & MDIO_DATA_MASK) >> MDIO_DATA_SHIFT);
}
+static uint32_t
+alc_mii_readreg_816x(struct alc_softc *sc, int phy, int reg)
+{
+ uint32_t clk, v;
+ int i;
+
+ if ((sc->alc_flags & ALC_FLAG_LINK) != 0)
+ clk = MDIO_CLK_25_128;
+ else
+ clk = MDIO_CLK_25_4;
+ CSR_WRITE_4(sc, ALC_MDIO, MDIO_OP_EXECUTE | MDIO_OP_READ |
+ MDIO_SUP_PREAMBLE | clk | MDIO_REG_ADDR(reg));
+ for (i = ALC_PHY_TIMEOUT; i > 0; i--) {
+ DELAY(5);
+ v = CSR_READ_4(sc, ALC_MDIO);
+ if ((v & MDIO_OP_BUSY) == 0)
+ break;
+ }
+
+ if (i == 0) {
+ device_printf(sc->alc_dev, "phy read timeout : %d\n", reg);
+ return (0);
+ }
+
+ return ((v & MDIO_DATA_MASK) >> MDIO_DATA_SHIFT);
+}
+
static int
alc_miibus_writereg(device_t dev, int phy, int reg, int val)
{
struct alc_softc *sc;
- uint32_t v;
- int i;
+ int v;
sc = device_get_softc(dev);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ v = alc_mii_writereg_816x(sc, phy, reg, val);
+ else
+ v = alc_mii_writereg_813x(sc, phy, reg, val);
+ return (v);
+}
+
+static uint32_t
+alc_mii_writereg_813x(struct alc_softc *sc, int phy, int reg, int val)
+{
+ uint32_t v;
+ int i;
CSR_WRITE_4(sc, ALC_MDIO, MDIO_OP_EXECUTE | MDIO_OP_WRITE |
(val & MDIO_DATA_MASK) << MDIO_DATA_SHIFT |
@@ -286,6 +366,32 @@ alc_miibus_writereg(device_t dev, int ph
return (0);
}
+static uint32_t
+alc_mii_writereg_816x(struct alc_softc *sc, int phy, int reg, int val)
+{
+ uint32_t clk, v;
+ int i;
+
+ if ((sc->alc_flags & ALC_FLAG_LINK) != 0)
+ clk = MDIO_CLK_25_128;
+ else
+ clk = MDIO_CLK_25_4;
+ CSR_WRITE_4(sc, ALC_MDIO, MDIO_OP_EXECUTE | MDIO_OP_WRITE |
+ ((val & MDIO_DATA_MASK) << MDIO_DATA_SHIFT) | MDIO_REG_ADDR(reg) |
+ MDIO_SUP_PREAMBLE | clk);
+ for (i = ALC_PHY_TIMEOUT; i > 0; i--) {
+ DELAY(5);
+ v = CSR_READ_4(sc, ALC_MDIO);
+ if ((v & MDIO_OP_BUSY) == 0)
+ break;
+ }
+
+ if (i == 0)
+ device_printf(sc->alc_dev, "phy write timeout : %d\n", reg);
+
+ return (0);
+}
+
static void
alc_miibus_statchg(device_t dev)
{
@@ -318,7 +424,6 @@ alc_miibus_statchg(device_t dev)
break;
}
}
- alc_stop_queue(sc);
/* Stop Rx/Tx MACs. */
alc_stop_mac(sc);
@@ -330,7 +435,159 @@ alc_miibus_statchg(device_t dev)
reg = CSR_READ_4(sc, ALC_MAC_CFG);
reg |= MAC_CFG_TX_ENB | MAC_CFG_RX_ENB;
CSR_WRITE_4(sc, ALC_MAC_CFG, reg);
- alc_aspm(sc, IFM_SUBTYPE(mii->mii_media_active));
+ }
+ alc_aspm(sc, 0, IFM_SUBTYPE(mii->mii_media_active));
+ alc_dsp_fixup(sc, IFM_SUBTYPE(mii->mii_media_active));
+}
+
+static uint32_t
+alc_miidbg_readreg(struct alc_softc *sc, int reg)
+{
+
+ alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr, ALC_MII_DBG_ADDR,
+ reg);
+ return (alc_miibus_readreg(sc->alc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA));
+}
+
+static uint32_t
+alc_miidbg_writereg(struct alc_softc *sc, int reg, int val)
+{
+
+ alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr, ALC_MII_DBG_ADDR,
+ reg);
+ return (alc_miibus_writereg(sc->alc_dev, sc->alc_phyaddr,
+ ALC_MII_DBG_DATA, val));
+}
+
+static uint32_t
+alc_miiext_readreg(struct alc_softc *sc, int devaddr, int reg)
+{
+ uint32_t clk, v;
+ int i;
+
+ CSR_WRITE_4(sc, ALC_EXT_MDIO, EXT_MDIO_REG(reg) |
+ EXT_MDIO_DEVADDR(devaddr));
+ if ((sc->alc_flags & ALC_FLAG_LINK) != 0)
+ clk = MDIO_CLK_25_128;
+ else
+ clk = MDIO_CLK_25_4;
+ CSR_WRITE_4(sc, ALC_MDIO, MDIO_OP_EXECUTE | MDIO_OP_READ |
+ MDIO_SUP_PREAMBLE | clk | MDIO_MODE_EXT);
+ for (i = ALC_PHY_TIMEOUT; i > 0; i--) {
+ DELAY(5);
+ v = CSR_READ_4(sc, ALC_MDIO);
+ if ((v & MDIO_OP_BUSY) == 0)
+ break;
+ }
+
+ if (i == 0) {
+ device_printf(sc->alc_dev, "phy ext read timeout : %d, %d\n",
+ devaddr, reg);
+ return (0);
+ }
+
+ return ((v & MDIO_DATA_MASK) >> MDIO_DATA_SHIFT);
+}
+
+static uint32_t
+alc_miiext_writereg(struct alc_softc *sc, int devaddr, int reg, int val)
+{
+ uint32_t clk, v;
+ int i;
+
+ CSR_WRITE_4(sc, ALC_EXT_MDIO, EXT_MDIO_REG(reg) |
+ EXT_MDIO_DEVADDR(devaddr));
+ if ((sc->alc_flags & ALC_FLAG_LINK) != 0)
+ clk = MDIO_CLK_25_128;
+ else
+ clk = MDIO_CLK_25_4;
+ CSR_WRITE_4(sc, ALC_MDIO, MDIO_OP_EXECUTE | MDIO_OP_WRITE |
+ ((val & MDIO_DATA_MASK) << MDIO_DATA_SHIFT) |
+ MDIO_SUP_PREAMBLE | clk | MDIO_MODE_EXT);
+ for (i = ALC_PHY_TIMEOUT; i > 0; i--) {
+ DELAY(5);
+ v = CSR_READ_4(sc, ALC_MDIO);
+ if ((v & MDIO_OP_BUSY) == 0)
+ break;
+ }
+
+ if (i == 0)
+ device_printf(sc->alc_dev, "phy ext write timeout : %d, %d\n",
+ devaddr, reg);
+
+ return (0);
+}
+
+static void
+alc_dsp_fixup(struct alc_softc *sc, int media)
+{
+ uint16_t agc, len, val;
+
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ return;
+ if (AR816X_REV(sc->alc_rev) >= AR816X_REV_C0)
+ return;
+
+ /*
+ * Vendor PHY magic.
+ * 1000BT/AZ, wrong cable length
+ */
+ if ((sc->alc_flags & ALC_FLAG_LINK) != 0) {
+ len = alc_miiext_readreg(sc, MII_EXT_PCS, MII_EXT_CLDCTL6);
+ len = (len >> EXT_CLDCTL6_CAB_LEN_SHIFT) &
+ EXT_CLDCTL6_CAB_LEN_MASK;
+ agc = alc_miidbg_readreg(sc, MII_DBG_AGC);
+ agc = (agc >> DBG_AGC_2_VGA_SHIFT) & DBG_AGC_2_VGA_MASK;
+ if ((media == IFM_1000_T && len > EXT_CLDCTL6_CAB_LEN_SHORT1G &&
+ agc > DBG_AGC_LONG1G_LIMT) ||
+ (media == IFM_100_TX && len > DBG_AGC_LONG100M_LIMT &&
+ agc > DBG_AGC_LONG1G_LIMT)) {
+ alc_miidbg_writereg(sc, MII_DBG_AZ_ANADECT,
+ DBG_AZ_ANADECT_LONG);
+ val = alc_miiext_readreg(sc, MII_EXT_ANEG,
+ MII_EXT_ANEG_AFE);
+ val |= ANEG_AFEE_10BT_100M_TH;
+ alc_miiext_writereg(sc, MII_EXT_ANEG, MII_EXT_ANEG_AFE,
+ val);
+ } else {
+ alc_miidbg_writereg(sc, MII_DBG_AZ_ANADECT,
+ DBG_AZ_ANADECT_DEFAULT);
+ val = alc_miiext_readreg(sc, MII_EXT_ANEG,
+ MII_EXT_ANEG_AFE);
+ val &= ~ANEG_AFEE_10BT_100M_TH;
+ alc_miiext_writereg(sc, MII_EXT_ANEG, MII_EXT_ANEG_AFE,
+ val);
+ }
+ if ((sc->alc_flags & ALC_FLAG_LINK_WAR) != 0 &&
+ AR816X_REV(sc->alc_rev) == AR816X_REV_B0) {
+ if (media == IFM_1000_T) {
+ /*
+ * Giga link threshold, raise the tolerance of
+ * noise 50%.
+ */
+ val = alc_miidbg_readreg(sc, MII_DBG_MSE20DB);
+ val &= ~DBG_MSE20DB_TH_MASK;
+ val |= (DBG_MSE20DB_TH_HI <<
+ DBG_MSE20DB_TH_SHIFT);
+ alc_miidbg_writereg(sc, MII_DBG_MSE20DB, val);
+ } else if (media == IFM_100_TX)
+ alc_miidbg_writereg(sc, MII_DBG_MSE16DB,
+ DBG_MSE16DB_UP);
+ }
+ } else {
+ val = alc_miiext_readreg(sc, MII_EXT_ANEG, MII_EXT_ANEG_AFE);
+ val &= ~ANEG_AFEE_10BT_100M_TH;
+ alc_miiext_writereg(sc, MII_EXT_ANEG, MII_EXT_ANEG_AFE, val);
+ if ((sc->alc_flags & ALC_FLAG_LINK_WAR) != 0 &&
+ AR816X_REV(sc->alc_rev) == AR816X_REV_B0) {
+ alc_miidbg_writereg(sc, MII_DBG_MSE16DB,
+ DBG_MSE16DB_DOWN);
+ val = alc_miidbg_readreg(sc, MII_DBG_MSE20DB);
+ val &= ~DBG_MSE20DB_TH_MASK;
+ val |= (DBG_MSE20DB_TH_DEFAULT << DBG_MSE20DB_TH_SHIFT);
+ alc_miidbg_writereg(sc, MII_DBG_MSE20DB, val);
+ }
}
}
@@ -358,17 +615,29 @@ static int
alc_mediachange(struct ifnet *ifp)
{
struct alc_softc *sc;
- struct mii_data *mii;
- struct mii_softc *miisc;
int error;
sc = ifp->if_softc;
ALC_LOCK(sc);
+ error = alc_mediachange_locked(sc);
+ ALC_UNLOCK(sc);
+
+ return (error);
+}
+
+static int
+alc_mediachange_locked(struct alc_softc *sc)
+{
+ struct mii_data *mii;
+ struct mii_softc *miisc;
+ int error;
+
+ ALC_LOCK_ASSERT(sc);
+
mii = device_get_softc(sc->alc_miibus);
LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
PHY_RESET(miisc);
error = mii_mediachg(mii);
- ALC_UNLOCK(sc);
return (error);
}
@@ -406,7 +675,17 @@ alc_probe(device_t dev)
static void
alc_get_macaddr(struct alc_softc *sc)
{
- uint32_t ea[2], opt;
+
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ alc_get_macaddr_816x(sc);
+ else
+ alc_get_macaddr_813x(sc);
+}
+
+static void
+alc_get_macaddr_813x(struct alc_softc *sc)
+{
+ uint32_t opt;
uint16_t val;
int eeprom, i;
@@ -501,6 +780,73 @@ alc_get_macaddr(struct alc_softc *sc)
}
}
+ alc_get_macaddr_par(sc);
+}
+
+static void
+alc_get_macaddr_816x(struct alc_softc *sc)
+{
+ uint32_t reg;
+ int i, reloaded;
+
+ reloaded = 0;
+ /* Try to reload station address via TWSI. */
+ for (i = 100; i > 0; i--) {
+ reg = CSR_READ_4(sc, ALC_SLD);
+ if ((reg & (SLD_PROGRESS | SLD_START)) == 0)
+ break;
+ DELAY(1000);
+ }
+ if (i != 0) {
+ CSR_WRITE_4(sc, ALC_SLD, reg | SLD_START);
+ for (i = 100; i > 0; i--) {
+ DELAY(1000);
+ reg = CSR_READ_4(sc, ALC_SLD);
+ if ((reg & SLD_START) == 0)
+ break;
+ }
+ if (i != 0)
+ reloaded++;
+ else if (bootverbose)
+ device_printf(sc->alc_dev,
+ "reloading station address via TWSI timed out!\n");
+ }
+
+ /* Try to reload station address from EEPROM or FLASH. */
+ if (reloaded == 0) {
+ reg = CSR_READ_4(sc, ALC_EEPROM_LD);
+ if ((reg & (EEPROM_LD_EEPROM_EXIST |
+ EEPROM_LD_FLASH_EXIST)) != 0) {
+ for (i = 100; i > 0; i--) {
+ reg = CSR_READ_4(sc, ALC_EEPROM_LD);
+ if ((reg & (EEPROM_LD_PROGRESS |
+ EEPROM_LD_START)) == 0)
+ break;
+ DELAY(1000);
+ }
+ if (i != 0) {
+ CSR_WRITE_4(sc, ALC_EEPROM_LD, reg |
+ EEPROM_LD_START);
+ for (i = 100; i > 0; i--) {
+ DELAY(1000);
+ reg = CSR_READ_4(sc, ALC_EEPROM_LD);
+ if ((reg & EEPROM_LD_START) == 0)
+ break;
+ }
+ } else if (bootverbose)
+ device_printf(sc->alc_dev,
+ "reloading EEPROM/FLASH timed out!\n");
+ }
+ }
+
+ alc_get_macaddr_par(sc);
+}
+
+static void
+alc_get_macaddr_par(struct alc_softc *sc)
+{
+ uint32_t ea[2];
+
ea[0] = CSR_READ_4(sc, ALC_PAR0);
ea[1] = CSR_READ_4(sc, ALC_PAR1);
sc->alc_eaddr[0] = (ea[1] >> 8) & 0xFF;
@@ -516,19 +862,31 @@ alc_disable_l0s_l1(struct alc_softc *sc)
{
uint32_t pmcfg;
- /* Another magic from vendor. */
- pmcfg = CSR_READ_4(sc, ALC_PM_CFG);
- pmcfg &= ~(PM_CFG_L1_ENTRY_TIMER_MASK | PM_CFG_CLK_SWH_L1 |
- PM_CFG_ASPM_L0S_ENB | PM_CFG_ASPM_L1_ENB | PM_CFG_MAC_ASPM_CHK |
- PM_CFG_SERDES_PD_EX_L1);
- pmcfg |= PM_CFG_SERDES_BUDS_RX_L1_ENB | PM_CFG_SERDES_PLL_L1_ENB |
- PM_CFG_SERDES_L1_ENB;
- CSR_WRITE_4(sc, ALC_PM_CFG, pmcfg);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) == 0) {
+ /* Another magic from vendor. */
+ pmcfg = CSR_READ_4(sc, ALC_PM_CFG);
+ pmcfg &= ~(PM_CFG_L1_ENTRY_TIMER_MASK | PM_CFG_CLK_SWH_L1 |
+ PM_CFG_ASPM_L0S_ENB | PM_CFG_ASPM_L1_ENB |
+ PM_CFG_MAC_ASPM_CHK | PM_CFG_SERDES_PD_EX_L1);
+ pmcfg |= PM_CFG_SERDES_BUDS_RX_L1_ENB |
+ PM_CFG_SERDES_PLL_L1_ENB | PM_CFG_SERDES_L1_ENB;
+ CSR_WRITE_4(sc, ALC_PM_CFG, pmcfg);
+ }
}
static void
alc_phy_reset(struct alc_softc *sc)
{
+
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ alc_phy_reset_816x(sc);
+ else
+ alc_phy_reset_813x(sc);
+}
+
+static void
+alc_phy_reset_813x(struct alc_softc *sc)
+{
uint16_t data;
/* Reset magic from Linux. */
@@ -641,12 +999,101 @@ alc_phy_reset(struct alc_softc *sc)
}
static void
+alc_phy_reset_816x(struct alc_softc *sc)
+{
+ uint32_t val;
+
+ val = CSR_READ_4(sc, ALC_GPHY_CFG);
+ val &= ~(GPHY_CFG_EXT_RESET | GPHY_CFG_LED_MODE |
+ GPHY_CFG_GATE_25M_ENB | GPHY_CFG_PHY_IDDQ | GPHY_CFG_PHY_PLL_ON |
+ GPHY_CFG_PWDOWN_HW | GPHY_CFG_100AB_ENB);
+ val |= GPHY_CFG_SEL_ANA_RESET;
+#ifdef notyet
+ val |= GPHY_CFG_HIB_PULSE | GPHY_CFG_HIB_EN | GPHY_CFG_SEL_ANA_RESET;
+#else
+ /* Disable PHY hibernation. */
+ val &= ~(GPHY_CFG_HIB_PULSE | GPHY_CFG_HIB_EN);
+#endif
+ CSR_WRITE_4(sc, ALC_GPHY_CFG, val);
+ DELAY(10);
+ CSR_WRITE_4(sc, ALC_GPHY_CFG, val | GPHY_CFG_EXT_RESET);
+ DELAY(800);
+
+ /* Vendor PHY magic. */
+#ifdef notyet
+ alc_miidbg_writereg(sc, MII_DBG_LEGCYPS, DBG_LEGCYPS_DEFAULT);
+ alc_miidbg_writereg(sc, MII_DBG_SYSMODCTL, DBG_SYSMODCTL_DEFAULT);
+ alc_miiext_writereg(sc, MII_EXT_PCS, MII_EXT_VDRVBIAS,
+ EXT_VDRVBIAS_DEFAULT);
+#else
+ /* Disable PHY hibernation. */
+ alc_miidbg_writereg(sc, MII_DBG_LEGCYPS,
+ DBG_LEGCYPS_DEFAULT & ~DBG_LEGCYPS_ENB);
+ alc_miidbg_writereg(sc, MII_DBG_HIBNEG,
+ DBG_HIBNEG_DEFAULT & ~(DBG_HIBNEG_PSHIB_EN | DBG_HIBNEG_HIB_PULSE));
+ alc_miidbg_writereg(sc, MII_DBG_GREENCFG, DBG_GREENCFG_DEFAULT);
+#endif
+
+ /* XXX Disable EEE. */
+ val = CSR_READ_4(sc, ALC_LPI_CTL);
+ val &= ~LPI_CTL_ENB;
+ CSR_WRITE_4(sc, ALC_LPI_CTL, val);
+ alc_miiext_writereg(sc, MII_EXT_ANEG, MII_EXT_ANEG_LOCAL_EEEADV, 0);
+
+ /* PHY power saving. */
+ alc_miidbg_writereg(sc, MII_DBG_TST10BTCFG, DBG_TST10BTCFG_DEFAULT);
+ alc_miidbg_writereg(sc, MII_DBG_SRDSYSMOD, DBG_SRDSYSMOD_DEFAULT);
+ alc_miidbg_writereg(sc, MII_DBG_TST100BTCFG, DBG_TST100BTCFG_DEFAULT);
+ alc_miidbg_writereg(sc, MII_DBG_ANACTL, DBG_ANACTL_DEFAULT);
+ val = alc_miidbg_readreg(sc, MII_DBG_GREENCFG2);
+ val &= ~DBG_GREENCFG2_GATE_DFSE_EN;
+ alc_miidbg_writereg(sc, MII_DBG_GREENCFG2, val);
+
+ /* RTL8139C, 120m issue. */
+ alc_miiext_writereg(sc, MII_EXT_ANEG, MII_EXT_ANEG_NLP78,
+ ANEG_NLP78_120M_DEFAULT);
+ alc_miiext_writereg(sc, MII_EXT_ANEG, MII_EXT_ANEG_S3DIG10,
+ ANEG_S3DIG10_DEFAULT);
+
+ if ((sc->alc_flags & ALC_FLAG_LINK_WAR) != 0) {
+ /* Turn off half amplitude. */
+ val = alc_miiext_readreg(sc, MII_EXT_PCS, MII_EXT_CLDCTL3);
+ val |= EXT_CLDCTL3_BP_CABLE1TH_DET_GT;
+ alc_miiext_writereg(sc, MII_EXT_PCS, MII_EXT_CLDCTL3, val);
+ /* Turn off Green feature. */
+ val = alc_miidbg_readreg(sc, MII_DBG_GREENCFG2);
+ val |= DBG_GREENCFG2_BP_GREEN;
+ alc_miidbg_writereg(sc, MII_DBG_GREENCFG2, val);
+ /* Turn off half bias. */
+ val = alc_miiext_readreg(sc, MII_EXT_PCS, MII_EXT_CLDCTL5);
+ val |= EXT_CLDCTL5_BP_VD_HLFBIAS;
+ alc_miiext_writereg(sc, MII_EXT_PCS, MII_EXT_CLDCTL5, val);
+ }
+}
+
+static void
alc_phy_down(struct alc_softc *sc)
{
+ uint32_t gphy;
switch (sc->alc_ident->deviceid) {
+ case DEVICEID_ATHEROS_AR8161:
+ case DEVICEID_ATHEROS_E2200:
+ case DEVICEID_ATHEROS_AR8162:
+ case DEVICEID_ATHEROS_AR8171:
+ case DEVICEID_ATHEROS_AR8172:
+ gphy = CSR_READ_4(sc, ALC_GPHY_CFG);
+ gphy &= ~(GPHY_CFG_EXT_RESET | GPHY_CFG_LED_MODE |
+ GPHY_CFG_100AB_ENB | GPHY_CFG_PHY_PLL_ON);
+ gphy |= GPHY_CFG_HIB_EN | GPHY_CFG_HIB_PULSE |
+ GPHY_CFG_SEL_ANA_RESET;
+ gphy |= GPHY_CFG_PHY_IDDQ | GPHY_CFG_PWDOWN_HW;
+ CSR_WRITE_4(sc, ALC_GPHY_CFG, gphy);
+ break;
case DEVICEID_ATHEROS_AR8151:
case DEVICEID_ATHEROS_AR8151_V2:
+ case DEVICEID_ATHEROS_AR8152_B:
+ case DEVICEID_ATHEROS_AR8152_B2:
/*
* GPHY power down caused more problems on AR8151 v2.0.
* When driver is reloaded after GPHY power down,
@@ -672,12 +1119,23 @@ alc_phy_down(struct alc_softc *sc)
}
static void
-alc_aspm(struct alc_softc *sc, int media)
+alc_aspm(struct alc_softc *sc, int init, int media)
+{
+
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ alc_aspm_816x(sc, init);
+ else
+ alc_aspm_813x(sc, media);
+}
+
+static void
+alc_aspm_813x(struct alc_softc *sc, int media)
{
uint32_t pmcfg;
uint16_t linkcfg;
- ALC_LOCK_ASSERT(sc);
+ if ((sc->alc_flags & ALC_FLAG_LINK) == 0)
+ return;
pmcfg = CSR_READ_4(sc, ALC_PM_CFG);
if ((sc->alc_flags & (ALC_FLAG_APS | ALC_FLAG_PCIE)) ==
@@ -758,71 +1216,61 @@ alc_aspm(struct alc_softc *sc, int media
CSR_WRITE_4(sc, ALC_PM_CFG, pmcfg);
}
-static int
-alc_attach(device_t dev)
+static void
+alc_aspm_816x(struct alc_softc *sc, int init)
{
- struct alc_softc *sc;
- struct ifnet *ifp;
- char *aspm_state[] = { "L0s/L1", "L0s", "L1", "L0s/L1" };
- uint16_t burst;
- int base, error, i, msic, msixc, state;
- uint32_t cap, ctl, val;
-
- error = 0;
- sc = device_get_softc(dev);
- sc->alc_dev = dev;
-
- mtx_init(&sc->alc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
- MTX_DEF);
- callout_init_mtx(&sc->alc_tick_ch, &sc->alc_mtx, 0);
- TASK_INIT(&sc->alc_int_task, 0, alc_int_task, sc);
- sc->alc_ident = alc_find_ident(dev);
+ uint32_t pmcfg;
- /* Map the device. */
- pci_enable_busmaster(dev);
- sc->alc_res_spec = alc_res_spec_mem;
- sc->alc_irq_spec = alc_irq_spec_legacy;
- error = bus_alloc_resources(dev, sc->alc_res_spec, sc->alc_res);
- if (error != 0) {
- device_printf(dev, "cannot allocate memory resources.\n");
- goto fail;
+ pmcfg = CSR_READ_4(sc, ALC_PM_CFG);
+ pmcfg &= ~PM_CFG_L1_ENTRY_TIMER_816X_MASK;
+ pmcfg |= PM_CFG_L1_ENTRY_TIMER_816X_DEFAULT;
+ pmcfg &= ~PM_CFG_PM_REQ_TIMER_MASK;
+ pmcfg |= PM_CFG_PM_REQ_TIMER_816X_DEFAULT;
+ pmcfg &= ~PM_CFG_LCKDET_TIMER_MASK;
+ pmcfg |= PM_CFG_LCKDET_TIMER_DEFAULT;
+ pmcfg |= PM_CFG_SERDES_PD_EX_L1 | PM_CFG_CLK_SWH_L1 | PM_CFG_PCIE_RECV;
+ pmcfg &= ~(PM_CFG_RX_L1_AFTER_L0S | PM_CFG_TX_L1_AFTER_L0S |
+ PM_CFG_ASPM_L1_ENB | PM_CFG_ASPM_L0S_ENB |
+ PM_CFG_SERDES_L1_ENB | PM_CFG_SERDES_PLL_L1_ENB |
+ PM_CFG_SERDES_BUDS_RX_L1_ENB | PM_CFG_SA_DLY_ENB |
+ PM_CFG_MAC_ASPM_CHK | PM_CFG_HOTRST);
+ if (AR816X_REV(sc->alc_rev) <= AR816X_REV_A1 &&
+ (sc->alc_rev & 0x01) != 0)
+ pmcfg |= PM_CFG_SERDES_L1_ENB | PM_CFG_SERDES_PLL_L1_ENB;
+ if ((sc->alc_flags & ALC_FLAG_LINK) != 0) {
+ /* Link up, enable both L0s, L1s. */
+ pmcfg |= PM_CFG_ASPM_L0S_ENB | PM_CFG_ASPM_L1_ENB |
+ PM_CFG_MAC_ASPM_CHK;
+ } else {
+ if (init != 0)
+ pmcfg |= PM_CFG_ASPM_L0S_ENB | PM_CFG_ASPM_L1_ENB |
+ PM_CFG_MAC_ASPM_CHK;
+ else if ((sc->alc_ifp->if_drv_flags & IFF_DRV_RUNNING) != 0)
+ pmcfg |= PM_CFG_ASPM_L1_ENB | PM_CFG_MAC_ASPM_CHK;
}
+ CSR_WRITE_4(sc, ALC_PM_CFG, pmcfg);
+}
- /* Set PHY address. */
- sc->alc_phyaddr = ALC_PHY_ADDR;
+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;
- /* Initialize DMA parameters. */
- sc->alc_dma_rd_burst = 0;
- sc->alc_dma_wr_burst = 0;
- sc->alc_rcb = DMA_CFG_RCB_64;
- if (pci_find_cap(dev, PCIY_EXPRESS, &base) == 0) {
- sc->alc_flags |= ALC_FLAG_PCIE;
- sc->alc_expcap = base;
- burst = CSR_READ_2(sc, base + PCIER_DEVICE_CTL);
- sc->alc_dma_rd_burst =
- (burst & PCIEM_CTL_MAX_READ_REQUEST) >> 12;
- sc->alc_dma_wr_burst = (burst & PCIEM_CTL_MAX_PAYLOAD) >> 5;
- if (bootverbose) {
- device_printf(dev, "Read request size : %u bytes.\n",
- alc_dma_burst[sc->alc_dma_rd_burst]);
- device_printf(dev, "TLP payload size : %u bytes.\n",
- alc_dma_burst[sc->alc_dma_wr_burst]);
- }
- if (alc_dma_burst[sc->alc_dma_rd_burst] > 1024)
- 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);
+ /* 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 == DEVICEID_ATHEROS_AR8152_B &&
- pci_get_revid(dev) == ATHEROS_AR8152_B_V10) {
+ 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);
@@ -831,13 +1279,13 @@ alc_attach(device_t dev)
CSR_WRITE_4(sc, ALC_PCIE_PHYMISC2, val);
}
/* Disable ASPM L0S and L1. */
- cap = CSR_READ_2(sc, base + PCIER_LINK_CAP);
+ cap = CSR_READ_2(sc, sc->alc_expcap + PCIER_LINK_CAP);
if ((cap & PCIEM_LINK_CAP_ASPM) != 0) {
- ctl = CSR_READ_2(sc, base + PCIER_LINK_CTL);
+ ctl = CSR_READ_2(sc, sc->alc_expcap + PCIER_LINK_CTL);
if ((ctl & 0x08) != 0)
sc->alc_rcb = DMA_CFG_RCB_128;
if (bootverbose)
- device_printf(dev, "RCB %u bytes\n",
+ device_printf(sc->alc_dev, "RCB %u bytes\n",
sc->alc_rcb == DMA_CFG_RCB_64 ? 64 : 128);
state = ctl & 0x03;
if (state & 0x01)
@@ -854,13 +1302,91 @@ alc_attach(device_t dev)
device_printf(sc->alc_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);
+}
- /* Reset PHY. */
- alc_phy_reset(sc);
+static void
+alc_config_msi(struct alc_softc *sc)
+{
+ uint32_t ctl, mod;
- /* Reset the ethernet controller. */
- alc_reset(sc);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0) {
+ /*
+ * It seems interrupt moderation is controlled by
+ * ALC_MSI_RETRANS_TIMER register if MSI/MSIX is active.
+ * Driver uses RX interrupt moderation parameter to
+ * program ALC_MSI_RETRANS_TIMER register.
+ */
+ ctl = CSR_READ_4(sc, ALC_MSI_RETRANS_TIMER);
+ ctl &= ~MSI_RETRANS_TIMER_MASK;
+ ctl &= ~MSI_RETRANS_MASK_SEL_LINE;
+ mod = ALC_USECS(sc->alc_int_rx_mod);
+ if (mod == 0)
+ mod = 1;
+ ctl |= mod;
+ if ((sc->alc_flags & ALC_FLAG_MSIX) != 0)
+ CSR_WRITE_4(sc, ALC_MSI_RETRANS_TIMER, ctl |
+ MSI_RETRANS_MASK_SEL_STD);
+ else if ((sc->alc_flags & ALC_FLAG_MSI) != 0)
+ CSR_WRITE_4(sc, ALC_MSI_RETRANS_TIMER, ctl |
+ MSI_RETRANS_MASK_SEL_LINE);
+ else
+ CSR_WRITE_4(sc, ALC_MSI_RETRANS_TIMER, 0);
+ }
+}
+
+static int
+alc_attach(device_t dev)
+{
+ struct alc_softc *sc;
+ struct ifnet *ifp;
+ int base, error, i, msic, msixc;
+ uint16_t burst;
+
+ error = 0;
+ sc = device_get_softc(dev);
+ sc->alc_dev = dev;
+ sc->alc_rev = pci_get_revid(dev);
+
+ mtx_init(&sc->alc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
+ MTX_DEF);
+ callout_init_mtx(&sc->alc_tick_ch, &sc->alc_mtx, 0);
+ TASK_INIT(&sc->alc_int_task, 0, alc_int_task, sc);
+ sc->alc_ident = alc_find_ident(dev);
+
+ /* Map the device. */
+ pci_enable_busmaster(dev);
+ sc->alc_res_spec = alc_res_spec_mem;
+ sc->alc_irq_spec = alc_irq_spec_legacy;
+ error = bus_alloc_resources(dev, sc->alc_res_spec, sc->alc_res);
+ if (error != 0) {
+ device_printf(dev, "cannot allocate memory resources.\n");
+ goto fail;
+ }
+
+ /* Set PHY address. */
+ sc->alc_phyaddr = ALC_PHY_ADDR;
/*
* One odd thing is AR8132 uses the same PHY hardware(F1
@@ -870,6 +1396,19 @@ alc_attach(device_t dev)
* shows the same PHY model/revision number of AR8131.
*/
switch (sc->alc_ident->deviceid) {
+ case DEVICEID_ATHEROS_AR8161:
+ if (pci_get_subvendor(dev) == VENDORID_ATHEROS &&
+ pci_get_subdevice(dev) == 0x0091 && sc->alc_rev == 0)
+ sc->alc_flags |= ALC_FLAG_LINK_WAR;
+ /* FALLTHROUGH */
+ case DEVICEID_ATHEROS_E2200:
+ case DEVICEID_ATHEROS_AR8171:
+ sc->alc_flags |= ALC_FLAG_AR816X_FAMILY;
+ break;
+ case DEVICEID_ATHEROS_AR8162:
+ case DEVICEID_ATHEROS_AR8172:
+ sc->alc_flags |= ALC_FLAG_FASTETHER | ALC_FLAG_AR816X_FAMILY;
+ break;
case DEVICEID_ATHEROS_AR8152_B:
case DEVICEID_ATHEROS_AR8152_B2:
sc->alc_flags |= ALC_FLAG_APS;
@@ -884,7 +1423,7 @@ alc_attach(device_t dev)
default:
break;
}
- sc->alc_flags |= ALC_FLAG_ASPM_MON | ALC_FLAG_JUMBO;
+ sc->alc_flags |= ALC_FLAG_JUMBO;
/*
* It seems that AR813x/AR815x has silicon bug for SMB. In
@@ -897,7 +1436,6 @@ alc_attach(device_t dev)
* Don't use Tx CMB. It is known to have silicon bug.
*/
sc->alc_flags |= ALC_FLAG_CMB_BUG;
- sc->alc_rev = pci_get_revid(dev);
sc->alc_chip_rev = CSR_READ_4(sc, ALC_MASTER_CFG) >>
MASTER_CHIP_REV_SHIFT;
if (bootverbose) {
@@ -905,11 +1443,45 @@ alc_attach(device_t dev)
sc->alc_rev);
device_printf(dev, "Chip id/revision : 0x%04x\n",
sc->alc_chip_rev);
+ if ((sc->alc_flags & ALC_FLAG_AR816X_FAMILY) != 0)
+ device_printf(dev, "AR816x revision : 0x%x\n",
+ AR816X_REV(sc->alc_rev));
}
device_printf(dev, "%u Tx FIFO, %u Rx FIFO\n",
CSR_READ_4(sc, ALC_SRAM_TX_FIFO_LEN) * 8,
CSR_READ_4(sc, ALC_SRAM_RX_FIFO_LEN) * 8);
+ /* Initialize DMA parameters. */
+ sc->alc_dma_rd_burst = 0;
+ sc->alc_dma_wr_burst = 0;
+ sc->alc_rcb = DMA_CFG_RCB_64;
+ if (pci_find_cap(dev, PCIY_EXPRESS, &base) == 0) {
+ sc->alc_flags |= ALC_FLAG_PCIE;
+ sc->alc_expcap = base;
+ burst = CSR_READ_2(sc, base + PCIER_DEVICE_CTL);
+ sc->alc_dma_rd_burst =
+ (burst & PCIEM_CTL_MAX_READ_REQUEST) >> 12;
+ sc->alc_dma_wr_burst = (burst & PCIEM_CTL_MAX_PAYLOAD) >> 5;
+ if (bootverbose) {
+ device_printf(dev, "Read request size : %u bytes.\n",
+ alc_dma_burst[sc->alc_dma_rd_burst]);
+ device_printf(dev, "TLP payload size : %u bytes.\n",
+ alc_dma_burst[sc->alc_dma_wr_burst]);
+ }
+ if (alc_dma_burst[sc->alc_dma_rd_burst] > 1024)
+ sc->alc_dma_rd_burst = 3;
+ if (alc_dma_burst[sc->alc_dma_wr_burst] > 1024)
+ sc->alc_dma_wr_burst = 3;
+ alc_init_pcie(sc);
+ }
+
+ /* Reset PHY. */
+ alc_phy_reset(sc);
+
+ /* Reset the ethernet controller. */
+ alc_stop_mac(sc);
+ alc_reset(sc);
+
/* Allocate IRQ resources. */
msixc = pci_msix_count(dev);
msic = pci_msi_count(dev);
@@ -917,11 +1489,20 @@ alc_attach(device_t dev)
device_printf(dev, "MSIX count : %d\n", msixc);
device_printf(dev, "MSI count : %d\n", msic);
}
- /* Prefer MSIX over MSI. */
+ if (msixc > 1)
+ msixc = 1;
+ if (msic > 1)
+ msic = 1;
+ /*
+ * Prefer MSIX over MSI.
+ * AR816x controller has a silicon bug that MSI interrupt
+ * does not assert if PCIM_CMD_INTxDIS bit of command
+ * register is set. pci(4) was taught to handle that case.
+ */
if (msix_disable == 0 || msi_disable == 0) {
- if (msix_disable == 0 && msixc == ALC_MSIX_MESSAGES &&
+ if (msix_disable == 0 && msixc > 0 &&
pci_alloc_msix(dev, &msixc) == 0) {
- if (msic == ALC_MSIX_MESSAGES) {
+ if (msic == 1) {
device_printf(dev,
"Using %d MSIX message(s).\n", msixc);
sc->alc_flags |= ALC_FLAG_MSIX;
@@ -930,9 +1511,8 @@ alc_attach(device_t dev)
pci_release_msi(dev);
}
if (msi_disable == 0 && (sc->alc_flags & ALC_FLAG_MSIX) == 0 &&
- msic == ALC_MSI_MESSAGES &&
- pci_alloc_msi(dev, &msic) == 0) {
- if (msic == ALC_MSI_MESSAGES) {
+ msic > 0 && pci_alloc_msi(dev, &msic) == 0) {
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable-9
mailing list