Skip to content

Commit

Permalink
Merge branch 'qed-aer'
Browse files Browse the repository at this point in the history
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: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 23, 2020
2 parents e131a56 + 731815e commit e6acd2b
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 1 deletion.
9 changes: 9 additions & 0 deletions drivers/net/ethernet/qlogic/qed/qed_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include <linux/qed/qed_if.h>
#include <linux/qed/qed_ll2_if.h>
#include <net/devlink.h>
#include <linux/aer.h>

#include "qed.h"
#include "qed_sriov.h"
Expand Down Expand Up @@ -129,6 +130,8 @@ static void qed_free_pci(struct qed_dev *cdev)
{
struct pci_dev *pdev = cdev->pdev;

pci_disable_pcie_error_reporting(pdev);

if (cdev->doorbells && cdev->db_size)
iounmap(cdev->doorbells);
if (cdev->regview)
Expand Down Expand Up @@ -231,6 +234,12 @@ static int qed_init_pci(struct qed_dev *cdev, struct pci_dev *pdev)
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;

err2:
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/qlogic/qede/qede.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
68 changes: 67 additions & 1 deletion drivers/net/ethernet/qlogic/qede/qede_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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,
Expand All @@ -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 = {
Expand Down Expand Up @@ -974,7 +982,8 @@ 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.
*/
qede_sriov_configure(edev->pdev, 0);
if (pci_num_vf(edev->pdev))
qede_sriov_configure(edev->pdev, 0);
#endif
qede_lock(edev);
qede_recovery_handler(edev);
Expand All @@ -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)
Expand Down Expand Up @@ -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;
}

0 comments on commit e6acd2b

Please sign in to comment.