Commit 2061ec3f authored by Ganesh Goudar's avatar Ganesh Goudar Committed by David S. Miller

cxgb4 : retrieve port information from firmware

issue get port information command to firmware to retrieve port
information and update if it is different from what was last
recorded and also add indication for supported link modes for
firmware port types FW_PORT_TYPE_SFP28, FW_PORT_TYPE_KR_SFP28,
FW_PORT_TYPE_CR4_QSFP.

Based on the original work by Casey Leedom <leedom@chelsio.com>
Signed-off-by: default avatarCasey Leedom <leedom@chelsio.com>
Signed-off-by: default avatarGanesh Goudar <ganeshgr@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 66aa0678
...@@ -1551,6 +1551,7 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf, ...@@ -1551,6 +1551,7 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
unsigned int vf, unsigned int eqid); unsigned int vf, unsigned int eqid);
int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox); int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox);
void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl); void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl);
int t4_update_port_info(struct port_info *pi);
int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl); int t4_handle_fw_rpl(struct adapter *adap, const __be64 *rpl);
void t4_db_full(struct adapter *adapter); void t4_db_full(struct adapter *adapter);
void t4_db_dropped(struct adapter *adapter); void t4_db_dropped(struct adapter *adapter);
......
...@@ -500,7 +500,11 @@ static int from_fw_port_mod_type(enum fw_port_type port_type, ...@@ -500,7 +500,11 @@ static int from_fw_port_mod_type(enum fw_port_type port_type,
} else if (port_type == FW_PORT_TYPE_SFP || } else if (port_type == FW_PORT_TYPE_SFP ||
port_type == FW_PORT_TYPE_QSFP_10G || port_type == FW_PORT_TYPE_QSFP_10G ||
port_type == FW_PORT_TYPE_QSA || port_type == FW_PORT_TYPE_QSA ||
port_type == FW_PORT_TYPE_QSFP) { port_type == FW_PORT_TYPE_QSFP ||
port_type == FW_PORT_TYPE_CR4_QSFP ||
port_type == FW_PORT_TYPE_CR_QSFP ||
port_type == FW_PORT_TYPE_CR2_QSFP ||
port_type == FW_PORT_TYPE_SFP28) {
if (mod_type == FW_PORT_MOD_TYPE_LR || if (mod_type == FW_PORT_MOD_TYPE_LR ||
mod_type == FW_PORT_MOD_TYPE_SR || mod_type == FW_PORT_MOD_TYPE_SR ||
mod_type == FW_PORT_MOD_TYPE_ER || mod_type == FW_PORT_MOD_TYPE_ER ||
...@@ -511,6 +515,9 @@ static int from_fw_port_mod_type(enum fw_port_type port_type, ...@@ -511,6 +515,9 @@ static int from_fw_port_mod_type(enum fw_port_type port_type,
return PORT_DA; return PORT_DA;
else else
return PORT_OTHER; return PORT_OTHER;
} else if (port_type == FW_PORT_TYPE_KR4_100G ||
port_type == FW_PORT_TYPE_KR_SFP28) {
return PORT_NONE;
} }
return PORT_OTHER; return PORT_OTHER;
...@@ -618,7 +625,21 @@ static void fw_caps_to_lmm(enum fw_port_type port_type, ...@@ -618,7 +625,21 @@ static void fw_caps_to_lmm(enum fw_port_type port_type,
case FW_PORT_TYPE_CR_QSFP: case FW_PORT_TYPE_CR_QSFP:
case FW_PORT_TYPE_SFP28: case FW_PORT_TYPE_SFP28:
SET_LMM(FIBRE); SET_LMM(FIBRE);
SET_LMM(25000baseCR_Full); FW_CAPS_TO_LMM(SPEED_1G, 1000baseT_Full);
FW_CAPS_TO_LMM(SPEED_10G, 10000baseT_Full);
FW_CAPS_TO_LMM(SPEED_25G, 25000baseCR_Full);
break;
case FW_PORT_TYPE_KR_SFP28:
SET_LMM(Backplane);
FW_CAPS_TO_LMM(SPEED_1G, 1000baseT_Full);
FW_CAPS_TO_LMM(SPEED_10G, 10000baseKR_Full);
FW_CAPS_TO_LMM(SPEED_25G, 25000baseKR_Full);
break;
case FW_PORT_TYPE_CR2_QSFP:
SET_LMM(FIBRE);
SET_LMM(50000baseSR2_Full);
break; break;
case FW_PORT_TYPE_KR4_100G: case FW_PORT_TYPE_KR4_100G:
...@@ -674,13 +695,20 @@ static unsigned int lmm_to_fw_caps(const unsigned long *link_mode_mask) ...@@ -674,13 +695,20 @@ static unsigned int lmm_to_fw_caps(const unsigned long *link_mode_mask)
static int get_link_ksettings(struct net_device *dev, static int get_link_ksettings(struct net_device *dev,
struct ethtool_link_ksettings *link_ksettings) struct ethtool_link_ksettings *link_ksettings)
{ {
const struct port_info *pi = netdev_priv(dev); struct port_info *pi = netdev_priv(dev);
struct ethtool_link_settings *base = &link_ksettings->base; struct ethtool_link_settings *base = &link_ksettings->base;
ethtool_link_ksettings_zero_link_mode(link_ksettings, supported); ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);
ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising); ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
ethtool_link_ksettings_zero_link_mode(link_ksettings, lp_advertising); ethtool_link_ksettings_zero_link_mode(link_ksettings, lp_advertising);
/* For the nonce, the Firmware doesn't send up Port State changes
* when the Virtual Interface attached to the Port is down. So
* if it's down, let's grab any changes.
*/
if (!netif_running(dev))
(void)t4_update_port_info(pi);
base->port = from_fw_port_mod_type(pi->port_type, pi->mod_type); base->port = from_fw_port_mod_type(pi->port_type, pi->mod_type);
if (pi->mdio_addr >= 0) { if (pi->mdio_addr >= 0) {
......
...@@ -2245,6 +2245,13 @@ static int cxgb_open(struct net_device *dev) ...@@ -2245,6 +2245,13 @@ static int cxgb_open(struct net_device *dev)
return err; return err;
} }
/* It's possible that the basic port information could have
* changed since we first read it.
*/
err = t4_update_port_info(pi);
if (err < 0)
return err;
err = link_start(dev); err = link_start(dev);
if (!err) if (!err)
netif_tx_start_all_queues(dev); netif_tx_start_all_queues(dev);
......
...@@ -7355,10 +7355,40 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl) ...@@ -7355,10 +7355,40 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
lc->fc = fc; lc->fc = fc;
lc->supported = be16_to_cpu(p->u.info.pcap); lc->supported = be16_to_cpu(p->u.info.pcap);
lc->lp_advertising = be16_to_cpu(p->u.info.lpacap); lc->lp_advertising = be16_to_cpu(p->u.info.lpacap);
t4_os_link_changed(adap, pi->port_id, link_ok); t4_os_link_changed(adap, pi->port_id, link_ok);
} }
} }
/**
* t4_update_port_info - retrieve and update port information if changed
* @pi: the port_info
*
* We issue a Get Port Information Command to the Firmware and, if
* successful, we check to see if anything is different from what we
* last recorded and update things accordingly.
*/
int t4_update_port_info(struct port_info *pi)
{
struct fw_port_cmd port_cmd;
int ret;
memset(&port_cmd, 0, sizeof(port_cmd));
port_cmd.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) |
FW_CMD_REQUEST_F | FW_CMD_READ_F |
FW_PORT_CMD_PORTID_V(pi->port_id));
port_cmd.action_to_len16 = cpu_to_be32(
FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_GET_PORT_INFO) |
FW_LEN16(port_cmd));
ret = t4_wr_mbox(pi->adapter, pi->adapter->mbox,
&port_cmd, sizeof(port_cmd), &port_cmd);
if (ret)
return ret;
t4_handle_get_port_info(pi, (__be64 *)&port_cmd);
return 0;
}
/** /**
* t4_handle_fw_rpl - process a FW reply message * t4_handle_fw_rpl - process a FW reply message
* @adap: the adapter * @adap: the adapter
......
...@@ -2572,6 +2572,7 @@ enum fw_port_type { ...@@ -2572,6 +2572,7 @@ enum fw_port_type {
FW_PORT_TYPE_CR_QSFP, FW_PORT_TYPE_CR_QSFP,
FW_PORT_TYPE_CR2_QSFP, FW_PORT_TYPE_CR2_QSFP,
FW_PORT_TYPE_SFP28, FW_PORT_TYPE_SFP28,
FW_PORT_TYPE_KR_SFP28,
FW_PORT_TYPE_NONE = FW_PORT_CMD_PTYPE_M FW_PORT_TYPE_NONE = FW_PORT_CMD_PTYPE_M
}; };
......
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