[PATCH 08/21] pSeries platform EEH wait PE state

2012-02-27 Thread Gavin Shan
On pSeries platform, the PE state might be temporarily unavailable.
In that case, the firmware will return the corresponding wait time.
That means the kernel has to wait for appropriate time in order to
get the PE state.

The patch does the implementation for that. Besides, the function
has been abstracted through struct eeh_ops::wait_state so that EEH core
components could support multiple platforms in future.

Signed-off-by: Gavin Shan sha...@linux.vnet.ibm.com
---
 arch/powerpc/include/asm/ppc-pci.h   |1 -
 arch/powerpc/platforms/pseries/eeh.c |   46 +
 arch/powerpc/platforms/pseries/eeh_driver.c  |2 +-
 arch/powerpc/platforms/pseries/eeh_pseries.c |   47 +-
 4 files changed, 49 insertions(+), 47 deletions(-)

diff --git a/arch/powerpc/include/asm/ppc-pci.h 
b/arch/powerpc/include/asm/ppc-pci.h
index 6150349..1cfb2b0 100644
--- a/arch/powerpc/include/asm/ppc-pci.h
+++ b/arch/powerpc/include/asm/ppc-pci.h
@@ -58,7 +58,6 @@ struct pci_dev *pci_get_device_by_addr(unsigned long addr);
 void eeh_slot_error_detail (struct pci_dn *pdn, int severity);
 int eeh_pci_enable(struct pci_dn *pdn, int function);
 int eeh_reset_pe(struct pci_dn *);
-int eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs);
 void eeh_restore_bars(struct pci_dn *);
 void eeh_configure_bridge(struct pci_dn *);
 int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
diff --git a/arch/powerpc/platforms/pseries/eeh.c 
b/arch/powerpc/platforms/pseries/eeh.c
index 8d11f1f..b5b03d4 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -287,48 +287,6 @@ void eeh_slot_error_detail(struct pci_dn *pdn, int 
severity)
 }
 
 /**
- * eeh_wait_for_slot_status - Returns error status of slot
- * @pdn: pci device node
- * @max_wait_msecs: maximum number to millisecs to wait
- *
- * Return negative value if a permanent error, else return
- * Partition Endpoint (PE) status value.
- *
- * If @max_wait_msecs is positive, then this routine will
- * sleep until a valid status can be obtained, or until
- * the max allowed wait time is exceeded, in which case
- * a -2 is returned.
- */
-int eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs)
-{
-   int rc;
-   int mwait;
-
-   while (1) {
-   rc = eeh_ops-get_state(pdn-node, mwait);
-   if (rc != EEH_STATE_UNAVAILABLE)
-   return rc;
-
-   if (max_wait_msecs = 0) break;
-
-   if (mwait = 0) {
-   printk(KERN_WARNING EEH: Firmware returned bad wait 
value=%d\n,
-   mwait);
-   mwait = 1000;
-   } else if (mwait  300*1000) {
-   printk(KERN_WARNING EEH: Firmware is taking too long, 
time=%d\n,
-   mwait);
-   mwait = 300*1000;
-   }
-   max_wait_msecs -= mwait;
-   msleep(mwait);
-   }
-
-   printk(KERN_WARNING EEH: Timed out waiting for slot status\n);
-   return -2;
-}
-
-/**
  * eeh_token_to_phys - Convert EEH address token to phys address
  * @token: I/O token, should be address in the form 0xA
  *
@@ -640,7 +598,7 @@ int eeh_pci_enable(struct pci_dn *pdn, int function)
printk(KERN_WARNING EEH: Unexpected state change %d, err=%d 
dn=%s\n,
function, rc, pdn-node-full_name);
 
-   rc = eeh_wait_for_slot_status(pdn, PCI_BUS_RESET_WAIT_MSEC);
+   rc = eeh_ops-wait_state(pdn-node, PCI_BUS_RESET_WAIT_MSEC);
if (rc  0  (rc  EEH_STATE_MMIO_ENABLED) 
   (function == EEH_OPT_THAW_MMIO))
return 0;
@@ -838,7 +796,7 @@ int eeh_reset_pe(struct pci_dn *pdn)
for (i=0; i3; i++) {
eeh_reset_pe_once(pdn);
 
-   rc = eeh_wait_for_slot_status(pdn, PCI_BUS_RESET_WAIT_MSEC);
+   rc = eeh_ops-wait_state(pdn-node, PCI_BUS_RESET_WAIT_MSEC);
if (rc == (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE))
return 0;
 
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c 
b/arch/powerpc/platforms/pseries/eeh_driver.c
index 4c6e0c1c..584defe 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -396,7 +396,7 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
 
/* Get the current PCI slot state. This can take a long time,
 * sometimes over 3 seconds for certain systems. */
-   rc = eeh_wait_for_slot_status (frozen_pdn, MAX_WAIT_FOR_RECOVERY*1000);
+   rc = eeh_ops-wait_state(frozen_pdn-node, MAX_WAIT_FOR_RECOVERY*1000);
if (rc  0 || rc == EEH_STATE_NOT_SUPPORT) {
printk(KERN_WARNING EEH: Permanent failure\n);
goto hard_fail;
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c 

[PATCH 08/21] pSeries platform EEH wait PE state

2012-02-24 Thread Gavin Shan
On pSeries platform, the PE state might be temporarily unavailable.
In that case, the firmware will return the corresponding wait time.
That means the kernel has to wait for appropriate time in order to
get the PE state.

The patch does the implementation for that. Besides, the function
has been abstracted through struct eeh_ops::wait_state so that EEH core
components could support multiple platforms in future.

Signed-off-by: Gavin Shan sha...@linux.vnet.ibm.com
---
 arch/powerpc/include/asm/ppc-pci.h   |1 -
 arch/powerpc/platforms/pseries/eeh.c |   46 +
 arch/powerpc/platforms/pseries/eeh_driver.c  |2 +-
 arch/powerpc/platforms/pseries/eeh_pseries.c |   47 +-
 4 files changed, 49 insertions(+), 47 deletions(-)

diff --git a/arch/powerpc/include/asm/ppc-pci.h 
b/arch/powerpc/include/asm/ppc-pci.h
index 6150349..1cfb2b0 100644
--- a/arch/powerpc/include/asm/ppc-pci.h
+++ b/arch/powerpc/include/asm/ppc-pci.h
@@ -58,7 +58,6 @@ struct pci_dev *pci_get_device_by_addr(unsigned long addr);
 void eeh_slot_error_detail (struct pci_dn *pdn, int severity);
 int eeh_pci_enable(struct pci_dn *pdn, int function);
 int eeh_reset_pe(struct pci_dn *);
-int eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs);
 void eeh_restore_bars(struct pci_dn *);
 void eeh_configure_bridge(struct pci_dn *);
 int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
diff --git a/arch/powerpc/platforms/pseries/eeh.c 
b/arch/powerpc/platforms/pseries/eeh.c
index 8d11f1f..b5b03d4 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -287,48 +287,6 @@ void eeh_slot_error_detail(struct pci_dn *pdn, int 
severity)
 }
 
 /**
- * eeh_wait_for_slot_status - Returns error status of slot
- * @pdn: pci device node
- * @max_wait_msecs: maximum number to millisecs to wait
- *
- * Return negative value if a permanent error, else return
- * Partition Endpoint (PE) status value.
- *
- * If @max_wait_msecs is positive, then this routine will
- * sleep until a valid status can be obtained, or until
- * the max allowed wait time is exceeded, in which case
- * a -2 is returned.
- */
-int eeh_wait_for_slot_status(struct pci_dn *pdn, int max_wait_msecs)
-{
-   int rc;
-   int mwait;
-
-   while (1) {
-   rc = eeh_ops-get_state(pdn-node, mwait);
-   if (rc != EEH_STATE_UNAVAILABLE)
-   return rc;
-
-   if (max_wait_msecs = 0) break;
-
-   if (mwait = 0) {
-   printk(KERN_WARNING EEH: Firmware returned bad wait 
value=%d\n,
-   mwait);
-   mwait = 1000;
-   } else if (mwait  300*1000) {
-   printk(KERN_WARNING EEH: Firmware is taking too long, 
time=%d\n,
-   mwait);
-   mwait = 300*1000;
-   }
-   max_wait_msecs -= mwait;
-   msleep(mwait);
-   }
-
-   printk(KERN_WARNING EEH: Timed out waiting for slot status\n);
-   return -2;
-}
-
-/**
  * eeh_token_to_phys - Convert EEH address token to phys address
  * @token: I/O token, should be address in the form 0xA
  *
@@ -640,7 +598,7 @@ int eeh_pci_enable(struct pci_dn *pdn, int function)
printk(KERN_WARNING EEH: Unexpected state change %d, err=%d 
dn=%s\n,
function, rc, pdn-node-full_name);
 
-   rc = eeh_wait_for_slot_status(pdn, PCI_BUS_RESET_WAIT_MSEC);
+   rc = eeh_ops-wait_state(pdn-node, PCI_BUS_RESET_WAIT_MSEC);
if (rc  0  (rc  EEH_STATE_MMIO_ENABLED) 
   (function == EEH_OPT_THAW_MMIO))
return 0;
@@ -838,7 +796,7 @@ int eeh_reset_pe(struct pci_dn *pdn)
for (i=0; i3; i++) {
eeh_reset_pe_once(pdn);
 
-   rc = eeh_wait_for_slot_status(pdn, PCI_BUS_RESET_WAIT_MSEC);
+   rc = eeh_ops-wait_state(pdn-node, PCI_BUS_RESET_WAIT_MSEC);
if (rc == (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE))
return 0;
 
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c 
b/arch/powerpc/platforms/pseries/eeh_driver.c
index 4c6e0c1c..584defe 100644
--- a/arch/powerpc/platforms/pseries/eeh_driver.c
+++ b/arch/powerpc/platforms/pseries/eeh_driver.c
@@ -396,7 +396,7 @@ struct pci_dn * handle_eeh_events (struct eeh_event *event)
 
/* Get the current PCI slot state. This can take a long time,
 * sometimes over 3 seconds for certain systems. */
-   rc = eeh_wait_for_slot_status (frozen_pdn, MAX_WAIT_FOR_RECOVERY*1000);
+   rc = eeh_ops-wait_state(frozen_pdn-node, MAX_WAIT_FOR_RECOVERY*1000);
if (rc  0 || rc == EEH_STATE_NOT_SUPPORT) {
printk(KERN_WARNING EEH: Permanent failure\n);
goto hard_fail;
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c