powerpc/eeh: Replace device_node with pci_dn in eeh_ops
There are 3 EEH operations whose arguments contain device_node: read_config(), write_config() and restore_config(). The patch replaces device_node with pci_dn. Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
ff57b454dd
commit
0bd785873c
5 changed files with 87 additions and 97 deletions
|
@ -217,10 +217,10 @@ struct eeh_ops {
|
||||||
int (*configure_bridge)(struct eeh_pe *pe);
|
int (*configure_bridge)(struct eeh_pe *pe);
|
||||||
int (*err_inject)(struct eeh_pe *pe, int type, int func,
|
int (*err_inject)(struct eeh_pe *pe, int type, int func,
|
||||||
unsigned long addr, unsigned long mask);
|
unsigned long addr, unsigned long mask);
|
||||||
int (*read_config)(struct device_node *dn, int where, int size, u32 *val);
|
int (*read_config)(struct pci_dn *pdn, int where, int size, u32 *val);
|
||||||
int (*write_config)(struct device_node *dn, int where, int size, u32 val);
|
int (*write_config)(struct pci_dn *pdn, int where, int size, u32 val);
|
||||||
int (*next_error)(struct eeh_pe **pe);
|
int (*next_error)(struct eeh_pe **pe);
|
||||||
int (*restore_config)(struct device_node *dn);
|
int (*restore_config)(struct pci_dn *pdn);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int eeh_subsystem_flags;
|
extern int eeh_subsystem_flags;
|
||||||
|
|
|
@ -164,30 +164,34 @@ __setup("eeh=", eeh_setup);
|
||||||
*/
|
*/
|
||||||
static size_t eeh_dump_dev_log(struct eeh_dev *edev, char *buf, size_t len)
|
static size_t eeh_dump_dev_log(struct eeh_dev *edev, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
struct device_node *dn = eeh_dev_to_of_node(edev);
|
struct pci_dn *pdn = eeh_dev_to_pdn(edev);
|
||||||
u32 cfg;
|
u32 cfg;
|
||||||
int cap, i;
|
int cap, i;
|
||||||
int n = 0, l = 0;
|
int n = 0, l = 0;
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
|
|
||||||
n += scnprintf(buf+n, len-n, "%s\n", dn->full_name);
|
n += scnprintf(buf+n, len-n, "%04x:%02x:%02x:%01x\n",
|
||||||
pr_warn("EEH: of node=%s\n", dn->full_name);
|
edev->phb->global_number, pdn->busno,
|
||||||
|
PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn));
|
||||||
|
pr_warn("EEH: of node=%04x:%02x:%02x:%01x\n",
|
||||||
|
edev->phb->global_number, pdn->busno,
|
||||||
|
PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn));
|
||||||
|
|
||||||
eeh_ops->read_config(dn, PCI_VENDOR_ID, 4, &cfg);
|
eeh_ops->read_config(pdn, PCI_VENDOR_ID, 4, &cfg);
|
||||||
n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg);
|
n += scnprintf(buf+n, len-n, "dev/vend:%08x\n", cfg);
|
||||||
pr_warn("EEH: PCI device/vendor: %08x\n", cfg);
|
pr_warn("EEH: PCI device/vendor: %08x\n", cfg);
|
||||||
|
|
||||||
eeh_ops->read_config(dn, PCI_COMMAND, 4, &cfg);
|
eeh_ops->read_config(pdn, PCI_COMMAND, 4, &cfg);
|
||||||
n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg);
|
n += scnprintf(buf+n, len-n, "cmd/stat:%x\n", cfg);
|
||||||
pr_warn("EEH: PCI cmd/status register: %08x\n", cfg);
|
pr_warn("EEH: PCI cmd/status register: %08x\n", cfg);
|
||||||
|
|
||||||
/* Gather bridge-specific registers */
|
/* Gather bridge-specific registers */
|
||||||
if (edev->mode & EEH_DEV_BRIDGE) {
|
if (edev->mode & EEH_DEV_BRIDGE) {
|
||||||
eeh_ops->read_config(dn, PCI_SEC_STATUS, 2, &cfg);
|
eeh_ops->read_config(pdn, PCI_SEC_STATUS, 2, &cfg);
|
||||||
n += scnprintf(buf+n, len-n, "sec stat:%x\n", cfg);
|
n += scnprintf(buf+n, len-n, "sec stat:%x\n", cfg);
|
||||||
pr_warn("EEH: Bridge secondary status: %04x\n", cfg);
|
pr_warn("EEH: Bridge secondary status: %04x\n", cfg);
|
||||||
|
|
||||||
eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &cfg);
|
eeh_ops->read_config(pdn, PCI_BRIDGE_CONTROL, 2, &cfg);
|
||||||
n += scnprintf(buf+n, len-n, "brdg ctl:%x\n", cfg);
|
n += scnprintf(buf+n, len-n, "brdg ctl:%x\n", cfg);
|
||||||
pr_warn("EEH: Bridge control: %04x\n", cfg);
|
pr_warn("EEH: Bridge control: %04x\n", cfg);
|
||||||
}
|
}
|
||||||
|
@ -195,11 +199,11 @@ static size_t eeh_dump_dev_log(struct eeh_dev *edev, char *buf, size_t len)
|
||||||
/* Dump out the PCI-X command and status regs */
|
/* Dump out the PCI-X command and status regs */
|
||||||
cap = edev->pcix_cap;
|
cap = edev->pcix_cap;
|
||||||
if (cap) {
|
if (cap) {
|
||||||
eeh_ops->read_config(dn, cap, 4, &cfg);
|
eeh_ops->read_config(pdn, cap, 4, &cfg);
|
||||||
n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg);
|
n += scnprintf(buf+n, len-n, "pcix-cmd:%x\n", cfg);
|
||||||
pr_warn("EEH: PCI-X cmd: %08x\n", cfg);
|
pr_warn("EEH: PCI-X cmd: %08x\n", cfg);
|
||||||
|
|
||||||
eeh_ops->read_config(dn, cap+4, 4, &cfg);
|
eeh_ops->read_config(pdn, cap+4, 4, &cfg);
|
||||||
n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg);
|
n += scnprintf(buf+n, len-n, "pcix-stat:%x\n", cfg);
|
||||||
pr_warn("EEH: PCI-X status: %08x\n", cfg);
|
pr_warn("EEH: PCI-X status: %08x\n", cfg);
|
||||||
}
|
}
|
||||||
|
@ -211,7 +215,7 @@ static size_t eeh_dump_dev_log(struct eeh_dev *edev, char *buf, size_t len)
|
||||||
pr_warn("EEH: PCI-E capabilities and status follow:\n");
|
pr_warn("EEH: PCI-E capabilities and status follow:\n");
|
||||||
|
|
||||||
for (i=0; i<=8; i++) {
|
for (i=0; i<=8; i++) {
|
||||||
eeh_ops->read_config(dn, cap+4*i, 4, &cfg);
|
eeh_ops->read_config(pdn, cap+4*i, 4, &cfg);
|
||||||
n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
|
n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
|
||||||
|
|
||||||
if ((i % 4) == 0) {
|
if ((i % 4) == 0) {
|
||||||
|
@ -238,7 +242,7 @@ static size_t eeh_dump_dev_log(struct eeh_dev *edev, char *buf, size_t len)
|
||||||
pr_warn("EEH: PCI-E AER capability register set follows:\n");
|
pr_warn("EEH: PCI-E AER capability register set follows:\n");
|
||||||
|
|
||||||
for (i=0; i<=13; i++) {
|
for (i=0; i<=13; i++) {
|
||||||
eeh_ops->read_config(dn, cap+4*i, 4, &cfg);
|
eeh_ops->read_config(pdn, cap+4*i, 4, &cfg);
|
||||||
n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
|
n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg);
|
||||||
|
|
||||||
if ((i % 4) == 0) {
|
if ((i % 4) == 0) {
|
||||||
|
@ -698,7 +702,7 @@ static void *eeh_disable_and_save_dev_state(void *data, void *userdata)
|
||||||
static void *eeh_restore_dev_state(void *data, void *userdata)
|
static void *eeh_restore_dev_state(void *data, void *userdata)
|
||||||
{
|
{
|
||||||
struct eeh_dev *edev = data;
|
struct eeh_dev *edev = data;
|
||||||
struct device_node *dn = eeh_dev_to_of_node(edev);
|
struct pci_dn *pdn = eeh_dev_to_pdn(edev);
|
||||||
struct pci_dev *pdev = eeh_dev_to_pci_dev(edev);
|
struct pci_dev *pdev = eeh_dev_to_pci_dev(edev);
|
||||||
struct pci_dev *dev = userdata;
|
struct pci_dev *dev = userdata;
|
||||||
|
|
||||||
|
@ -706,8 +710,8 @@ static void *eeh_restore_dev_state(void *data, void *userdata)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* Apply customization from firmware */
|
/* Apply customization from firmware */
|
||||||
if (dn && eeh_ops->restore_config)
|
if (pdn && eeh_ops->restore_config)
|
||||||
eeh_ops->restore_config(dn);
|
eeh_ops->restore_config(pdn);
|
||||||
|
|
||||||
/* The caller should restore state for the specified device */
|
/* The caller should restore state for the specified device */
|
||||||
if (pdev != dev)
|
if (pdev != dev)
|
||||||
|
@ -870,15 +874,15 @@ out:
|
||||||
*/
|
*/
|
||||||
void eeh_save_bars(struct eeh_dev *edev)
|
void eeh_save_bars(struct eeh_dev *edev)
|
||||||
{
|
{
|
||||||
|
struct pci_dn *pdn;
|
||||||
int i;
|
int i;
|
||||||
struct device_node *dn;
|
|
||||||
|
|
||||||
if (!edev)
|
pdn = eeh_dev_to_pdn(edev);
|
||||||
|
if (!pdn)
|
||||||
return;
|
return;
|
||||||
dn = eeh_dev_to_of_node(edev);
|
|
||||||
|
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++)
|
||||||
eeh_ops->read_config(dn, i * 4, 4, &edev->config_space[i]);
|
eeh_ops->read_config(pdn, i * 4, 4, &edev->config_space[i]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For PCI bridges including root port, we need enable bus
|
* For PCI bridges including root port, we need enable bus
|
||||||
|
|
|
@ -291,27 +291,25 @@ struct eeh_pe *eeh_pe_get(struct eeh_dev *edev)
|
||||||
*/
|
*/
|
||||||
static struct eeh_pe *eeh_pe_get_parent(struct eeh_dev *edev)
|
static struct eeh_pe *eeh_pe_get_parent(struct eeh_dev *edev)
|
||||||
{
|
{
|
||||||
struct device_node *dn;
|
|
||||||
struct eeh_dev *parent;
|
struct eeh_dev *parent;
|
||||||
|
struct pci_dn *pdn = eeh_dev_to_pdn(edev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It might have the case for the indirect parent
|
* It might have the case for the indirect parent
|
||||||
* EEH device already having associated PE, but
|
* EEH device already having associated PE, but
|
||||||
* the direct parent EEH device doesn't have yet.
|
* the direct parent EEH device doesn't have yet.
|
||||||
*/
|
*/
|
||||||
dn = edev->dn->parent;
|
pdn = pdn ? pdn->parent : NULL;
|
||||||
while (dn) {
|
while (pdn) {
|
||||||
/* We're poking out of PCI territory */
|
/* We're poking out of PCI territory */
|
||||||
if (!PCI_DN(dn)) return NULL;
|
parent = pdn_to_eeh_dev(pdn);
|
||||||
|
if (!parent)
|
||||||
parent = of_node_to_eeh_dev(dn);
|
return NULL;
|
||||||
/* We're poking out of PCI territory */
|
|
||||||
if (!parent) return NULL;
|
|
||||||
|
|
||||||
if (parent->pe)
|
if (parent->pe)
|
||||||
return parent->pe;
|
return parent->pe;
|
||||||
|
|
||||||
dn = dn->parent;
|
pdn = pdn->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -653,9 +651,9 @@ void eeh_pe_state_clear(struct eeh_pe *pe, int state)
|
||||||
* blocked on normal path during the stage. So we need utilize
|
* blocked on normal path during the stage. So we need utilize
|
||||||
* eeh operations, which is always permitted.
|
* eeh operations, which is always permitted.
|
||||||
*/
|
*/
|
||||||
static void eeh_bridge_check_link(struct eeh_dev *edev,
|
static void eeh_bridge_check_link(struct eeh_dev *edev)
|
||||||
struct device_node *dn)
|
|
||||||
{
|
{
|
||||||
|
struct pci_dn *pdn = eeh_dev_to_pdn(edev);
|
||||||
int cap;
|
int cap;
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
int timeout = 0;
|
int timeout = 0;
|
||||||
|
@ -675,32 +673,32 @@ static void eeh_bridge_check_link(struct eeh_dev *edev,
|
||||||
|
|
||||||
/* Check slot status */
|
/* Check slot status */
|
||||||
cap = edev->pcie_cap;
|
cap = edev->pcie_cap;
|
||||||
eeh_ops->read_config(dn, cap + PCI_EXP_SLTSTA, 2, &val);
|
eeh_ops->read_config(pdn, cap + PCI_EXP_SLTSTA, 2, &val);
|
||||||
if (!(val & PCI_EXP_SLTSTA_PDS)) {
|
if (!(val & PCI_EXP_SLTSTA_PDS)) {
|
||||||
pr_debug(" No card in the slot (0x%04x) !\n", val);
|
pr_debug(" No card in the slot (0x%04x) !\n", val);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check power status if we have the capability */
|
/* Check power status if we have the capability */
|
||||||
eeh_ops->read_config(dn, cap + PCI_EXP_SLTCAP, 2, &val);
|
eeh_ops->read_config(pdn, cap + PCI_EXP_SLTCAP, 2, &val);
|
||||||
if (val & PCI_EXP_SLTCAP_PCP) {
|
if (val & PCI_EXP_SLTCAP_PCP) {
|
||||||
eeh_ops->read_config(dn, cap + PCI_EXP_SLTCTL, 2, &val);
|
eeh_ops->read_config(pdn, cap + PCI_EXP_SLTCTL, 2, &val);
|
||||||
if (val & PCI_EXP_SLTCTL_PCC) {
|
if (val & PCI_EXP_SLTCTL_PCC) {
|
||||||
pr_debug(" In power-off state, power it on ...\n");
|
pr_debug(" In power-off state, power it on ...\n");
|
||||||
val &= ~(PCI_EXP_SLTCTL_PCC | PCI_EXP_SLTCTL_PIC);
|
val &= ~(PCI_EXP_SLTCTL_PCC | PCI_EXP_SLTCTL_PIC);
|
||||||
val |= (0x0100 & PCI_EXP_SLTCTL_PIC);
|
val |= (0x0100 & PCI_EXP_SLTCTL_PIC);
|
||||||
eeh_ops->write_config(dn, cap + PCI_EXP_SLTCTL, 2, val);
|
eeh_ops->write_config(pdn, cap + PCI_EXP_SLTCTL, 2, val);
|
||||||
msleep(2 * 1000);
|
msleep(2 * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable link */
|
/* Enable link */
|
||||||
eeh_ops->read_config(dn, cap + PCI_EXP_LNKCTL, 2, &val);
|
eeh_ops->read_config(pdn, cap + PCI_EXP_LNKCTL, 2, &val);
|
||||||
val &= ~PCI_EXP_LNKCTL_LD;
|
val &= ~PCI_EXP_LNKCTL_LD;
|
||||||
eeh_ops->write_config(dn, cap + PCI_EXP_LNKCTL, 2, val);
|
eeh_ops->write_config(pdn, cap + PCI_EXP_LNKCTL, 2, val);
|
||||||
|
|
||||||
/* Check link */
|
/* Check link */
|
||||||
eeh_ops->read_config(dn, cap + PCI_EXP_LNKCAP, 4, &val);
|
eeh_ops->read_config(pdn, cap + PCI_EXP_LNKCAP, 4, &val);
|
||||||
if (!(val & PCI_EXP_LNKCAP_DLLLARC)) {
|
if (!(val & PCI_EXP_LNKCAP_DLLLARC)) {
|
||||||
pr_debug(" No link reporting capability (0x%08x) \n", val);
|
pr_debug(" No link reporting capability (0x%08x) \n", val);
|
||||||
msleep(1000);
|
msleep(1000);
|
||||||
|
@ -713,7 +711,7 @@ static void eeh_bridge_check_link(struct eeh_dev *edev,
|
||||||
msleep(20);
|
msleep(20);
|
||||||
timeout += 20;
|
timeout += 20;
|
||||||
|
|
||||||
eeh_ops->read_config(dn, cap + PCI_EXP_LNKSTA, 2, &val);
|
eeh_ops->read_config(pdn, cap + PCI_EXP_LNKSTA, 2, &val);
|
||||||
if (val & PCI_EXP_LNKSTA_DLLLA)
|
if (val & PCI_EXP_LNKSTA_DLLLA)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -728,9 +726,9 @@ static void eeh_bridge_check_link(struct eeh_dev *edev,
|
||||||
#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
|
#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
|
||||||
#define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)])
|
#define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)])
|
||||||
|
|
||||||
static void eeh_restore_bridge_bars(struct eeh_dev *edev,
|
static void eeh_restore_bridge_bars(struct eeh_dev *edev)
|
||||||
struct device_node *dn)
|
|
||||||
{
|
{
|
||||||
|
struct pci_dn *pdn = eeh_dev_to_pdn(edev);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -738,49 +736,49 @@ static void eeh_restore_bridge_bars(struct eeh_dev *edev,
|
||||||
* Bus numbers and windows: 0x18 - 0x30
|
* Bus numbers and windows: 0x18 - 0x30
|
||||||
*/
|
*/
|
||||||
for (i = 4; i < 13; i++)
|
for (i = 4; i < 13; i++)
|
||||||
eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]);
|
eeh_ops->write_config(pdn, i*4, 4, edev->config_space[i]);
|
||||||
/* Rom: 0x38 */
|
/* Rom: 0x38 */
|
||||||
eeh_ops->write_config(dn, 14*4, 4, edev->config_space[14]);
|
eeh_ops->write_config(pdn, 14*4, 4, edev->config_space[14]);
|
||||||
|
|
||||||
/* Cache line & Latency timer: 0xC 0xD */
|
/* Cache line & Latency timer: 0xC 0xD */
|
||||||
eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1,
|
eeh_ops->write_config(pdn, PCI_CACHE_LINE_SIZE, 1,
|
||||||
SAVED_BYTE(PCI_CACHE_LINE_SIZE));
|
SAVED_BYTE(PCI_CACHE_LINE_SIZE));
|
||||||
eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1,
|
eeh_ops->write_config(pdn, PCI_LATENCY_TIMER, 1,
|
||||||
SAVED_BYTE(PCI_LATENCY_TIMER));
|
SAVED_BYTE(PCI_LATENCY_TIMER));
|
||||||
/* Max latency, min grant, interrupt ping and line: 0x3C */
|
/* Max latency, min grant, interrupt ping and line: 0x3C */
|
||||||
eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]);
|
eeh_ops->write_config(pdn, 15*4, 4, edev->config_space[15]);
|
||||||
|
|
||||||
/* PCI Command: 0x4 */
|
/* PCI Command: 0x4 */
|
||||||
eeh_ops->write_config(dn, PCI_COMMAND, 4, edev->config_space[1]);
|
eeh_ops->write_config(pdn, PCI_COMMAND, 4, edev->config_space[1]);
|
||||||
|
|
||||||
/* Check the PCIe link is ready */
|
/* Check the PCIe link is ready */
|
||||||
eeh_bridge_check_link(edev, dn);
|
eeh_bridge_check_link(edev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void eeh_restore_device_bars(struct eeh_dev *edev,
|
static void eeh_restore_device_bars(struct eeh_dev *edev)
|
||||||
struct device_node *dn)
|
|
||||||
{
|
{
|
||||||
|
struct pci_dn *pdn = eeh_dev_to_pdn(edev);
|
||||||
int i;
|
int i;
|
||||||
u32 cmd;
|
u32 cmd;
|
||||||
|
|
||||||
for (i = 4; i < 10; i++)
|
for (i = 4; i < 10; i++)
|
||||||
eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]);
|
eeh_ops->write_config(pdn, i*4, 4, edev->config_space[i]);
|
||||||
/* 12 == Expansion ROM Address */
|
/* 12 == Expansion ROM Address */
|
||||||
eeh_ops->write_config(dn, 12*4, 4, edev->config_space[12]);
|
eeh_ops->write_config(pdn, 12*4, 4, edev->config_space[12]);
|
||||||
|
|
||||||
eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1,
|
eeh_ops->write_config(pdn, PCI_CACHE_LINE_SIZE, 1,
|
||||||
SAVED_BYTE(PCI_CACHE_LINE_SIZE));
|
SAVED_BYTE(PCI_CACHE_LINE_SIZE));
|
||||||
eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1,
|
eeh_ops->write_config(pdn, PCI_LATENCY_TIMER, 1,
|
||||||
SAVED_BYTE(PCI_LATENCY_TIMER));
|
SAVED_BYTE(PCI_LATENCY_TIMER));
|
||||||
|
|
||||||
/* max latency, min grant, interrupt pin and line */
|
/* max latency, min grant, interrupt pin and line */
|
||||||
eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]);
|
eeh_ops->write_config(pdn, 15*4, 4, edev->config_space[15]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Restore PERR & SERR bits, some devices require it,
|
* Restore PERR & SERR bits, some devices require it,
|
||||||
* don't touch the other command bits
|
* don't touch the other command bits
|
||||||
*/
|
*/
|
||||||
eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd);
|
eeh_ops->read_config(pdn, PCI_COMMAND, 4, &cmd);
|
||||||
if (edev->config_space[1] & PCI_COMMAND_PARITY)
|
if (edev->config_space[1] & PCI_COMMAND_PARITY)
|
||||||
cmd |= PCI_COMMAND_PARITY;
|
cmd |= PCI_COMMAND_PARITY;
|
||||||
else
|
else
|
||||||
|
@ -789,7 +787,7 @@ static void eeh_restore_device_bars(struct eeh_dev *edev,
|
||||||
cmd |= PCI_COMMAND_SERR;
|
cmd |= PCI_COMMAND_SERR;
|
||||||
else
|
else
|
||||||
cmd &= ~PCI_COMMAND_SERR;
|
cmd &= ~PCI_COMMAND_SERR;
|
||||||
eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd);
|
eeh_ops->write_config(pdn, PCI_COMMAND, 4, cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -804,16 +802,16 @@ static void eeh_restore_device_bars(struct eeh_dev *edev,
|
||||||
static void *eeh_restore_one_device_bars(void *data, void *flag)
|
static void *eeh_restore_one_device_bars(void *data, void *flag)
|
||||||
{
|
{
|
||||||
struct eeh_dev *edev = (struct eeh_dev *)data;
|
struct eeh_dev *edev = (struct eeh_dev *)data;
|
||||||
struct device_node *dn = eeh_dev_to_of_node(edev);
|
struct pci_dn *pdn = eeh_dev_to_pdn(edev);
|
||||||
|
|
||||||
/* Do special restore for bridges */
|
/* Do special restore for bridges */
|
||||||
if (edev->mode & EEH_DEV_BRIDGE)
|
if (edev->mode & EEH_DEV_BRIDGE)
|
||||||
eeh_restore_bridge_bars(edev, dn);
|
eeh_restore_bridge_bars(edev);
|
||||||
else
|
else
|
||||||
eeh_restore_device_bars(edev, dn);
|
eeh_restore_device_bars(edev);
|
||||||
|
|
||||||
if (eeh_ops->restore_config)
|
if (eeh_ops->restore_config && pdn)
|
||||||
eeh_ops->restore_config(dn);
|
eeh_ops->restore_config(pdn);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -842,8 +842,8 @@ out:
|
||||||
|
|
||||||
static int pnv_eeh_bridge_reset(struct pci_dev *dev, int option)
|
static int pnv_eeh_bridge_reset(struct pci_dev *dev, int option)
|
||||||
{
|
{
|
||||||
struct device_node *dn = pci_device_to_OF_node(dev);
|
struct pci_dn *pdn = pci_get_pdn_by_devfn(dev->bus, dev->devfn);
|
||||||
struct eeh_dev *edev = of_node_to_eeh_dev(dn);
|
struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
|
||||||
int aer = edev ? edev->aer_cap : 0;
|
int aer = edev ? edev->aer_cap : 0;
|
||||||
u32 ctrl;
|
u32 ctrl;
|
||||||
|
|
||||||
|
@ -856,32 +856,32 @@ static int pnv_eeh_bridge_reset(struct pci_dev *dev, int option)
|
||||||
case EEH_RESET_HOT:
|
case EEH_RESET_HOT:
|
||||||
/* Don't report linkDown event */
|
/* Don't report linkDown event */
|
||||||
if (aer) {
|
if (aer) {
|
||||||
eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK,
|
eeh_ops->read_config(pdn, aer + PCI_ERR_UNCOR_MASK,
|
||||||
4, &ctrl);
|
4, &ctrl);
|
||||||
ctrl |= PCI_ERR_UNC_SURPDN;
|
ctrl |= PCI_ERR_UNC_SURPDN;
|
||||||
eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK,
|
eeh_ops->write_config(pdn, aer + PCI_ERR_UNCOR_MASK,
|
||||||
4, ctrl);
|
4, ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl);
|
eeh_ops->read_config(pdn, PCI_BRIDGE_CONTROL, 2, &ctrl);
|
||||||
ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
|
ctrl |= PCI_BRIDGE_CTL_BUS_RESET;
|
||||||
eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl);
|
eeh_ops->write_config(pdn, PCI_BRIDGE_CONTROL, 2, ctrl);
|
||||||
|
|
||||||
msleep(EEH_PE_RST_HOLD_TIME);
|
msleep(EEH_PE_RST_HOLD_TIME);
|
||||||
break;
|
break;
|
||||||
case EEH_RESET_DEACTIVATE:
|
case EEH_RESET_DEACTIVATE:
|
||||||
eeh_ops->read_config(dn, PCI_BRIDGE_CONTROL, 2, &ctrl);
|
eeh_ops->read_config(pdn, PCI_BRIDGE_CONTROL, 2, &ctrl);
|
||||||
ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
|
ctrl &= ~PCI_BRIDGE_CTL_BUS_RESET;
|
||||||
eeh_ops->write_config(dn, PCI_BRIDGE_CONTROL, 2, ctrl);
|
eeh_ops->write_config(pdn, PCI_BRIDGE_CONTROL, 2, ctrl);
|
||||||
|
|
||||||
msleep(EEH_PE_RST_SETTLE_TIME);
|
msleep(EEH_PE_RST_SETTLE_TIME);
|
||||||
|
|
||||||
/* Continue reporting linkDown event */
|
/* Continue reporting linkDown event */
|
||||||
if (aer) {
|
if (aer) {
|
||||||
eeh_ops->read_config(dn, aer + PCI_ERR_UNCOR_MASK,
|
eeh_ops->read_config(pdn, aer + PCI_ERR_UNCOR_MASK,
|
||||||
4, &ctrl);
|
4, &ctrl);
|
||||||
ctrl &= ~PCI_ERR_UNC_SURPDN;
|
ctrl &= ~PCI_ERR_UNC_SURPDN;
|
||||||
eeh_ops->write_config(dn, aer + PCI_ERR_UNCOR_MASK,
|
eeh_ops->write_config(pdn, aer + PCI_ERR_UNCOR_MASK,
|
||||||
4, ctrl);
|
4, ctrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1099,9 +1099,9 @@ static int pnv_eeh_err_inject(struct eeh_pe *pe, int type, int func,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool pnv_eeh_cfg_blocked(struct device_node *dn)
|
static inline bool pnv_eeh_cfg_blocked(struct pci_dn *pdn)
|
||||||
{
|
{
|
||||||
struct eeh_dev *edev = of_node_to_eeh_dev(dn);
|
struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
|
||||||
|
|
||||||
if (!edev || !edev->pe)
|
if (!edev || !edev->pe)
|
||||||
return false;
|
return false;
|
||||||
|
@ -1112,15 +1112,13 @@ static inline bool pnv_eeh_cfg_blocked(struct device_node *dn)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pnv_eeh_read_config(struct device_node *dn,
|
static int pnv_eeh_read_config(struct pci_dn *pdn,
|
||||||
int where, int size, u32 *val)
|
int where, int size, u32 *val)
|
||||||
{
|
{
|
||||||
struct pci_dn *pdn = PCI_DN(dn);
|
|
||||||
|
|
||||||
if (!pdn)
|
if (!pdn)
|
||||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||||
|
|
||||||
if (pnv_eeh_cfg_blocked(dn)) {
|
if (pnv_eeh_cfg_blocked(pdn)) {
|
||||||
*val = 0xFFFFFFFF;
|
*val = 0xFFFFFFFF;
|
||||||
return PCIBIOS_SET_FAILED;
|
return PCIBIOS_SET_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -1128,15 +1126,13 @@ static int pnv_eeh_read_config(struct device_node *dn,
|
||||||
return pnv_pci_cfg_read(pdn, where, size, val);
|
return pnv_pci_cfg_read(pdn, where, size, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pnv_eeh_write_config(struct device_node *dn,
|
static int pnv_eeh_write_config(struct pci_dn *pdn,
|
||||||
int where, int size, u32 val)
|
int where, int size, u32 val)
|
||||||
{
|
{
|
||||||
struct pci_dn *pdn = PCI_DN(dn);
|
|
||||||
|
|
||||||
if (!pdn)
|
if (!pdn)
|
||||||
return PCIBIOS_DEVICE_NOT_FOUND;
|
return PCIBIOS_DEVICE_NOT_FOUND;
|
||||||
|
|
||||||
if (pnv_eeh_cfg_blocked(dn))
|
if (pnv_eeh_cfg_blocked(pdn))
|
||||||
return PCIBIOS_SET_FAILED;
|
return PCIBIOS_SET_FAILED;
|
||||||
|
|
||||||
return pnv_pci_cfg_write(pdn, where, size, val);
|
return pnv_pci_cfg_write(pdn, where, size, val);
|
||||||
|
@ -1484,9 +1480,9 @@ static int pnv_eeh_next_error(struct eeh_pe **pe)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pnv_eeh_restore_config(struct device_node *dn)
|
static int pnv_eeh_restore_config(struct pci_dn *pdn)
|
||||||
{
|
{
|
||||||
struct eeh_dev *edev = of_node_to_eeh_dev(dn);
|
struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
|
||||||
struct pnv_phb *phb;
|
struct pnv_phb *phb;
|
||||||
s64 ret;
|
s64 ret;
|
||||||
|
|
||||||
|
|
|
@ -651,37 +651,29 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pseries_eeh_read_config - Read PCI config space
|
* pseries_eeh_read_config - Read PCI config space
|
||||||
* @dn: device node
|
* @pdn: PCI device node
|
||||||
* @where: PCI address
|
* @where: PCI address
|
||||||
* @size: size to read
|
* @size: size to read
|
||||||
* @val: return value
|
* @val: return value
|
||||||
*
|
*
|
||||||
* Read config space from the speicifed device
|
* Read config space from the speicifed device
|
||||||
*/
|
*/
|
||||||
static int pseries_eeh_read_config(struct device_node *dn, int where, int size, u32 *val)
|
static int pseries_eeh_read_config(struct pci_dn *pdn, int where, int size, u32 *val)
|
||||||
{
|
{
|
||||||
struct pci_dn *pdn;
|
|
||||||
|
|
||||||
pdn = PCI_DN(dn);
|
|
||||||
|
|
||||||
return rtas_read_config(pdn, where, size, val);
|
return rtas_read_config(pdn, where, size, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pseries_eeh_write_config - Write PCI config space
|
* pseries_eeh_write_config - Write PCI config space
|
||||||
* @dn: device node
|
* @pdn: PCI device node
|
||||||
* @where: PCI address
|
* @where: PCI address
|
||||||
* @size: size to write
|
* @size: size to write
|
||||||
* @val: value to be written
|
* @val: value to be written
|
||||||
*
|
*
|
||||||
* Write config space to the specified device
|
* Write config space to the specified device
|
||||||
*/
|
*/
|
||||||
static int pseries_eeh_write_config(struct device_node *dn, int where, int size, u32 val)
|
static int pseries_eeh_write_config(struct pci_dn *pdn, int where, int size, u32 val)
|
||||||
{
|
{
|
||||||
struct pci_dn *pdn;
|
|
||||||
|
|
||||||
pdn = PCI_DN(dn);
|
|
||||||
|
|
||||||
return rtas_write_config(pdn, where, size, val);
|
return rtas_write_config(pdn, where, size, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue