[PATCH 09/21] pSeries platform EEH reset PE

2012-02-27 Thread Gavin Shan
On RTAS compliant pSeries platform, there is a dedicated RTAS call
(ibm,set-slot-reset) to reset the specified PE. Furthermore, two
types of resets are supported: hot and fundamental. the type of
reset is to be used actually depends on the included PCI device's
requirements.

The patch implements resetting PE on pSeries platform through RTAS
call. Besides, it has been abstracted through struct eeh_ops::reset
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/eeh.h   |3 +
 arch/powerpc/platforms/pseries/eeh.c |   63 +++---
 arch/powerpc/platforms/pseries/eeh_pseries.c |   25 ++-
 3 files changed, 33 insertions(+), 58 deletions(-)

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index 1d3c9e5..894ea6c 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -49,6 +49,9 @@ struct device_node;
 #define EEH_STATE_DMA_ACTIVE   (1  4)/* Active DMA   */
 #define EEH_STATE_MMIO_ENABLED (1  5)/* MMIO enabled */
 #define EEH_STATE_DMA_ENABLED  (1  6)/* DMA enabled  */
+#define EEH_RESET_DEACTIVATE   0   /* Deactivate the PE reset  */
+#define EEH_RESET_HOT  1   /* Hot reset*/
+#define EEH_RESET_FUNDAMENTAL  3   /* Fundamental reset*/
 
 struct eeh_ops {
char *name;
diff --git a/arch/powerpc/platforms/pseries/eeh.c 
b/arch/powerpc/platforms/pseries/eeh.c
index b5b03d4..4f329f5 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_slot_reset;
 static int ibm_slot_error_detail;
 static int ibm_configure_bridge;
 static int ibm_configure_pe;
@@ -607,54 +606,6 @@ int eeh_pci_enable(struct pci_dn *pdn, int function)
 }
 
 /**
- * eeh_slot_reset - Raises/Lowers the pci #RST line
- * @pdn: pci device node
- * @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 eeh_slot_reset(struct pci_dn *pdn, int state)
-{
-   int config_addr;
-   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;
-   }
-
-   /* 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_slot_reset, 4, 1, NULL,
-  config_addr,
-  BUID_HI(pdn-phb-buid),
-  BUID_LO(pdn-phb-buid),
-  state);
-
-   /* Fundamental-reset not supported on this PE, try hot-reset */
-   if (rc == -8  state == 3) {
-   rc = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
-  config_addr,
-  BUID_HI(pdn-phb-buid),
-  BUID_LO(pdn-phb-buid), 1);
-   if (rc)
-   printk(KERN_WARNING
-   EEH: Unable to reset the failed slot,
-#RST=%d dn=%s\n,
-   rc, pdn-node-full_name);
-   }
-}
-
-/**
  * pcibios_set_pcie_slot_reset - Set PCI-E reset state
  * @dev: pci device struct
  * @state: reset state to enter
@@ -665,17 +616,16 @@ static void eeh_slot_reset(struct pci_dn *pdn, int state)
 int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state 
state)
 {
struct device_node *dn = pci_device_to_OF_node(dev);
-   struct pci_dn *pdn = PCI_DN(dn);
 
switch (state) {
case pcie_deassert_reset:
-   eeh_slot_reset(pdn, 0);
+   eeh_ops-reset(dn, EEH_RESET_DEACTIVATE);
break;
case pcie_hot_reset:
-   eeh_slot_reset(pdn, 1);
+   eeh_ops-reset(dn, EEH_RESET_HOT);
break;
case pcie_warm_reset:
-   eeh_slot_reset(pdn, 3);
+   eeh_ops-reset(dn, EEH_RESET_FUNDAMENTAL);
break;
default:
return -EINVAL;
@@ -754,9 +704,9 @@ static void eeh_reset_pe_once(struct pci_dn *pdn)
eeh_set_pe_freset(pdn-node, freset);
 
if (freset)
-   eeh_slot_reset(pdn, 3);
+   eeh_ops-reset(pdn-node, EEH_RESET_FUNDAMENTAL);
else
-   eeh_slot_reset(pdn, 1);
+   eeh_ops-reset(pdn-node, EEH_RESET_HOT);
 
/* The PCI bus requires that the reset be held 

[PATCH 09/21] pSeries platform EEH reset PE

2012-02-24 Thread Gavin Shan
On RTAS compliant pSeries platform, there is a dedicated RTAS call
(ibm,set-slot-reset) to reset the specified PE. Furthermore, two
types of resets are supported: hot and fundamental. the type of
reset is to be used actually depends on the included PCI device's
requirements.

The patch implements resetting PE on pSeries platform through RTAS
call. Besides, it has been abstracted through struct eeh_ops::reset
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/eeh.h   |3 +
 arch/powerpc/platforms/pseries/eeh.c |   63 +++---
 arch/powerpc/platforms/pseries/eeh_pseries.c |   25 ++-
 3 files changed, 33 insertions(+), 58 deletions(-)

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index 1d3c9e5..894ea6c 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -49,6 +49,9 @@ struct device_node;
 #define EEH_STATE_DMA_ACTIVE   (1  4)/* Active DMA   */
 #define EEH_STATE_MMIO_ENABLED (1  5)/* MMIO enabled */
 #define EEH_STATE_DMA_ENABLED  (1  6)/* DMA enabled  */
+#define EEH_RESET_DEACTIVATE   0   /* Deactivate the PE reset  */
+#define EEH_RESET_HOT  1   /* Hot reset*/
+#define EEH_RESET_FUNDAMENTAL  3   /* Fundamental reset*/
 
 struct eeh_ops {
char *name;
diff --git a/arch/powerpc/platforms/pseries/eeh.c 
b/arch/powerpc/platforms/pseries/eeh.c
index b5b03d4..4f329f5 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_slot_reset;
 static int ibm_slot_error_detail;
 static int ibm_configure_bridge;
 static int ibm_configure_pe;
@@ -607,54 +606,6 @@ int eeh_pci_enable(struct pci_dn *pdn, int function)
 }
 
 /**
- * eeh_slot_reset - Raises/Lowers the pci #RST line
- * @pdn: pci device node
- * @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 eeh_slot_reset(struct pci_dn *pdn, int state)
-{
-   int config_addr;
-   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;
-   }
-
-   /* 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_slot_reset, 4, 1, NULL,
-  config_addr,
-  BUID_HI(pdn-phb-buid),
-  BUID_LO(pdn-phb-buid),
-  state);
-
-   /* Fundamental-reset not supported on this PE, try hot-reset */
-   if (rc == -8  state == 3) {
-   rc = rtas_call(ibm_set_slot_reset, 4, 1, NULL,
-  config_addr,
-  BUID_HI(pdn-phb-buid),
-  BUID_LO(pdn-phb-buid), 1);
-   if (rc)
-   printk(KERN_WARNING
-   EEH: Unable to reset the failed slot,
-#RST=%d dn=%s\n,
-   rc, pdn-node-full_name);
-   }
-}
-
-/**
  * pcibios_set_pcie_slot_reset - Set PCI-E reset state
  * @dev: pci device struct
  * @state: reset state to enter
@@ -665,17 +616,16 @@ static void eeh_slot_reset(struct pci_dn *pdn, int state)
 int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state 
state)
 {
struct device_node *dn = pci_device_to_OF_node(dev);
-   struct pci_dn *pdn = PCI_DN(dn);
 
switch (state) {
case pcie_deassert_reset:
-   eeh_slot_reset(pdn, 0);
+   eeh_ops-reset(dn, EEH_RESET_DEACTIVATE);
break;
case pcie_hot_reset:
-   eeh_slot_reset(pdn, 1);
+   eeh_ops-reset(dn, EEH_RESET_HOT);
break;
case pcie_warm_reset:
-   eeh_slot_reset(pdn, 3);
+   eeh_ops-reset(dn, EEH_RESET_FUNDAMENTAL);
break;
default:
return -EINVAL;
@@ -754,9 +704,9 @@ static void eeh_reset_pe_once(struct pci_dn *pdn)
eeh_set_pe_freset(pdn-node, freset);
 
if (freset)
-   eeh_slot_reset(pdn, 3);
+   eeh_ops-reset(pdn-node, EEH_RESET_FUNDAMENTAL);
else
-   eeh_slot_reset(pdn, 1);
+   eeh_ops-reset(pdn-node, EEH_RESET_HOT);
 
/* The PCI bus requires that the reset be held