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

Commit d8110f62 authored by Padmanabh Ratnakar's avatar Padmanabh Ratnakar Committed by David S. Miller
Browse files

be2net: Add error handling for Lancer



Detect error in Lancer by polling a HW register and
recover from this error if it is recoverable.

Signed-off-by: default avatarPadmanabh Ratnakar <padmanabh.ratnakar@emulex.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3bb62f4f
Loading
Loading
Loading
Loading
+106 −49
Original line number Diff line number Diff line
@@ -2044,52 +2044,6 @@ void be_detect_dump_ue(struct be_adapter *adapter)
	}
}

static void be_worker(struct work_struct *work)
{
	struct be_adapter *adapter =
		container_of(work, struct be_adapter, work.work);
	struct be_rx_obj *rxo;
	int i;

	be_detect_dump_ue(adapter);

	/* when interrupts are not yet enabled, just reap any pending
	* mcc completions */
	if (!netif_running(adapter->netdev)) {
		int mcc_compl, status = 0;

		mcc_compl = be_process_mcc(adapter, &status);

		if (mcc_compl) {
			struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
			be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl);
		}

		goto reschedule;
	}

	if (!adapter->stats_cmd_sent) {
		if (lancer_chip(adapter))
			lancer_cmd_get_pport_stats(adapter,
						&adapter->stats_cmd);
		else
			be_cmd_get_stats(adapter, &adapter->stats_cmd);
	}

	for_all_rx_queues(adapter, rxo, i) {
		be_rx_eqd_update(adapter, rxo);

		if (rxo->rx_post_starved) {
			rxo->rx_post_starved = false;
			be_post_rx_frags(rxo, GFP_KERNEL);
		}
	}

reschedule:
	adapter->work_counter++;
	schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
}

static void be_msix_disable(struct be_adapter *adapter)
{
	if (msix_enabled(adapter)) {
@@ -3328,7 +3282,7 @@ static int be_dev_family_check(struct be_adapter *adapter)

static int lancer_wait_ready(struct be_adapter *adapter)
{
#define SLIPORT_READY_TIMEOUT 500
#define SLIPORT_READY_TIMEOUT 30
	u32 sliport_status;
	int status = 0, i;

@@ -3337,7 +3291,7 @@ static int lancer_wait_ready(struct be_adapter *adapter)
		if (sliport_status & SLIPORT_STATUS_RDY_MASK)
			break;

		msleep(20);
		msleep(1000);
	}

	if (i == SLIPORT_READY_TIMEOUT)
@@ -3374,6 +3328,104 @@ static int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
	return status;
}

static void lancer_test_and_recover_fn_err(struct be_adapter *adapter)
{
	int status;
	u32 sliport_status;

	if (adapter->eeh_err || adapter->ue_detected)
		return;

	sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);

	if (sliport_status & SLIPORT_STATUS_ERR_MASK) {
		dev_err(&adapter->pdev->dev,
				"Adapter in error state."
				"Trying to recover.\n");

		status = lancer_test_and_set_rdy_state(adapter);
		if (status)
			goto err;

		netif_device_detach(adapter->netdev);

		if (netif_running(adapter->netdev))
			be_close(adapter->netdev);

		be_clear(adapter);

		adapter->fw_timeout = false;

		status = be_setup(adapter);
		if (status)
			goto err;

		if (netif_running(adapter->netdev)) {
			status = be_open(adapter->netdev);
			if (status)
				goto err;
		}

		netif_device_attach(adapter->netdev);

		dev_err(&adapter->pdev->dev,
				"Adapter error recovery succeeded\n");
	}
	return;
err:
	dev_err(&adapter->pdev->dev,
			"Adapter error recovery failed\n");
}

static void be_worker(struct work_struct *work)
{
	struct be_adapter *adapter =
		container_of(work, struct be_adapter, work.work);
	struct be_rx_obj *rxo;
	int i;

	if (lancer_chip(adapter))
		lancer_test_and_recover_fn_err(adapter);

	be_detect_dump_ue(adapter);

	/* when interrupts are not yet enabled, just reap any pending
	* mcc completions */
	if (!netif_running(adapter->netdev)) {
		int mcc_compl, status = 0;

		mcc_compl = be_process_mcc(adapter, &status);

		if (mcc_compl) {
			struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
			be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl);
		}

		goto reschedule;
	}

	if (!adapter->stats_cmd_sent) {
		if (lancer_chip(adapter))
			lancer_cmd_get_pport_stats(adapter,
						&adapter->stats_cmd);
		else
			be_cmd_get_stats(adapter, &adapter->stats_cmd);
	}

	for_all_rx_queues(adapter, rxo, i) {
		be_rx_eqd_update(adapter, rxo);

		if (rxo->rx_post_starved) {
			rxo->rx_post_starved = false;
			be_post_rx_frags(rxo, GFP_KERNEL);
		}
	}

reschedule:
	adapter->work_counter++;
	schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
}

static int __devinit be_probe(struct pci_dev *pdev,
			const struct pci_device_id *pdev_id)
{
@@ -3426,7 +3478,12 @@ static int __devinit be_probe(struct pci_dev *pdev,
		goto disable_sriov;

	if (lancer_chip(adapter)) {
		status = lancer_wait_ready(adapter);
		if (!status) {
			iowrite32(SLI_PORT_CONTROL_IP_MASK,
					adapter->db + SLIPORT_CONTROL_OFFSET);
			status = lancer_test_and_set_rdy_state(adapter);
		}
		if (status) {
			dev_err(&pdev->dev, "Adapter in non recoverable error\n");
			goto ctrl_clean;