Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -961,6 +961,7 @@ struct qlcnic_ipaddr {
#define __QLCNIC_SRIOV_CAPABLE		11
#define __QLCNIC_MBX_POLL_ENABLE	12
#define __QLCNIC_DIAG_MODE		13
#define __QLCNIC_MAINTENANCE_MODE	16

#define QLCNIC_INTERRUPT_TEST		1
#define QLCNIC_LOOPBACK_TEST		2
+24 −8
Original line number Diff line number Diff line
@@ -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)
{
	if (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;

	msleep(20);

	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)
{
@@ -760,6 +764,9 @@ int qlcnic_83xx_issue_cmd(struct qlcnic_adapter *adapter,
	int cmd_type, err, opcode;
	unsigned long timeout;

	if (!mbx)
		return -EIO;

	opcode = LSW(cmd->req.arg[0]);
	cmd_type = cmd->type;
	err = mbx->ops->enqueue_cmd(adapter, cmd, &timeout);
@@ -3049,11 +3056,14 @@ int qlcnic_83xx_get_settings(struct qlcnic_adapter *adapter,
	int status = 0;
	struct qlcnic_hardware_context *ahw = adapter->ahw;

	if (!test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state)) {
		/* Get port configuration info */
		status = qlcnic_83xx_get_port_info(adapter);
		/* Get Link Status related info */
		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 */
	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)
{
	if (!mbx)
		return;

	destroy_workqueue(mbx->work_q);
	kfree(mbx);
}
@@ -3650,6 +3663,9 @@ void qlcnic_83xx_detach_mailbox_work(struct qlcnic_adapter *adapter)
{
	struct qlcnic_mailbox *mbx = adapter->ahw->mailbox;

	if (!mbx)
		return;

	clear_bit(QLC_83XX_MBX_READY, &mbx->status);
	complete(&mbx->completion);
	cancel_work_sync(&mbx->work);
+9 −7
Original line number Diff line number Diff line
@@ -2190,20 +2190,24 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter, int pci_using_dac)
			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);
	if (err)
		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);
	if (err)
		goto detach_mbx;

	err = qlcnic_83xx_idc_init(adapter);
	if (err)
		goto clear_fw_info;
		goto detach_mbx;

	err = qlcnic_setup_intr(adapter, 0, 0);
	if (err) {
@@ -2247,12 +2251,10 @@ disable_mbx_intr:
disable_intr:
	qlcnic_teardown_intr(adapter);

clear_fw_info:
	kfree(ahw->fw_info);

detach_mbx:
	qlcnic_83xx_detach_mailbox_work(adapter);
	qlcnic_83xx_free_mailbox(ahw->mailbox);
	ahw->mailbox = NULL;
exit:
	return err;
}
+2 −4
Original line number Diff line number Diff line
@@ -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;
	bool valid_mask = false;
	int i, ret = 0;
	u32 state;

	switch (val->flag) {
	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_RESET_QUIESCENT:
		state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
		if (state == QLCNIC_DEV_FAILED || (state == QLCNIC_DEV_BADBAD))
			netdev_info(netdev, "Device in FAILED state\n");
		if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state))
			netdev_info(netdev, "Device is in non-operational state\n");
		break;

	default:
+29 −8
Original line number Diff line number Diff line
@@ -2307,10 +2307,23 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
		qlcnic_83xx_check_vf(adapter, ent);
		adapter->portnum = adapter->ahw->pci_func;
		err = qlcnic_83xx_init(adapter, pci_using_dac);

		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;
			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))
			return 0;
	} else {
@@ -2412,8 +2425,16 @@ err_out_disable_pdev:
	return err;

err_out_maintenance_mode:
	set_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state);
	netdev->netdev_ops = &qlcnic_netdev_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);

	if (err) {
@@ -2535,12 +2556,11 @@ static int qlcnic_resume(struct pci_dev *pdev)
static int qlcnic_open(struct net_device *netdev)
{
	struct qlcnic_adapter *adapter = netdev_priv(netdev);
	u32 state;
	int err;

	state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE);
	if (state == QLCNIC_DEV_FAILED || state == QLCNIC_DEV_BADBAD) {
		netdev_err(netdev, "%s: Device is in FAILED state\n", __func__);
	if (test_bit(__QLCNIC_MAINTENANCE_MODE, &adapter->state)) {
		netdev_err(netdev, "%s: Device is in non-operational state\n",
			   __func__);

		return -EIO;
	}
@@ -3253,8 +3273,9 @@ void qlcnic_82xx_dev_request_reset(struct qlcnic_adapter *adapter, u32 key)
		return;

	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__);
		qlcnic_api_unlock(adapter);

Loading