Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 13714
b: refs/heads/master
c: 6dee3fb
h: refs/heads/master
v: v3
  • Loading branch information
Linas Vepstas authored and Paul Mackerras committed Nov 10, 2005
1 parent 8995e5d commit ceb7780
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 172ca9261800bacbbc7d320d9924d9b482dff8de
refs/heads/master: 6dee3fb94004c43ce09f6bf5e7c0b778ec5b8cc8
99 changes: 99 additions & 0 deletions trunk/arch/powerpc/platforms/pseries/eeh.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

#include <linux/delay.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/pci.h>
Expand Down Expand Up @@ -676,6 +677,104 @@ unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned lon

EXPORT_SYMBOL(eeh_check_failure);

/* ------------------------------------------------------------- */
/* The code below deals with error recovery */

/** Return negative value if a permanent error, else return
* a number of milliseconds to wait until the PCI slot is
* ready to be used.
*/
static int
eeh_slot_availability(struct pci_dn *pdn)
{
int rc;
int rets[3];

rc = read_slot_reset_state(pdn, rets);

if (rc) return rc;

if (rets[1] == 0) return -1; /* EEH is not supported */
if (rets[0] == 0) return 0; /* Oll Korrect */
if (rets[0] == 5) {
if (rets[2] == 0) return -1; /* permanently unavailable */
return rets[2]; /* number of millisecs to wait */
}
return -1;
}

/** rtas_pci_slot_reset raises/lowers the pci #RST line
* state: 1/0 to raise/lower the #RST
*
* Clear the EEH-frozen condition on a slot. This routine
* asserts the PCI #RST line if the 'state' argument is '1',
* and drops the #RST line if 'state is '0'. This routine is
* safe to call in an interrupt context.
*
*/

static void
rtas_pci_slot_reset(struct pci_dn *pdn, int state)
{
int rc;

BUG_ON (pdn==NULL);

if (!pdn->phb) {
printk (KERN_WARNING "EEH: in slot reset, device node %s has no phb\n",
pdn->node->full_name);
return;
}

rc = rtas_call(ibm_set_slot_reset,4,1, NULL,
pdn->eeh_config_addr,
BUID_HI(pdn->phb->buid),
BUID_LO(pdn->phb->buid),
state);
if (rc) {
printk (KERN_WARNING "EEH: Unable to reset the failed slot, (%d) #RST=%d dn=%s\n",
rc, state, pdn->node->full_name);
return;
}

if (state == 0)
eeh_clear_slot (pdn->node->parent->child);
}

/** rtas_set_slot_reset -- assert the pci #RST line for 1/4 second
* dn -- device node to be reset.
*/

void
rtas_set_slot_reset(struct pci_dn *pdn)
{
int i, rc;

rtas_pci_slot_reset (pdn, 1);

/* The PCI bus requires that the reset be held high for at least
* a 100 milliseconds. We wait a bit longer 'just in case'. */

#define PCI_BUS_RST_HOLD_TIME_MSEC 250
msleep (PCI_BUS_RST_HOLD_TIME_MSEC);
rtas_pci_slot_reset (pdn, 0);

/* After a PCI slot has been reset, the PCI Express spec requires
* a 1.5 second idle time for the bus to stabilize, before starting
* up traffic. */
#define PCI_BUS_SETTLE_TIME_MSEC 1800
msleep (PCI_BUS_SETTLE_TIME_MSEC);

/* Now double check with the firmware to make sure the device is
* ready to be used; if not, wait for recovery. */
for (i=0; i<10; i++) {
rc = eeh_slot_availability (pdn);
if (rc <= 0) break;

msleep (rc+100);
}
}

/* ------------------------------------------------------------- */
/* The code below deals with enabling EEH for devices during the
* early boot sequence. EEH must be enabled before any PCI probing
Expand Down
14 changes: 14 additions & 0 deletions trunk/include/asm-powerpc/ppc-pci.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,18 @@ extern unsigned long pci_probe_only;
extern unsigned long pci_assign_all_buses;
extern int pci_read_irq_line(struct pci_dev *pci_dev);

/* ---- EEH internal-use-only related routines ---- */
#ifdef CONFIG_EEH
/**
* rtas_set_slot_reset -- unfreeze a frozen slot
*
* Clear the EEH-frozen condition on a slot. This routine
* does this by asserting the PCI #RST line for 1/8th of
* a second; this routine will sleep while the adapter is
* being reset.
*/
void rtas_set_slot_reset (struct pci_dn *);

#endif

#endif /* _ASM_POWERPC_PPC_PCI_H */

0 comments on commit ceb7780

Please sign in to comment.