net/cxgbe: rework and simplify link handling
Rework and simplify link handling code. Remove redundant variables in link configuration structure and directly extract information from the 32-bit link capabilities. Signed-off-by: Karra Satwik <kaara.satwik@chelsio.com> Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@chelsio.com>
This commit is contained in:
parent
439009e4ef
commit
a83041b1e9
@ -39,9 +39,6 @@ struct port_info {
|
||||
short int xact_addr_filt; /* index of exact MAC address filter */
|
||||
|
||||
u16 viid; /* associated virtual interface id */
|
||||
s8 mdio_addr; /* address of the PHY */
|
||||
u8 port_type; /* firmware port type */
|
||||
u8 mod_type; /* firmware module type */
|
||||
u8 port_id; /* physical port ID */
|
||||
u8 pidx; /* port index for this PF */
|
||||
u8 tx_chan; /* associated channel */
|
||||
@ -63,12 +60,6 @@ struct port_info {
|
||||
u8 vivld;
|
||||
};
|
||||
|
||||
/* Enable or disable autonegotiation. If this is set to enable,
|
||||
* the forced link modes above are completely ignored.
|
||||
*/
|
||||
#define AUTONEG_DISABLE 0x00
|
||||
#define AUTONEG_ENABLE 0x01
|
||||
|
||||
enum { /* adapter flags */
|
||||
FULL_INIT_DONE = (1 << 0),
|
||||
USING_MSI = (1 << 1),
|
||||
@ -801,7 +792,6 @@ void t4_free_mem(void *addr);
|
||||
#define t4_os_free(_ptr) t4_free_mem((_ptr))
|
||||
|
||||
void t4_os_portmod_changed(const struct adapter *adap, int port_id);
|
||||
void t4_os_link_changed(struct adapter *adap, int port_id, int link_stat);
|
||||
|
||||
void reclaim_completed_tx(struct sge_txq *q);
|
||||
void t4_free_sge_resources(struct adapter *adap);
|
||||
|
@ -38,18 +38,6 @@ enum dev_master { MASTER_CANT, MASTER_MAY, MASTER_MUST };
|
||||
|
||||
enum dev_state { DEV_STATE_UNINIT, DEV_STATE_INIT, DEV_STATE_ERR };
|
||||
|
||||
enum cc_pause {
|
||||
PAUSE_RX = 1 << 0,
|
||||
PAUSE_TX = 1 << 1,
|
||||
PAUSE_AUTONEG = 1 << 2
|
||||
};
|
||||
|
||||
enum cc_fec {
|
||||
FEC_AUTO = 1 << 0, /* IEEE 802.3 "automatic" */
|
||||
FEC_RS = 1 << 1, /* Reed-Solomon */
|
||||
FEC_BASER_RS = 1 << 2, /* BaseR/Reed-Solomon */
|
||||
};
|
||||
|
||||
enum { MEM_EDC0, MEM_EDC1, MEM_MC, MEM_MC0 = MEM_MC, MEM_MC1 };
|
||||
|
||||
struct port_stats {
|
||||
@ -281,28 +269,19 @@ struct adapter_params {
|
||||
|
||||
/* Firmware Port Capabilities types.
|
||||
*/
|
||||
typedef u32 fw_port_cap32_t; /* 32-bit Port Capabilities integral value */
|
||||
|
||||
struct link_config {
|
||||
fw_port_cap32_t pcaps; /* link capabilities */
|
||||
fw_port_cap32_t acaps; /* advertised capabilities */
|
||||
u32 pcaps; /* Physically supported link caps */
|
||||
u32 acaps; /* Advertised link caps */
|
||||
|
||||
u32 requested_speed; /* speed (Mb/s) user has requested */
|
||||
u32 speed; /* actual link speed (Mb/s) */
|
||||
u32 link_caps; /* Current link caps */
|
||||
u32 admin_caps; /* Admin configured link caps */
|
||||
|
||||
enum cc_pause requested_fc; /* flow control user has requested */
|
||||
enum cc_pause fc; /* actual link flow control */
|
||||
u8 mdio_addr; /* Address of the PHY */
|
||||
u8 port_type; /* Firmware port type */
|
||||
u8 mod_type; /* Firmware module type */
|
||||
|
||||
enum cc_fec auto_fec; /* Forward Error Correction
|
||||
* "automatic" (IEEE 802.3)
|
||||
*/
|
||||
enum cc_fec requested_fec; /* Forward Error Correction requested */
|
||||
enum cc_fec fec; /* Forward Error Correction actual */
|
||||
|
||||
unsigned char autoneg; /* autonegotiating? */
|
||||
|
||||
unsigned char link_ok; /* link up? */
|
||||
unsigned char link_down_rc; /* link down reason */
|
||||
u8 link_ok; /* Link up? */
|
||||
u8 link_down_rc; /* Link down reason */
|
||||
};
|
||||
|
||||
#include "adapter.h"
|
||||
@ -338,8 +317,21 @@ void t4_tp_wr_bits_indirect(struct adapter *adap, unsigned int addr,
|
||||
unsigned int mask, unsigned int val);
|
||||
void t4_intr_enable(struct adapter *adapter);
|
||||
void t4_intr_disable(struct adapter *adapter);
|
||||
int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
|
||||
struct link_config *lc);
|
||||
int t4_link_l1cfg_core(struct port_info *pi, u32 caps, u8 sleep_ok);
|
||||
static inline int t4_link_l1cfg(struct port_info *pi, u32 caps)
|
||||
{
|
||||
return t4_link_l1cfg_core(pi, caps, true);
|
||||
}
|
||||
|
||||
static inline int t4_link_l1cfg_ns(struct port_info *pi, u32 caps)
|
||||
{
|
||||
return t4_link_l1cfg_core(pi, caps, false);
|
||||
}
|
||||
|
||||
int t4_set_link_speed(struct port_info *pi, u32 speed, u32 *new_caps);
|
||||
int t4_set_link_pause(struct port_info *pi, u8 autoneg, u8 pause_tx,
|
||||
u8 pause_rx, u32 *new_caps);
|
||||
unsigned int t4_fwcap_to_speed(u32 caps);
|
||||
void t4_load_mtus(struct adapter *adap, const unsigned short *mtus,
|
||||
const unsigned short *alpha, const unsigned short *beta);
|
||||
int t4_fw_hello(struct adapter *adap, unsigned int mbox, unsigned int evt_mbox,
|
||||
@ -496,8 +488,8 @@ void t4_get_port_stats_offset(struct adapter *adap, int idx,
|
||||
struct port_stats *stats,
|
||||
struct port_stats *offset);
|
||||
void t4_clr_port_stats(struct adapter *adap, int idx);
|
||||
void init_link_config(struct link_config *lc, fw_port_cap32_t pcaps,
|
||||
fw_port_cap32_t acaps);
|
||||
void t4_init_link_config(struct port_info *pi, u32 pcaps, u32 acaps,
|
||||
u8 mdio_addr, u8 port_type, u8 mod_type);
|
||||
void t4_reset_link_config(struct adapter *adap, int idx);
|
||||
int t4_get_version_info(struct adapter *adapter);
|
||||
void t4_dump_version_info(struct adapter *adapter);
|
||||
|
@ -2809,67 +2809,11 @@ void t4_dump_version_info(struct adapter *adapter)
|
||||
G_FW_HDR_FW_VER_BUILD(adapter->params.er_vers));
|
||||
}
|
||||
|
||||
#define ADVERT_MASK (V_FW_PORT_CAP32_SPEED(M_FW_PORT_CAP32_SPEED) | \
|
||||
FW_PORT_CAP32_ANEG)
|
||||
|
||||
/* Translate Firmware Pause specification to Common Code */
|
||||
static inline enum cc_pause fwcap_to_cc_pause(fw_port_cap32_t fw_pause)
|
||||
{
|
||||
enum cc_pause cc_pause = 0;
|
||||
|
||||
if (fw_pause & FW_PORT_CAP32_FC_RX)
|
||||
cc_pause |= PAUSE_RX;
|
||||
if (fw_pause & FW_PORT_CAP32_FC_TX)
|
||||
cc_pause |= PAUSE_TX;
|
||||
|
||||
return cc_pause;
|
||||
}
|
||||
|
||||
/* Translate Common Code Pause Frame specification into Firmware */
|
||||
static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause)
|
||||
{
|
||||
fw_port_cap32_t fw_pause = 0;
|
||||
|
||||
if (cc_pause & PAUSE_RX)
|
||||
fw_pause |= FW_PORT_CAP32_FC_RX;
|
||||
if (cc_pause & PAUSE_TX)
|
||||
fw_pause |= FW_PORT_CAP32_FC_TX;
|
||||
|
||||
return fw_pause;
|
||||
}
|
||||
|
||||
/* Translate Firmware Forward Error Correction specification to Common Code */
|
||||
static inline enum cc_fec fwcap_to_cc_fec(fw_port_cap32_t fw_fec)
|
||||
{
|
||||
enum cc_fec cc_fec = 0;
|
||||
|
||||
if (fw_fec & FW_PORT_CAP32_FEC_RS)
|
||||
cc_fec |= FEC_RS;
|
||||
if (fw_fec & FW_PORT_CAP32_FEC_BASER_RS)
|
||||
cc_fec |= FEC_BASER_RS;
|
||||
|
||||
return cc_fec;
|
||||
}
|
||||
|
||||
/* Translate Common Code Forward Error Correction specification to Firmware */
|
||||
static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec)
|
||||
{
|
||||
fw_port_cap32_t fw_fec = 0;
|
||||
|
||||
if (cc_fec & FEC_RS)
|
||||
fw_fec |= FW_PORT_CAP32_FEC_RS;
|
||||
if (cc_fec & FEC_BASER_RS)
|
||||
fw_fec |= FW_PORT_CAP32_FEC_BASER_RS;
|
||||
|
||||
return fw_fec;
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_link_l1cfg - apply link configuration to MAC/PHY
|
||||
* @adapter: the adapter
|
||||
* @mbox: the Firmware Mailbox to use
|
||||
* @port: the Port ID
|
||||
* @lc: the Port's Link Configuration
|
||||
* t4_link_l1cfg_core - apply link configuration to MAC/PHY
|
||||
* @pi: the port info
|
||||
* @caps: link capabilities to configure
|
||||
* @sleep_ok: if true we may sleep while awaiting command completion
|
||||
*
|
||||
* Set up a port's MAC and PHY according to a desired link configuration.
|
||||
* - If the PHY can auto-negotiate first decide what to advertise, then
|
||||
@ -2878,57 +2822,36 @@ static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec)
|
||||
* - If auto-negotiation is off set the MAC to the proper speed/duplex/FC,
|
||||
* otherwise do it later based on the outcome of auto-negotiation.
|
||||
*/
|
||||
int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
|
||||
struct link_config *lc)
|
||||
int t4_link_l1cfg_core(struct port_info *pi, u32 caps, u8 sleep_ok)
|
||||
{
|
||||
unsigned int fw_mdi = V_FW_PORT_CAP32_MDI(FW_PORT_CAP32_MDI_AUTO);
|
||||
fw_port_cap32_t fw_fc, cc_fec, fw_fec, rcap;
|
||||
struct link_config *lc = &pi->link_cfg;
|
||||
struct adapter *adap = pi->adapter;
|
||||
struct fw_port_cmd cmd;
|
||||
int ret;
|
||||
|
||||
lc->link_ok = 0;
|
||||
|
||||
fw_fc = cc_to_fwcap_pause(lc->requested_fc);
|
||||
|
||||
/* Convert Common Code Forward Error Control settings into the
|
||||
* Firmware's API. If the current Requested FEC has "Automatic"
|
||||
* (IEEE 802.3) specified, then we use whatever the Firmware
|
||||
* sent us as part of it's IEEE 802.3-based interpratation of
|
||||
* the Transceiver Module EPROM FEC parameters. Otherwise we
|
||||
* use whatever is in the current Requested FEC settings.
|
||||
*/
|
||||
if (lc->requested_fec & FEC_AUTO)
|
||||
cc_fec = lc->auto_fec;
|
||||
else
|
||||
cc_fec = lc->requested_fec;
|
||||
fw_fec = cc_to_fwcap_fec(cc_fec);
|
||||
|
||||
/* Figure out what our Requested Port Capabilities are going to be.
|
||||
*/
|
||||
if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) {
|
||||
rcap = (lc->pcaps & ADVERT_MASK) | fw_fc | fw_fec;
|
||||
lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
|
||||
lc->fec = cc_fec;
|
||||
} else if (lc->autoneg == AUTONEG_DISABLE) {
|
||||
rcap = lc->requested_speed | fw_fc | fw_fec | fw_mdi;
|
||||
lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
|
||||
lc->fec = cc_fec;
|
||||
} else {
|
||||
rcap = lc->acaps | fw_fc | fw_fec | fw_mdi;
|
||||
}
|
||||
|
||||
/* And send that on to the Firmware ...
|
||||
*/
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.op_to_portid = cpu_to_be32(V_FW_CMD_OP(FW_PORT_CMD) |
|
||||
F_FW_CMD_REQUEST | F_FW_CMD_EXEC |
|
||||
V_FW_PORT_CMD_PORTID(port));
|
||||
V_FW_PORT_CMD_PORTID(pi->port_id));
|
||||
cmd.action_to_len16 =
|
||||
cpu_to_be32(V_FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG32) |
|
||||
FW_LEN16(cmd));
|
||||
|
||||
cmd.u.l1cfg32.rcap32 = cpu_to_be32(rcap);
|
||||
cmd.u.l1cfg32.rcap32 = cpu_to_be32(caps);
|
||||
|
||||
return t4_wr_mbox(adap, mbox, &cmd, sizeof(cmd), NULL);
|
||||
if (sleep_ok)
|
||||
ret = t4_wr_mbox(adap, adap->mbox, &cmd, sizeof(cmd), NULL);
|
||||
else
|
||||
ret = t4_wr_mbox_ns(adap, adap->mbox, &cmd, sizeof(cmd), NULL);
|
||||
|
||||
if (ret == FW_SUCCESS)
|
||||
lc->link_caps = caps;
|
||||
else
|
||||
dev_err(adap,
|
||||
"Requested Port Capabilities %#x rejected, error %d\n",
|
||||
caps, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4426,8 +4349,32 @@ static const char *t4_link_down_rc_str(unsigned char link_down_rc)
|
||||
return reason[link_down_rc];
|
||||
}
|
||||
|
||||
static u32 t4_speed_to_fwcap(u32 speed)
|
||||
{
|
||||
switch (speed) {
|
||||
case 100000:
|
||||
return FW_PORT_CAP32_SPEED_100G;
|
||||
case 50000:
|
||||
return FW_PORT_CAP32_SPEED_50G;
|
||||
case 40000:
|
||||
return FW_PORT_CAP32_SPEED_40G;
|
||||
case 25000:
|
||||
return FW_PORT_CAP32_SPEED_25G;
|
||||
case 10000:
|
||||
return FW_PORT_CAP32_SPEED_10G;
|
||||
case 1000:
|
||||
return FW_PORT_CAP32_SPEED_1G;
|
||||
case 100:
|
||||
return FW_PORT_CAP32_SPEED_100M;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return the highest speed set in the port capabilities, in Mb/s. */
|
||||
static unsigned int fwcap_to_speed(fw_port_cap32_t caps)
|
||||
unsigned int t4_fwcap_to_speed(u32 caps)
|
||||
{
|
||||
#define TEST_SPEED_RETURN(__caps_speed, __speed) \
|
||||
do { \
|
||||
@ -4448,6 +4395,84 @@ static unsigned int fwcap_to_speed(fw_port_cap32_t caps)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void t4_set_link_autoneg_speed(struct port_info *pi, u32 *new_caps)
|
||||
{
|
||||
struct link_config *lc = &pi->link_cfg;
|
||||
u32 caps = *new_caps;
|
||||
|
||||
caps &= ~V_FW_PORT_CAP32_SPEED(M_FW_PORT_CAP32_SPEED);
|
||||
caps |= G_FW_PORT_CAP32_SPEED(lc->acaps);
|
||||
|
||||
*new_caps = caps;
|
||||
}
|
||||
|
||||
int t4_set_link_speed(struct port_info *pi, u32 speed, u32 *new_caps)
|
||||
{
|
||||
u32 fw_speed_cap = t4_speed_to_fwcap(speed);
|
||||
struct link_config *lc = &pi->link_cfg;
|
||||
u32 caps = *new_caps;
|
||||
|
||||
if (!(lc->pcaps & fw_speed_cap))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
caps &= ~V_FW_PORT_CAP32_SPEED(M_FW_PORT_CAP32_SPEED);
|
||||
caps |= fw_speed_cap;
|
||||
|
||||
*new_caps = caps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int t4_set_link_pause(struct port_info *pi, u8 autoneg, u8 pause_tx,
|
||||
u8 pause_rx, u32 *new_caps)
|
||||
{
|
||||
struct link_config *lc = &pi->link_cfg;
|
||||
u32 caps = *new_caps;
|
||||
u32 max_speed;
|
||||
|
||||
max_speed = t4_fwcap_to_speed(lc->link_caps);
|
||||
|
||||
if (autoneg) {
|
||||
if (!(lc->pcaps & FW_PORT_CAP32_ANEG))
|
||||
return -EINVAL;
|
||||
|
||||
caps |= FW_PORT_CAP32_ANEG;
|
||||
t4_set_link_autoneg_speed(pi, &caps);
|
||||
} else {
|
||||
if (!max_speed)
|
||||
max_speed = t4_fwcap_to_speed(lc->acaps);
|
||||
|
||||
caps &= ~FW_PORT_CAP32_ANEG;
|
||||
t4_set_link_speed(pi, max_speed, &caps);
|
||||
}
|
||||
|
||||
if (lc->pcaps & FW_PORT_CAP32_MDIAUTO)
|
||||
caps |= V_FW_PORT_CAP32_MDI(FW_PORT_CAP32_MDI_AUTO);
|
||||
|
||||
caps &= ~V_FW_PORT_CAP32_FC(M_FW_PORT_CAP32_FC);
|
||||
caps &= ~V_FW_PORT_CAP32_802_3(M_FW_PORT_CAP32_802_3);
|
||||
if (pause_tx && pause_rx) {
|
||||
caps |= FW_PORT_CAP32_FC_TX | FW_PORT_CAP32_FC_RX;
|
||||
if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
|
||||
caps |= FW_PORT_CAP32_802_3_PAUSE;
|
||||
} else if (pause_tx) {
|
||||
caps |= FW_PORT_CAP32_FC_TX;
|
||||
if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
|
||||
caps |= FW_PORT_CAP32_802_3_ASM_DIR;
|
||||
} else if (pause_rx) {
|
||||
caps |= FW_PORT_CAP32_FC_RX;
|
||||
if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE)
|
||||
caps |= FW_PORT_CAP32_802_3_PAUSE;
|
||||
|
||||
if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR)
|
||||
caps |= FW_PORT_CAP32_802_3_ASM_DIR;
|
||||
}
|
||||
|
||||
*new_caps = caps;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* t4_handle_get_port_info - process a FW reply message
|
||||
* @pi: the port info
|
||||
@ -4459,10 +4484,10 @@ static void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
|
||||
{
|
||||
const struct fw_port_cmd *cmd = (const void *)rpl;
|
||||
u8 link_ok, link_down_rc, mod_type, port_type;
|
||||
u32 action, pcaps, acaps, linkattr, lstatus;
|
||||
u32 action, pcaps, acaps, link_caps, lstatus;
|
||||
struct link_config *lc = &pi->link_cfg;
|
||||
struct adapter *adapter = pi->adapter;
|
||||
unsigned int speed, fc, fec;
|
||||
u8 mod_changed = 0;
|
||||
|
||||
/* Extract the various fields from the Port Information message.
|
||||
*/
|
||||
@ -4481,21 +4506,16 @@ static void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
|
||||
|
||||
pcaps = be32_to_cpu(cmd->u.info32.pcaps32);
|
||||
acaps = be32_to_cpu(cmd->u.info32.acaps32);
|
||||
linkattr = be32_to_cpu(cmd->u.info32.linkattr32);
|
||||
link_caps = be32_to_cpu(cmd->u.info32.linkattr32);
|
||||
|
||||
fec = fwcap_to_cc_fec(acaps);
|
||||
|
||||
fc = fwcap_to_cc_pause(linkattr);
|
||||
speed = fwcap_to_speed(linkattr);
|
||||
|
||||
if (mod_type != pi->mod_type) {
|
||||
lc->auto_fec = fec;
|
||||
pi->port_type = port_type;
|
||||
pi->mod_type = mod_type;
|
||||
if (mod_type != lc->mod_type) {
|
||||
t4_init_link_config(pi, pcaps, acaps, lc->mdio_addr,
|
||||
port_type, mod_type);
|
||||
t4_os_portmod_changed(adapter, pi->pidx);
|
||||
mod_changed = 1;
|
||||
}
|
||||
if (link_ok != lc->link_ok || speed != lc->speed ||
|
||||
fc != lc->fc || fec != lc->fec) { /* something changed */
|
||||
if (link_ok != lc->link_ok || acaps != lc->acaps ||
|
||||
link_caps != lc->link_caps) { /* something changed */
|
||||
if (!link_ok && lc->link_ok) {
|
||||
lc->link_down_rc = link_down_rc;
|
||||
dev_warn(adap, "Port %d link down, reason: %s\n",
|
||||
@ -4503,23 +4523,19 @@ static void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
|
||||
t4_link_down_rc_str(link_down_rc));
|
||||
}
|
||||
lc->link_ok = link_ok;
|
||||
lc->speed = speed;
|
||||
lc->fc = fc;
|
||||
lc->fec = fec;
|
||||
lc->pcaps = pcaps;
|
||||
lc->acaps = acaps & ADVERT_MASK;
|
||||
lc->acaps = acaps;
|
||||
lc->link_caps = link_caps;
|
||||
}
|
||||
|
||||
if (lc->acaps & FW_PORT_CAP32_ANEG) {
|
||||
lc->autoneg = AUTONEG_ENABLE;
|
||||
} else {
|
||||
/* When Autoneg is disabled, user needs to set
|
||||
* single speed.
|
||||
* Similar to cxgb4_ethtool.c: set_link_ksettings
|
||||
*/
|
||||
lc->acaps = 0;
|
||||
lc->requested_speed = fwcap_to_speed(acaps);
|
||||
lc->autoneg = AUTONEG_DISABLE;
|
||||
}
|
||||
if (mod_changed) {
|
||||
u32 mod_caps = lc->admin_caps;
|
||||
int ret;
|
||||
|
||||
ret = t4_link_l1cfg_ns(pi, mod_caps);
|
||||
if (ret != FW_SUCCESS)
|
||||
dev_warn(adapter,
|
||||
"Attempt to update new Transceiver Module settings %#x failed with error: %d\n",
|
||||
mod_caps, ret);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4595,45 +4611,49 @@ void t4_reset_link_config(struct adapter *adap, int idx)
|
||||
struct link_config *lc = &pi->link_cfg;
|
||||
|
||||
lc->link_ok = 0;
|
||||
lc->requested_speed = 0;
|
||||
lc->requested_fc = 0;
|
||||
lc->speed = 0;
|
||||
lc->fc = 0;
|
||||
lc->link_down_rc = 0;
|
||||
lc->link_caps = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* init_link_config - initialize a link's SW state
|
||||
* @lc: structure holding the link state
|
||||
* t4_init_link_config - initialize a link's SW state
|
||||
* @pi: the port info
|
||||
* @pcaps: link Port Capabilities
|
||||
* @acaps: link current Advertised Port Capabilities
|
||||
* @mdio_addr : address of the PHY
|
||||
* @port_type : firmware port type
|
||||
* @mod_type : firmware module type
|
||||
*
|
||||
* Initializes the SW state maintained for each link, including the link's
|
||||
* capabilities and default speed/flow-control/autonegotiation settings.
|
||||
*/
|
||||
void init_link_config(struct link_config *lc, fw_port_cap32_t pcaps,
|
||||
fw_port_cap32_t acaps)
|
||||
void t4_init_link_config(struct port_info *pi, u32 pcaps, u32 acaps,
|
||||
u8 mdio_addr, u8 port_type, u8 mod_type)
|
||||
{
|
||||
struct link_config *lc = &pi->link_cfg;
|
||||
|
||||
lc->pcaps = pcaps;
|
||||
lc->requested_speed = 0;
|
||||
lc->speed = 0;
|
||||
lc->requested_fc = 0;
|
||||
lc->fc = 0;
|
||||
lc->acaps = acaps;
|
||||
lc->admin_caps = acaps;
|
||||
lc->link_caps = 0;
|
||||
|
||||
/**
|
||||
* For Forward Error Control, we default to whatever the Firmware
|
||||
* tells us the Link is currently advertising.
|
||||
*/
|
||||
lc->auto_fec = fwcap_to_cc_fec(acaps);
|
||||
lc->requested_fec = FEC_AUTO;
|
||||
lc->fec = lc->auto_fec;
|
||||
lc->mdio_addr = mdio_addr;
|
||||
lc->port_type = port_type;
|
||||
lc->mod_type = mod_type;
|
||||
|
||||
if (lc->pcaps & FW_PORT_CAP32_ANEG) {
|
||||
lc->acaps = lc->pcaps & ADVERT_MASK;
|
||||
lc->autoneg = AUTONEG_ENABLE;
|
||||
lc->requested_fc |= PAUSE_AUTONEG;
|
||||
} else {
|
||||
lc->acaps = 0;
|
||||
lc->autoneg = AUTONEG_DISABLE;
|
||||
lc->link_ok = 0;
|
||||
lc->link_down_rc = 0;
|
||||
|
||||
/* Turn Tx and Rx pause off by default */
|
||||
lc->admin_caps &= ~V_FW_PORT_CAP32_FC(M_FW_PORT_CAP32_FC);
|
||||
lc->admin_caps &= ~V_FW_PORT_CAP32_802_3(M_FW_PORT_CAP32_802_3);
|
||||
if (lc->pcaps & FW_PORT_CAP32_FORCE_PAUSE)
|
||||
lc->admin_caps &= ~FW_PORT_CAP32_FORCE_PAUSE;
|
||||
|
||||
/* Reset MDI to AUTO */
|
||||
if (lc->pcaps & FW_PORT_CAP32_MDIAUTO) {
|
||||
lc->admin_caps &= ~V_FW_PORT_CAP32_MDI(M_FW_PORT_CAP32_MDI);
|
||||
lc->admin_caps |= V_FW_PORT_CAP32_MDI(FW_PORT_CAP32_MDI_AUTO);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5271,12 +5291,11 @@ int t4_init_rss_mode(struct adapter *adap, int mbox)
|
||||
|
||||
int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
|
||||
{
|
||||
fw_port_cap32_t pcaps, acaps;
|
||||
u32 param, val, pcaps, acaps;
|
||||
enum fw_port_type port_type;
|
||||
struct fw_port_cmd cmd;
|
||||
u8 vivld = 0, vin = 0;
|
||||
int ret, i, j = 0;
|
||||
u32 param, val;
|
||||
int mdio_addr;
|
||||
u8 addr[6];
|
||||
|
||||
@ -5342,11 +5361,8 @@ int t4_port_init(struct adapter *adap, int mbox, int pf, int vf)
|
||||
pi->vin = G_FW_VIID_VIN(pi->viid);
|
||||
}
|
||||
|
||||
pi->port_type = port_type;
|
||||
pi->mdio_addr = mdio_addr;
|
||||
pi->mod_type = FW_PORT_MOD_TYPE_NA;
|
||||
|
||||
init_link_config(&pi->link_cfg, pcaps, acaps);
|
||||
t4_init_link_config(pi, pcaps, acaps, mdio_addr, port_type,
|
||||
FW_PORT_MOD_TYPE_NA);
|
||||
j++;
|
||||
}
|
||||
return 0;
|
||||
|
@ -1615,6 +1615,7 @@ struct fw_vi_stats_cmd {
|
||||
#define FW_PORT_CAP32_MDIAUTO 0x00400000UL
|
||||
#define FW_PORT_CAP32_FEC_RS 0x00800000UL
|
||||
#define FW_PORT_CAP32_FEC_BASER_RS 0x01000000UL
|
||||
#define FW_PORT_CAP32_FORCE_PAUSE 0x10000000UL
|
||||
|
||||
#define S_FW_PORT_CAP32_SPEED 0
|
||||
#define M_FW_PORT_CAP32_SPEED 0xfff
|
||||
@ -1622,8 +1623,16 @@ struct fw_vi_stats_cmd {
|
||||
#define G_FW_PORT_CAP32_SPEED(x) \
|
||||
(((x) >> S_FW_PORT_CAP32_SPEED) & M_FW_PORT_CAP32_SPEED)
|
||||
|
||||
#define S_FW_PORT_CAP32_FC 16
|
||||
#define M_FW_PORT_CAP32_FC 0x3
|
||||
#define V_FW_PORT_CAP32_FC(x) ((x) << S_FW_PORT_CAP32_FC)
|
||||
|
||||
#define S_FW_PORT_CAP32_802_3 18
|
||||
#define M_FW_PORT_CAP32_802_3 0x3
|
||||
#define V_FW_PORT_CAP32_802_3(x) ((x) << S_FW_PORT_CAP32_802_3)
|
||||
|
||||
enum fw_port_mdi32 {
|
||||
FW_PORT_CAP32_MDI_AUTO,
|
||||
FW_PORT_CAP32_MDI_AUTO = 1,
|
||||
};
|
||||
|
||||
#define S_FW_PORT_CAP32_MDI 21
|
||||
|
@ -768,9 +768,8 @@ int t4vf_port_init(struct adapter *adapter)
|
||||
{
|
||||
struct fw_port_cmd port_cmd, port_rpl, rpl;
|
||||
struct fw_vi_cmd vi_cmd, vi_rpl;
|
||||
fw_port_cap32_t pcaps, acaps;
|
||||
u32 param, val, pcaps, acaps;
|
||||
enum fw_port_type port_type;
|
||||
u32 param, val;
|
||||
int mdio_addr;
|
||||
int ret, i;
|
||||
|
||||
@ -844,10 +843,8 @@ int t4vf_port_init(struct adapter *adapter)
|
||||
pcaps = be32_to_cpu(port_rpl.u.info32.pcaps32);
|
||||
acaps = be32_to_cpu(port_rpl.u.info32.acaps32);
|
||||
|
||||
p->port_type = port_type;
|
||||
p->mdio_addr = mdio_addr;
|
||||
p->mod_type = FW_PORT_MOD_TYPE_NA;
|
||||
init_link_config(&p->link_cfg, pcaps, acaps);
|
||||
t4_init_link_config(p, pcaps, acaps, mdio_addr, port_type,
|
||||
FW_PORT_MOD_TYPE_NA);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -193,11 +193,12 @@ int cxgbe_dev_link_update(struct rte_eth_dev *eth_dev,
|
||||
int wait_to_complete)
|
||||
{
|
||||
struct port_info *pi = eth_dev->data->dev_private;
|
||||
struct adapter *adapter = pi->adapter;
|
||||
struct sge *s = &adapter->sge;
|
||||
struct rte_eth_link new_link = { 0 };
|
||||
unsigned int i, work_done, budget = 32;
|
||||
struct link_config *lc = &pi->link_cfg;
|
||||
struct adapter *adapter = pi->adapter;
|
||||
struct rte_eth_link new_link = { 0 };
|
||||
u8 old_link = pi->link_cfg.link_ok;
|
||||
struct sge *s = &adapter->sge;
|
||||
|
||||
for (i = 0; i < CXGBE_LINK_STATUS_POLL_CNT; i++) {
|
||||
if (!s->fw_evtq.desc)
|
||||
@ -218,9 +219,9 @@ int cxgbe_dev_link_update(struct rte_eth_dev *eth_dev,
|
||||
|
||||
new_link.link_status = cxgbe_force_linkup(adapter) ?
|
||||
ETH_LINK_UP : pi->link_cfg.link_ok;
|
||||
new_link.link_autoneg = pi->link_cfg.autoneg;
|
||||
new_link.link_autoneg = (lc->link_caps & FW_PORT_CAP32_ANEG) ? 1 : 0;
|
||||
new_link.link_duplex = ETH_LINK_FULL_DUPLEX;
|
||||
new_link.link_speed = pi->link_cfg.speed;
|
||||
new_link.link_speed = t4_fwcap_to_speed(lc->link_caps);
|
||||
|
||||
return rte_eth_linkstatus_set(eth_dev, &new_link);
|
||||
}
|
||||
@ -787,11 +788,17 @@ static int cxgbe_flow_ctrl_get(struct rte_eth_dev *eth_dev,
|
||||
{
|
||||
struct port_info *pi = eth_dev->data->dev_private;
|
||||
struct link_config *lc = &pi->link_cfg;
|
||||
int rx_pause, tx_pause;
|
||||
u8 rx_pause = 0, tx_pause = 0;
|
||||
u32 caps = lc->link_caps;
|
||||
|
||||
fc_conf->autoneg = lc->fc & PAUSE_AUTONEG;
|
||||
rx_pause = lc->fc & PAUSE_RX;
|
||||
tx_pause = lc->fc & PAUSE_TX;
|
||||
if (caps & FW_PORT_CAP32_ANEG)
|
||||
fc_conf->autoneg = 1;
|
||||
|
||||
if (caps & FW_PORT_CAP32_FC_TX)
|
||||
tx_pause = 1;
|
||||
|
||||
if (caps & FW_PORT_CAP32_FC_RX)
|
||||
rx_pause = 1;
|
||||
|
||||
if (rx_pause && tx_pause)
|
||||
fc_conf->mode = RTE_FC_FULL;
|
||||
@ -808,30 +815,39 @@ static int cxgbe_flow_ctrl_set(struct rte_eth_dev *eth_dev,
|
||||
struct rte_eth_fc_conf *fc_conf)
|
||||
{
|
||||
struct port_info *pi = eth_dev->data->dev_private;
|
||||
struct adapter *adapter = pi->adapter;
|
||||
struct link_config *lc = &pi->link_cfg;
|
||||
u32 new_caps = lc->admin_caps;
|
||||
u8 tx_pause = 0, rx_pause = 0;
|
||||
int ret;
|
||||
|
||||
if (lc->pcaps & FW_PORT_CAP32_ANEG) {
|
||||
if (fc_conf->autoneg)
|
||||
lc->requested_fc |= PAUSE_AUTONEG;
|
||||
else
|
||||
lc->requested_fc &= ~PAUSE_AUTONEG;
|
||||
if (fc_conf->mode == RTE_FC_FULL) {
|
||||
tx_pause = 1;
|
||||
rx_pause = 1;
|
||||
} else if (fc_conf->mode == RTE_FC_TX_PAUSE) {
|
||||
tx_pause = 1;
|
||||
} else if (fc_conf->mode == RTE_FC_RX_PAUSE) {
|
||||
rx_pause = 1;
|
||||
}
|
||||
|
||||
if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
|
||||
(fc_conf->mode & RTE_FC_RX_PAUSE))
|
||||
lc->requested_fc |= PAUSE_RX;
|
||||
else
|
||||
lc->requested_fc &= ~PAUSE_RX;
|
||||
ret = t4_set_link_pause(pi, fc_conf->autoneg, tx_pause,
|
||||
rx_pause, &new_caps);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
|
||||
(fc_conf->mode & RTE_FC_TX_PAUSE))
|
||||
lc->requested_fc |= PAUSE_TX;
|
||||
else
|
||||
lc->requested_fc &= ~PAUSE_TX;
|
||||
if (!fc_conf->autoneg) {
|
||||
if (lc->pcaps & FW_PORT_CAP32_FORCE_PAUSE)
|
||||
new_caps |= FW_PORT_CAP32_FORCE_PAUSE;
|
||||
} else {
|
||||
new_caps &= ~FW_PORT_CAP32_FORCE_PAUSE;
|
||||
}
|
||||
|
||||
return t4_link_l1cfg(adapter, adapter->mbox, pi->tx_chan,
|
||||
&pi->link_cfg);
|
||||
if (new_caps != lc->admin_caps) {
|
||||
ret = t4_link_l1cfg(pi, new_caps);
|
||||
if (ret == 0)
|
||||
lc->admin_caps = new_caps;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const uint32_t *
|
||||
|
@ -732,7 +732,7 @@ void cxgbe_print_port_info(struct adapter *adap)
|
||||
--bufp;
|
||||
sprintf(bufp, "BASE-%s",
|
||||
t4_get_port_type_description(
|
||||
(enum fw_port_type)pi->port_type));
|
||||
(enum fw_port_type)pi->link_cfg.port_type));
|
||||
|
||||
dev_info(adap,
|
||||
" " PCI_PRI_FMT " Chelsio rev %d %s %s\n",
|
||||
@ -1575,23 +1575,23 @@ void t4_os_portmod_changed(const struct adapter *adap, int port_id)
|
||||
|
||||
const struct port_info *pi = adap2pinfo(adap, port_id);
|
||||
|
||||
if (pi->mod_type == FW_PORT_MOD_TYPE_NONE)
|
||||
if (pi->link_cfg.mod_type == FW_PORT_MOD_TYPE_NONE)
|
||||
dev_info(adap, "Port%d: port module unplugged\n", pi->port_id);
|
||||
else if (pi->mod_type < ARRAY_SIZE(mod_str))
|
||||
else if (pi->link_cfg.mod_type < ARRAY_SIZE(mod_str))
|
||||
dev_info(adap, "Port%d: %s port module inserted\n", pi->port_id,
|
||||
mod_str[pi->mod_type]);
|
||||
else if (pi->mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED)
|
||||
mod_str[pi->link_cfg.mod_type]);
|
||||
else if (pi->link_cfg.mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED)
|
||||
dev_info(adap, "Port%d: unsupported port module inserted\n",
|
||||
pi->port_id);
|
||||
else if (pi->mod_type == FW_PORT_MOD_TYPE_UNKNOWN)
|
||||
else if (pi->link_cfg.mod_type == FW_PORT_MOD_TYPE_UNKNOWN)
|
||||
dev_info(adap, "Port%d: unknown port module inserted\n",
|
||||
pi->port_id);
|
||||
else if (pi->mod_type == FW_PORT_MOD_TYPE_ERROR)
|
||||
else if (pi->link_cfg.mod_type == FW_PORT_MOD_TYPE_ERROR)
|
||||
dev_info(adap, "Port%d: transceiver module error\n",
|
||||
pi->port_id);
|
||||
else
|
||||
dev_info(adap, "Port%d: unknown module type %d inserted\n",
|
||||
pi->port_id, pi->mod_type);
|
||||
pi->port_id, pi->link_cfg.mod_type);
|
||||
}
|
||||
|
||||
bool cxgbe_force_linkup(struct adapter *adap)
|
||||
@ -1636,8 +1636,7 @@ int cxgbe_link_start(struct port_info *pi)
|
||||
}
|
||||
}
|
||||
if (ret == 0 && is_pf4(adapter))
|
||||
ret = t4_link_l1cfg(adapter, adapter->mbox, pi->tx_chan,
|
||||
&pi->link_cfg);
|
||||
ret = t4_link_l1cfg(pi, pi->link_cfg.admin_caps);
|
||||
if (ret == 0) {
|
||||
/*
|
||||
* Enabling a Virtual Interface can result in an interrupt
|
||||
@ -1905,7 +1904,7 @@ void cxgbe_get_speed_caps(struct port_info *pi, u32 *speed_caps)
|
||||
{
|
||||
*speed_caps = 0;
|
||||
|
||||
fw_caps_to_speed_caps(pi->port_type, pi->link_cfg.pcaps,
|
||||
fw_caps_to_speed_caps(pi->link_cfg.port_type, pi->link_cfg.pcaps,
|
||||
speed_caps);
|
||||
|
||||
if (!(pi->link_cfg.pcaps & FW_PORT_CAP32_ANEG))
|
||||
|
Loading…
x
Reference in New Issue
Block a user