Commit 856e1eb9 authored by Bryant G. Ly's avatar Bryant G. Ly Committed by Michael Ellerman

PCI/AER: Add uevents in AER and EEH error/resume

Devices can go offline when erors reported. This patch adds a change
to the kernel object and lets udev know of error. When device resumes,
a change is also set reporting device as online. Therefore, EEH and
AER events are better propagated to user space for PCI devices in all
arches.
Signed-off-by: default avatarBryant G. Ly <bryantly@linux.vnet.ibm.com>
Signed-off-by: default avatarJuan J. Alvarez <jjalvare@linux.vnet.ibm.com>
Acked-by: default avatarBjorn Helgaas <bhelgaas@google.com>
Acked-by: default avatarRussell Currey <ruscur@russell.cc>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent 64ba3dc7
...@@ -228,6 +228,7 @@ static void *eeh_report_error(void *data, void *userdata) ...@@ -228,6 +228,7 @@ static void *eeh_report_error(void *data, void *userdata)
edev->in_error = true; edev->in_error = true;
eeh_pcid_put(dev); eeh_pcid_put(dev);
pci_uevent_ers(dev, PCI_ERS_RESULT_NONE);
return NULL; return NULL;
} }
...@@ -381,6 +382,10 @@ static void *eeh_report_resume(void *data, void *userdata) ...@@ -381,6 +382,10 @@ static void *eeh_report_resume(void *data, void *userdata)
driver->err_handler->resume(dev); driver->err_handler->resume(dev);
eeh_pcid_put(dev); eeh_pcid_put(dev);
pci_uevent_ers(dev, PCI_ERS_RESULT_RECOVERED);
#ifdef CONFIG_PCI_IOV
eeh_ops->notify_resume(eeh_dev_to_pdn(edev));
#endif
return NULL; return NULL;
} }
...@@ -416,6 +421,7 @@ static void *eeh_report_failure(void *data, void *userdata) ...@@ -416,6 +421,7 @@ static void *eeh_report_failure(void *data, void *userdata)
driver->err_handler->error_detected(dev, pci_channel_io_perm_failure); driver->err_handler->error_detected(dev, pci_channel_io_perm_failure);
eeh_pcid_put(dev); eeh_pcid_put(dev);
pci_uevent_ers(dev, PCI_ERS_RESULT_DISCONNECT);
return NULL; return NULL;
} }
......
...@@ -278,6 +278,7 @@ static int report_error_detected(struct pci_dev *dev, void *data) ...@@ -278,6 +278,7 @@ static int report_error_detected(struct pci_dev *dev, void *data)
} else { } else {
err_handler = dev->driver->err_handler; err_handler = dev->driver->err_handler;
vote = err_handler->error_detected(dev, result_data->state); vote = err_handler->error_detected(dev, result_data->state);
pci_uevent_ers(dev, PCI_ERS_RESULT_NONE);
} }
result_data->result = merge_result(result_data->result, vote); result_data->result = merge_result(result_data->result, vote);
...@@ -341,6 +342,7 @@ static int report_resume(struct pci_dev *dev, void *data) ...@@ -341,6 +342,7 @@ static int report_resume(struct pci_dev *dev, void *data)
err_handler = dev->driver->err_handler; err_handler = dev->driver->err_handler;
err_handler->resume(dev); err_handler->resume(dev);
pci_uevent_ers(dev, PCI_ERS_RESULT_RECOVERED);
out: out:
device_unlock(&dev->dev); device_unlock(&dev->dev);
return 0; return 0;
...@@ -541,6 +543,7 @@ static void do_recovery(struct pci_dev *dev, int severity) ...@@ -541,6 +543,7 @@ static void do_recovery(struct pci_dev *dev, int severity)
return; return;
failed: failed:
pci_uevent_ers(dev, PCI_ERS_RESULT_DISCONNECT);
/* TODO: Should kernel panic here? */ /* TODO: Should kernel panic here? */
dev_info(&dev->dev, "AER: Device recovery failed\n"); dev_info(&dev->dev, "AER: Device recovery failed\n");
} }
......
...@@ -2277,6 +2277,42 @@ static inline bool pci_is_thunderbolt_attached(struct pci_dev *pdev) ...@@ -2277,6 +2277,42 @@ static inline bool pci_is_thunderbolt_attached(struct pci_dev *pdev)
return false; return false;
} }
/**
* pci_uevent_ers - emit a uevent during recovery path of pci device
* @pdev: pci device to check
* @err_type: type of error event
*
*/
static inline void pci_uevent_ers(struct pci_dev *pdev,
enum pci_ers_result err_type)
{
int idx = 0;
char *envp[3];
switch (err_type) {
case PCI_ERS_RESULT_NONE:
case PCI_ERS_RESULT_CAN_RECOVER:
envp[idx++] = "ERROR_EVENT=BEGIN_RECOVERY";
envp[idx++] = "DEVICE_ONLINE=0";
break;
case PCI_ERS_RESULT_RECOVERED:
envp[idx++] = "ERROR_EVENT=SUCCESSFUL_RECOVERY";
envp[idx++] = "DEVICE_ONLINE=1";
break;
case PCI_ERS_RESULT_DISCONNECT:
envp[idx++] = "ERROR_EVENT=FAILED_RECOVERY";
envp[idx++] = "DEVICE_ONLINE=0";
break;
default:
break;
}
if (idx > 0) {
envp[idx++] = NULL;
kobject_uevent_env(&pdev->dev.kobj, KOBJ_CHANGE, envp);
}
}
/* provide the legacy pci_dma_* API */ /* provide the legacy pci_dma_* API */
#include <linux/pci-dma-compat.h> #include <linux/pci-dma-compat.h>
......
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