Commit 731815e7 authored by Sudarsana Reddy Kalluru's avatar Sudarsana Reddy Kalluru Committed by David S. Miller
Browse files

qede: Add support for handling the pcie errors.



The error recovery is handled by management firmware (MFW) with the help of
qed/qede drivers. Upon detecting the errors, driver informs MFW about this
event which in turn starts a recovery process. MFW sends ERROR_RECOVERY
notification to the driver which performs the required cleanup/recovery
from the driver side.

Signed-off-by: default avatarSudarsana Reddy Kalluru <skalluru@marvell.com>
Acked-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2196d831
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -485,6 +485,7 @@ struct qede_fastpath {

#define QEDE_SP_RECOVERY		0
#define QEDE_SP_RX_MODE			1
#define QEDE_SP_AER			7

#ifdef CONFIG_RFS_ACCEL
int qede_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
+67 −1
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@
#include <net/ip6_checksum.h>
#include <linux/bitops.h>
#include <linux/vmalloc.h>
#include <linux/aer.h>
#include "qede.h"
#include "qede_ptp.h"

@@ -124,6 +125,8 @@ static const struct pci_device_id qede_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, qede_pci_tbl);

static int qede_probe(struct pci_dev *pdev, const struct pci_device_id *id);
static pci_ers_result_t
qede_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state);

#define TX_TIMEOUT		(5 * HZ)

@@ -203,6 +206,10 @@ static int qede_sriov_configure(struct pci_dev *pdev, int num_vfs_param)
}
#endif

static const struct pci_error_handlers qede_err_handler = {
	.error_detected = qede_io_error_detected,
};

static struct pci_driver qede_pci_driver = {
	.name = "qede",
	.id_table = qede_pci_tbl,
@@ -212,6 +219,7 @@ static struct pci_driver qede_pci_driver = {
#ifdef CONFIG_QED_SRIOV
	.sriov_configure = qede_sriov_configure,
#endif
	.err_handler = &qede_err_handler,
};

static struct qed_eth_cb_ops qede_ll_ops = {
@@ -974,6 +982,7 @@ static void qede_sp_task(struct work_struct *work)
		/* SRIOV must be disabled outside the lock to avoid a deadlock.
		 * The recovery of the active VFs is currently not supported.
		 */
		if (pci_num_vf(edev->pdev))
			qede_sriov_configure(edev->pdev, 0);
#endif
		qede_lock(edev);
@@ -994,6 +1003,17 @@ static void qede_sp_task(struct work_struct *work)
	}
#endif
	__qede_unlock(edev);

	if (test_and_clear_bit(QEDE_SP_AER, &edev->sp_flags)) {
#ifdef CONFIG_QED_SRIOV
		/* SRIOV must be disabled outside the lock to avoid a deadlock.
		 * The recovery of the active VFs is currently not supported.
		 */
		if (pci_num_vf(edev->pdev))
			qede_sriov_configure(edev->pdev, 0);
#endif
		edev->ops->common->recovery_process(edev->cdev);
	}
}

static void qede_update_pf_params(struct qed_dev *cdev)
@@ -2579,3 +2599,49 @@ static void qede_get_eth_tlv_data(void *dev, void *data)
	etlv->num_txqs_full_set = true;
	etlv->num_rxqs_full_set = true;
}

/**
 * qede_io_error_detected - called when PCI error is detected
 * @pdev: Pointer to PCI device
 * @state: The current pci connection state
 *
 * This function is called after a PCI bus error affecting
 * this device has been detected.
 */
static pci_ers_result_t
qede_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{
	struct net_device *dev = pci_get_drvdata(pdev);
	struct qede_dev *edev = netdev_priv(dev);

	if (!edev)
		return PCI_ERS_RESULT_NONE;

	DP_NOTICE(edev, "IO error detected [%d]\n", state);

	__qede_lock(edev);
	if (edev->state == QEDE_STATE_RECOVERY) {
		DP_NOTICE(edev, "Device already in the recovery state\n");
		__qede_unlock(edev);
		return PCI_ERS_RESULT_NONE;
	}

	/* PF handles the recovery of its VFs */
	if (IS_VF(edev)) {
		DP_VERBOSE(edev, QED_MSG_IOV,
			   "VF recovery is handled by its PF\n");
		__qede_unlock(edev);
		return PCI_ERS_RESULT_RECOVERED;
	}

	/* Close OS Tx */
	netif_tx_disable(edev->ndev);
	netif_carrier_off(edev->ndev);

	set_bit(QEDE_SP_AER, &edev->sp_flags);
	schedule_delayed_work(&edev->sp_task, 0);

	__qede_unlock(edev);

	return PCI_ERS_RESULT_CAN_RECOVER;
}