Commit 8156b0ba authored by Ganesh Goudar's avatar Ganesh Goudar Committed by David S. Miller

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: 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 1d19023f
...@@ -491,6 +491,9 @@ struct link_config { ...@@ -491,6 +491,9 @@ struct link_config {
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 */
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) #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, ...@@ -1324,7 +1327,7 @@ static inline unsigned int qtimer_val(const struct adapter *adap,
extern char cxgb4_driver_name[]; extern char cxgb4_driver_name[];
extern const char cxgb4_driver_version[]; 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_os_link_changed(struct adapter *adap, int port_id, int link_stat);
void t4_free_sge_resources(struct adapter *adap); void t4_free_sge_resources(struct adapter *adap);
...@@ -1505,8 +1508,25 @@ void t4_intr_disable(struct adapter *adapter); ...@@ -1505,8 +1508,25 @@ void t4_intr_disable(struct adapter *adapter);
int t4_slow_intr_handler(struct adapter *adapter); int t4_slow_intr_handler(struct adapter *adapter);
int t4_wait_dev_ready(void __iomem *regs); 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); int t4_restart_aneg(struct adapter *adap, unsigned int mbox, unsigned int port);
u32 t4_read_pcie_cfg4(struct adapter *adap, int reg); u32 t4_read_pcie_cfg4(struct adapter *adap, int reg);
......
...@@ -301,14 +301,14 @@ void t4_os_link_changed(struct adapter *adapter, int port_id, int link_stat) ...@@ -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[] = { static const char *mod_str[] = {
NULL, "LR", "SR", "ER", "passive DA", "active DA", "LRM" NULL, "LR", "SR", "ER", "passive DA", "active DA", "LRM"
}; };
const struct net_device *dev = adap->port[port_id]; struct net_device *dev = adap->port[port_id];
const struct port_info *pi = netdev_priv(dev); struct port_info *pi = netdev_priv(dev);
if (pi->mod_type == FW_PORT_MOD_TYPE_NONE) if (pi->mod_type == FW_PORT_MOD_TYPE_NONE)
netdev_info(dev, "port module unplugged\n"); netdev_info(dev, "port module unplugged\n");
...@@ -325,6 +325,11 @@ void t4_os_portmod_changed(const struct adapter *adap, int port_id) ...@@ -325,6 +325,11 @@ void t4_os_portmod_changed(const struct adapter *adap, int port_id)
else else
netdev_info(dev, "%s: unknown module type %d inserted\n", netdev_info(dev, "%s: unknown module type %d inserted\n",
dev->name, pi->mod_type); 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 */ int dbfifo_int_thresh = 10; /* 10 == 640 entry threshold */
......
...@@ -4058,14 +4058,16 @@ static inline fw_port_cap32_t cc_to_fwcap_fec(enum cc_fec cc_fec) ...@@ -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, * - 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. * otherwise do it later based on the outcome of auto-negotiation.
*/ */
int t4_link_l1cfg(struct adapter *adapter, unsigned int mbox, int t4_link_l1cfg_core(struct adapter *adapter, unsigned int mbox,
unsigned int port, struct link_config *lc) unsigned int port, struct link_config *lc,
bool sleep_ok, int timeout)
{ {
unsigned int fw_caps = adapter->params.fw_caps_support; 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; 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 /* Convert driver coding of Pause Frame Flow Control settings into the
* Firmware's API. * Firmware's API.
*/ */
...@@ -4087,7 +4089,7 @@ int t4_link_l1cfg(struct adapter *adapter, unsigned int mbox, ...@@ -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. /* Figure out what our Requested Port Capabilities are going to be.
*/ */
if (!(lc->pcaps & FW_PORT_CAP32_ANEG)) { 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->fc = lc->requested_fc & ~PAUSE_AUTONEG;
lc->fec = cc_fec; lc->fec = cc_fec;
} else if (lc->autoneg == AUTONEG_DISABLE) { } else if (lc->autoneg == AUTONEG_DISABLE) {
...@@ -4113,7 +4115,8 @@ int t4_link_l1cfg(struct adapter *adapter, unsigned int mbox, ...@@ -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)); cmd.u.l1cfg.rcap = cpu_to_be32(fwcaps32_to_caps16(rcap));
else else
cmd.u.l1cfg32.rcap32 = cpu_to_be32(rcap); 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) ...@@ -8335,6 +8338,9 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
fc = fwcap_to_cc_pause(linkattr); fc = fwcap_to_cc_pause(linkattr);
speed = fwcap_to_speed(linkattr); speed = fwcap_to_speed(linkattr);
lc->new_module = false;
lc->redo_l1cfg = false;
if (mod_type != pi->mod_type) { if (mod_type != pi->mod_type) {
/* With the newer SFP28 and QSFP28 Transceiver Module Types, /* With the newer SFP28 and QSFP28 Transceiver Module Types,
* various fundamental Port Capabilities which used to be * 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) ...@@ -8369,6 +8375,8 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
pi->port_type = port_type; pi->port_type = port_type;
pi->mod_type = mod_type; pi->mod_type = mod_type;
lc->new_module = t4_is_inserted_mod_type(mod_type);
t4_os_portmod_changed(adapter, pi->port_id); 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) ...@@ -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); 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;
} }
/** /**
......
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