Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 261152
b: refs/heads/master
c: 0918472
h: refs/heads/master
v: v3
  • Loading branch information
Huang Ying authored and Jesse Barnes committed Jul 22, 2011
1 parent d54da8e commit 485be5b
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 0aba496fc820d7c36775f2fd0ef81994e1af67a8
refs/heads/master: 0918472ceeffad234df5589e45b646a94476f835
76 changes: 69 additions & 7 deletions trunk/drivers/pci/pcie/aer/aerdrv_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <linux/suspend.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/kfifo.h>
#include "aerdrv.h"

static int forceload;
Expand Down Expand Up @@ -445,8 +446,7 @@ static struct pcie_port_service_driver *find_aer_service(struct pci_dev *dev)
return drv;
}

static pci_ers_result_t reset_link(struct pcie_device *aerdev,
struct pci_dev *dev)
static pci_ers_result_t reset_link(struct pci_dev *dev)
{
struct pci_dev *udev;
pci_ers_result_t status;
Expand Down Expand Up @@ -486,16 +486,14 @@ static pci_ers_result_t reset_link(struct pcie_device *aerdev,

/**
* do_recovery - handle nonfatal/fatal error recovery process
* @aerdev: pointer to a pcie_device data structure of root port
* @dev: pointer to a pci_dev data structure of agent detecting an error
* @severity: error severity type
*
* Invoked when an error is nonfatal/fatal. Once being invoked, broadcast
* error detected message to all downstream drivers within a hierarchy in
* question and return the returned code.
*/
static void do_recovery(struct pcie_device *aerdev, struct pci_dev *dev,
int severity)
static void do_recovery(struct pci_dev *dev, int severity)
{
pci_ers_result_t status, result = PCI_ERS_RESULT_RECOVERED;
enum pci_channel_state state;
Expand All @@ -511,7 +509,7 @@ static void do_recovery(struct pcie_device *aerdev, struct pci_dev *dev,
report_error_detected);

if (severity == AER_FATAL) {
result = reset_link(aerdev, dev);
result = reset_link(dev);
if (result != PCI_ERS_RESULT_RECOVERED)
goto failed;
}
Expand Down Expand Up @@ -576,9 +574,73 @@ static void handle_error_source(struct pcie_device *aerdev,
pci_write_config_dword(dev, pos + PCI_ERR_COR_STATUS,
info->status);
} else
do_recovery(aerdev, dev, info->severity);
do_recovery(dev, info->severity);
}

#ifdef CONFIG_ACPI_APEI_PCIEAER
static void aer_recover_work_func(struct work_struct *work);

#define AER_RECOVER_RING_ORDER 4
#define AER_RECOVER_RING_SIZE (1 << AER_RECOVER_RING_ORDER)

struct aer_recover_entry
{
u8 bus;
u8 devfn;
u16 domain;
int severity;
};

static DEFINE_KFIFO(aer_recover_ring, struct aer_recover_entry,
AER_RECOVER_RING_SIZE);
/*
* Mutual exclusion for writers of aer_recover_ring, reader side don't
* need lock, because there is only one reader and lock is not needed
* between reader and writer.
*/
static DEFINE_SPINLOCK(aer_recover_ring_lock);
static DECLARE_WORK(aer_recover_work, aer_recover_work_func);

void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
int severity)
{
unsigned long flags;
struct aer_recover_entry entry = {
.bus = bus,
.devfn = devfn,
.domain = domain,
.severity = severity,
};

spin_lock_irqsave(&aer_recover_ring_lock, flags);
if (kfifo_put(&aer_recover_ring, &entry))
schedule_work(&aer_recover_work);
else
pr_err("AER recover: Buffer overflow when recovering AER for %04x:%02x:%02x:%x\n",
domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
spin_unlock_irqrestore(&aer_recover_ring_lock, flags);
}
EXPORT_SYMBOL_GPL(aer_recover_queue);

static void aer_recover_work_func(struct work_struct *work)
{
struct aer_recover_entry entry;
struct pci_dev *pdev;

while (kfifo_get(&aer_recover_ring, &entry)) {
pdev = pci_get_domain_bus_and_slot(entry.domain, entry.bus,
entry.devfn);
if (!pdev) {
pr_err("AER recover: Can not find pci_dev for %04x:%02x:%02x:%x\n",
entry.domain, entry.bus,
PCI_SLOT(entry.devfn), PCI_FUNC(entry.devfn));
continue;
}
do_recovery(pdev, entry.severity);
}
}
#endif

/**
* get_device_error_info - read error status from dev and store it to info
* @dev: pointer to the device expected to have a error record
Expand Down
3 changes: 2 additions & 1 deletion trunk/drivers/pci/pcie/aer/aerdrv_errprint.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info)
}

#ifdef CONFIG_ACPI_APEI_PCIEAER
static int cper_severity_to_aer(int cper_severity)
int cper_severity_to_aer(int cper_severity)
{
switch (cper_severity) {
case CPER_SEV_RECOVERABLE:
Expand All @@ -215,6 +215,7 @@ static int cper_severity_to_aer(int cper_severity)
return AER_CORRECTABLE;
}
}
EXPORT_SYMBOL_GPL(cper_severity_to_aer);

void cper_print_aer(const char *prefix, int cper_severity,
struct aer_capability_regs *aer)
Expand Down
3 changes: 3 additions & 0 deletions trunk/include/linux/aer.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,8 @@ static inline int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev)

extern void cper_print_aer(const char *prefix, int cper_severity,
struct aer_capability_regs *aer);
extern int cper_severity_to_aer(int cper_severity);
extern void aer_recover_queue(int domain, unsigned int bus, unsigned int devfn,
int severity);
#endif //_AER_H_

0 comments on commit 485be5b

Please sign in to comment.