[PATCH 05/21] pSeries platform EEH operation

2012-02-27 Thread Gavin Shan
There're 4 EEH operations that are covered by the dedicated RTAS
call ibm,set-eeh-option: enable or disable EEH, enable MMIO and
enable DMA. At early stage of system boot, the EEH would be tried
to enable on PCI device related device node. MMIO and DMA for
particular PE should be enabled when doing recovery on EEH errors
so that the PE could function properly again.

The patch implements it and abstract that through struct
eeh_ops::set_eeh. It would be help for EEH to support multiple
platforms in future.

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

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index 0666c52..76f7b3f 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -38,6 +38,10 @@ struct device_node;
  * platform should register its own EEH operation callback
  * functions before any EEH further operations.
  */
+#define EEH_OPT_DISABLE0   /* EEH disable  */
+#define EEH_OPT_ENABLE 1   /* EEH enable   */
+#define EEH_OPT_THAW_MMIO  2   /* MMIO enable  */
+#define EEH_OPT_THAW_DMA   3   /* DMA enable   */
 struct eeh_ops {
char *name;
int (*init)(void);
diff --git a/arch/powerpc/include/asm/ppc-pci.h 
b/arch/powerpc/include/asm/ppc-pci.h
index 605a970..6150349 100644
--- a/arch/powerpc/include/asm/ppc-pci.h
+++ b/arch/powerpc/include/asm/ppc-pci.h
@@ -56,8 +56,6 @@ struct pci_dev *pci_get_device_by_addr(unsigned long addr);
 #define EEH_LOG_TEMP_FAILURE 1
 #define EEH_LOG_PERM_FAILURE 2
 void eeh_slot_error_detail (struct pci_dn *pdn, int severity);
-#define EEH_THAW_MMIO 2
-#define EEH_THAW_DMA  3
 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);
diff --git a/arch/powerpc/platforms/pseries/eeh.c 
b/arch/powerpc/platforms/pseries/eeh.c
index bb6de6c..70a9617 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -87,7 +87,6 @@
 #define PCI_BUS_RESET_WAIT_MSEC (60*1000)
 
 /* RTAS tokens */
-static int ibm_set_eeh_option;
 static int ibm_set_slot_reset;
 static int ibm_read_slot_reset_state;
 static int ibm_read_slot_reset_state2;
@@ -283,7 +282,7 @@ void eeh_slot_error_detail(struct pci_dn *pdn, int severity)
size_t loglen = 0;
pci_regs_buf[0] = 0;
 
-   eeh_pci_enable(pdn, EEH_THAW_MMIO);
+   eeh_pci_enable(pdn, EEH_OPT_THAW_MMIO);
eeh_configure_bridge(pdn);
eeh_restore_bars(pdn);
loglen = eeh_gather_pci_data(pdn, pci_regs_buf, EEH_PCI_REGS_LOG_LEN);
@@ -698,26 +697,15 @@ EXPORT_SYMBOL(eeh_check_failure);
  */
 int eeh_pci_enable(struct pci_dn *pdn, int function)
 {
-   int config_addr;
int rc;
 
-   /* Use PE configuration address, if present */
-   config_addr = pdn-eeh_config_addr;
-   if (pdn-eeh_pe_config_addr)
-   config_addr = pdn-eeh_pe_config_addr;
-
-   rc = rtas_call(ibm_set_eeh_option, 4, 1, NULL,
-  config_addr,
-  BUID_HI(pdn-phb-buid),
-  BUID_LO(pdn-phb-buid),
-   function);
-
+   rc = eeh_ops-set_option(pdn-node, function);
if (rc)
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);
-   if ((rc == 4)  (function == EEH_THAW_MMIO))
+   if ((rc == 4)  (function == EEH_OPT_THAW_MMIO))
return 0;
 
return rc;
@@ -1158,9 +1146,7 @@ static void *eeh_early_enable(struct device_node *dn, 
void *data)
if (regs) {
/* First register entry is addr (00BBSS00)  */
/* Try to enable eeh */
-   ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL,
-   regs[0], info-buid_hi, info-buid_lo,
-   EEH_ENABLE);
+   ret = eeh_ops-set_option(dn, EEH_OPT_ENABLE);
 
enable = 0;
if (ret == 0) {
@@ -1299,7 +1285,6 @@ void __init eeh_init(void)
if (np == NULL)
return;
 
-   ibm_set_eeh_option = rtas_token(ibm,set-eeh-option);
ibm_set_slot_reset = rtas_token(ibm,set-slot-reset);
ibm_read_slot_reset_state2 = rtas_token(ibm,read-slot-reset-state2);
ibm_read_slot_reset_state = rtas_token(ibm,read-slot-reset-state);
@@ -1309,9 +1294,6 @@ void __init eeh_init(void)
ibm_configure_bridge = 

[PATCH 05/21] pSeries platform EEH operation

2012-02-24 Thread Gavin Shan
There're 4 EEH operations that are covered by the dedicated RTAS
call ibm,set-eeh-option: enable or disable EEH, enable MMIO and
enable DMA. At early stage of system boot, the EEH would be tried
to enable on PCI device related device node. MMIO and DMA for
particular PE should be enabled when doing recovery on EEH errors
so that the PE could function properly again.

The patch implements it and abstract that through struct
eeh_ops::set_eeh. It would be help for EEH to support multiple
platforms in future.

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

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index 0666c52..76f7b3f 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -38,6 +38,10 @@ struct device_node;
  * platform should register its own EEH operation callback
  * functions before any EEH further operations.
  */
+#define EEH_OPT_DISABLE0   /* EEH disable  */
+#define EEH_OPT_ENABLE 1   /* EEH enable   */
+#define EEH_OPT_THAW_MMIO  2   /* MMIO enable  */
+#define EEH_OPT_THAW_DMA   3   /* DMA enable   */
 struct eeh_ops {
char *name;
int (*init)(void);
diff --git a/arch/powerpc/include/asm/ppc-pci.h 
b/arch/powerpc/include/asm/ppc-pci.h
index 605a970..6150349 100644
--- a/arch/powerpc/include/asm/ppc-pci.h
+++ b/arch/powerpc/include/asm/ppc-pci.h
@@ -56,8 +56,6 @@ struct pci_dev *pci_get_device_by_addr(unsigned long addr);
 #define EEH_LOG_TEMP_FAILURE 1
 #define EEH_LOG_PERM_FAILURE 2
 void eeh_slot_error_detail (struct pci_dn *pdn, int severity);
-#define EEH_THAW_MMIO 2
-#define EEH_THAW_DMA  3
 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);
diff --git a/arch/powerpc/platforms/pseries/eeh.c 
b/arch/powerpc/platforms/pseries/eeh.c
index bb6de6c..70a9617 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -87,7 +87,6 @@
 #define PCI_BUS_RESET_WAIT_MSEC (60*1000)
 
 /* RTAS tokens */
-static int ibm_set_eeh_option;
 static int ibm_set_slot_reset;
 static int ibm_read_slot_reset_state;
 static int ibm_read_slot_reset_state2;
@@ -283,7 +282,7 @@ void eeh_slot_error_detail(struct pci_dn *pdn, int severity)
size_t loglen = 0;
pci_regs_buf[0] = 0;
 
-   eeh_pci_enable(pdn, EEH_THAW_MMIO);
+   eeh_pci_enable(pdn, EEH_OPT_THAW_MMIO);
eeh_configure_bridge(pdn);
eeh_restore_bars(pdn);
loglen = eeh_gather_pci_data(pdn, pci_regs_buf, EEH_PCI_REGS_LOG_LEN);
@@ -698,26 +697,15 @@ EXPORT_SYMBOL(eeh_check_failure);
  */
 int eeh_pci_enable(struct pci_dn *pdn, int function)
 {
-   int config_addr;
int rc;
 
-   /* Use PE configuration address, if present */
-   config_addr = pdn-eeh_config_addr;
-   if (pdn-eeh_pe_config_addr)
-   config_addr = pdn-eeh_pe_config_addr;
-
-   rc = rtas_call(ibm_set_eeh_option, 4, 1, NULL,
-  config_addr,
-  BUID_HI(pdn-phb-buid),
-  BUID_LO(pdn-phb-buid),
-   function);
-
+   rc = eeh_ops-set_option(pdn-node, function);
if (rc)
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);
-   if ((rc == 4)  (function == EEH_THAW_MMIO))
+   if ((rc == 4)  (function == EEH_OPT_THAW_MMIO))
return 0;
 
return rc;
@@ -1158,9 +1146,7 @@ static void *eeh_early_enable(struct device_node *dn, 
void *data)
if (regs) {
/* First register entry is addr (00BBSS00)  */
/* Try to enable eeh */
-   ret = rtas_call(ibm_set_eeh_option, 4, 1, NULL,
-   regs[0], info-buid_hi, info-buid_lo,
-   EEH_ENABLE);
+   ret = eeh_ops-set_option(dn, EEH_OPT_ENABLE);
 
enable = 0;
if (ret == 0) {
@@ -1299,7 +1285,6 @@ void __init eeh_init(void)
if (np == NULL)
return;
 
-   ibm_set_eeh_option = rtas_token(ibm,set-eeh-option);
ibm_set_slot_reset = rtas_token(ibm,set-slot-reset);
ibm_read_slot_reset_state2 = rtas_token(ibm,read-slot-reset-state2);
ibm_read_slot_reset_state = rtas_token(ibm,read-slot-reset-state);
@@ -1309,9 +1294,6 @@ void __init eeh_init(void)
ibm_configure_bridge =