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: Casey Leedom <leedom@chelsio.com> Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
66aa0678ef
commit
2061ec3f13
|
@ -1551,6 +1551,7 @@ int t4_ofld_eq_free(struct adapter *adap, unsigned int mbox, unsigned int pf,
|
|||
unsigned int vf, unsigned int eqid);
|
||||
int t4_sge_ctxt_flush(struct adapter *adap, unsigned int mbox);
|
||||
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);
|
||||
void t4_db_full(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,
|
|||
} else if (port_type == FW_PORT_TYPE_SFP ||
|
||||
port_type == FW_PORT_TYPE_QSFP_10G ||
|
||||
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 ||
|
||||
mod_type == FW_PORT_MOD_TYPE_SR ||
|
||||
mod_type == FW_PORT_MOD_TYPE_ER ||
|
||||
|
@ -511,6 +515,9 @@ static int from_fw_port_mod_type(enum fw_port_type port_type,
|
|||
return PORT_DA;
|
||||
else
|
||||
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;
|
||||
|
@ -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_SFP28:
|
||||
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;
|
||||
|
||||
case FW_PORT_TYPE_KR4_100G:
|
||||
|
@ -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,
|
||||
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;
|
||||
|
||||
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, 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);
|
||||
|
||||
if (pi->mdio_addr >= 0) {
|
||||
|
|
|
@ -2245,6 +2245,13 @@ static int cxgb_open(struct net_device *dev)
|
|||
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);
|
||||
if (!err)
|
||||
netif_tx_start_all_queues(dev);
|
||||
|
|
|
@ -7355,10 +7355,40 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
|
|||
lc->fc = fc;
|
||||
lc->supported = be16_to_cpu(p->u.info.pcap);
|
||||
lc->lp_advertising = be16_to_cpu(p->u.info.lpacap);
|
||||
|
||||
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
|
||||
* @adap: the adapter
|
||||
|
|
|
@ -2572,6 +2572,7 @@ enum fw_port_type {
|
|||
FW_PORT_TYPE_CR_QSFP,
|
||||
FW_PORT_TYPE_CR2_QSFP,
|
||||
FW_PORT_TYPE_SFP28,
|
||||
FW_PORT_TYPE_KR_SFP28,
|
||||
|
||||
FW_PORT_TYPE_NONE = FW_PORT_CMD_PTYPE_M
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue