[Skiboot] [PATCH v7 16/17] core/opal: Switch to PCI slot

Gavin Shan gwshan at linux.vnet.ibm.com
Thu Jun 4 16:19:08 AEST 2015


Apart from IODA table and error injection reset, we use PCI slot
to help completing various resets. It's notable that bit#0 of
"id" is indicator of compound (PHB OPAL ID + Slot ID), or just
slot ID. In order for back-compatibility, PHB OPAL ID is stored
in bits[48:63] while slot ID stored in bits[32:47].

The patch also adds two more OPAL APIs to help managing PCI slots:
opal_pci_get_power_status() and opal_pci_get_presence_status().
Those two APIs might need run internal state machine to get the
final result and opal_pci_poll() is involved for that.

Signed-off-by: Gavin Shan <gwshan at linux.vnet.ibm.com>
---
 core/pci-opal.c    | 168 +++++++++++++++++++++++++++++++++++------------------
 include/opal-api.h |   5 +-
 include/pci.h      |  72 -----------------------
 3 files changed, 117 insertions(+), 128 deletions(-)

diff --git a/core/pci-opal.c b/core/pci-opal.c
index 75c689e..5dae0e3 100644
--- a/core/pci-opal.c
+++ b/core/pci-opal.c
@@ -16,8 +16,9 @@
 
 #include <skiboot.h>
 #include <opal-api.h>
-#include <pci.h>
 #include <pci-cfg.h>
+#include <pci.h>
+#include <pci-slot.h>
 #include <timebase.h>
 #include <lock.h>
 
@@ -481,83 +482,95 @@ static int64_t opal_pci_map_pe_dma_window_real(uint64_t phb_id,
 }
 opal_call(OPAL_PCI_MAP_PE_DMA_WINDOW_REAL, opal_pci_map_pe_dma_window_real, 5);
 
-static int64_t opal_pci_reset(uint64_t phb_id, uint8_t reset_scope,
-                              uint8_t assert_state)
+static int64_t opal_pci_ret_to_ms(int64_t val)
+{
+	/*
+	 * If the return value is positive, translate
+	 * it to milliseconds. Otherwise, the original
+	 * value is returned
+	 */
+	if (val > 0) {
+		val = tb_to_msecs(val);
+		if (val == 0)
+			val = 1;
+	}
+
+	return val;
+}
+
+static int64_t opal_pci_reset(uint64_t id,
+			      uint8_t reset_scope,
+			      uint8_t assert_state)
 {
-	struct phb *phb = pci_get_phb(phb_id);
+	struct pci_slot *slot = pci_slot_find(id);
 	int64_t rc = OPAL_SUCCESS;
 
-	if (!phb)
+	if (!slot || !slot->phb || !slot->phb->ops || !slot->phb->ops->lock)
 		return OPAL_PARAMETER;
-	if (!phb->ops)
-		return OPAL_UNSUPPORTED;
 	if (assert_state != OPAL_ASSERT_RESET &&
 	    assert_state != OPAL_DEASSERT_RESET)
 		return OPAL_PARAMETER;
 
-	phb->ops->lock(phb);
+	slot->phb->ops->lock(slot->phb);
 
 	switch(reset_scope) {
 	case OPAL_RESET_PHB_COMPLETE:
-		if (!phb->ops->complete_reset) {
+		if (assert_state != OPAL_ASSERT_RESET)
+			break;
+		if (!slot->ops.creset) {
 			rc = OPAL_UNSUPPORTED;
 			break;
 		}
 
-		rc = phb->ops->complete_reset(phb, assert_state);
-		if (rc < 0)
-			prerror("PHB#%d: Failure on complete reset, rc=%lld\n",
-				phb->opal_id, rc);
+		rc = slot->ops.creset(slot);
 		break;
 	case OPAL_RESET_PCI_FUNDAMENTAL:
-		if (!phb->ops->fundamental_reset) {
+		if (assert_state != OPAL_ASSERT_RESET)
+			break;
+		if (!slot->ops.freset) {
 			rc = OPAL_UNSUPPORTED;
 			break;
 		}
 
-		/* We need do nothing on deassert time */
-		if (assert_state != OPAL_ASSERT_RESET)
-			break;
-
-		rc = phb->ops->fundamental_reset(phb);
-		if (rc < 0)
-			prerror("PHB#%d: Failure on fundamental reset, rc=%lld\n",
-				phb->opal_id, rc);
+		rc = slot->ops.freset(slot);
 		break;
 	case OPAL_RESET_PCI_HOT:
-		if (!phb->ops->hot_reset) {
+		if (assert_state != OPAL_ASSERT_RESET)
+			break;
+		if (!slot->ops.hreset) {
 			rc = OPAL_UNSUPPORTED;
 			break;
 		}
 
-		/* We need do nothing on deassert time */
-		if (assert_state != OPAL_ASSERT_RESET)
-			break;
-
-		rc = phb->ops->hot_reset(phb);
-		if (rc < 0)
-			prerror("PHB#%d: Failure on hot reset, rc=%lld\n",
-				phb->opal_id, rc);
+		rc = slot->ops.hreset(slot);
 		break;
 	case OPAL_RESET_PCI_IODA_TABLE:
 		if (assert_state != OPAL_ASSERT_RESET)
 			break;
-		if (phb->ops->ioda_reset)
-			phb->ops->ioda_reset(phb, true);
+		if (!slot->phb->ops->ioda_reset) {
+			rc = OPAL_UNSUPPORTED;
+			break;
+		}
+
+		rc = slot->phb->ops->ioda_reset(slot->phb, true);
 		break;
 	case OPAL_RESET_PHB_ERROR:
 		if (assert_state != OPAL_ASSERT_RESET)
 			break;
-		if (phb->ops->papr_errinjct_reset)
-			phb->ops->papr_errinjct_reset(phb);
+		if (!slot->phb->ops->papr_errinjct_reset) {
+			rc = OPAL_UNSUPPORTED;
+			break;
+		}
+
+		rc = slot->phb->ops->papr_errinjct_reset(slot->phb);
 		break;
 	default:
 		rc = OPAL_UNSUPPORTED;
 	}
-	phb->ops->unlock(phb);
-	pci_put_phb(phb);
+	slot->phb->ops->unlock(slot->phb);
+	pci_put_phb(slot->phb);
 
-	return (rc > 0) ? tb_to_msecs(rc) : rc;
+	return opal_pci_ret_to_ms(rc);
 }
 opal_call(OPAL_PCI_RESET, opal_pci_reset, 3);
 
@@ -582,31 +595,76 @@ static int64_t opal_pci_reinit(uint64_t phb_id,
 }
 opal_call(OPAL_PCI_REINIT, opal_pci_reinit, 3);
 
-static int64_t opal_pci_poll(uint64_t phb_id)
+static int64_t opal_pci_get_presence_status(uint64_t id, uint8_t *val)
 {
-	struct phb *phb = pci_get_phb(phb_id);
-	int64_t rc;
+	struct pci_slot *slot = pci_slot_find(id);
+	int64_t rc = OPAL_SUCCESS;
 
-	if (!phb)
+	if (!slot || !slot->phb || !slot->phb->ops || !slot->phb->ops->lock)
 		return OPAL_PARAMETER;
-	if (!phb->ops || !phb->ops->poll)
+	if (!slot->ops.get_presence_status)
 		return OPAL_UNSUPPORTED;
 
-	phb->ops->lock(phb);
-	rc = phb->ops->poll(phb);
-	phb->ops->unlock(phb);
-	pci_put_phb(phb);
+	slot->phb->ops->lock(slot->phb);
+	rc = slot->ops.get_presence_status(slot, val);
+	slot->phb->ops->unlock(slot->phb);
+	pci_put_phb(slot->phb);
+	return opal_pci_ret_to_ms(rc);
+}
+opal_call(OPAL_PCI_GET_PRESENCE_STATUS, opal_pci_get_presence_status, 2);
 
-	/* Return milliseconds for caller to sleep: round up */
-	if (rc > 0) {
-		rc = tb_to_msecs(rc);
-		if (rc == 0)
-			rc = 1;
-	}
+static int64_t opal_pci_get_power_status(uint64_t id, uint8_t *val)
+{
+	struct pci_slot *slot = pci_slot_find(id);
+	int64_t rc = OPAL_SUCCESS;
 
-	return rc;
+	if (!slot || !slot->phb || !slot->phb->ops || !slot->phb->ops->lock)
+		return OPAL_PARAMETER;
+	if (!slot->ops.get_power_status)
+		return OPAL_UNSUPPORTED;
+
+	slot->phb->ops->lock(slot->phb);
+	rc = slot->ops.get_power_status(slot, val);
+	slot->phb->ops->unlock(slot->phb);
+	pci_put_phb(slot->phb);
+	return opal_pci_ret_to_ms(rc);
+}
+opal_call(OPAL_PCI_GET_POWER_STATUS, opal_pci_get_power_status, 2);
+
+static int64_t opal_pci_set_power_status(uint64_t id, uint8_t val)
+{
+	struct pci_slot *slot = pci_slot_find(id);
+	int64_t rc = OPAL_SUCCESS;
+
+	if (!slot || !slot->phb || !slot->phb->ops || !slot->phb->ops->lock)
+		return OPAL_PARAMETER;
+	if (!slot->ops.get_power_status)
+		return OPAL_UNSUPPORTED;
+
+	slot->phb->ops->lock(slot->phb);
+	rc = slot->ops.set_power_status(slot, val);
+	slot->phb->ops->unlock(slot->phb);
+	pci_put_phb(slot->phb);
+	return opal_pci_ret_to_ms(rc);
+}
+opal_call(OPAL_PCI_SET_POWER_STATUS, opal_pci_set_power_status, 2);
+
+static int64_t opal_pci_poll(uint64_t id, uint8_t *val)
+{
+	struct pci_slot *slot = pci_slot_find(id);
+	int64_t rc;
+
+	if (!slot || !slot->phb || !slot->phb->ops || !slot->phb->ops->lock)
+		return OPAL_PARAMETER;
+
+	slot->phb->ops->lock(slot->phb);
+	rc = slot->ops.poll(slot, val);
+	slot->phb->ops->unlock(slot->phb);
+	pci_put_phb(slot->phb);
+
+	return opal_pci_ret_to_ms(rc);
 }
-opal_call(OPAL_PCI_POLL, opal_pci_poll, 1);
+opal_call(OPAL_PCI_POLL, opal_pci_poll, 2);
 
 static int64_t opal_pci_set_phb_tce_memory(uint64_t phb_id,
 					   uint64_t tce_mem_addr,
diff --git a/include/opal-api.h b/include/opal-api.h
index 27a4b4c..f3a653f 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -162,7 +162,10 @@
 #define OPAL_LEDS_GET_INDICATOR			114
 #define OPAL_LEDS_SET_INDICATOR			115
 #define OPAL_GET_OVERLAY_DT			116
-#define OPAL_LAST				115
+#define OPAL_PCI_GET_PRESENCE_STATUS		117
+#define OPAL_PCI_GET_POWER_STATUS		118
+#define OPAL_PCI_SET_POWER_STATUS		119
+#define OPAL_LAST				119
 
 /* Device tree flags */
 
diff --git a/include/pci.h b/include/pci.h
index 1e23be8..405755f 100644
--- a/include/pci.h
+++ b/include/pci.h
@@ -269,78 +269,6 @@ struct phb_ops {
 	 */
 	int64_t (*pci_msi_eoi)(struct phb *phb, uint32_t hwirq);
 
-	/*
-	 * Slot control
-	 */
-
-	/* presence_detect - Check for a present device
-	 *
-	 * Immediate return of:
-	 *
-	 * OPAL_SHPC_DEV_NOT_PRESENT = 0,
-	 * OPAL_SHPC_DEV_PRESENT = 1
-	 *
-	 * or a negative OPAL error code
-	 */
-	int64_t (*presence_detect)(struct phb *phb);
-
-	/* link_state - Check link state
-	 *
-	 * Immediate return of:
-	 *
-	 * OPAL_SHPC_LINK_DOWN = 0,
-	 * OPAL_SHPC_LINK_UP_x1 = 1,
-	 * OPAL_SHPC_LINK_UP_x2 = 2,
-	 * OPAL_SHPC_LINK_UP_x4 = 4,
-	 * OPAL_SHPC_LINK_UP_x8 = 8,
-	 * OPAL_SHPC_LINK_UP_x16 = 16,
-	 * OPAL_SHPC_LINK_UP_x32 = 32
-	 *
-	 * or a negative OPAL error code
-	 */
-	int64_t (*link_state)(struct phb *phb);
-
-	/* power_state - Check slot power state
-	 *
-	 * Immediate return of:
-	 *
-	 * OPAL_SLOT_POWER_OFF = 0,
-	 * OPAL_SLOT_POWER_ON = 1,
-	 *
-	 * or a negative OPAL error code
-	 */
-	int64_t (*power_state)(struct phb *phb);
-
-	/* slot_power_off - Start slot power off sequence
-	 *
-	 * Asynchronous function, returns a positive delay
-	 * or a negative error code
-	 */
-	int64_t (*slot_power_off)(struct phb *phb);
-
-	/* slot_power_on - Start slot power on sequence
-	 *
-	 * Asynchronous function, returns a positive delay
-	 * or a negative error code.
-	 */
-	int64_t (*slot_power_on)(struct phb *phb);
-
-	/* PHB power off and on after complete init */
-	int64_t (*complete_reset)(struct phb *phb, uint8_t assert);
-
-	/* hot_reset - Hot Reset sequence */
-	int64_t (*hot_reset)(struct phb *phb);
-
-	/* Fundamental reset */
-	int64_t (*fundamental_reset)(struct phb *phb);
-
-	/* poll - Poll and advance asynchronous operations
-	 *
-	 * Returns a positive delay, 0 for success or a
-	 * negative OPAL error code
-	 */
-	int64_t (*poll)(struct phb *phb);
-
 	/* Put phb in capi mode or pcie mode */
 	int64_t (*set_capi_mode)(struct phb *phb, uint64_t mode, uint64_t pe_number);
 
-- 
2.1.0



More information about the Skiboot mailing list