cxgbe(4): Change the way t4_shutdown_adapter brings the link(s) down.

Modify the GPIO pins only on the Base-T cards and even there drive all
of them low instead of putting them in hi-z state.  For the rest (this
is the common case), directly power off the PLLs of the high speed
serdes.  This is the simplest method that does not involve or conflict
with the firmware but still works with all T4-T6 cards regardless of
what's plugged into the port.

This fixes a problem where the peer wouldn't always see a link down if
it is connected to the device using a -CR4 copper cable.

MFC after:	3 weeks
Sponsored by:	Chelsio Communications
This commit is contained in:
Navdeep Parhar 2021-11-15 10:55:04 -08:00
parent 83a54b582f
commit a8eacf9329
4 changed files with 28 additions and 12 deletions

View file

@ -930,7 +930,8 @@ struct adapter {
struct tls_tunables tlst;
uint8_t doorbells;
int offload_map; /* ports with IFCAP_TOE enabled */
int offload_map; /* port_id's with IFCAP_TOE enabled */
int bt_map; /* tx_chan's with BASE-T */
int active_ulds; /* ULDs activated on this adapter */
int flags;
int debug_flags;

View file

@ -3827,15 +3827,6 @@ static uint16_t fwcaps32_to_caps16(uint32_t caps32)
return caps16;
}
static bool
is_bt(struct port_info *pi)
{
return (pi->port_type == FW_PORT_TYPE_BT_SGMII ||
pi->port_type == FW_PORT_TYPE_BT_XFI ||
pi->port_type == FW_PORT_TYPE_BT_XAUI);
}
static int8_t fwcap_to_fec(uint32_t caps, bool unset_means_none)
{
int8_t fec = 0;
@ -3970,7 +3961,7 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
}
/* Force AN on for BT cards. */
if (is_bt(adap->port[adap->chan_map[port]]))
if (isset(&adap->bt_map, port))
aneg = lc->pcaps & FW_PORT_CAP32_ANEG;
rcap = aneg | speed | fc | fec;
@ -9414,9 +9405,11 @@ int t4_prep_adapter(struct adapter *adapter, u32 *buf)
int t4_shutdown_adapter(struct adapter *adapter)
{
int port;
const bool bt = adapter->bt_map != 0;
t4_intr_disable(adapter);
t4_write_reg(adapter, A_DBG_GPIO_EN, 0);
if (bt)
t4_write_reg(adapter, A_DBG_GPIO_EN, 0xffff0000);
for_each_port(adapter, port) {
u32 a_port_cfg = is_t4(adapter) ?
PORT_REG(port, A_XGMAC_PORT_CFG) :
@ -9425,6 +9418,15 @@ int t4_shutdown_adapter(struct adapter *adapter)
t4_write_reg(adapter, a_port_cfg,
t4_read_reg(adapter, a_port_cfg)
& ~V_SIGNAL_DET(1));
if (!bt) {
u32 hss_cfg0 = is_t4(adapter) ?
PORT_REG(port, A_XGMAC_PORT_HSS_CFG0) :
T5_PORT_REG(port, A_MAC_PORT_HSS_CFG0);
t4_set_reg_field(adapter, hss_cfg0, F_HSSPDWNPLLB |
F_HSSPDWNPLLA | F_HSSPLLBYPB | F_HSSPLLBYPA,
F_HSSPDWNPLLB | F_HSSPDWNPLLA | F_HSSPLLBYPB |
F_HSSPLLBYPA);
}
}
t4_set_reg_field(adapter, A_SGE_CONTROL, F_GLOBALENABLE, 0);

View file

@ -7804,6 +7804,14 @@ enum fw_port_type {
FW_PORT_TYPE_NONE = M_FW_PORT_CMD_PTYPE
};
static inline bool
is_bt(enum fw_port_type port_type)
{
return (port_type == FW_PORT_TYPE_BT_SGMII ||
port_type == FW_PORT_TYPE_BT_XFI ||
port_type == FW_PORT_TYPE_BT_XAUI);
}
/* These are read from module's EEPROM and determined once the
module is inserted. */
enum fw_port_module_type {

View file

@ -1313,6 +1313,11 @@ t4_attach(device_t dev)
goto done;
}
if (is_bt(pi->port_type))
setbit(&sc->bt_map, pi->tx_chan);
else
MPASS(!isset(&sc->bt_map, pi->tx_chan));
snprintf(pi->lockname, sizeof(pi->lockname), "%sp%d",
device_get_nameunit(dev), i);
mtx_init(&pi->pi_lock, pi->lockname, 0, MTX_DEF);