Commit 3be0679b authored by Hariprasad Shenai's avatar Hariprasad Shenai Committed by David S. Miller

cxgb4: Shutdown adapter if firmware times out or errors out

Perform an emergency shutdown of the adapter and stop it from
continuing any further communication on the ports or DMA to the
host. This is typically used when the adapter and/or firmware
have crashed and we want to prevent any further accidental
communication with the rest of the world. This will also force
the port Link Status to go down -- if register writes work --
which should help our peers figure out that we're down.
Signed-off-by: default avatarHariprasad Shenai <hariprasad@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 51c89e6a
...@@ -1501,6 +1501,7 @@ int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info, ...@@ -1501,6 +1501,7 @@ int t4_prep_fw(struct adapter *adap, struct fw_info *fw_info,
const u8 *fw_data, unsigned int fw_size, const u8 *fw_data, unsigned int fw_size,
struct fw_hdr *card_fw, enum dev_state state, int *reset); struct fw_hdr *card_fw, enum dev_state state, int *reset);
int t4_prep_adapter(struct adapter *adapter); int t4_prep_adapter(struct adapter *adapter);
int t4_shutdown_adapter(struct adapter *adapter);
enum t4_bar2_qtype { T4_BAR2_QTYPE_EGRESS, T4_BAR2_QTYPE_INGRESS }; enum t4_bar2_qtype { T4_BAR2_QTYPE_EGRESS, T4_BAR2_QTYPE_INGRESS };
int t4_bar2_sge_qregs(struct adapter *adapter, int t4_bar2_sge_qregs(struct adapter *adapter,
......
...@@ -2782,8 +2782,24 @@ static const struct ethtool_ops cxgb4_mgmt_ethtool_ops = { ...@@ -2782,8 +2782,24 @@ static const struct ethtool_ops cxgb4_mgmt_ethtool_ops = {
void t4_fatal_err(struct adapter *adap) void t4_fatal_err(struct adapter *adap)
{ {
t4_set_reg_field(adap, SGE_CONTROL_A, GLOBALENABLE_F, 0); int port;
t4_intr_disable(adap);
/* Disable the SGE since ULDs are going to free resources that
* could be exposed to the adapter. RDMA MWs for example...
*/
t4_shutdown_adapter(adap);
for_each_port(adap, port) {
struct net_device *dev = adap->port[port];
/* If we get here in very early initialization the network
* devices may not have been set up yet.
*/
if (!dev)
continue;
netif_tx_stop_all_queues(dev);
netif_carrier_off(dev);
}
dev_alert(adap->pdev_dev, "encountered fatal error, adapter stopped\n"); dev_alert(adap->pdev_dev, "encountered fatal error, adapter stopped\n");
} }
......
...@@ -330,11 +330,12 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd, ...@@ -330,11 +330,12 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd,
* mailbox access list but this is a start. We very rearely * mailbox access list but this is a start. We very rearely
* contend on access to the mailbox ... * contend on access to the mailbox ...
*/ */
if (i > FW_CMD_MAX_TIMEOUT) { pcie_fw = t4_read_reg(adap, PCIE_FW_A);
if (i > FW_CMD_MAX_TIMEOUT || (pcie_fw & PCIE_FW_ERR_F)) {
spin_lock(&adap->mbox_lock); spin_lock(&adap->mbox_lock);
list_del(&entry.list); list_del(&entry.list);
spin_unlock(&adap->mbox_lock); spin_unlock(&adap->mbox_lock);
ret = -EBUSY; ret = (pcie_fw & PCIE_FW_ERR_F) ? -ENXIO : -EBUSY;
t4_record_mbox(adap, cmd, size, access, ret); t4_record_mbox(adap, cmd, size, access, ret);
return ret; return ret;
} }
...@@ -432,6 +433,7 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd, ...@@ -432,6 +433,7 @@ int t4_wr_mbox_meat_timeout(struct adapter *adap, int mbox, const void *cmd,
spin_lock(&adap->mbox_lock); spin_lock(&adap->mbox_lock);
list_del(&entry.list); list_del(&entry.list);
spin_unlock(&adap->mbox_lock); spin_unlock(&adap->mbox_lock);
t4_fatal_err(adap);
return ret; return ret;
} }
...@@ -7557,6 +7559,39 @@ int t4_prep_adapter(struct adapter *adapter) ...@@ -7557,6 +7559,39 @@ int t4_prep_adapter(struct adapter *adapter)
return 0; return 0;
} }
/**
* t4_shutdown_adapter - shut down adapter, host & wire
* @adapter: the adapter
*
* Perform an emergency shutdown of the adapter and stop it from
* continuing any further communication on the ports or DMA to the
* host. This is typically used when the adapter and/or firmware
* have crashed and we want to prevent any further accidental
* communication with the rest of the world. This will also force
* the port Link Status to go down -- if register writes work --
* which should help our peers figure out that we're down.
*/
int t4_shutdown_adapter(struct adapter *adapter)
{
int port;
t4_intr_disable(adapter);
t4_write_reg(adapter, DBG_GPIO_EN_A, 0);
for_each_port(adapter, port) {
u32 a_port_cfg = PORT_REG(port,
is_t4(adapter->params.chip)
? XGMAC_PORT_CFG_A
: MAC_PORT_CFG_A);
t4_write_reg(adapter, a_port_cfg,
t4_read_reg(adapter, a_port_cfg)
& ~SIGNAL_DET_V(1));
}
t4_set_reg_field(adapter, SGE_CONTROL_A, GLOBALENABLE_F, 0);
return 0;
}
/** /**
* t4_bar2_sge_qregs - return BAR2 SGE Queue register information * t4_bar2_sge_qregs - return BAR2 SGE Queue register information
* @adapter: the adapter * @adapter: the adapter
......
...@@ -855,6 +855,14 @@ ...@@ -855,6 +855,14 @@
#define PERR_INT_CAUSE_V(x) ((x) << PERR_INT_CAUSE_S) #define PERR_INT_CAUSE_V(x) ((x) << PERR_INT_CAUSE_S)
#define PERR_INT_CAUSE_F PERR_INT_CAUSE_V(1U) #define PERR_INT_CAUSE_F PERR_INT_CAUSE_V(1U)
#define DBG_GPIO_EN_A 0x6010
#define XGMAC_PORT_CFG_A 0x1000
#define MAC_PORT_CFG_A 0x800
#define SIGNAL_DET_S 14
#define SIGNAL_DET_V(x) ((x) << SIGNAL_DET_S)
#define SIGNAL_DET_F SIGNAL_DET_V(1U)
#define MC_ECC_STATUS_A 0x751c #define MC_ECC_STATUS_A 0x751c
#define MC_P_ECC_STATUS_A 0x4131c #define MC_P_ECC_STATUS_A 0x4131c
......
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