Commit e6acd2b6 authored by David S. Miller's avatar David S. Miller

Merge branch 'qed-aer'

Sudarsana Reddy Kalluru says:

====================
qed*: Add support for pcie advanced error recovery.

The patch series adds qed/qede driver changes for PCIe Advanced Error
Recovery (AER) support.
Patch (1) adds qed changes to enable the device to send error messages
to root port when detected.
Patch (2) adds qede support for handling the detected errors (AERs).

Changes from previous version:
-------------------------------
v2: use pci_num_vf() instead of caching the value in edev.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e131a563 731815e7
...@@ -49,6 +49,7 @@ ...@@ -49,6 +49,7 @@
#include <linux/qed/qed_if.h> #include <linux/qed/qed_if.h>
#include <linux/qed/qed_ll2_if.h> #include <linux/qed/qed_ll2_if.h>
#include <net/devlink.h> #include <net/devlink.h>
#include <linux/aer.h>
#include "qed.h" #include "qed.h"
#include "qed_sriov.h" #include "qed_sriov.h"
...@@ -129,6 +130,8 @@ static void qed_free_pci(struct qed_dev *cdev) ...@@ -129,6 +130,8 @@ static void qed_free_pci(struct qed_dev *cdev)
{ {
struct pci_dev *pdev = cdev->pdev; struct pci_dev *pdev = cdev->pdev;
pci_disable_pcie_error_reporting(pdev);
if (cdev->doorbells && cdev->db_size) if (cdev->doorbells && cdev->db_size)
iounmap(cdev->doorbells); iounmap(cdev->doorbells);
if (cdev->regview) if (cdev->regview)
...@@ -231,6 +234,12 @@ static int qed_init_pci(struct qed_dev *cdev, struct pci_dev *pdev) ...@@ -231,6 +234,12 @@ static int qed_init_pci(struct qed_dev *cdev, struct pci_dev *pdev)
return -ENOMEM; return -ENOMEM;
} }
/* AER (Advanced Error reporting) configuration */
rc = pci_enable_pcie_error_reporting(pdev);
if (rc)
DP_VERBOSE(cdev, NETIF_MSG_DRV,
"Failed to configure PCIe AER [%d]\n", rc);
return 0; return 0;
err2: err2:
......
...@@ -485,6 +485,7 @@ struct qede_fastpath { ...@@ -485,6 +485,7 @@ struct qede_fastpath {
#define QEDE_SP_RECOVERY 0 #define QEDE_SP_RECOVERY 0
#define QEDE_SP_RX_MODE 1 #define QEDE_SP_RX_MODE 1
#define QEDE_SP_AER 7
#ifdef CONFIG_RFS_ACCEL #ifdef CONFIG_RFS_ACCEL
int qede_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, int qede_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
......
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
#include <net/ip6_checksum.h> #include <net/ip6_checksum.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/aer.h>
#include "qede.h" #include "qede.h"
#include "qede_ptp.h" #include "qede_ptp.h"
...@@ -124,6 +125,8 @@ static const struct pci_device_id qede_pci_tbl[] = { ...@@ -124,6 +125,8 @@ static const struct pci_device_id qede_pci_tbl[] = {
MODULE_DEVICE_TABLE(pci, 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 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) #define TX_TIMEOUT (5 * HZ)
...@@ -203,6 +206,10 @@ static int qede_sriov_configure(struct pci_dev *pdev, int num_vfs_param) ...@@ -203,6 +206,10 @@ static int qede_sriov_configure(struct pci_dev *pdev, int num_vfs_param)
} }
#endif #endif
static const struct pci_error_handlers qede_err_handler = {
.error_detected = qede_io_error_detected,
};
static struct pci_driver qede_pci_driver = { static struct pci_driver qede_pci_driver = {
.name = "qede", .name = "qede",
.id_table = qede_pci_tbl, .id_table = qede_pci_tbl,
...@@ -212,6 +219,7 @@ static struct pci_driver qede_pci_driver = { ...@@ -212,6 +219,7 @@ static struct pci_driver qede_pci_driver = {
#ifdef CONFIG_QED_SRIOV #ifdef CONFIG_QED_SRIOV
.sriov_configure = qede_sriov_configure, .sriov_configure = qede_sriov_configure,
#endif #endif
.err_handler = &qede_err_handler,
}; };
static struct qed_eth_cb_ops qede_ll_ops = { static struct qed_eth_cb_ops qede_ll_ops = {
...@@ -974,6 +982,7 @@ static void qede_sp_task(struct work_struct *work) ...@@ -974,6 +982,7 @@ static void qede_sp_task(struct work_struct *work)
/* SRIOV must be disabled outside the lock to avoid a deadlock. /* SRIOV must be disabled outside the lock to avoid a deadlock.
* The recovery of the active VFs is currently not supported. * The recovery of the active VFs is currently not supported.
*/ */
if (pci_num_vf(edev->pdev))
qede_sriov_configure(edev->pdev, 0); qede_sriov_configure(edev->pdev, 0);
#endif #endif
qede_lock(edev); qede_lock(edev);
...@@ -994,6 +1003,17 @@ static void qede_sp_task(struct work_struct *work) ...@@ -994,6 +1003,17 @@ static void qede_sp_task(struct work_struct *work)
} }
#endif #endif
__qede_unlock(edev); __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) 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) ...@@ -2579,3 +2599,49 @@ static void qede_get_eth_tlv_data(void *dev, void *data)
etlv->num_txqs_full_set = true; etlv->num_txqs_full_set = true;
etlv->num_rxqs_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;
}
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