cxgb4: do L1 config when module is inserted

trigger an L1 configure operation when a transceiver module
is inserted in order to cause current "sticky" options like
Requested Forward Error Correction to be reapplied.

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:
Ganesh Goudar 2018-05-23 20:03:33 +05:30 committed by David S. Miller
parent 1d19023fa6
commit 8156b0ba74
3 changed files with 65 additions and 12 deletions

View File

@ -491,6 +491,9 @@ struct link_config {
unsigned char link_ok; /* link up? */
unsigned char link_down_rc; /* link down reason */
bool new_module; /* ->OS Transceiver Module inserted */
bool redo_l1cfg; /* ->CC redo current "sticky" L1 CFG */
};
#define FW_LEN16(fw_struct) FW_CMD_LEN16_V(sizeof(fw_struct) / 16)
@ -1324,7 +1327,7 @@ static inline unsigned int qtimer_val(const struct adapter *adap,
extern char cxgb4_driver_name[];
extern const char cxgb4_driver_version[];
void t4_os_portmod_changed(const struct adapter *adap, int port_id);
void t4_os_portmod_changed(struct adapter *adap, int port_id);
void t4_os_link_changed(struct adapter *adap, int port_id, int link_stat);
void t4_free_sge_resources(struct adapter *adap);
@ -1505,8 +1508,25 @@ void t4_intr_disable(struct adapter *adapter);
int t4_slow_intr_handler(struct adapter *adapter);
int t4_wait_dev_ready(void __iomem *regs);
int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
struct link_config *lc);
int t4_link_l1cfg_core(struct adapter *adap, unsigned int mbox,
unsigned int port, struct link_config *lc,
bool sleep_ok, int timeout);
static inline int t4_link_l1cfg(struct adapter *adapter, unsigned int mbox,
unsigned int port, struct link_config *lc)
{
return t4_link_l1cfg_core(adapter, mbox, port, lc,
true, FW_CMD_MAX_TIMEOUT);
}
static inline int t4_link_l1cfg_ns(struct adapter *adapter, unsigned int mbox,
unsigned int port, struct link_config *lc)
{
return t4_link_l1cfg_core(adapter, mbox, port, lc,
false, FW_CMD_MAX_TIMEOUT);
}
int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port);
u32 t4_read_pcie_cfg4(struct adapter *adap, int reg);

View File

@ -301,14 +301,14 @@ void t4_os_link_changed(struct adapter *adapter, int port_id, int link_stat)
}
}
void t4_os_portmod_changed(const struct adapter *adap, int port_id)
void t4_os_portmod_changed(struct adapter *adap, int port_id)
{
static const char *mod_str[] = {
NULL, "LR", "SR", "ER", "passive DA", "active DA", "LRM"
};
const struct net_device *dev = adap->port[port_id];
const struct port_info *pi = netdev_priv(dev);
struct net_device *dev = adap->port[port_id];
struct port_info *pi = netdev_priv(dev);
if (pi->mod_type == FW_PORT_MOD_TYPE_NONE)
netdev_info(dev, "port module unplugged\n");
@ -325,6 +325,11 @@ void t4_os_portmod_changed(const struct adapter *adap, int port_id)
else
netdev_info(dev, "%s: unknown module type %d inserted\n",
dev->name, pi->mod_type);
/* If the interface is running, then we'll need any "sticky" Link
* Parameters redone with a new Transceiver Module.
*/
pi->link_cfg.redo_l1cfg = netif_running(dev);
}
int dbfifo_int_thresh = 10; /* 10 == 640 entry threshold */

View File

@ -4058,14 +4058,16 @@ 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 *adapter, unsigned int mbox,
unsigned int port, struct link_config *lc)
int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
unsigned int port, struct link_config *lc,
bool sleep_ok, int timeout)
{
unsigned int fw_caps = adapter->params.fw_caps_support;
struct fw_port_cmd cmd;
unsigned int fw_mdi = FW_PORT_CAP32_MDI_V(FW_PORT_CAP32_MDI_AUTO);
fw_port_cap32_t fw_fc, cc_fec, fw_fec, rcap;
struct fw_port_cmd cmd;
unsigned int fw_mdi;
fw_mdi = (FW_PORT_CAP32_MDI_V(FW_PORT_CAP32_MDI_AUTO) & lc->pcaps);
/* Convert driver coding of Pause Frame Flow Control settings into the
* Firmware's API.
*/
@ -4087,7 +4089,7 @@ int t4_link_l1cfg(struct adapter *adapter, unsigned int mbox,
/* 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;
rcap = lc->acaps | fw_fc | fw_fec;
lc->fc = lc->requested_fc & ~PAUSE_AUTONEG;
lc->fec = cc_fec;
} else if (lc->autoneg == AUTONEG_DISABLE) {
@ -4113,7 +4115,8 @@ int t4_link_l1cfg(struct adapter *adapter, unsigned int mbox,
cmd.u.l1cfg.rcap = cpu_to_be32(fwcaps32_to_caps16(rcap));
else
cmd.u.l1cfg32.rcap32 = cpu_to_be32(rcap);
return t4_wr_mbox(adapter, mbox, &cmd, sizeof(cmd), NULL);
return t4_wr_mbox_meat_timeout(adapter, mbox, &cmd, sizeof(cmd), NULL,
sleep_ok, timeout);
}
/**
@ -8335,6 +8338,9 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
fc = fwcap_to_cc_pause(linkattr);
speed = fwcap_to_speed(linkattr);
lc->new_module = false;
lc->redo_l1cfg = false;
if (mod_type != pi->mod_type) {
/* With the newer SFP28 and QSFP28 Transceiver Module Types,
* various fundamental Port Capabilities which used to be
@ -8369,6 +8375,8 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
pi->port_type = port_type;
pi->mod_type = mod_type;
lc->new_module = t4_is_inserted_mod_type(mod_type);
t4_os_portmod_changed(adapter, pi->port_id);
}
@ -8401,6 +8409,26 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
t4_os_link_changed(adapter, pi->port_id, link_ok);
}
if (lc->new_module && lc->redo_l1cfg) {
struct link_config old_lc;
int ret;
/* Save the current L1 Configuration and restore it if an
* error occurs. We probably should fix the l1_cfg*()
* routines not to change the link_config when an error
* occurs ...
*/
old_lc = *lc;
ret = t4_link_l1cfg_ns(adapter, adapter->mbox, pi->lport, lc);
if (ret) {
*lc = old_lc;
dev_warn(adapter->pdev_dev,
"Attempt to update new Transceiver Module settings failed\n");
}
}
lc->new_module = false;
lc->redo_l1cfg = false;
}
/**