Commit 78ea2d97 authored by Sucheta Chakraborty's avatar Sucheta Chakraborty Committed by David S. Miller

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: default avatarSucheta Chakraborty <sucheta.chakraborty@qlogic.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@qlogic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 16514839
...@@ -961,6 +961,7 @@ struct qlcnic_ipaddr { ...@@ -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,7 +325,8 @@ inline void qlcnic_83xx_clear_legacy_intr_mask(struct qlcnic_adapter *adapter) ...@@ -325,7 +325,8 @@ 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)
{ {
writel(1, adapter->tgt_mask_reg); if (adapter->tgt_mask_reg)
writel(1, adapter->tgt_mask_reg);
} }
/* Enable MSI-x and INT-x interrupts */ /* Enable MSI-x and INT-x interrupts */
...@@ -498,8 +499,11 @@ void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter) ...@@ -498,8 +499,11 @@ void qlcnic_83xx_free_mbx_intr(struct qlcnic_adapter *adapter)
num_msix = 0; num_msix = 0;
msleep(20); msleep(20);
synchronize_irq(adapter->msix_entries[num_msix].vector);
free_irq(adapter->msix_entries[num_msix].vector, adapter); if (adapter->msix_entries) {
synchronize_irq(adapter->msix_entries[num_msix].vector);
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, ...@@ -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, ...@@ -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;
/* Get port configuration info */ if (!test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state)) {
status = qlcnic_83xx_get_port_info(adapter); /* Get port configuration info */
/* Get Link Status related info */ status = qlcnic_83xx_get_port_info(adapter);
config = qlcnic_83xx_test_link(adapter); /* Get Link Status related info */
ahw->module_type = QLC_83XX_SFP_MODULE_TYPE(config); config = qlcnic_83xx_test_link(adapter);
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) ...@@ -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) ...@@ -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) ...@@ -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 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac) ...@@ -2247,12 +2251,10 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
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) ...@@ -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) ...@@ -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) ...@@ -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) {
goto err_out_free_hw; 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;
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 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2412,8 +2425,16 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
......
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