qlcnic: Register netdev in FAILED state for 83xx/84xx
o Without failing probe, register netdev when device is in FAILED state. o Device will come up with minimum functionality and allow diagnostics and repair of the adapter. Signed-off-by: Sucheta Chakraborty <sucheta.chakraborty@qlogic.com> Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
165148396d
commit
78ea2d977a
6 changed files with 67 additions and 33 deletions
|
@ -961,6 +961,7 @@ struct qlcnic_ipaddr {
|
||||||
#define __QLCNIC_SRIOV_CAPABLE 11
|
#define __QLCNIC_SRIOV_CAPABLE 11
|
||||||
#define __QLCNIC_MBX_POLL_ENABLE 12
|
#define __QLCNIC_MBX_POLL_ENABLE 12
|
||||||
#define __QLCNIC_DIAG_MODE 13
|
#define __QLCNIC_DIAG_MODE 13
|
||||||
|
#define __QLCNIC_MAINTENANCE_MODE 16
|
||||||
|
|
||||||
#define QLCNIC_INTERRUPT_TEST 1
|
#define QLCNIC_INTERRUPT_TEST 1
|
||||||
#define QLCNIC_LOOPBACK_TEST 2
|
#define QLCNIC_LOOPBACK_TEST 2
|
||||||
|
|
|
@ -325,6 +325,7 @@ inline void qlcnic_83xx_clear_legacy_intr_mask(struct qlcnic_adapter *adapter)
|
||||||
|
|
||||||
inline void qlcnic_83xx_set_legacy_intr_mask(struct qlcnic_adapter *adapter)
|
inline void qlcnic_83xx_set_legacy_intr_mask(struct qlcnic_adapter *adapter)
|
||||||
{
|
{
|
||||||
|
if (adapter->tgt_mask_reg)
|
||||||
writel(1, adapter->tgt_mask_reg);
|
writel(1, adapter->tgt_mask_reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -498,9 +499,12 @@ void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter)
|
||||||
num_msix = 0;
|
num_msix = 0;
|
||||||
|
|
||||||
msleep(20);
|
msleep(20);
|
||||||
|
|
||||||
|
if (adapter->msix_entries) {
|
||||||
synchronize_irq(adapter->msix_entries[num_msix].vector);
|
synchronize_irq(adapter->msix_entries[num_msix].vector);
|
||||||
free_irq(adapter->msix_entries[num_msix].vector, adapter);
|
free_irq(adapter->msix_entries[num_msix].vector, adapter);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
|
int qlcnic_83xx_setup_mbx_intr(struct qlcnic_adapter *adapter)
|
||||||
{
|
{
|
||||||
|
@ -760,6 +764,9 @@ int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *adapter,
|
||||||
int cmd_type, err, opcode;
|
int cmd_type, err, opcode;
|
||||||
unsigned long timeout;
|
unsigned long timeout;
|
||||||
|
|
||||||
|
if (!mbx)
|
||||||
|
return -EIO;
|
||||||
|
|
||||||
opcode = LSW(cmd->req.arg[0]);
|
opcode = LSW(cmd->req.arg[0]);
|
||||||
cmd_type = cmd->type;
|
cmd_type = cmd->type;
|
||||||
err = mbx->ops->enqueue_cmd(adapter, cmd, &timeout);
|
err = mbx->ops->enqueue_cmd(adapter, cmd, &timeout);
|
||||||
|
@ -3049,11 +3056,14 @@ int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter,
|
||||||
int status = 0;
|
int status = 0;
|
||||||
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
struct qlcnic_hardware_context *ahw = adapter->ahw;
|
||||||
|
|
||||||
|
if (!test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state)) {
|
||||||
/* Get port configuration info */
|
/* Get port configuration info */
|
||||||
status = qlcnic_83xx_get_port_info(adapter);
|
status = qlcnic_83xx_get_port_info(adapter);
|
||||||
/* Get Link Status related info */
|
/* Get Link Status related info */
|
||||||
config = qlcnic_83xx_test_link(adapter);
|
config = qlcnic_83xx_test_link(adapter);
|
||||||
ahw->module_type = QLC_83XX_SFP_MODULE_TYPE(config);
|
ahw->module_type = QLC_83XX_SFP_MODULE_TYPE(config);
|
||||||
|
}
|
||||||
|
|
||||||
/* hard code until there is a way to get it from flash */
|
/* hard code until there is a way to get it from flash */
|
||||||
ahw->board_type = QLCNIC_BRDTYPE_83XX_10G;
|
ahw->board_type = QLCNIC_BRDTYPE_83XX_10G;
|
||||||
|
|
||||||
|
@ -3530,6 +3540,9 @@ void qlcnic_83xx_reinit_mbx_work(struct qlcnic_mailbox *mbx)
|
||||||
|
|
||||||
void qlcnic_83xx_free_mailbox(struct qlcnic_mailbox *mbx)
|
void qlcnic_83xx_free_mailbox(struct qlcnic_mailbox *mbx)
|
||||||
{
|
{
|
||||||
|
if (!mbx)
|
||||||
|
return;
|
||||||
|
|
||||||
destroy_workqueue(mbx->work_q);
|
destroy_workqueue(mbx->work_q);
|
||||||
kfree(mbx);
|
kfree(mbx);
|
||||||
}
|
}
|
||||||
|
@ -3650,6 +3663,9 @@ void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *adapter)
|
||||||
{
|
{
|
||||||
struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
|
struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;
|
||||||
|
|
||||||
|
if (!mbx)
|
||||||
|
return;
|
||||||
|
|
||||||
clear_bit(QLC_83XX_MBX_READY, &mbx->status);
|
clear_bit(QLC_83XX_MBX_READY, &mbx->status);
|
||||||
complete(&mbx->completion);
|
complete(&mbx->completion);
|
||||||
cancel_work_sync(&mbx->work);
|
cancel_work_sync(&mbx->work);
|
||||||
|
|
|
@ -2190,20 +2190,24 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (qlcnic_83xx_read_flash_descriptor_table(adapter) ||
|
||||||
|
qlcnic_83xx_read_flash_mfg_id(adapter)) {
|
||||||
|
dev_err(&adapter->pdev->dev, "Failed reading flash mfg id\n");
|
||||||
|
err = -ENOTRECOVERABLE;
|
||||||
|
goto detach_mbx;
|
||||||
|
}
|
||||||
|
|
||||||
err = qlcnic_83xx_check_hw_status(adapter);
|
err = qlcnic_83xx_check_hw_status(adapter);
|
||||||
if (err)
|
if (err)
|
||||||
goto detach_mbx;
|
goto detach_mbx;
|
||||||
|
|
||||||
if (!qlcnic_83xx_read_flash_descriptor_table(adapter))
|
|
||||||
qlcnic_83xx_read_flash_mfg_id(adapter);
|
|
||||||
|
|
||||||
err = qlcnic_83xx_get_fw_info(adapter);
|
err = qlcnic_83xx_get_fw_info(adapter);
|
||||||
if (err)
|
if (err)
|
||||||
goto detach_mbx;
|
goto detach_mbx;
|
||||||
|
|
||||||
err = qlcnic_83xx_idc_init(adapter);
|
err = qlcnic_83xx_idc_init(adapter);
|
||||||
if (err)
|
if (err)
|
||||||
goto clear_fw_info;
|
goto detach_mbx;
|
||||||
|
|
||||||
err = qlcnic_setup_intr(adapter, 0, 0);
|
err = qlcnic_setup_intr(adapter, 0, 0);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -2247,12 +2251,10 @@ disable_mbx_intr:
|
||||||
disable_intr:
|
disable_intr:
|
||||||
qlcnic_teardown_intr(adapter);
|
qlcnic_teardown_intr(adapter);
|
||||||
|
|
||||||
clear_fw_info:
|
|
||||||
kfree(ahw->fw_info);
|
|
||||||
|
|
||||||
detach_mbx:
|
detach_mbx:
|
||||||
qlcnic_83xx_detach_mailbox_work(adapter);
|
qlcnic_83xx_detach_mailbox_work(adapter);
|
||||||
qlcnic_83xx_free_mailbox(ahw->mailbox);
|
qlcnic_83xx_free_mailbox(ahw->mailbox);
|
||||||
|
ahw->mailbox = NULL;
|
||||||
exit:
|
exit:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1685,7 +1685,6 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
|
||||||
struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
|
struct qlcnic_fw_dump *fw_dump = &adapter->ahw->fw_dump;
|
||||||
bool valid_mask = false;
|
bool valid_mask = false;
|
||||||
int i, ret = 0;
|
int i, ret = 0;
|
||||||
u32 state;
|
|
||||||
|
|
||||||
switch (val->flag) {
|
switch (val->flag) {
|
||||||
case QLCNIC_FORCE_FW_DUMP_KEY:
|
case QLCNIC_FORCE_FW_DUMP_KEY:
|
||||||
|
@ -1738,9 +1737,8 @@ qlcnic_set_dump(struct net_device *netdev, struct ethtool_dump *val)
|
||||||
|
|
||||||
case QLCNIC_SET_QUIESCENT:
|
case QLCNIC_SET_QUIESCENT:
|
||||||
case QLCNIC_RESET_QUIESCENT:
|
case QLCNIC_RESET_QUIESCENT:
|
||||||
state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
|
if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state))
|
||||||
if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
|
netdev_info(netdev, "Device is in non-operational state\n");
|
||||||
netdev_info(netdev, "Device in FAILED state\n");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -2307,10 +2307,23 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
||||||
qlcnic_83xx_check_vf(adapter, ent);
|
qlcnic_83xx_check_vf(adapter, ent);
|
||||||
adapter->portnum = adapter->ahw->pci_func;
|
adapter->portnum = adapter->ahw->pci_func;
|
||||||
err = qlcnic_83xx_init(adapter, pci_using_dac);
|
err = qlcnic_83xx_init(adapter, pci_using_dac);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
dev_err(&pdev->dev, "%s: failed\n", __func__);
|
switch (err) {
|
||||||
|
case -ENOTRECOVERABLE:
|
||||||
|
dev_err(&pdev->dev, "Adapter initialization failed due to a faulty hardware. Please reboot\n");
|
||||||
|
dev_err(&pdev->dev, "If reboot doesn't help, please replace the adapter with new one and return the faulty adapter for repair\n");
|
||||||
goto err_out_free_hw;
|
goto err_out_free_hw;
|
||||||
|
case -ENOMEM:
|
||||||
|
dev_err(&pdev->dev, "Adapter initialization failed. Please reboot\n");
|
||||||
|
goto err_out_free_hw;
|
||||||
|
default:
|
||||||
|
dev_err(&pdev->dev, "Adapter initialization failed. A reboot may be required to recover from this failure\n");
|
||||||
|
dev_err(&pdev->dev, "If reboot does not help to recover from this failure, try a flash update of the adapter\n");
|
||||||
|
goto err_out_maintenance_mode;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (qlcnic_sriov_vf_check(adapter))
|
if (qlcnic_sriov_vf_check(adapter))
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2412,8 +2425,16 @@ err_out_disable_pdev:
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
err_out_maintenance_mode:
|
err_out_maintenance_mode:
|
||||||
|
set_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state);
|
||||||
netdev->netdev_ops = &qlcnic_netdev_failed_ops;
|
netdev->netdev_ops = &qlcnic_netdev_failed_ops;
|
||||||
SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_failed_ops);
|
SET_ETHTOOL_OPS(netdev, &qlcnic_ethtool_failed_ops);
|
||||||
|
ahw->port_type = QLCNIC_XGBE;
|
||||||
|
|
||||||
|
if (qlcnic_83xx_check(adapter))
|
||||||
|
adapter->tgt_status_reg = NULL;
|
||||||
|
else
|
||||||
|
ahw->board_type = QLCNIC_BRDTYPE_P3P_10G_SFP_PLUS;
|
||||||
|
|
||||||
err = register_netdev(netdev);
|
err = register_netdev(netdev);
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -2535,12 +2556,11 @@ static int qlcnic_resume(struct pci_dev *pdev)
|
||||||
static int qlcnic_open(struct net_device *netdev)
|
static int qlcnic_open(struct net_device *netdev)
|
||||||
{
|
{
|
||||||
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
struct qlcnic_adapter *adapter = netdev_priv(netdev);
|
||||||
u32 state;
|
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
|
if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state)) {
|
||||||
if (state == QLCNIC_DEV_FAILED || state == QLCNIC_DEV_BADBAD) {
|
netdev_err(netdev, "%s: Device is in non-operational state\n",
|
||||||
netdev_err(netdev, "%s: Device is in FAILED state\n", __func__);
|
__func__);
|
||||||
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
@ -3253,8 +3273,9 @@ void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *adapter, u32 key)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
|
state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
|
||||||
if (state == QLCNIC_DEV_FAILED || state == QLCNIC_DEV_BADBAD) {
|
|
||||||
netdev_err(adapter->netdev, "%s: Device is in FAILED state\n",
|
if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state)) {
|
||||||
|
netdev_err(adapter->netdev, "%s: Device is in non-operational state\n",
|
||||||
__func__);
|
__func__);
|
||||||
qlcnic_api_unlock(adapter);
|
qlcnic_api_unlock(adapter);
|
||||||
|
|
||||||
|
|
|
@ -1272,7 +1272,6 @@ void qlcnic_remove_sysfs_entries(struct qlcnic_adapter *adapter)
|
||||||
void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
|
void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
|
||||||
{
|
{
|
||||||
struct device *dev = &adapter->pdev->dev;
|
struct device *dev = &adapter->pdev->dev;
|
||||||
u32 state;
|
|
||||||
|
|
||||||
if (device_create_bin_file(dev, &bin_attr_port_stats))
|
if (device_create_bin_file(dev, &bin_attr_port_stats))
|
||||||
dev_info(dev, "failed to create port stats sysfs entry");
|
dev_info(dev, "failed to create port stats sysfs entry");
|
||||||
|
@ -1286,8 +1285,7 @@ void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
|
||||||
if (device_create_bin_file(dev, &bin_attr_mem))
|
if (device_create_bin_file(dev, &bin_attr_mem))
|
||||||
dev_info(dev, "failed to create mem sysfs entry\n");
|
dev_info(dev, "failed to create mem sysfs entry\n");
|
||||||
|
|
||||||
state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
|
if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state))
|
||||||
if (state == QLCNIC_DEV_FAILED || state == QLCNIC_DEV_BADBAD)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (device_create_bin_file(dev, &bin_attr_pci_config))
|
if (device_create_bin_file(dev, &bin_attr_pci_config))
|
||||||
|
@ -1313,7 +1311,6 @@ void qlcnic_create_diag_entries(struct qlcnic_adapter *adapter)
|
||||||
void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
|
void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
|
||||||
{
|
{
|
||||||
struct device *dev = &adapter->pdev->dev;
|
struct device *dev = &adapter->pdev->dev;
|
||||||
u32 state;
|
|
||||||
|
|
||||||
device_remove_bin_file(dev, &bin_attr_port_stats);
|
device_remove_bin_file(dev, &bin_attr_port_stats);
|
||||||
|
|
||||||
|
@ -1323,8 +1320,7 @@ void qlcnic_remove_diag_entries(struct qlcnic_adapter *adapter)
|
||||||
device_remove_bin_file(dev, &bin_attr_crb);
|
device_remove_bin_file(dev, &bin_attr_crb);
|
||||||
device_remove_bin_file(dev, &bin_attr_mem);
|
device_remove_bin_file(dev, &bin_attr_mem);
|
||||||
|
|
||||||
state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
|
if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state))
|
||||||
if (state == QLCNIC_DEV_FAILED || state == QLCNIC_DEV_BADBAD)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
device_remove_bin_file(dev, &bin_attr_pci_config);
|
device_remove_bin_file(dev, &bin_attr_pci_config);
|
||||||
|
|
Loading…
Add table
Reference in a new issue