From patchwork Thu Jun 4 06:19:08 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gavin Shan X-Patchwork-Id: 480430 X-Patchwork-Delegate: benh@kernel.crashing.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 5C6111402B1 for ; Thu, 4 Jun 2015 16:20:29 +1000 (AEST) Received: from ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 40B121A0ACC for ; Thu, 4 Jun 2015 16:20:29 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from e23smtp03.au.ibm.com (e23smtp03.au.ibm.com [202.81.31.145]) (using TLSv1 with cipher CAMELLIA256-SHA (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 1FE7B1A025F for ; Thu, 4 Jun 2015 16:20:13 +1000 (AEST) Received: from /spool/local by e23smtp03.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 4 Jun 2015 16:20:12 +1000 Received: from d23dlp02.au.ibm.com (202.81.31.213) by e23smtp03.au.ibm.com (202.81.31.209) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 4 Jun 2015 16:20:10 +1000 Received: from d23relay08.au.ibm.com (d23relay08.au.ibm.com [9.185.71.33]) by d23dlp02.au.ibm.com (Postfix) with ESMTP id 7354F2BB0060 for ; Thu, 4 Jun 2015 16:20:09 +1000 (EST) Received: from d23av02.au.ibm.com (d23av02.au.ibm.com [9.190.235.138]) by d23relay08.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t546Jxw165208410 for ; Thu, 4 Jun 2015 16:20:08 +1000 Received: from d23av02.au.ibm.com (localhost [127.0.0.1]) by d23av02.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t546Ja1U030272 for ; Thu, 4 Jun 2015 16:19:36 +1000 Received: from ozlabs.au.ibm.com (ozlabs.au.ibm.com [9.192.253.14]) by d23av02.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t546JZL0029443; Thu, 4 Jun 2015 16:19:36 +1000 Received: from bran.ozlabs.ibm.com (unknown [9.192.254.114]) by ozlabs.au.ibm.com (Postfix) with ESMTP id 02CFDA03E9; Thu, 4 Jun 2015 16:19:15 +1000 (AEST) Received: from gwshan (shangw.ozlabs.ibm.com [10.61.2.199]) by bran.ozlabs.ibm.com (Postfix) with ESMTP id 0EEE7E387C; Thu, 4 Jun 2015 16:19:15 +1000 (AEST) Received: by gwshan (Postfix, from userid 1000) id 030289422B2; Thu, 4 Jun 2015 16:19:14 +1000 (AEST) From: Gavin Shan To: skiboot@lists.ozlabs.org Date: Thu, 4 Jun 2015 16:19:08 +1000 Message-Id: <1433398749-15096-17-git-send-email-gwshan@linux.vnet.ibm.com> X-Mailer: git-send-email 2.1.0 In-Reply-To: <1433398749-15096-1-git-send-email-gwshan@linux.vnet.ibm.com> References: <1433398749-15096-1-git-send-email-gwshan@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15060406-0009-0000-0000-00000183D1B5 Subject: [Skiboot] [PATCH v7 16/17] core/opal: Switch to PCI slot X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" 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 --- 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 #include -#include #include +#include +#include #include #include @@ -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);