cxgb(4) updates, including:
- support for the new Gen-2, BT, and LP-CR cards. - T3 firmware 7.7.0 - shared "common code" updates. Approved by: gnn (mentor) Obtained from: Chelsio MFC after: 1 month
This commit is contained in:
parent
2880192bf2
commit
c01f2b8301
@ -774,6 +774,8 @@ dev/cxgb/common/cxgb_vsc8211.c optional cxgb pci \
|
||||
compile-with "${NORMAL_C} -I$S/dev/cxgb"
|
||||
dev/cxgb/common/cxgb_ael1002.c optional cxgb pci \
|
||||
compile-with "${NORMAL_C} -I$S/dev/cxgb"
|
||||
dev/cxgb/common/cxgb_aq100x.c optional cxgb pci \
|
||||
compile-with "${NORMAL_C} -I$S/dev/cxgb"
|
||||
dev/cxgb/common/cxgb_mv88e1xxx.c optional cxgb pci \
|
||||
compile-with "${NORMAL_C} -I$S/dev/cxgb"
|
||||
dev/cxgb/common/cxgb_xgmac.c optional cxgb pci \
|
||||
|
File diff suppressed because it is too large
Load Diff
544
sys/dev/cxgb/common/cxgb_aq100x.c
Normal file
544
sys/dev/cxgb/common/cxgb_aq100x.c
Normal file
@ -0,0 +1,544 @@
|
||||
/**************************************************************************
|
||||
|
||||
Copyright (c) 2009 Chelsio Inc.
|
||||
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. Neither the name of the Chelsio Corporation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <cxgb_include.h>
|
||||
|
||||
#undef msleep
|
||||
#define msleep t3_os_sleep
|
||||
|
||||
enum {
|
||||
/* MDIO_DEV_PMA_PMD registers */
|
||||
AQ_LINK_STAT = 0xe800,
|
||||
|
||||
/* MDIO_DEV_XGXS registers */
|
||||
AQ_XAUI_RX_CFG = 0xc400,
|
||||
AQ_XAUI_KX_CFG = 0xc440,
|
||||
AQ_XAUI_TX_CFG = 0xe400,
|
||||
|
||||
/* MDIO_DEV_ANEG registers */
|
||||
AQ_100M_CTRL = 0x0010,
|
||||
AQ_10G_CTRL = 0x0020,
|
||||
AQ_1G_CTRL = 0xc400,
|
||||
AQ_ANEG_STAT = 0xc800,
|
||||
|
||||
/* MDIO_DEV_VEND1 registers */
|
||||
AQ_FW_VERSION = 0x0020,
|
||||
AQ_THERMAL_THR = 0xc421,
|
||||
AQ_THERMAL1 = 0xc820,
|
||||
AQ_THERMAL2 = 0xc821,
|
||||
AQ_IFLAG_GLOBAL = 0xfc00,
|
||||
AQ_IMASK_GLOBAL = 0xff00,
|
||||
};
|
||||
|
||||
#define AQBIT(x) (1 << (0x##x))
|
||||
#define ADV_1G_FULL AQBIT(f)
|
||||
#define ADV_1G_HALF AQBIT(e)
|
||||
#define ADV_10G_FULL AQBIT(c)
|
||||
|
||||
#define AQ_WRITE_REGS(phy, regs) do { \
|
||||
int i; \
|
||||
for (i = 0; i < ARRAY_SIZE(regs); i++) { \
|
||||
(void) mdio_write(phy, regs[i].mmd, regs[i].reg, regs[i].val); \
|
||||
} \
|
||||
} while (0)
|
||||
#define AQ_READ_REGS(phy, regs) do { \
|
||||
unsigned i, v; \
|
||||
for (i = 0; i < ARRAY_SIZE(regs); i++) { \
|
||||
(void) mdio_read(phy, regs[i].mmd, regs[i].reg, &v); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Return value is temperature in celcius, 0xffff for error or don't know.
|
||||
*/
|
||||
static int
|
||||
aq100x_temperature(struct cphy *phy)
|
||||
{
|
||||
unsigned int v;
|
||||
|
||||
if (mdio_read(phy, MDIO_DEV_VEND1, AQ_THERMAL2, &v) ||
|
||||
v == 0xffff || (v & 1) != 1)
|
||||
return (0xffff);
|
||||
|
||||
if (mdio_read(phy, MDIO_DEV_VEND1, AQ_THERMAL1, &v))
|
||||
return (0xffff);
|
||||
|
||||
return ((int)((signed char)(v >> 8)));
|
||||
}
|
||||
|
||||
static int
|
||||
aq100x_set_defaults(struct cphy *phy)
|
||||
{
|
||||
return mdio_write(phy, MDIO_DEV_VEND1, AQ_THERMAL_THR, 0x6c00);
|
||||
}
|
||||
|
||||
static int
|
||||
aq100x_reset(struct cphy *phy, int wait)
|
||||
{
|
||||
int err;
|
||||
err = t3_phy_reset(phy, MDIO_DEV_PMA_PMD, wait);
|
||||
if (!err)
|
||||
err = aq100x_set_defaults(phy);
|
||||
return (err);
|
||||
}
|
||||
|
||||
static int
|
||||
aq100x_intr_enable(struct cphy *phy)
|
||||
{
|
||||
struct {
|
||||
int mmd;
|
||||
int reg;
|
||||
int val;
|
||||
} imasks[] = {
|
||||
{MDIO_DEV_VEND1, 0xd400, AQBIT(e)},
|
||||
{MDIO_DEV_VEND1, 0xff01, AQBIT(2)},
|
||||
{MDIO_DEV_VEND1, AQ_IMASK_GLOBAL, AQBIT(0)}
|
||||
};
|
||||
|
||||
AQ_WRITE_REGS(phy, imasks);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aq100x_intr_disable(struct cphy *phy)
|
||||
{
|
||||
struct {
|
||||
int mmd;
|
||||
int reg;
|
||||
int val;
|
||||
} imasks[] = {
|
||||
{MDIO_DEV_VEND1, 0xd400, 0},
|
||||
{MDIO_DEV_VEND1, 0xff01, 0},
|
||||
{MDIO_DEV_VEND1, AQ_IMASK_GLOBAL, 0}
|
||||
};
|
||||
|
||||
AQ_WRITE_REGS(phy, imasks);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aq100x_intr_clear(struct cphy *phy)
|
||||
{
|
||||
struct {
|
||||
int mmd;
|
||||
int reg;
|
||||
} iclr[] = {
|
||||
{MDIO_DEV_VEND1, 0xcc00},
|
||||
{MDIO_DEV_VEND1, AQ_IMASK_GLOBAL} /* needed? */
|
||||
};
|
||||
|
||||
AQ_READ_REGS(phy, iclr);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aq100x_vendor_intr(struct cphy *phy, int *rc)
|
||||
{
|
||||
int err;
|
||||
unsigned int cause, v;
|
||||
|
||||
err = mdio_read(phy, MDIO_DEV_VEND1, 0xfc01, &cause);
|
||||
if (err)
|
||||
return (err);
|
||||
|
||||
if (cause & AQBIT(2)) {
|
||||
err = mdio_read(phy, MDIO_DEV_VEND1, 0xcc00, &v);
|
||||
if (err)
|
||||
return (err);
|
||||
|
||||
if (v & AQBIT(e)) {
|
||||
CH_WARN(phy->adapter, "PHY%d: temperature is now %dC\n",
|
||||
phy->addr, aq100x_temperature(phy));
|
||||
|
||||
t3_set_reg_field(phy->adapter, A_T3DBG_GPIO_EN,
|
||||
phy->addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL, 0);
|
||||
|
||||
*rc |= cphy_cause_alarm;
|
||||
}
|
||||
|
||||
cause &= ~4;
|
||||
}
|
||||
|
||||
if (cause)
|
||||
CH_WARN(phy->adapter, "PHY%d: unhandled vendor interrupt"
|
||||
" (0x%x)\n", phy->addr, cause);
|
||||
|
||||
return (0);
|
||||
|
||||
}
|
||||
|
||||
static int
|
||||
aq100x_intr_handler(struct cphy *phy)
|
||||
{
|
||||
int err, rc = 0;
|
||||
unsigned int cause;
|
||||
|
||||
err = mdio_read(phy, MDIO_DEV_VEND1, AQ_IFLAG_GLOBAL, &cause);
|
||||
if (err)
|
||||
return (err);
|
||||
|
||||
if (cause & AQBIT(0)) {
|
||||
err = aq100x_vendor_intr(phy, &rc);
|
||||
if (err)
|
||||
return (err);
|
||||
cause &= ~AQBIT(0);
|
||||
}
|
||||
|
||||
if (cause)
|
||||
CH_WARN(phy->adapter, "PHY%d: unhandled interrupt (0x%x)\n",
|
||||
phy->addr, cause);
|
||||
|
||||
return (rc);
|
||||
}
|
||||
|
||||
static int
|
||||
aq100x_power_down(struct cphy *phy, int off)
|
||||
{
|
||||
int err, wait = 500;
|
||||
unsigned int v;
|
||||
|
||||
err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR, BMCR_PDOWN,
|
||||
off ? BMCR_PDOWN : 0);
|
||||
if (err || off)
|
||||
return (v);
|
||||
|
||||
msleep(300);
|
||||
do {
|
||||
err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
|
||||
if (err)
|
||||
return (err);
|
||||
v &= BMCR_RESET;
|
||||
if (v)
|
||||
msleep(10);
|
||||
} while (v && --wait);
|
||||
if (v) {
|
||||
CH_WARN(phy->adapter, "PHY%d: power-up timed out (0x%x).\n",
|
||||
phy->addr, v);
|
||||
return (ETIMEDOUT);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aq100x_autoneg_enable(struct cphy *phy)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = aq100x_power_down(phy, 0);
|
||||
if (!err)
|
||||
err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, MII_BMCR,
|
||||
BMCR_RESET, BMCR_ANENABLE | BMCR_ANRESTART);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
static int
|
||||
aq100x_autoneg_restart(struct cphy *phy)
|
||||
{
|
||||
return aq100x_autoneg_enable(phy);
|
||||
}
|
||||
|
||||
static int
|
||||
aq100x_advertise(struct cphy *phy, unsigned int advertise_map)
|
||||
{
|
||||
unsigned int adv;
|
||||
int err;
|
||||
|
||||
/* 10G advertisement */
|
||||
adv = 0;
|
||||
if (advertise_map & ADVERTISED_10000baseT_Full)
|
||||
adv |= ADV_10G_FULL;
|
||||
err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_10G_CTRL,
|
||||
ADV_10G_FULL, adv);
|
||||
if (err)
|
||||
return (err);
|
||||
|
||||
/* 1G advertisement */
|
||||
adv = 0;
|
||||
if (advertise_map & ADVERTISED_1000baseT_Full)
|
||||
adv |= ADV_1G_FULL;
|
||||
if (advertise_map & ADVERTISED_1000baseT_Half)
|
||||
adv |= ADV_1G_HALF;
|
||||
err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_1G_CTRL,
|
||||
ADV_1G_FULL | ADV_1G_HALF, adv);
|
||||
if (err)
|
||||
return (err);
|
||||
|
||||
/* 100M, pause advertisement */
|
||||
adv = 0;
|
||||
if (advertise_map & ADVERTISED_100baseT_Half)
|
||||
adv |= ADVERTISE_100HALF;
|
||||
if (advertise_map & ADVERTISED_100baseT_Full)
|
||||
adv |= ADVERTISE_100FULL;
|
||||
if (advertise_map & ADVERTISED_Pause)
|
||||
adv |= ADVERTISE_PAUSE_CAP;
|
||||
if (advertise_map & ADVERTISED_Asym_Pause)
|
||||
adv |= ADVERTISE_PAUSE_ASYM;
|
||||
err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, AQ_100M_CTRL, 0xfe0, adv);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
static int
|
||||
aq100x_set_loopback(struct cphy *phy, int mmd, int dir, int enable)
|
||||
{
|
||||
return t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
|
||||
BMCR_LOOPBACK, enable ? BMCR_LOOPBACK : 0);
|
||||
}
|
||||
|
||||
static int
|
||||
aq100x_set_speed_duplex(struct cphy *phy, int speed, int duplex)
|
||||
{
|
||||
int err, set;
|
||||
|
||||
if (speed == SPEED_100)
|
||||
set = BMCR_SPEED100;
|
||||
else if (speed == SPEED_1000)
|
||||
set = BMCR_SPEED1000;
|
||||
else if (speed == SPEED_10000)
|
||||
set = BMCR_SPEED1000 | BMCR_SPEED100;
|
||||
else
|
||||
return (EINVAL);
|
||||
|
||||
if (duplex != DUPLEX_FULL)
|
||||
return (EINVAL);
|
||||
|
||||
err = t3_mdio_change_bits(phy, MDIO_DEV_ANEG, MII_BMCR,
|
||||
BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART, 0);
|
||||
if (err)
|
||||
return (err);
|
||||
|
||||
err = t3_mdio_change_bits(phy, MDIO_DEV_PMA_PMD, MII_BMCR,
|
||||
BMCR_SPEED1000 | BMCR_SPEED100, set);
|
||||
if (err)
|
||||
return (err);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
aq100x_get_link_status(struct cphy *phy, int *link_ok, int *speed, int *duplex,
|
||||
int *fc)
|
||||
{
|
||||
int err;
|
||||
unsigned int v, link = 0;
|
||||
|
||||
err = mdio_read(phy, MDIO_DEV_PMA_PMD, AQ_LINK_STAT, &v);
|
||||
if (err)
|
||||
return (err);
|
||||
if (v == 0xffff || !(v & 1))
|
||||
goto done;
|
||||
|
||||
err = mdio_read(phy, MDIO_DEV_ANEG, MII_BMCR, &v);
|
||||
if (err)
|
||||
return (err);
|
||||
if (v & 0x8000)
|
||||
goto done;
|
||||
if (v & BMCR_ANENABLE) {
|
||||
|
||||
err = mdio_read(phy, MDIO_DEV_ANEG, 1, &v);
|
||||
if (err)
|
||||
return (err);
|
||||
if ((v & 0x20) == 0)
|
||||
goto done;
|
||||
|
||||
err = mdio_read(phy, MDIO_DEV_ANEG, AQ_ANEG_STAT, &v);
|
||||
if (err)
|
||||
return (err);
|
||||
|
||||
if (speed) {
|
||||
switch (v & 0x6) {
|
||||
case 0x6: *speed = SPEED_10000;
|
||||
break;
|
||||
case 0x4: *speed = SPEED_1000;
|
||||
break;
|
||||
case 0x2: *speed = SPEED_100;
|
||||
break;
|
||||
case 0x0: *speed = SPEED_10;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (duplex)
|
||||
*duplex = v & 1 ? DUPLEX_FULL : DUPLEX_HALF;
|
||||
|
||||
if (fc) {
|
||||
unsigned int lpa, adv;
|
||||
err = mdio_read(phy, MDIO_DEV_ANEG, 0x13, &lpa);
|
||||
if (!err)
|
||||
err = mdio_read(phy, MDIO_DEV_ANEG,
|
||||
AQ_100M_CTRL, &adv);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (lpa & adv & ADVERTISE_PAUSE_CAP)
|
||||
*fc = PAUSE_RX | PAUSE_TX;
|
||||
else if (lpa & ADVERTISE_PAUSE_CAP &&
|
||||
lpa & ADVERTISE_PAUSE_ASYM &&
|
||||
adv & ADVERTISE_PAUSE_ASYM)
|
||||
*fc = PAUSE_TX;
|
||||
else if (lpa & ADVERTISE_PAUSE_ASYM &&
|
||||
adv & ADVERTISE_PAUSE_CAP)
|
||||
*fc = PAUSE_RX;
|
||||
else
|
||||
*fc = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
|
||||
if (err)
|
||||
return (err);
|
||||
|
||||
v &= BMCR_SPEED1000 | BMCR_SPEED100;
|
||||
if (speed) {
|
||||
if (v == (BMCR_SPEED1000 | BMCR_SPEED100))
|
||||
*speed = SPEED_10000;
|
||||
else if (v == BMCR_SPEED1000)
|
||||
*speed = SPEED_1000;
|
||||
else if (v == BMCR_SPEED100)
|
||||
*speed = SPEED_100;
|
||||
else
|
||||
*speed = SPEED_10;
|
||||
}
|
||||
|
||||
if (duplex)
|
||||
*duplex = DUPLEX_FULL;
|
||||
}
|
||||
|
||||
link = 1;
|
||||
done:
|
||||
if (link_ok)
|
||||
*link_ok = link;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct cphy_ops aq100x_ops = {
|
||||
.reset = aq100x_reset,
|
||||
.intr_enable = aq100x_intr_enable,
|
||||
.intr_disable = aq100x_intr_disable,
|
||||
.intr_clear = aq100x_intr_clear,
|
||||
.intr_handler = aq100x_intr_handler,
|
||||
.autoneg_enable = aq100x_autoneg_enable,
|
||||
.autoneg_restart = aq100x_autoneg_restart,
|
||||
.advertise = aq100x_advertise,
|
||||
.set_loopback = aq100x_set_loopback,
|
||||
.set_speed_duplex = aq100x_set_speed_duplex,
|
||||
.get_link_status = aq100x_get_link_status,
|
||||
.power_down = aq100x_power_down,
|
||||
};
|
||||
|
||||
int
|
||||
t3_aq100x_phy_prep(pinfo_t *pinfo, int phy_addr,
|
||||
const struct mdio_ops *mdio_ops)
|
||||
{
|
||||
struct cphy *phy = &pinfo->phy;
|
||||
unsigned int v, v2, gpio, wait;
|
||||
int err;
|
||||
adapter_t *adapter = pinfo->adapter;
|
||||
|
||||
cphy_init(&pinfo->phy, adapter, pinfo, phy_addr, &aq100x_ops, mdio_ops,
|
||||
SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full |
|
||||
SUPPORTED_TP | SUPPORTED_Autoneg | SUPPORTED_AUI |
|
||||
SUPPORTED_MISC_IRQ, "1000/10GBASE-T");
|
||||
|
||||
/*
|
||||
* Hard reset the PHY.
|
||||
*/
|
||||
gpio = phy_addr ? F_GPIO10_OUT_VAL : F_GPIO6_OUT_VAL;
|
||||
t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, 0);
|
||||
msleep(1);
|
||||
t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, gpio, gpio);
|
||||
|
||||
/*
|
||||
* Give it enough time to load the firmware and get ready for mdio.
|
||||
*/
|
||||
msleep(1000);
|
||||
wait = 500; /* in 10ms increments */
|
||||
do {
|
||||
err = mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
|
||||
if (err || v == 0xffff) {
|
||||
|
||||
/* Allow prep_adapter to succeed when ffff is read */
|
||||
|
||||
CH_WARN(adapter, "PHY%d: reset failed (0x%x, 0x%x).\n",
|
||||
phy_addr, err, v);
|
||||
goto done;
|
||||
}
|
||||
|
||||
v &= BMCR_RESET;
|
||||
if (v)
|
||||
msleep(10);
|
||||
} while (v && --wait);
|
||||
if (v) {
|
||||
CH_WARN(adapter, "PHY%d: reset timed out (0x%x).\n",
|
||||
phy_addr, v);
|
||||
|
||||
goto done; /* let prep_adapter succeed */
|
||||
}
|
||||
|
||||
/* Firmware version check. */
|
||||
(void) mdio_read(phy, MDIO_DEV_VEND1, AQ_FW_VERSION, &v);
|
||||
if (v < 0x115)
|
||||
CH_WARN(adapter, "PHY%d: unknown firmware %d.%d\n", phy_addr,
|
||||
v >> 8, v & 0xff);
|
||||
|
||||
#if 0
|
||||
/* The PHY should start in really-low-power mode. */
|
||||
(void) mdio_read(phy, MDIO_DEV_PMA_PMD, MII_BMCR, &v);
|
||||
if ((v & BMCR_PDOWN) == 0)
|
||||
CH_WARN(adapter, "PHY%d does not start in low power mode.\n",
|
||||
phy_addr);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Verify XAUI and 1000-X settings, but let prep succeed no matter what.
|
||||
*/
|
||||
v = v2 = 0;
|
||||
(void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_RX_CFG, &v);
|
||||
(void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_TX_CFG, &v2);
|
||||
if (v != 0x1b || v2 != 0x1b)
|
||||
CH_WARN(adapter, "PHY%d: incorrect XAUI settings "
|
||||
"(0x%x, 0x%x).\n", phy_addr, v, v2);
|
||||
v = 0;
|
||||
(void) mdio_read(phy, MDIO_DEV_XGXS, AQ_XAUI_KX_CFG, &v);
|
||||
if ((v & 0xf) != 0xf)
|
||||
CH_WARN(adapter, "PHY%d: incorrect 1000-X settings "
|
||||
"(0x%x).\n", phy_addr, v);
|
||||
|
||||
(void) aq100x_set_defaults(phy);
|
||||
done:
|
||||
return (err);
|
||||
}
|
@ -56,7 +56,11 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
SUPPORTED_IRQ = 1 << 24
|
||||
SUPPORTED_LINK_IRQ = 1 << 24,
|
||||
/* skip 25 */
|
||||
SUPPORTED_MISC_IRQ = 1 << 26,
|
||||
SUPPORTED_IRQ = (SUPPORTED_LINK_IRQ | SUPPORTED_MISC_IRQ),
|
||||
POLL_LINK_1ST_TIME = 1 << 27
|
||||
};
|
||||
|
||||
enum { /* adapter interrupt-maintained statistics */
|
||||
@ -93,7 +97,7 @@ enum {
|
||||
|
||||
enum {
|
||||
FW_VERSION_MAJOR = 7,
|
||||
FW_VERSION_MINOR = 1,
|
||||
FW_VERSION_MINOR = 7,
|
||||
FW_VERSION_MICRO = 0
|
||||
};
|
||||
|
||||
@ -484,6 +488,7 @@ struct cmac {
|
||||
u64 rx_mcnt;
|
||||
unsigned int toggle_cnt;
|
||||
unsigned int txen;
|
||||
unsigned int was_reset;
|
||||
u64 rx_pause;
|
||||
struct mac_stats stats;
|
||||
};
|
||||
@ -526,6 +531,7 @@ enum {
|
||||
cphy_cause_link_change = 1,
|
||||
cphy_cause_fifo_error = 2,
|
||||
cphy_cause_module_change = 4,
|
||||
cphy_cause_alarm = 8,
|
||||
};
|
||||
|
||||
/* PHY module types */
|
||||
@ -563,9 +569,10 @@ struct cphy_ops {
|
||||
struct cphy {
|
||||
u8 addr; /* PHY address */
|
||||
u8 modtype; /* PHY module type */
|
||||
short priv; /* scratch pad */
|
||||
unsigned int priv; /* scratch pad */
|
||||
unsigned int caps; /* PHY capabilities */
|
||||
adapter_t *adapter; /* associated adapter */
|
||||
pinfo_t *pinfo; /* associated port */
|
||||
const char *desc; /* PHY description */
|
||||
unsigned long fifo_errors; /* FIFO over/under-flows */
|
||||
const struct cphy_ops *ops; /* PHY operations */
|
||||
@ -589,7 +596,7 @@ static inline int mdio_write(struct cphy *phy, int mmd, int reg,
|
||||
}
|
||||
|
||||
/* Convenience initializer */
|
||||
static inline void cphy_init(struct cphy *phy, adapter_t *adapter,
|
||||
static inline void cphy_init(struct cphy *phy, adapter_t *adapter, pinfo_t *pinfo,
|
||||
int phy_addr, struct cphy_ops *phy_ops,
|
||||
const struct mdio_ops *mdio_ops, unsigned int caps,
|
||||
const char *desc)
|
||||
@ -597,6 +604,7 @@ static inline void cphy_init(struct cphy *phy, adapter_t *adapter,
|
||||
phy->addr = (u8)phy_addr;
|
||||
phy->caps = caps;
|
||||
phy->adapter = adapter;
|
||||
phy->pinfo = pinfo;
|
||||
phy->desc = desc;
|
||||
phy->ops = phy_ops;
|
||||
if (mdio_ops) {
|
||||
@ -742,7 +750,7 @@ int t3_cim_ctl_blk_read(adapter_t *adap, unsigned int addr, unsigned int n,
|
||||
int t3_mc7_bd_read(struct mc7 *mc7, unsigned int start, unsigned int n,
|
||||
u64 *buf);
|
||||
|
||||
int t3_mac_reset(struct cmac *mac);
|
||||
int t3_mac_init(struct cmac *mac);
|
||||
void t3b_pcs_reset(struct cmac *mac);
|
||||
void t3_mac_disable_exact_filters(struct cmac *mac);
|
||||
void t3_mac_enable_exact_filters(struct cmac *mac);
|
||||
@ -827,25 +835,33 @@ int t3_vsc7323_enable(adapter_t *adap, int port, int which);
|
||||
int t3_vsc7323_disable(adapter_t *adap, int port, int which);
|
||||
const struct mac_stats *t3_vsc7323_update_stats(struct cmac *mac);
|
||||
|
||||
int t3_i2c_read8(adapter_t *adapter, int chained, u8 *valp);
|
||||
int t3_i2c_write8(adapter_t *adapter, int chained, u8 val);
|
||||
|
||||
int t3_mi1_read(adapter_t *adapter, int phy_addr, int mmd_addr, int reg_addr,
|
||||
unsigned int *valp);
|
||||
int t3_mi1_write(adapter_t *adapter, int phy_addr, int mmd_addr, int reg_addr,
|
||||
unsigned int val);
|
||||
|
||||
int t3_mv88e1xxx_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
|
||||
int t3_mv88e1xxx_phy_prep(pinfo_t *pinfo, int phy_addr,
|
||||
const struct mdio_ops *mdio_ops);
|
||||
int t3_vsc8211_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
|
||||
int t3_vsc8211_phy_prep(pinfo_t *pinfo, int phy_addr,
|
||||
const struct mdio_ops *mdio_ops);
|
||||
int t3_ael1002_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
|
||||
int t3_vsc8211_fifo_depth(adapter_t *adap, unsigned int mtu, int port);
|
||||
int t3_ael1002_phy_prep(pinfo_t *pinfo, int phy_addr,
|
||||
const struct mdio_ops *mdio_ops);
|
||||
int t3_ael1006_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
|
||||
int t3_ael1006_phy_prep(pinfo_t *pinfo, int phy_addr,
|
||||
const struct mdio_ops *mdio_ops);
|
||||
int t3_ael2005_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
|
||||
int t3_ael2005_phy_prep(pinfo_t *pinfo, int phy_addr,
|
||||
const struct mdio_ops *mdio_ops);
|
||||
int t3_qt2045_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
|
||||
int t3_ael2020_phy_prep(pinfo_t *pinfo, int phy_addr,
|
||||
const struct mdio_ops *mdio_ops);
|
||||
int t3_qt2045_phy_prep(pinfo_t *pinfo, int phy_addr,
|
||||
const struct mdio_ops *mdio_ops);
|
||||
int t3_tn1010_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
|
||||
int t3_tn1010_phy_prep(pinfo_t *pinfo, int phy_addr,
|
||||
const struct mdio_ops *mdio_ops);
|
||||
int t3_xaui_direct_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
|
||||
int t3_xaui_direct_phy_prep(pinfo_t *pinfo, int phy_addr,
|
||||
const struct mdio_ops *mdio_ops);
|
||||
int t3_aq100x_phy_prep(pinfo_t *pinfo, int phy_addr,
|
||||
const struct mdio_ops *mdio_ops);
|
||||
#endif /* __CHELSIO_COMMON_H */
|
||||
|
@ -294,12 +294,13 @@ static struct cphy_ops mv88e1xxx_ops = {
|
||||
};
|
||||
#endif
|
||||
|
||||
int t3_mv88e1xxx_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
|
||||
int t3_mv88e1xxx_phy_prep(pinfo_t *pinfo, int phy_addr,
|
||||
const struct mdio_ops *mdio_ops)
|
||||
{
|
||||
struct cphy *phy = &pinfo->phy;
|
||||
int err;
|
||||
|
||||
cphy_init(phy, adapter, phy_addr, &mv88e1xxx_ops, mdio_ops,
|
||||
cphy_init(phy, pinfo->adapter, pinfo, phy_addr, &mv88e1xxx_ops, mdio_ops,
|
||||
SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full |
|
||||
SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII |
|
||||
SUPPORTED_TP | SUPPORTED_IRQ, "10/100/1000BASE-T");
|
||||
|
@ -280,6 +280,11 @@ $FreeBSD$
|
||||
#define V_RSPQ7STARVED(x) ((x) << S_RSPQ7STARVED)
|
||||
#define F_RSPQ7STARVED V_RSPQ7STARVED(1U)
|
||||
|
||||
#define S_RSPQXSTARVED 0
|
||||
#define M_RSPQXSTARVED 0xff
|
||||
#define V_RSPQXSTARVED(x) ((x) << S_RSPQXSTARVED)
|
||||
#define G_RSPQXSTARVED(x) (((x) >> S_RSPQXSTARVED) & M_RSPQXSTARVED)
|
||||
|
||||
#define S_RSPQ0DISABLED 8
|
||||
#define V_RSPQ0DISABLED(x) ((x) << S_RSPQ0DISABLED)
|
||||
#define F_RSPQ0DISABLED V_RSPQ0DISABLED(1U)
|
||||
@ -376,6 +381,11 @@ $FreeBSD$
|
||||
#define V_FL15EMPTY(x) ((x) << S_FL15EMPTY)
|
||||
#define F_FL15EMPTY V_FL15EMPTY(1U)
|
||||
|
||||
#define S_FLXEMPTY 16
|
||||
#define M_FLXEMPTY 0xffff
|
||||
#define V_FLXEMPTY(x) ((x) << S_FLXEMPTY)
|
||||
#define G_FLXEMPTY(x) (((x) >> S_FLXEMPTY) & M_FLXEMPTY)
|
||||
|
||||
#define A_SG_EGR_PRI_CNT 0x50
|
||||
|
||||
#define S_EGRERROPCODE 24
|
||||
@ -6235,10 +6245,28 @@ $FreeBSD$
|
||||
#define V_ACK(x) ((x) << S_ACK)
|
||||
#define F_ACK V_ACK(1U)
|
||||
|
||||
#define S_I2C_DATA 0
|
||||
#define M_I2C_DATA 0xff
|
||||
#define V_I2C_DATA(x) ((x) << S_I2C_DATA)
|
||||
#define G_I2C_DATA(x) (((x) >> S_I2C_DATA) & M_I2C_DATA)
|
||||
|
||||
#define S_I2C_BUSY 31
|
||||
#define V_I2C_BUSY(x) ((x) << S_I2C_BUSY)
|
||||
#define F_I2C_BUSY V_I2C_BUSY(1U)
|
||||
|
||||
#define S_I2C_ACK 30
|
||||
#define V_I2C_ACK(x) ((x) << S_I2C_ACK)
|
||||
#define F_I2C_ACK V_I2C_ACK(1U)
|
||||
|
||||
#define S_I2C_CONT 1
|
||||
#define V_I2C_CONT(x) ((x) << S_I2C_CONT)
|
||||
#define F_I2C_CONT V_I2C_CONT(1U)
|
||||
|
||||
#define S_I2C_RDWR 0
|
||||
#define V_I2C_RDWR(x) ((x) << S_I2C_RDWR)
|
||||
#define F_I2C_READ V_I2C_RDWR(0U)
|
||||
#define F_I2C_WRITE V_I2C_RDWR(1U)
|
||||
|
||||
/* registers for module MI1 */
|
||||
#define MI1_BASE_ADDR 0x6b0
|
||||
|
||||
|
@ -188,6 +188,62 @@ int t3_mc7_bd_read(struct mc7 *mc7, unsigned int start, unsigned int n,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Low-level I2C read and write routines. These simply read and write a
|
||||
* single byte with the option of indicating a "continue" if another operation
|
||||
* is to be chained. Generally most code will use higher-level routines to
|
||||
* read and write to I2C Slave Devices.
|
||||
*/
|
||||
#define I2C_ATTEMPTS 100
|
||||
|
||||
/*
|
||||
* Read an 8-bit value from the I2C bus. If the "chained" parameter is
|
||||
* non-zero then a STOP bit will not be written after the read command. On
|
||||
* error (the read timed out, etc.), a negative errno will be returned (e.g.
|
||||
* -EAGAIN, etc.). On success, the 8-bit value read from the I2C bus is
|
||||
* stored into the buffer *valp and the value of the I2C ACK bit is returned
|
||||
* as a 0/1 value.
|
||||
*/
|
||||
int t3_i2c_read8(adapter_t *adapter, int chained, u8 *valp)
|
||||
{
|
||||
int ret;
|
||||
u32 opval;
|
||||
MDIO_LOCK(adapter);
|
||||
t3_write_reg(adapter, A_I2C_OP,
|
||||
F_I2C_READ | (chained ? F_I2C_CONT : 0));
|
||||
ret = t3_wait_op_done_val(adapter, A_I2C_OP, F_I2C_BUSY, 0,
|
||||
I2C_ATTEMPTS, 10, &opval);
|
||||
if (ret >= 0) {
|
||||
ret = ((opval & F_I2C_ACK) == F_I2C_ACK);
|
||||
*valp = G_I2C_DATA(t3_read_reg(adapter, A_I2C_DATA));
|
||||
}
|
||||
MDIO_UNLOCK(adapter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write an 8-bit value to the I2C bus. If the "chained" parameter is
|
||||
* non-zero, then a STOP bit will not be written after the write command. On
|
||||
* error (the write timed out, etc.), a negative errno will be returned (e.g.
|
||||
* -EAGAIN, etc.). On success, the value of the I2C ACK bit is returned as a
|
||||
* 0/1 value.
|
||||
*/
|
||||
int t3_i2c_write8(adapter_t *adapter, int chained, u8 val)
|
||||
{
|
||||
int ret;
|
||||
u32 opval;
|
||||
MDIO_LOCK(adapter);
|
||||
t3_write_reg(adapter, A_I2C_DATA, V_I2C_DATA(val));
|
||||
t3_write_reg(adapter, A_I2C_OP,
|
||||
F_I2C_WRITE | (chained ? F_I2C_CONT : 0));
|
||||
ret = t3_wait_op_done_val(adapter, A_I2C_OP, F_I2C_BUSY, 0,
|
||||
I2C_ATTEMPTS, 10, &opval);
|
||||
if (ret >= 0)
|
||||
ret = ((opval & F_I2C_ACK) == F_I2C_ACK);
|
||||
MDIO_UNLOCK(adapter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize MI1.
|
||||
*/
|
||||
@ -515,7 +571,12 @@ static struct adapter_info t3_adap_info[] = {
|
||||
F_GPIO1_OEN | F_GPIO2_OEN | F_GPIO4_OEN | F_GPIO6_OEN | F_GPIO7_OEN |
|
||||
F_GPIO10_OEN | F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL | F_GPIO10_OUT_VAL,
|
||||
{ S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
|
||||
&mi1_mdio_ext_ops, "Chelsio N310" }
|
||||
&mi1_mdio_ext_ops, "Chelsio T310" },
|
||||
{ 1, 0, 0,
|
||||
F_GPIO1_OEN | F_GPIO6_OEN | F_GPIO7_OEN |
|
||||
F_GPIO1_OUT_VAL | F_GPIO6_OUT_VAL,
|
||||
{ S_GPIO9 }, SUPPORTED_10000baseT_Full | SUPPORTED_AUI,
|
||||
&mi1_mdio_ext_ops, "Chelsio N320E-G2" },
|
||||
};
|
||||
|
||||
/*
|
||||
@ -528,7 +589,7 @@ const struct adapter_info *t3_get_adapter_info(unsigned int id)
|
||||
}
|
||||
|
||||
struct port_type_info {
|
||||
int (*phy_prep)(struct cphy *phy, adapter_t *adapter, int phy_addr,
|
||||
int (*phy_prep)(pinfo_t *pinfo, int phy_addr,
|
||||
const struct mdio_ops *ops);
|
||||
};
|
||||
|
||||
@ -542,6 +603,8 @@ static struct port_type_info port_types[] = {
|
||||
{ t3_qt2045_phy_prep },
|
||||
{ t3_ael1006_phy_prep },
|
||||
{ t3_tn1010_phy_prep },
|
||||
{ t3_aq100x_phy_prep },
|
||||
{ t3_ael2020_phy_prep },
|
||||
};
|
||||
|
||||
#define VPD_ENTRY(name, len) \
|
||||
@ -669,6 +732,125 @@ static unsigned int hex2int(unsigned char c)
|
||||
return isdigit(c) ? c - '0' : toupper(c) - 'A' + 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_desc_len - get the length of a vpd descriptor.
|
||||
* @adapter: the adapter
|
||||
* @offset: first byte offset of the vpd descriptor
|
||||
*
|
||||
* Retrieves the length of the small/large resource
|
||||
* data type starting at offset.
|
||||
*/
|
||||
static int get_desc_len(adapter_t *adapter, u32 offset)
|
||||
{
|
||||
u32 read_offset, tmp, shift, len = 0;
|
||||
u8 tag, buf[8];
|
||||
int ret;
|
||||
|
||||
read_offset = offset & 0xfffffffc;
|
||||
shift = offset & 0x03;
|
||||
|
||||
ret = t3_seeprom_read(adapter, read_offset, &tmp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*((u32 *)buf) = cpu_to_le32(tmp);
|
||||
|
||||
tag = buf[shift];
|
||||
if (tag & 0x80) {
|
||||
ret = t3_seeprom_read(adapter, read_offset + 4, &tmp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*((u32 *)(&buf[4])) = cpu_to_le32(tmp);
|
||||
len = (buf[shift + 1] & 0xff) +
|
||||
((buf[shift+2] << 8) & 0xff00) + 3;
|
||||
} else
|
||||
len = (tag & 0x07) + 1;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* is_end_tag - Check if a vpd tag is the end tag.
|
||||
* @adapter: the adapter
|
||||
* @offset: first byte offset of the tag
|
||||
*
|
||||
* Checks if the tag located at offset is the end tag.
|
||||
*/
|
||||
static int is_end_tag(adapter_t * adapter, u32 offset)
|
||||
{
|
||||
u32 read_offset, shift, ret, tmp;
|
||||
u8 buf[4];
|
||||
|
||||
read_offset = offset & 0xfffffffc;
|
||||
shift = offset & 0x03;
|
||||
|
||||
ret = t3_seeprom_read(adapter, read_offset, &tmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
*((u32 *)buf) = cpu_to_le32(tmp);
|
||||
|
||||
if (buf[shift] == 0x78)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* t3_get_vpd_len - computes the length of a vpd structure
|
||||
* @adapter: the adapter
|
||||
* @vpd: contains the offset of first byte of vpd
|
||||
*
|
||||
* Computes the lentgh of the vpd structure starting at vpd->offset.
|
||||
*/
|
||||
|
||||
int t3_get_vpd_len(adapter_t * adapter, struct generic_vpd *vpd)
|
||||
{
|
||||
u32 len=0, offset;
|
||||
int inc, ret;
|
||||
|
||||
offset = vpd->offset;
|
||||
|
||||
while (offset < (vpd->offset + MAX_VPD_BYTES)) {
|
||||
ret = is_end_tag(adapter, offset);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else if (ret == 1)
|
||||
break;
|
||||
|
||||
inc = get_desc_len(adapter, offset);
|
||||
if (inc < 0)
|
||||
return inc;
|
||||
len += inc;
|
||||
offset += inc;
|
||||
}
|
||||
return (len + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* t3_read_vpd - reads the stream of bytes containing a vpd structure
|
||||
* @adapter: the adapter
|
||||
* @vpd: contains a buffer that would hold the stream of bytes
|
||||
*
|
||||
* Reads the vpd structure starting at vpd->offset into vpd->data,
|
||||
* the length of the byte stream to read is vpd->len.
|
||||
*/
|
||||
|
||||
int t3_read_vpd(adapter_t *adapter, struct generic_vpd *vpd)
|
||||
{
|
||||
u32 i, ret;
|
||||
|
||||
for (i = 0; i < vpd->len; i += 4) {
|
||||
ret = t3_seeprom_read(adapter, vpd->offset + i,
|
||||
(u32 *) &(vpd->data[i]));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get_vpd_params - read VPD parameters from VPD EEPROM
|
||||
* @adapter: adapter to read
|
||||
@ -1313,11 +1495,6 @@ static void t3_clear_faults(adapter_t *adapter, int port_id)
|
||||
struct port_info *pi = adap2pinfo(adapter, port_id);
|
||||
struct cmac *mac = &pi->mac;
|
||||
|
||||
t3_set_reg_field(adapter, A_XGM_TXFIFO_CFG + mac->offset,
|
||||
F_ENDROPPKT, 0);
|
||||
t3_mac_enable(mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
|
||||
t3_set_reg_field(adapter, A_XGM_STAT_CTRL + mac->offset, F_CLRSTATS, 1);
|
||||
|
||||
if (adapter->params.nports <= 2) {
|
||||
t3_xgm_intr_disable(adapter, pi->port_id);
|
||||
t3_read_reg(adapter, A_XGM_INT_STATUS + mac->offset);
|
||||
@ -1339,7 +1516,7 @@ static void t3_clear_faults(adapter_t *adapter, int port_id)
|
||||
*/
|
||||
void t3_link_changed(adapter_t *adapter, int port_id)
|
||||
{
|
||||
int link_ok, speed, duplex, fc, link_fault, link_change;
|
||||
int link_ok, speed, duplex, fc, link_fault;
|
||||
struct port_info *pi = adap2pinfo(adapter, port_id);
|
||||
struct cphy *phy = &pi->phy;
|
||||
struct cmac *mac = &pi->mac;
|
||||
@ -1353,6 +1530,16 @@ void t3_link_changed(adapter_t *adapter, int port_id)
|
||||
|
||||
phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc);
|
||||
|
||||
if (lc->requested_fc & PAUSE_AUTONEG)
|
||||
fc &= lc->requested_fc;
|
||||
else
|
||||
fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
|
||||
|
||||
/* Update mac speed before checking for link fault. */
|
||||
if (link_ok && speed >= 0 && lc->autoneg == AUTONEG_ENABLE &&
|
||||
(speed != lc->speed || duplex != lc->duplex || fc != lc->fc))
|
||||
t3_mac_set_speed_duplex_fc(mac, speed, duplex, fc);
|
||||
|
||||
/*
|
||||
* Check for link faults if any of these is true:
|
||||
* a) A link fault is suspected, and PHY says link ok
|
||||
@ -1368,11 +1555,8 @@ void t3_link_changed(adapter_t *adapter, int port_id)
|
||||
pi->link_fault = LF_YES;
|
||||
}
|
||||
|
||||
/* Don't report link up or any other change */
|
||||
/* Don't report link up */
|
||||
link_ok = 0;
|
||||
speed = lc->speed;
|
||||
duplex = lc->duplex;
|
||||
fc = lc->fc;
|
||||
} else {
|
||||
/* clear faults here if this was a false alarm. */
|
||||
if (pi->link_fault == LF_MAYBE &&
|
||||
@ -1383,37 +1567,29 @@ void t3_link_changed(adapter_t *adapter, int port_id)
|
||||
}
|
||||
}
|
||||
|
||||
if (lc->requested_fc & PAUSE_AUTONEG)
|
||||
fc &= lc->requested_fc;
|
||||
else
|
||||
fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
|
||||
|
||||
if (link_ok == lc->link_ok && speed == lc->speed &&
|
||||
duplex == lc->duplex && fc == lc->fc)
|
||||
return; /* nothing changed */
|
||||
|
||||
link_change = link_ok != lc->link_ok;
|
||||
lc->link_ok = (unsigned char)link_ok;
|
||||
lc->speed = speed < 0 ? SPEED_INVALID : speed;
|
||||
lc->duplex = duplex < 0 ? DUPLEX_INVALID : duplex;
|
||||
lc->fc = fc;
|
||||
|
||||
if (link_ok) {
|
||||
|
||||
/* down -> up, or up -> up with changed settings */
|
||||
|
||||
if (link_change && adapter->params.rev > 0 &&
|
||||
uses_xaui(adapter)) {
|
||||
t3b_pcs_reset(mac);
|
||||
if (adapter->params.rev > 0 && uses_xaui(adapter)) {
|
||||
t3_write_reg(adapter, A_XGM_XAUI_ACT_CTRL + mac->offset,
|
||||
F_TXACTENABLE | F_RXEN);
|
||||
}
|
||||
|
||||
if (speed >= 0 && lc->autoneg == AUTONEG_ENABLE) {
|
||||
/* Set MAC settings to match PHY. */
|
||||
t3_mac_set_speed_duplex_fc(mac, speed, duplex, fc);
|
||||
lc->fc = (unsigned char)fc;
|
||||
}
|
||||
|
||||
t3_set_reg_field(adapter, A_XGM_TXFIFO_CFG + mac->offset,
|
||||
F_ENDROPPKT, 0);
|
||||
t3_mac_enable(mac, MAC_DIRECTION_TX | MAC_DIRECTION_RX);
|
||||
t3_set_reg_field(adapter, A_XGM_STAT_CTRL + mac->offset,
|
||||
F_CLRSTATS, 1);
|
||||
t3_clear_faults(adapter, port_id);
|
||||
|
||||
} else {
|
||||
@ -1450,7 +1626,9 @@ void t3_link_changed(adapter_t *adapter, int port_id)
|
||||
t3_write_reg(adapter, A_XGM_RX_CTRL + mac->offset, F_RXEN);
|
||||
}
|
||||
|
||||
t3_os_link_changed(adapter, port_id, link_ok, speed, duplex, fc);
|
||||
t3_os_link_changed(adapter, port_id, link_ok, speed, duplex, fc,
|
||||
mac->was_reset);
|
||||
mac->was_reset = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1478,6 +1656,7 @@ int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc)
|
||||
if (fc & PAUSE_RX)
|
||||
lc->advertising |= ADVERTISED_Pause;
|
||||
}
|
||||
|
||||
phy->ops->advertise(phy, lc->advertising);
|
||||
|
||||
if (lc->autoneg == AUTONEG_DISABLE) {
|
||||
@ -1490,7 +1669,7 @@ int t3_link_start(struct cphy *phy, struct cmac *mac, struct link_config *lc)
|
||||
phy->ops->set_speed_duplex(phy, lc->speed, lc->duplex);
|
||||
/* PR 5666. Power phy up when doing an ifup */
|
||||
if (!is_10G(phy->adapter))
|
||||
phy->ops->power_down(phy, 0);
|
||||
phy->ops->power_down(phy, 0);
|
||||
} else
|
||||
phy->ops->autoneg_enable(phy);
|
||||
} else {
|
||||
@ -2020,6 +2199,10 @@ int t3_phy_intr_handler(adapter_t *adapter)
|
||||
p->phy.fifo_errors++;
|
||||
if (phy_cause & cphy_cause_module_change)
|
||||
t3_os_phymod_changed(adapter, i);
|
||||
if (phy_cause & cphy_cause_alarm)
|
||||
CH_WARN(adapter, "Operation affected due to "
|
||||
"adverse environment. Check the spec "
|
||||
"sheet for corrective action.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -3871,7 +4054,7 @@ static void config_pcie(adapter_t *adap)
|
||||
{ 201, 321, 258, 450, 834, 1602 }
|
||||
};
|
||||
|
||||
u16 val;
|
||||
u16 val, devid;
|
||||
unsigned int log2_width, pldsize;
|
||||
unsigned int fst_trn_rx, fst_trn_tx, acklat, rpllmt;
|
||||
|
||||
@ -3880,6 +4063,18 @@ static void config_pcie(adapter_t *adap)
|
||||
&val);
|
||||
pldsize = (val & PCI_EXP_DEVCTL_PAYLOAD) >> 5;
|
||||
|
||||
/*
|
||||
* Gen2 adapter pcie bridge compatibility requires minimum
|
||||
* Max_Read_Request_size
|
||||
*/
|
||||
t3_os_pci_read_config_2(adap, 0x2, &devid);
|
||||
if (devid == 0x37) {
|
||||
t3_os_pci_write_config_2(adap,
|
||||
adap->params.pci.pcie_cap_addr + PCI_EXP_DEVCTL,
|
||||
val & ~PCI_EXP_DEVCTL_READRQ & ~PCI_EXP_DEVCTL_PAYLOAD);
|
||||
pldsize = 0;
|
||||
}
|
||||
|
||||
t3_os_pci_read_config_2(adap,
|
||||
adap->params.pci.pcie_cap_addr + PCI_EXP_LNKCTL,
|
||||
&val);
|
||||
@ -3934,7 +4129,7 @@ int t3_init_hw(adapter_t *adapter, u32 fw_params)
|
||||
goto out_err;
|
||||
|
||||
if (adapter->params.nports > 2)
|
||||
t3_mac_reset(&adap2pinfo(adapter, 0)->mac);
|
||||
t3_mac_init(&adap2pinfo(adapter, 0)->mac);
|
||||
|
||||
if (vpd->mclk) {
|
||||
partition_mem(adapter, &adapter->params.tp);
|
||||
@ -4098,15 +4293,25 @@ static void __devinit mc7_prep(adapter_t *adapter, struct mc7 *mc7,
|
||||
|
||||
void mac_prep(struct cmac *mac, adapter_t *adapter, int index)
|
||||
{
|
||||
u16 devid;
|
||||
|
||||
mac->adapter = adapter;
|
||||
mac->multiport = adapter->params.nports > 2;
|
||||
if (mac->multiport) {
|
||||
mac->ext_port = (unsigned char)index;
|
||||
mac->nucast = 8;
|
||||
index = 0;
|
||||
} else
|
||||
mac->nucast = 1;
|
||||
|
||||
/* Gen2 adapter uses VPD xauicfg[] to notify driver which MAC
|
||||
is connected to each port, its suppose to be using xgmac0 for both ports
|
||||
*/
|
||||
t3_os_pci_read_config_2(adapter, 0x2, &devid);
|
||||
|
||||
if (mac->multiport ||
|
||||
(!adapter->params.vpd.xauicfg[1] && (devid==0x37)))
|
||||
index = 0;
|
||||
|
||||
mac->offset = (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR) * index;
|
||||
|
||||
if (adapter->params.rev == 0 && uses_xaui(adapter)) {
|
||||
@ -4336,7 +4541,7 @@ int __devinit t3_prep_adapter(adapter_t *adapter,
|
||||
if (j >= ARRAY_SIZE(adapter->params.vpd.port_type))
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = pti->phy_prep(&p->phy, adapter, ai->phy_base_addr + j,
|
||||
ret = pti->phy_prep(p, ai->phy_base_addr + j,
|
||||
ai->mdio_ops);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -4408,7 +4613,7 @@ int t3_reinit_adapter(adapter_t *adap)
|
||||
if (j >= ARRAY_SIZE(adap->params.vpd.port_type))
|
||||
return -EINVAL;
|
||||
}
|
||||
ret = pti->phy_prep(&p->phy, adap, p->phy.addr, NULL);
|
||||
ret = pti->phy_prep(p, p->phy.addr, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
p->phy.ops->power_down(&p->phy, 1);
|
||||
|
@ -209,10 +209,10 @@ static struct cphy_ops tn1010_ops = {
|
||||
};
|
||||
#endif
|
||||
|
||||
int t3_tn1010_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
|
||||
int t3_tn1010_phy_prep(pinfo_t *pinfo, int phy_addr,
|
||||
const struct mdio_ops *mdio_ops)
|
||||
{
|
||||
cphy_init(phy, adapter, phy_addr, &tn1010_ops, mdio_ops,
|
||||
cphy_init(&pinfo->phy, pinfo->adapter, pinfo, phy_addr, &tn1010_ops, mdio_ops,
|
||||
SUPPORTED_1000baseT_Full | SUPPORTED_10000baseT_Full |
|
||||
SUPPORTED_Autoneg | SUPPORTED_AUI | SUPPORTED_TP,
|
||||
"1000/10GBASE-T");
|
||||
|
@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
|
||||
enum {
|
||||
VSC8211_SIGDET_CTRL = 19,
|
||||
VSC8211_EXT_CTRL = 23,
|
||||
VSC8211_PHY_CTRL = 24,
|
||||
VSC8211_INTR_ENABLE = 25,
|
||||
VSC8211_INTR_STATUS = 26,
|
||||
VSC8211_LED_CTRL = 27,
|
||||
@ -375,13 +376,62 @@ static struct cphy_ops vsc8211_fiber_ops = {
|
||||
};
|
||||
#endif
|
||||
|
||||
int t3_vsc8211_phy_prep(struct cphy *phy, adapter_t *adapter, int phy_addr,
|
||||
#define VSC8211_PHY_CTRL 24
|
||||
|
||||
#define S_VSC8211_TXFIFODEPTH 7
|
||||
#define M_VSC8211_TXFIFODEPTH 0x7
|
||||
#define V_VSC8211_TXFIFODEPTH(x) ((x) << S_VSC8211_TXFIFODEPTH)
|
||||
#define G_VSC8211_TXFIFODEPTH(x) (((x) >> S_VSC8211_TXFIFODEPTH) & M_VSC8211_TXFIFODEPTH)
|
||||
|
||||
#define S_VSC8211_RXFIFODEPTH 4
|
||||
#define M_VSC8211_RXFIFODEPTH 0x7
|
||||
#define V_VSC8211_RXFIFODEPTH(x) ((x) << S_VSC8211_RXFIFODEPTH)
|
||||
#define G_VSC8211_RXFIFODEPTH(x) (((x) >> S_VSC8211_RXFIFODEPTH) & M_VSC8211_RXFIFODEPTH)
|
||||
|
||||
int t3_vsc8211_fifo_depth(adapter_t *adap, unsigned int mtu, int port)
|
||||
{
|
||||
/* TX FIFO Depth set bits 9:7 to 100 (IEEE mode) */
|
||||
unsigned int val = 4;
|
||||
unsigned int currentregval;
|
||||
unsigned int regval;
|
||||
int err;
|
||||
|
||||
/* Retrieve the port info structure from adater_t */
|
||||
struct port_info *portinfo = adap2pinfo(adap, port);
|
||||
|
||||
/* What phy is this */
|
||||
struct cphy *phy = &portinfo->phy;
|
||||
|
||||
/* Read the current value of the PHY control Register */
|
||||
err = mdio_read(phy, 0, VSC8211_PHY_CTRL, ¤tregval);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* IEEE mode supports up to 1518 bytes */
|
||||
/* mtu does not contain the header + FCS (18 bytes) */
|
||||
if (mtu > 1500)
|
||||
/*
|
||||
* If using a packet size > 1500 set TX FIFO Depth bits
|
||||
* 9:7 to 011 (Jumbo packet mode)
|
||||
*/
|
||||
val = 3;
|
||||
|
||||
regval = V_VSC8211_TXFIFODEPTH(val) | V_VSC8211_RXFIFODEPTH(val) |
|
||||
(currentregval & ~V_VSC8211_TXFIFODEPTH(M_VSC8211_TXFIFODEPTH) &
|
||||
~V_VSC8211_RXFIFODEPTH(M_VSC8211_RXFIFODEPTH));
|
||||
|
||||
return mdio_write(phy, 0, VSC8211_PHY_CTRL, regval);
|
||||
}
|
||||
|
||||
int t3_vsc8211_phy_prep(pinfo_t *pinfo, int phy_addr,
|
||||
const struct mdio_ops *mdio_ops)
|
||||
{
|
||||
struct cphy *phy = &pinfo->phy;
|
||||
int err;
|
||||
unsigned int val;
|
||||
|
||||
cphy_init(phy, adapter, phy_addr, &vsc8211_ops, mdio_ops,
|
||||
cphy_init(&pinfo->phy, pinfo->adapter, pinfo, phy_addr, &vsc8211_ops, mdio_ops,
|
||||
SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full |
|
||||
SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII |
|
||||
SUPPORTED_TP | SUPPORTED_IRQ, "10/100/1000BASE-T");
|
||||
|
@ -41,6 +41,28 @@ static inline int macidx(const struct cmac *mac)
|
||||
return mac->offset / (XGMAC0_1_BASE_ADDR - XGMAC0_0_BASE_ADDR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a reasonable A_XGM_RESET_CTRL value for the mac specified.
|
||||
*/
|
||||
static inline int xgm_reset_ctrl(const struct cmac *mac)
|
||||
{
|
||||
adapter_t *adap = mac->adapter;
|
||||
int val = F_MAC_RESET_ | F_XGMAC_STOP_EN;
|
||||
|
||||
if (is_10G(adap)) {
|
||||
int cfg = t3_read_reg(adap, A_XGM_PORT_CFG + mac->offset);
|
||||
|
||||
val |= F_PCS_RESET_;
|
||||
if (G_PORTSPEED(cfg) != 3) /* not running at 10G */
|
||||
val |= F_XG2G_RESET_;
|
||||
} else if (uses_xaui(adap))
|
||||
val |= F_PCS_RESET_ | F_XG2G_RESET_;
|
||||
else
|
||||
val |= F_RGMII_RESET_ | F_XG2G_RESET_;
|
||||
|
||||
return (val);
|
||||
}
|
||||
|
||||
static void xaui_serdes_reset(struct cmac *mac)
|
||||
{
|
||||
static const unsigned int clear[] = {
|
||||
@ -81,12 +103,12 @@ void t3b_pcs_reset(struct cmac *mac)
|
||||
}
|
||||
|
||||
/**
|
||||
* t3_mac_reset - reset a MAC
|
||||
* @mac: the MAC to reset
|
||||
* t3_mac_init - initialize a MAC
|
||||
* @mac: the MAC to initialize
|
||||
*
|
||||
* Reset the given MAC.
|
||||
* Initialize the given MAC.
|
||||
*/
|
||||
int t3_mac_reset(struct cmac *mac)
|
||||
int t3_mac_init(struct cmac *mac)
|
||||
{
|
||||
static struct addr_val_pair mac_reset_avp[] = {
|
||||
{ A_XGM_TX_CTRL, 0 },
|
||||
@ -138,7 +160,7 @@ int t3_mac_reset(struct cmac *mac)
|
||||
|
||||
if (mac->multiport) {
|
||||
t3_write_reg(adap, A_XGM_RX_MAX_PKT_SIZE + oft,
|
||||
MAX_FRAME_SIZE - 4);
|
||||
V_RXMAXPKTSIZE(MAX_FRAME_SIZE - 4));
|
||||
t3_set_reg_field(adap, A_XGM_TXFIFO_CFG + oft, 0,
|
||||
F_DISPREAMBLE);
|
||||
t3_set_reg_field(adap, A_XGM_RX_CFG + oft, 0, F_COPYPREAMBLE |
|
||||
@ -154,13 +176,7 @@ int t3_mac_reset(struct cmac *mac)
|
||||
V_RXMAXFRAMERSIZE(M_RXMAXFRAMERSIZE),
|
||||
V_RXMAXFRAMERSIZE(MAX_FRAME_SIZE) | F_RXENFRAMER);
|
||||
|
||||
val = F_MAC_RESET_ | F_XGMAC_STOP_EN;
|
||||
if (!mac->multiport)
|
||||
val |= F_XG2G_RESET_;
|
||||
if (uses_xaui(adap))
|
||||
val |= F_PCS_RESET_;
|
||||
else
|
||||
val |= F_RGMII_RESET_;
|
||||
val = xgm_reset_ctrl(mac);
|
||||
t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
|
||||
(void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
|
||||
if ((val & F_PCS_RESET_) && adap->params.rev) {
|
||||
@ -172,16 +188,17 @@ int t3_mac_reset(struct cmac *mac)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int t3b2_mac_reset(struct cmac *mac)
|
||||
static int t3_mac_reset(struct cmac *mac, int portspeed)
|
||||
{
|
||||
u32 val;
|
||||
u32 val, store_mps;
|
||||
adapter_t *adap = mac->adapter;
|
||||
unsigned int oft = mac->offset;
|
||||
int idx = macidx(mac);
|
||||
unsigned int store;
|
||||
|
||||
/* Stop egress traffic to xgm*/
|
||||
if (!macidx(mac))
|
||||
store_mps = t3_read_reg(adap, A_MPS_CFG);
|
||||
if (!idx)
|
||||
t3_set_reg_field(adap, A_MPS_CFG, F_PORT0ACTIVE, 0);
|
||||
else
|
||||
t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE, 0);
|
||||
@ -198,7 +215,7 @@ static int t3b2_mac_reset(struct cmac *mac)
|
||||
|
||||
/* Store A_TP_TX_DROP_CFG_CH0 */
|
||||
t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
|
||||
store = t3_read_reg(adap, A_TP_TX_DROP_CFG_CH0 + idx);
|
||||
store = t3_read_reg(adap, A_TP_PIO_DATA);
|
||||
|
||||
msleep(10);
|
||||
|
||||
@ -209,44 +226,55 @@ static int t3b2_mac_reset(struct cmac *mac)
|
||||
/* Check for xgm Rx fifo empty */
|
||||
/* Increased loop count to 1000 from 5 cover 1G and 100Mbps case */
|
||||
if (t3_wait_op_done(adap, A_XGM_RX_MAX_PKT_SIZE_ERR_CNT + oft,
|
||||
0x80000000, 1, 1000, 2)) {
|
||||
CH_ERR(adap, "MAC %d Rx fifo drain failed\n",
|
||||
macidx(mac));
|
||||
0x80000000, 1, 1000, 2) && portspeed < 0) {
|
||||
CH_ERR(adap, "MAC %d Rx fifo drain failed\n", idx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0); /*MAC in reset*/
|
||||
(void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
|
||||
if (portspeed >= 0) {
|
||||
u32 intr = t3_read_reg(adap, A_XGM_INT_ENABLE + oft);
|
||||
|
||||
val = F_MAC_RESET_;
|
||||
if (is_10G(adap))
|
||||
val |= F_PCS_RESET_;
|
||||
else if (uses_xaui(adap))
|
||||
val |= F_PCS_RESET_ | F_XG2G_RESET_;
|
||||
else
|
||||
val |= F_RGMII_RESET_ | F_XG2G_RESET_;
|
||||
t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
|
||||
(void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
|
||||
if ((val & F_PCS_RESET_) && adap->params.rev) {
|
||||
msleep(1);
|
||||
t3b_pcs_reset(mac);
|
||||
/*
|
||||
* safespeedchange: wipes out pretty much all XGMAC registers.
|
||||
*/
|
||||
|
||||
t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
|
||||
V_PORTSPEED(M_PORTSPEED) | F_SAFESPEEDCHANGE,
|
||||
portspeed | F_SAFESPEEDCHANGE);
|
||||
(void) t3_read_reg(adap, A_XGM_PORT_CFG + oft);
|
||||
t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
|
||||
F_SAFESPEEDCHANGE, 0);
|
||||
(void) t3_read_reg(adap, A_XGM_PORT_CFG + oft);
|
||||
t3_mac_init(mac);
|
||||
|
||||
t3_write_reg(adap, A_XGM_INT_ENABLE + oft, intr);
|
||||
} else {
|
||||
|
||||
t3_write_reg(adap, A_XGM_RESET_CTRL + oft, 0); /*MAC in reset*/
|
||||
(void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
|
||||
|
||||
val = xgm_reset_ctrl(mac);
|
||||
t3_write_reg(adap, A_XGM_RESET_CTRL + oft, val);
|
||||
(void) t3_read_reg(adap, A_XGM_RESET_CTRL + oft); /* flush */
|
||||
if ((val & F_PCS_RESET_) && adap->params.rev) {
|
||||
msleep(1);
|
||||
t3b_pcs_reset(mac);
|
||||
}
|
||||
t3_write_reg(adap, A_XGM_RX_CFG + oft,
|
||||
F_DISPAUSEFRAMES | F_EN1536BFRAMES |
|
||||
F_RMFCS | F_ENJUMBO | F_ENHASHMCAST );
|
||||
}
|
||||
t3_write_reg(adap, A_XGM_RX_CFG + oft,
|
||||
F_DISPAUSEFRAMES | F_EN1536BFRAMES |
|
||||
F_RMFCS | F_ENJUMBO | F_ENHASHMCAST );
|
||||
|
||||
/* Restore the DROP_CFG */
|
||||
t3_write_reg(adap, A_TP_PIO_ADDR, A_TP_TX_DROP_CFG_CH0 + idx);
|
||||
t3_write_reg(adap, A_TP_PIO_DATA, store);
|
||||
|
||||
/* Resume egress traffic to xgm */
|
||||
if (!macidx(mac))
|
||||
t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT0ACTIVE);
|
||||
else
|
||||
t3_set_reg_field(adap, A_MPS_CFG, 0, F_PORT1ACTIVE);
|
||||
t3_set_reg_field(adap, A_MPS_CFG, F_PORT1ACTIVE | F_PORT0ACTIVE,
|
||||
store_mps);
|
||||
|
||||
/* Set: re-enable NIC traffic */
|
||||
t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, 1);
|
||||
t3_set_reg_field(adap, A_MPS_CFG, F_ENFORCEPKT, F_ENFORCEPKT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -409,6 +437,8 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
|
||||
int ipg;
|
||||
unsigned int thres, v, reg;
|
||||
adapter_t *adap = mac->adapter;
|
||||
unsigned port_type = adap->params.vpd.port_type[macidx(mac)];
|
||||
unsigned int orig_mtu=mtu;
|
||||
|
||||
/*
|
||||
* MAX_FRAME_SIZE inludes header + FCS, mtu doesn't. The HW max
|
||||
@ -422,6 +452,14 @@ int t3_mac_set_mtu(struct cmac *mac, unsigned int mtu)
|
||||
if (mac->multiport)
|
||||
return t3_vsc7323_set_mtu(adap, mtu - 4, mac->ext_port);
|
||||
|
||||
/* Modify the TX and RX fifo depth only if the card has a vsc8211 phy */
|
||||
if (port_type == 2) {
|
||||
int err = t3_vsc8211_fifo_depth(adap,orig_mtu,macidx(mac));
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (adap->params.rev >= T3_REV_B2 &&
|
||||
(t3_read_reg(adap, A_XGM_RX_CTRL + mac->offset) & F_RXEN)) {
|
||||
t3_mac_disable_exact_filters(mac);
|
||||
@ -507,10 +545,12 @@ int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc)
|
||||
if (duplex >= 0 && duplex != DUPLEX_FULL)
|
||||
return -EINVAL;
|
||||
if (mac->multiport) {
|
||||
u32 rx_max_pkt_size =
|
||||
G_RXMAXPKTSIZE(t3_read_reg(adap,
|
||||
A_XGM_RX_MAX_PKT_SIZE + oft));
|
||||
val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
|
||||
val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
|
||||
val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(t3_read_reg(adap,
|
||||
A_XGM_RX_MAX_PKT_SIZE + oft)) / 8);
|
||||
val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8);
|
||||
t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
|
||||
|
||||
t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
|
||||
@ -529,15 +569,27 @@ int t3_mac_set_speed_duplex_fc(struct cmac *mac, int speed, int duplex, int fc)
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
|
||||
V_PORTSPEED(M_PORTSPEED), val);
|
||||
if (!uses_xaui(adap)) /* T302 */
|
||||
t3_set_reg_field(adap, A_XGM_PORT_CFG + oft,
|
||||
V_PORTSPEED(M_PORTSPEED), val);
|
||||
else {
|
||||
u32 old = t3_read_reg(adap, A_XGM_PORT_CFG + oft);
|
||||
|
||||
if ((old & V_PORTSPEED(M_PORTSPEED)) != val) {
|
||||
t3_mac_reset(mac, val);
|
||||
mac->was_reset = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val = t3_read_reg(adap, A_XGM_RXFIFO_CFG + oft);
|
||||
val &= ~V_RXFIFOPAUSEHWM(M_RXFIFOPAUSEHWM);
|
||||
if (fc & PAUSE_TX)
|
||||
val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(t3_read_reg(adap,
|
||||
A_XGM_RX_MAX_PKT_SIZE + oft)) / 8);
|
||||
if (fc & PAUSE_TX) {
|
||||
u32 rx_max_pkt_size =
|
||||
G_RXMAXPKTSIZE(t3_read_reg(adap,
|
||||
A_XGM_RX_MAX_PKT_SIZE + oft));
|
||||
val |= V_RXFIFOPAUSEHWM(rx_fifo_hwm(rx_max_pkt_size) / 8);
|
||||
}
|
||||
t3_write_reg(adap, A_XGM_RXFIFO_CFG + oft, val);
|
||||
|
||||
t3_set_reg_field(adap, A_XGM_TX_CFG + oft, F_TXPAUSEEN,
|
||||
@ -618,18 +670,12 @@ int t3_mac_disable(struct cmac *mac, int which)
|
||||
mac->txen = 0;
|
||||
}
|
||||
if (which & MAC_DIRECTION_RX) {
|
||||
int val = F_MAC_RESET_;
|
||||
int val = xgm_reset_ctrl(mac);
|
||||
|
||||
t3_set_reg_field(mac->adapter, A_XGM_RESET_CTRL + mac->offset,
|
||||
F_PCS_RESET_, 0);
|
||||
msleep(100);
|
||||
t3_write_reg(adap, A_XGM_RX_CTRL + mac->offset, 0);
|
||||
if (is_10G(adap))
|
||||
val |= F_PCS_RESET_;
|
||||
else if (uses_xaui(adap))
|
||||
val |= F_PCS_RESET_ | F_XG2G_RESET_;
|
||||
else
|
||||
val |= F_RGMII_RESET_ | F_XG2G_RESET_;
|
||||
t3_write_reg(mac->adapter, A_XGM_RESET_CTRL + mac->offset, val);
|
||||
}
|
||||
return 0;
|
||||
@ -650,10 +696,15 @@ int t3b2_mac_watchdog_task(struct cmac *mac)
|
||||
tx_xcnt = 1; /* By default tx_xcnt is making progress*/
|
||||
tx_tcnt = mac->tx_tcnt; /* If tx_mcnt is progressing ignore tx_tcnt*/
|
||||
if (tx_mcnt == mac->tx_mcnt && mac->rx_pause == s->rx_pause) {
|
||||
u32 cfg, active, enforcepkt;
|
||||
|
||||
tx_xcnt = (G_TXSPI4SOPCNT(t3_read_reg(adap,
|
||||
A_XGM_TX_SPI4_SOP_EOP_CNT +
|
||||
mac->offset)));
|
||||
if (tx_xcnt == 0) {
|
||||
cfg = t3_read_reg(adap, A_MPS_CFG);
|
||||
active = macidx(mac) ? cfg & F_PORT1ACTIVE : cfg & F_PORT0ACTIVE;
|
||||
enforcepkt = cfg & F_ENFORCEPKT;
|
||||
if (active && enforcepkt && (tx_xcnt == 0)) {
|
||||
t3_write_reg(adap, A_TP_PIO_ADDR,
|
||||
A_TP_TX_DROP_CNT_CH0 + macidx(mac));
|
||||
tx_tcnt = (G_TXDROPCNTCH0RCVD(t3_read_reg(adap,
|
||||
@ -691,7 +742,7 @@ out:
|
||||
t3_read_reg(adap, A_XGM_TX_CTRL + mac->offset); /* flush */
|
||||
mac->toggle_cnt++;
|
||||
} else if (status == 2) {
|
||||
t3b2_mac_reset(mac);
|
||||
t3_mac_reset(mac, -1);
|
||||
mac->toggle_cnt = 0;
|
||||
}
|
||||
return status;
|
||||
|
@ -361,8 +361,6 @@ struct adapter {
|
||||
struct callout cxgb_tick_ch;
|
||||
struct callout sge_timer_ch;
|
||||
|
||||
unsigned int check_task_cnt;
|
||||
|
||||
/* Register lock for use by the hardware layer */
|
||||
struct mtx mdio_lock;
|
||||
struct mtx elmer_lock;
|
||||
@ -500,7 +498,7 @@ int t3_os_find_pci_capability(adapter_t *adapter, int cap);
|
||||
int t3_os_pci_save_state(struct adapter *adapter);
|
||||
int t3_os_pci_restore_state(struct adapter *adapter);
|
||||
void t3_os_link_changed(adapter_t *adapter, int port_id, int link_status,
|
||||
int speed, int duplex, int fc);
|
||||
int speed, int duplex, int fc, int mac_was_reset);
|
||||
void t3_os_phymod_changed(struct adapter *adap, int port_id);
|
||||
void t3_sge_err_intr_handler(adapter_t *adapter);
|
||||
int t3_offload_tx(struct t3cdev *, struct mbuf *);
|
||||
|
@ -116,7 +116,7 @@ static int cxgb_get_regs_len(void);
|
||||
static int offload_open(struct port_info *pi);
|
||||
static void touch_bars(device_t dev);
|
||||
static int offload_close(struct t3cdev *tdev);
|
||||
int t3_detect_link_fault(adapter_t *adapter, int port_id);
|
||||
static void cxgb_update_mac_settings(struct port_info *p);
|
||||
|
||||
static device_method_t cxgb_controller_methods[] = {
|
||||
DEVMETHOD(device_probe, cxgb_controller_probe),
|
||||
@ -291,7 +291,9 @@ struct cxgb_ident {
|
||||
{PCI_VENDOR_ID_CHELSIO, 0x0031, 3, "T3B20"},
|
||||
{PCI_VENDOR_ID_CHELSIO, 0x0032, 1, "T3B02"},
|
||||
{PCI_VENDOR_ID_CHELSIO, 0x0033, 4, "T3B04"},
|
||||
{PCI_VENDOR_ID_CHELSIO, 0x0035, 6, "N310E"},
|
||||
{PCI_VENDOR_ID_CHELSIO, 0x0035, 6, "T3C10"},
|
||||
{PCI_VENDOR_ID_CHELSIO, 0x0036, 3, "S320E-CR"},
|
||||
{PCI_VENDOR_ID_CHELSIO, 0x0037, 7, "N320E-G2"},
|
||||
{0, 0, 0, NULL}
|
||||
};
|
||||
|
||||
@ -508,6 +510,9 @@ cxgb_controller_attach(device_t dev)
|
||||
sc->bh = rman_get_bushandle(sc->regs_res);
|
||||
sc->mmio_len = rman_get_size(sc->regs_res);
|
||||
|
||||
for (i = 0; i < MAX_NPORTS; i++)
|
||||
sc->port[i].adapter = sc;
|
||||
|
||||
if (t3_prep_adapter(sc, ai, 1) < 0) {
|
||||
printf("prep adapter failed\n");
|
||||
error = ENODEV;
|
||||
@ -1222,8 +1227,8 @@ t3_os_pci_restore_state(struct adapter *sc)
|
||||
|
||||
/**
|
||||
* t3_os_link_changed - handle link status changes
|
||||
* @adapter: the adapter associated with the link change
|
||||
* @port_id: the port index whose limk status has changed
|
||||
* @sc: the adapter associated with the link change
|
||||
* @port_id: the port index whose link status has changed
|
||||
* @link_status: the new status of the link
|
||||
* @speed: the new speed setting
|
||||
* @duplex: the new duplex setting
|
||||
@ -1235,7 +1240,7 @@ t3_os_pci_restore_state(struct adapter *sc)
|
||||
*/
|
||||
void
|
||||
t3_os_link_changed(adapter_t *adapter, int port_id, int link_status, int speed,
|
||||
int duplex, int fc)
|
||||
int duplex, int fc, int mac_was_reset)
|
||||
{
|
||||
struct port_info *pi = &adapter->port[port_id];
|
||||
struct ifnet *ifp = pi->ifp;
|
||||
@ -1243,6 +1248,13 @@ t3_os_link_changed(adapter_t *adapter, int port_id, int link_status, int speed,
|
||||
/* no race with detach, so ifp should always be good */
|
||||
KASSERT(ifp, ("%s: if detached.", __func__));
|
||||
|
||||
/* Reapply mac settings if they were lost due to a reset */
|
||||
if (mac_was_reset) {
|
||||
PORT_LOCK(pi);
|
||||
cxgb_update_mac_settings(pi);
|
||||
PORT_UNLOCK(pi);
|
||||
}
|
||||
|
||||
if (link_status) {
|
||||
ifp->if_baudrate = IF_Mbps(speed);
|
||||
if_link_state_change(ifp, LINK_STATE_UP);
|
||||
@ -1917,7 +1929,7 @@ cxgb_init_synchronized(struct port_info *p)
|
||||
PORT_LOCK(p);
|
||||
t3_port_intr_enable(sc, p->port_id);
|
||||
if (!mac->multiport)
|
||||
t3_mac_reset(mac);
|
||||
t3_mac_init(mac);
|
||||
cxgb_update_mac_settings(p);
|
||||
t3_link_start(&p->phy, mac, &p->link_config);
|
||||
t3_mac_enable(mac, MAC_DIRECTION_RX | MAC_DIRECTION_TX);
|
||||
@ -1992,7 +2004,7 @@ cxgb_uninit_synchronized(struct port_info *pi)
|
||||
PORT_UNLOCK(pi);
|
||||
|
||||
pi->link_config.link_ok = 0;
|
||||
t3_os_link_changed(sc, pi->port_id, 0, 0, 0, 0);
|
||||
t3_os_link_changed(sc, pi->port_id, 0, 0, 0, 0, 0);
|
||||
|
||||
if ((sc->open_device_map & PORT_MASK) == 0)
|
||||
offload_close(&sc->tdev);
|
||||
@ -2335,6 +2347,19 @@ cxgb_ext_intr_handler(void *arg, int count)
|
||||
ADAPTER_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static inline int
|
||||
link_poll_needed(struct port_info *p)
|
||||
{
|
||||
struct cphy *phy = &p->phy;
|
||||
|
||||
if (phy->caps & POLL_LINK_1ST_TIME) {
|
||||
p->phy.caps &= ~POLL_LINK_1ST_TIME;
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (p->link_fault || !(phy->caps & SUPPORTED_LINK_IRQ));
|
||||
}
|
||||
|
||||
static void
|
||||
check_link_status(adapter_t *sc)
|
||||
{
|
||||
@ -2346,7 +2371,7 @@ check_link_status(adapter_t *sc)
|
||||
if (!isset(&sc->open_device_map, p->port_id))
|
||||
continue;
|
||||
|
||||
if (p->link_fault || !(p->phy.caps & SUPPORTED_IRQ))
|
||||
if (link_poll_needed(p))
|
||||
t3_link_changed(sc, i);
|
||||
}
|
||||
}
|
||||
@ -2366,7 +2391,8 @@ check_t3b2_mac(struct adapter *sc)
|
||||
struct ifnet *ifp = p->ifp;
|
||||
#endif
|
||||
|
||||
if (!isset(&sc->open_device_map, p->port_id))
|
||||
if (!isset(&sc->open_device_map, p->port_id) || p->link_fault ||
|
||||
!p->link_config.link_ok)
|
||||
continue;
|
||||
|
||||
KASSERT(ifp->if_drv_flags & IFF_DRV_RUNNING,
|
||||
@ -2414,7 +2440,6 @@ cxgb_tick_handler(void *arg, int count)
|
||||
return;
|
||||
|
||||
check_link_status(sc);
|
||||
sc->check_task_cnt++;
|
||||
|
||||
if (p->rev == T3_REV_B2 && p->nports < 4 && sc->open_device_map)
|
||||
check_t3b2_mac(sc);
|
||||
|
@ -48,6 +48,7 @@ $FreeBSD$
|
||||
#define _CXGB_OSDEP_H_
|
||||
|
||||
typedef struct adapter adapter_t;
|
||||
typedef struct port_info pinfo_t;
|
||||
struct sge_rspq;
|
||||
|
||||
enum {
|
||||
@ -247,10 +248,10 @@ static const int debug_flags = DBG_RX;
|
||||
#define MII_CTRL1000 MII_100T2CR
|
||||
|
||||
#define ADVERTISE_PAUSE_CAP ANAR_FC
|
||||
#define ADVERTISE_PAUSE_ASYM ANAR_X_PAUSE_ASYM
|
||||
#define ADVERTISE_PAUSE ANAR_X_PAUSE_SYM
|
||||
#define ADVERTISE_1000HALF ANAR_X_HD
|
||||
#define ADVERTISE_1000FULL ANAR_X_FD
|
||||
#define ADVERTISE_PAUSE_ASYM 0x800
|
||||
#define ADVERTISE_PAUSE ANAR_FC
|
||||
#define ADVERTISE_1000HALF 0x100
|
||||
#define ADVERTISE_1000FULL 0x200
|
||||
#define ADVERTISE_10FULL ANAR_10_FD
|
||||
#define ADVERTISE_10HALF ANAR_10
|
||||
#define ADVERTISE_100FULL ANAR_TX_FD
|
||||
@ -266,17 +267,18 @@ static const int debug_flags = DBG_RX;
|
||||
#define ADVERTISE_NPAGE ANAR_NP
|
||||
|
||||
|
||||
/* Standard PCI Extended Capaibilities definitions */
|
||||
#define PCI_CAP_ID_VPD 0x03
|
||||
#define PCI_VPD_ADDR 2
|
||||
/* Standard PCI Extended Capabilities definitions */
|
||||
#define PCI_CAP_ID_VPD PCIY_VPD
|
||||
#define PCI_VPD_ADDR PCIR_VPD_ADDR
|
||||
#define PCI_VPD_ADDR_F 0x8000
|
||||
#define PCI_VPD_DATA 4
|
||||
#define PCI_VPD_DATA PCIR_VPD_DATA
|
||||
|
||||
#define PCI_CAP_ID_EXP 0x10
|
||||
#define PCI_EXP_DEVCTL 8
|
||||
#define PCI_EXP_DEVCTL_PAYLOAD 0x00e0
|
||||
#define PCI_EXP_LNKCTL 16
|
||||
#define PCI_EXP_LNKSTA 18
|
||||
#define PCI_CAP_ID_EXP PCIY_EXPRESS
|
||||
#define PCI_EXP_DEVCTL PCIR_EXPRESS_DEVICE_CTL
|
||||
#define PCI_EXP_DEVCTL_PAYLOAD PCIM_EXP_CTL_MAX_PAYLOAD
|
||||
#define PCI_EXP_DEVCTL_READRQ PCIM_EXP_CTL_MAX_READ_REQUEST
|
||||
#define PCI_EXP_LNKCTL PCIR_EXPRESS_LINK_CTL
|
||||
#define PCI_EXP_LNKSTA PCIR_EXPRESS_LINK_STA
|
||||
|
||||
/*
|
||||
* Linux compatibility macros
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,7 @@ CXGB = ${.CURDIR}/../../../dev/cxgb
|
||||
|
||||
KMOD= if_cxgb
|
||||
SRCS= cxgb_mc5.c cxgb_vsc8211.c cxgb_ael1002.c cxgb_mv88e1xxx.c
|
||||
SRCS+= cxgb_xgmac.c cxgb_vsc7323.c cxgb_t3_hw.c cxgb_main.c
|
||||
SRCS+= cxgb_xgmac.c cxgb_vsc7323.c cxgb_t3_hw.c cxgb_main.c cxgb_aq100x.c
|
||||
SRCS+= cxgb_sge.c cxgb_offload.c cxgb_tn1010.c
|
||||
SRCS+= device_if.h bus_if.h pci_if.h
|
||||
SRCS+= opt_inet.h opt_zero.h opt_sched.h
|
||||
|
Loading…
x
Reference in New Issue
Block a user