Commit 3bb4858f authored by Ganesh Goudar's avatar Ganesh Goudar Committed by David S. Miller

cxgb4: avoid disabling FEC by default

Recent Chelsio firmware started using few port capablity bits to
manage FEC and as driver was not aware of FEC changes those bits
were zeroed, consequently disabling FEC.

Avoid zeroing those bits and default to whatever the firmware
tells us the Link is currently advertising.
Signed-off-by: default avatarGanesh Goudar <ganeshgr@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8ce7aaaa
...@@ -108,6 +108,12 @@ enum { ...@@ -108,6 +108,12 @@ enum {
PAUSE_AUTONEG = 1 << 2 PAUSE_AUTONEG = 1 << 2
}; };
enum {
FEC_AUTO = 1 << 0, /* IEEE 802.3 "automatic" */
FEC_RS = 1 << 1, /* Reed-Solomon */
FEC_BASER_RS = 1 << 2 /* BaseR/Reed-Solomon */
};
struct port_stats { struct port_stats {
u64 tx_octets; /* total # of octets in good frames */ u64 tx_octets; /* total # of octets in good frames */
u64 tx_frames; /* all good frames */ u64 tx_frames; /* all good frames */
...@@ -432,6 +438,9 @@ struct link_config { ...@@ -432,6 +438,9 @@ struct link_config {
unsigned int speed; /* actual link speed */ unsigned int speed; /* actual link speed */
unsigned char requested_fc; /* flow control user has requested */ unsigned char requested_fc; /* flow control user has requested */
unsigned char fc; /* actual link flow control */ unsigned char fc; /* actual link flow control */
unsigned char auto_fec; /* Forward Error Correction: */
unsigned char requested_fec; /* "automatic" (IEEE 802.3), */
unsigned char fec; /* requested, and actual in use */
unsigned char autoneg; /* autonegotiating? */ unsigned char autoneg; /* autonegotiating? */
unsigned char link_ok; /* link up? */ unsigned char link_ok; /* link up? */
unsigned char link_down_rc; /* link down reason */ unsigned char link_down_rc; /* link down reason */
......
...@@ -3707,7 +3707,8 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port, ...@@ -3707,7 +3707,8 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
struct link_config *lc) struct link_config *lc)
{ {
struct fw_port_cmd c; struct fw_port_cmd c;
unsigned int fc = 0, mdi = FW_PORT_CAP_MDI_V(FW_PORT_CAP_MDI_AUTO); unsigned int mdi = FW_PORT_CAP_MDI_V(FW_PORT_CAP_MDI_AUTO);
unsigned int fc = 0, fec = 0, fw_fec = 0;
lc->link_ok = 0; lc->link_ok = 0;
if (lc->requested_fc & PAUSE_RX) if (lc->requested_fc & PAUSE_RX)
...@@ -3715,6 +3716,13 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port, ...@@ -3715,6 +3716,13 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
if (lc->requested_fc & PAUSE_TX) if (lc->requested_fc & PAUSE_TX)
fc |= FW_PORT_CAP_FC_TX; fc |= FW_PORT_CAP_FC_TX;
fec = lc->requested_fec & FEC_AUTO ? lc->auto_fec : lc->requested_fec;
if (fec & FEC_RS)
fw_fec |= FW_PORT_CAP_FEC_RS;
if (fec & FEC_BASER_RS)
fw_fec |= FW_PORT_CAP_FEC_BASER_RS;
memset(&c, 0, sizeof(c)); memset(&c, 0, sizeof(c));
c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) | c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) |
FW_CMD_REQUEST_F | FW_CMD_EXEC_F | FW_CMD_REQUEST_F | FW_CMD_EXEC_F |
...@@ -3725,13 +3733,15 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port, ...@@ -3725,13 +3733,15 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
if (!(lc->supported & FW_PORT_CAP_ANEG)) { if (!(lc->supported & FW_PORT_CAP_ANEG)) {
c.u.l1cfg.rcap = cpu_to_be32((lc->supported & ADVERT_MASK) | c.u.l1cfg.rcap = cpu_to_be32((lc->supported & ADVERT_MASK) |
fc); fc | fw_fec);
lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX); lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
} else if (lc->autoneg == AUTONEG_DISABLE) { } else if (lc->autoneg == AUTONEG_DISABLE) {
c.u.l1cfg.rcap = cpu_to_be32(lc->requested_speed | fc | mdi); c.u.l1cfg.rcap = cpu_to_be32(lc->requested_speed | fc |
fw_fec | mdi);
lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX); lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
} else } else
c.u.l1cfg.rcap = cpu_to_be32(lc->advertising | fc | mdi); c.u.l1cfg.rcap = cpu_to_be32(lc->advertising | fc |
fw_fec | mdi);
return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL); return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
} }
...@@ -7407,13 +7417,26 @@ static void get_pci_mode(struct adapter *adapter, struct pci_params *p) ...@@ -7407,13 +7417,26 @@ static void get_pci_mode(struct adapter *adapter, struct pci_params *p)
* Initializes the SW state maintained for each link, including the link's * Initializes the SW state maintained for each link, including the link's
* capabilities and default speed/flow-control/autonegotiation settings. * capabilities and default speed/flow-control/autonegotiation settings.
*/ */
static void init_link_config(struct link_config *lc, unsigned int caps) static void init_link_config(struct link_config *lc, unsigned int pcaps,
unsigned int acaps)
{ {
lc->supported = caps; lc->supported = pcaps;
lc->lp_advertising = 0; lc->lp_advertising = 0;
lc->requested_speed = 0; lc->requested_speed = 0;
lc->speed = 0; lc->speed = 0;
lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX; lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX;
lc->auto_fec = 0;
/* For Forward Error Control, we default to whatever the Firmware
* tells us the Link is currently advertising.
*/
if (acaps & FW_PORT_CAP_FEC_RS)
lc->auto_fec |= FEC_RS;
if (acaps & FW_PORT_CAP_FEC_BASER_RS)
lc->auto_fec |= FEC_BASER_RS;
lc->requested_fec = FEC_AUTO;
lc->fec = lc->auto_fec;
if (lc->supported & FW_PORT_CAP_ANEG) { if (lc->supported & FW_PORT_CAP_ANEG) {
lc->advertising = lc->supported & ADVERT_MASK; lc->advertising = lc->supported & ADVERT_MASK;
lc->autoneg = AUTONEG_ENABLE; lc->autoneg = AUTONEG_ENABLE;
...@@ -7991,7 +8014,8 @@ int t4_init_portinfo(struct port_info *pi, int mbox, ...@@ -7991,7 +8014,8 @@ int t4_init_portinfo(struct port_info *pi, int mbox,
pi->port_type = FW_PORT_CMD_PTYPE_G(ret); pi->port_type = FW_PORT_CMD_PTYPE_G(ret);
pi->mod_type = FW_PORT_MOD_TYPE_NA; pi->mod_type = FW_PORT_MOD_TYPE_NA;
init_link_config(&pi->link_cfg, be16_to_cpu(c.u.info.pcap)); init_link_config(&pi->link_cfg, be16_to_cpu(c.u.info.pcap),
be16_to_cpu(c.u.info.acap));
return 0; return 0;
} }
......
...@@ -2263,9 +2263,9 @@ enum fw_port_cap { ...@@ -2263,9 +2263,9 @@ enum fw_port_cap {
FW_PORT_CAP_ANEG = 0x0100, FW_PORT_CAP_ANEG = 0x0100,
FW_PORT_CAP_MDIX = 0x0200, FW_PORT_CAP_MDIX = 0x0200,
FW_PORT_CAP_MDIAUTO = 0x0400, FW_PORT_CAP_MDIAUTO = 0x0400,
FW_PORT_CAP_FEC = 0x0800, FW_PORT_CAP_FEC_RS = 0x0800,
FW_PORT_CAP_TECHKR = 0x1000, FW_PORT_CAP_FEC_BASER_RS = 0x1000,
FW_PORT_CAP_TECHKX4 = 0x2000, FW_PORT_CAP_FEC_RESERVED = 0x2000,
FW_PORT_CAP_802_3_PAUSE = 0x4000, FW_PORT_CAP_802_3_PAUSE = 0x4000,
FW_PORT_CAP_802_3_ASM_DIR = 0x8000, FW_PORT_CAP_802_3_ASM_DIR = 0x8000,
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment