Merge branch 'pds_core-AER-handling'

Shannon Nelson says:

====================
pds_core: AER handling

Add simple handlers for the PCI AER callbacks, and improve
the reset handling.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2024-02-19 10:29:08 +00:00
commit da4a154ca2
4 changed files with 62 additions and 9 deletions

View file

@ -184,6 +184,9 @@ int pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf)
struct pds_auxiliary_dev *padev;
int err = 0;
if (!cf)
return -ENODEV;
mutex_lock(&pf->config_lock);
padev = pf->vfs[cf->vf_id].padev;
@ -202,14 +205,27 @@ int pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf)
int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf)
{
struct pds_auxiliary_dev *padev;
enum pds_core_vif_types vt;
char devname[PDS_DEVNAME_LEN];
enum pds_core_vif_types vt;
unsigned long mask;
u16 vt_support;
int client_id;
int err = 0;
if (!cf)
return -ENODEV;
mutex_lock(&pf->config_lock);
mask = BIT_ULL(PDSC_S_FW_DEAD) |
BIT_ULL(PDSC_S_STOPPING_DRIVER);
if (cf->state & mask) {
dev_err(pf->dev, "%s: can't add dev, VF client in bad state %#lx\n",
__func__, cf->state);
err = -ENXIO;
goto out_unlock;
}
/* We only support vDPA so far, so it is the only one to
* be verified that it is available in the Core device and
* enabled in the devlink param. In the future this might

View file

@ -607,8 +607,7 @@ static void pdsc_check_pci_health(struct pdsc *pdsc)
if (fw_status != PDS_RC_BAD_PCI)
return;
pdsc_reset_prepare(pdsc->pdev);
pdsc_reset_done(pdsc->pdev);
pci_reset_function(pdsc->pdev);
}
void pdsc_health_thread(struct work_struct *work)

View file

@ -284,9 +284,6 @@ int pdsc_devcmd_reset(struct pdsc *pdsc);
int pdsc_dev_init(struct pdsc *pdsc);
void pdsc_dev_uninit(struct pdsc *pdsc);
void pdsc_reset_prepare(struct pci_dev *pdev);
void pdsc_reset_done(struct pci_dev *pdev);
int pdsc_intr_alloc(struct pdsc *pdsc, char *name,
irq_handler_t handler, void *data);
void pdsc_intr_free(struct pdsc *pdsc, int index);

View file

@ -45,6 +45,7 @@ static void pdsc_unmap_bars(struct pdsc *pdsc)
for (i = 0; i < PDS_CORE_BARS_MAX; i++) {
if (bars[i].vaddr)
pci_iounmap(pdsc->pdev, bars[i].vaddr);
bars[i].vaddr = NULL;
}
}
@ -468,19 +469,28 @@ static void pdsc_restart_health_thread(struct pdsc *pdsc)
mod_timer(&pdsc->wdtimer, jiffies + 1);
}
void pdsc_reset_prepare(struct pci_dev *pdev)
static void pdsc_reset_prepare(struct pci_dev *pdev)
{
struct pdsc *pdsc = pci_get_drvdata(pdev);
pdsc_stop_health_thread(pdsc);
pdsc_fw_down(pdsc);
if (pdev->is_virtfn) {
struct pdsc *pf;
pf = pdsc_get_pf_struct(pdsc->pdev);
if (!IS_ERR(pf))
pdsc_auxbus_dev_del(pdsc, pf);
}
pdsc_unmap_bars(pdsc);
pci_release_regions(pdev);
pci_disable_device(pdev);
if (pci_is_enabled(pdev))
pci_disable_device(pdev);
}
void pdsc_reset_done(struct pci_dev *pdev)
static void pdsc_reset_done(struct pci_dev *pdev)
{
struct pdsc *pdsc = pci_get_drvdata(pdev);
struct device *dev = pdsc->dev;
@ -510,12 +520,43 @@ void pdsc_reset_done(struct pci_dev *pdev)
pdsc_fw_up(pdsc);
pdsc_restart_health_thread(pdsc);
if (pdev->is_virtfn) {
struct pdsc *pf;
pf = pdsc_get_pf_struct(pdsc->pdev);
if (!IS_ERR(pf))
pdsc_auxbus_dev_add(pdsc, pf);
}
}
static pci_ers_result_t pdsc_pci_error_detected(struct pci_dev *pdev,
pci_channel_state_t error)
{
if (error == pci_channel_io_frozen) {
pdsc_reset_prepare(pdev);
return PCI_ERS_RESULT_NEED_RESET;
}
return PCI_ERS_RESULT_NONE;
}
static void pdsc_pci_error_resume(struct pci_dev *pdev)
{
struct pdsc *pdsc = pci_get_drvdata(pdev);
if (test_bit(PDSC_S_FW_DEAD, &pdsc->state))
pci_reset_function_locked(pdev);
}
static const struct pci_error_handlers pdsc_err_handler = {
/* FLR handling */
.reset_prepare = pdsc_reset_prepare,
.reset_done = pdsc_reset_done,
/* AER handling */
.error_detected = pdsc_pci_error_detected,
.resume = pdsc_pci_error_resume,
};
static struct pci_driver pdsc_driver = {