From patchwork Tue Aug 22 08:15:43 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver O'Halloran X-Patchwork-Id: 804333 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3xc3l02mwqz9sNd for ; Tue, 22 Aug 2017 18:34:36 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="R/rykWUr"; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3xc3l01cdVzDrJN for ; Tue, 22 Aug 2017 18:34:36 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="R/rykWUr"; dkim-atps=neutral X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from mail-pf0-x243.google.com (mail-pf0-x243.google.com [IPv6:2607:f8b0:400e:c00::243]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3xc3Kb4ZjSzDq8f for ; Tue, 22 Aug 2017 18:16:03 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="R/rykWUr"; dkim-atps=neutral Received: by mail-pf0-x243.google.com with SMTP id x137so626363pfd.0 for ; Tue, 22 Aug 2017 01:16:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=NM7LEE6nBty9sEelFjLIsRbtBzps8nPyjQqN04l2pls=; b=R/rykWUrxHEcW1WtGfjrOLulutbCfY4TDgOWyWOlh+sMUa3MI2LumeZJk3ZE1zykDR quEBn7FehX1bK6Q5o83vz8pnL1xL1i25XXnrWE15Qp6AHFDNT3ygKwAG/8MexN2yxHXy bKYxL6NaptdvjZLW+Bec2PEIgK+gr6GpBd5J6Ho4vm9dqpiRhvsekv0JvSKbXDbnzuT+ cxjPXDgaYokjI5Twq9SO3xkIim7V5xFI7HkomZcjKGyfxi12S6Jrh36oWaIYfuGdKPCJ MIrffULqo3bkqMe9TR4PZRU8hCFpPMW5Z4kN7mzSETz3tu+5LbV63GIAGucWDztXnx0y CACg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=NM7LEE6nBty9sEelFjLIsRbtBzps8nPyjQqN04l2pls=; b=buCkvfbeaiRKXqP3Ltvs6l6Syt4Bv+Ic0jC0BemggNuU0+DcpqpWGUluQpAeImmSIo VufpUEIt5F6qD93Slf/n6ZGJNaOkR7JDugZULevdm+19tLzTxJMmb5mujUnIxxDly3FR IXXrDfSn8vYdq2xx9ONmMdWdrigU+nVfYL8ysz3BtmOkBnimmQggUvWANXQ2oay0uDxT IjJ/ryokcvcSaS0CRzc4xQ/R0f8RBwW+jJk8durbbfKlRuHSs4ydB+H5BbAnMfTS0+kK H90i4HOISp0q78pyr2AeDRp2fnYErY/cx4yMrNyBHLdMsEDHY+LlgxKqYPGex/KAPhGi +z5A== X-Gm-Message-State: AHYfb5hdesw4R1mOvs95ZpMdijMUtJ6SjySENSnAtmIpsL9KBOGJZLja occh+xSuD9QqDpCs X-Received: by 10.98.99.131 with SMTP id x125mr9695383pfb.285.1503389761351; Tue, 22 Aug 2017 01:16:01 -0700 (PDT) Received: from flat-canetoad.ozlabs.ibm.com ([122.99.82.10]) by smtp.gmail.com with ESMTPSA id a22sm24074476pfj.94.2017.08.22.01.15.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 22 Aug 2017 01:16:00 -0700 (PDT) From: Oliver O'Halloran To: skiboot@lists.ozlabs.org Date: Tue, 22 Aug 2017 18:15:43 +1000 Message-Id: <20170822081543.30506-3-oohall@gmail.com> X-Mailer: git-send-email 2.9.5 In-Reply-To: <20170822081543.30506-1-oohall@gmail.com> References: <20170822081543.30506-1-oohall@gmail.com> Subject: [Skiboot] [PATCH 3/3] pci-virt: Add generic slot and cfg functions X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: alistair@popple.id.au MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" Currently we only use the virtual PHB infrastructure for creating the emulated NVlink PHBs. As a result npu.c and npu2.c contain functionality useful for any virtual PHB which should really be generic code. This patch moves this functionality into pci-virt.c to reduce the duplication. Signed-off-by: Oliver O'Halloran --- core/pci-virt.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++ hw/npu.c | 98 ++++-------------------------------------------------- hw/npu2.c | 97 ++++------------------------------------------------- include/pci-virt.h | 40 +++++++++++++++++++++- 4 files changed, 140 insertions(+), 182 deletions(-) diff --git a/core/pci-virt.c b/core/pci-virt.c index b531470bbae7..38c4fd745034 100644 --- a/core/pci-virt.c +++ b/core/pci-virt.c @@ -17,6 +17,7 @@ #include #include #include +#include void pci_virt_cfg_read_raw(struct pci_virt_device *pvd, uint32_t space, uint32_t offset, @@ -217,6 +218,35 @@ out: return OPAL_SUCCESS; } +#define PCI_VIRT_CFG_READ(size, type) \ +int64_t pci_virt_cfg_read##size(struct phb *phb, uint32_t bdfn, \ + uint32_t offset, type *data) \ +{ \ + uint32_t val; \ + int64_t ret; \ + \ + ret = pci_virt_cfg_read(phb, bdfn, offset, sizeof(*data), &val); \ + *data = (type)val; \ + return ret; \ +} + +#define PCI_VIRT_CFG_WRITE(size, type) \ +int64_t pci_virt_cfg_write##size(struct phb *phb, uint32_t bdfn, \ + uint32_t offset, type data) \ +{ \ + uint32_t val = data; \ + \ + return pci_virt_cfg_write(phb, bdfn, offset, sizeof(data), val); \ +} + +PCI_VIRT_CFG_READ(8, u8); +PCI_VIRT_CFG_READ(16, u16); +PCI_VIRT_CFG_READ(32, u32); +PCI_VIRT_CFG_WRITE(8, u8); +PCI_VIRT_CFG_WRITE(16, u16); +PCI_VIRT_CFG_WRITE(32, u32); + + struct pci_virt_device *pci_virt_add_device(struct phb *phb, uint32_t bdfn, uint32_t cfg_size, void *data) { @@ -263,3 +293,60 @@ struct pci_virt_device *pci_virt_add_device(struct phb *phb, uint32_t bdfn, return pvd; } + +/* dummy slot management */ + +static int64_t virt_get_link_state(struct pci_slot *slot __unused, uint8_t *val) +{ + /* + * As we're emulating all PCI stuff, the link bandwidth + * isn't big deal anyway. + */ + *val = OPAL_SHPC_LINK_UP_x1; + return OPAL_SUCCESS; +} + +static int64_t virt_get_power_state(struct pci_slot *slot __unused, uint8_t *val) +{ + *val = PCI_SLOT_POWER_ON; + return OPAL_SUCCESS; +} + +static int64_t virt_hreset(struct pci_slot *slot __unused) +{ + return OPAL_SUCCESS; +} + +static int64_t virt_freset(struct pci_slot *slot __unused) +{ + /* FIXME: PHB fundamental reset, which need to be + * figured out later. It's used by EEH recovery + * upon fenced AT. + */ + return OPAL_SUCCESS; +} + +struct pci_slot *virt_slot_create(struct phb *phb) +{ + struct pci_slot *slot; + + slot = pci_slot_alloc(phb, NULL); + if (!slot) + return slot; + + /* Elementary functions */ + slot->ops.get_presence_state = NULL; + slot->ops.get_link_state = virt_get_link_state; + slot->ops.get_power_state = virt_get_power_state; + slot->ops.get_attention_state = NULL; + slot->ops.get_latch_state = NULL; + slot->ops.set_power_state = NULL; + slot->ops.set_attention_state = NULL; + slot->ops.prepare_link_change = NULL; + slot->ops.poll_link = NULL; + slot->ops.hreset = virt_hreset; + slot->ops.freset = virt_freset; + slot->ops.creset = NULL; + + return slot; +} diff --git a/hw/npu.c b/hw/npu.c index ad44a56000a2..31e54a7a2f0d 100644 --- a/hw/npu.c +++ b/hw/npu.c @@ -311,33 +311,6 @@ static struct npu_dev *bdfn_to_npu_dev(struct npu *p, uint32_t bdfn) return NULL; } -#define NPU_CFG_READ(size, type) \ -static int64_t npu_cfg_read##size(struct phb *phb, uint32_t bdfn, \ - uint32_t offset, type *data) \ -{ \ - uint32_t val; \ - int64_t ret; \ - \ - ret = pci_virt_cfg_read(phb, bdfn, offset, sizeof(*data), &val); \ - *data = (type)val; \ - return ret; \ -} -#define NPU_CFG_WRITE(size, type) \ -static int64_t npu_cfg_write##size(struct phb *phb, uint32_t bdfn, \ - uint32_t offset, type data) \ -{ \ - uint32_t val = data; \ - \ - return pci_virt_cfg_write(phb, bdfn, offset, sizeof(data), val); \ -} - -NPU_CFG_READ(8, u8); -NPU_CFG_READ(16, u16); -NPU_CFG_READ(32, u32); -NPU_CFG_WRITE(8, u8); -NPU_CFG_WRITE(16, u16); -NPU_CFG_WRITE(32, u32); - /* * Locate the real PCI device targeted by this NVlink by matching devices * against slots. @@ -737,63 +710,6 @@ static int64_t npu_set_pe(struct phb *phb, return OPAL_SUCCESS; } -static int64_t npu_get_link_state(struct pci_slot *slot __unused, uint8_t *val) -{ - /* As we're emulating all PCI stuff, the link bandwidth - * isn't big deal anyway. - */ - *val = OPAL_SHPC_LINK_UP_x1; - return OPAL_SUCCESS; -} - -static int64_t npu_get_power_state(struct pci_slot *slot __unused, uint8_t *val) -{ - *val = PCI_SLOT_POWER_ON; - return OPAL_SUCCESS; -} - -static int64_t npu_hreset(struct pci_slot *slot __unused) -{ - prlog(PR_DEBUG, "NPU: driver should call reset procedure here\n"); - - return OPAL_SUCCESS; -} - -static int64_t npu_freset(struct pci_slot *slot __unused) -{ - /* FIXME: PHB fundamental reset, which need to be - * figured out later. It's used by EEH recovery - * upon fenced AT. - */ - return OPAL_SUCCESS; -} - -static struct pci_slot *npu_slot_create(struct phb *phb) -{ - struct pci_slot *slot; - - slot = pci_slot_alloc(phb, NULL); - if (!slot) - return slot; - - /* Elementary functions */ - slot->ops.get_presence_state = NULL; - slot->ops.get_link_state = npu_get_link_state; - slot->ops.get_power_state = npu_get_power_state; - slot->ops.get_attention_state = NULL; - slot->ops.get_latch_state = NULL; - slot->ops.set_power_state = NULL; - slot->ops.set_attention_state = NULL; - - slot->ops.prepare_link_change = NULL; - slot->ops.poll_link = NULL; - slot->ops.hreset = npu_hreset; - slot->ops.freset = npu_freset; - slot->ops.creset = NULL; - - return slot; -} - static int64_t npu_freeze_status(struct phb *phb, uint64_t pe_number __unused, uint8_t *freeze_state, @@ -903,12 +819,12 @@ static int64_t npu_err_inject(struct phb *phb, uint64_t pe_number, } static const struct phb_ops npu_ops = { - .cfg_read8 = npu_cfg_read8, - .cfg_read16 = npu_cfg_read16, - .cfg_read32 = npu_cfg_read32, - .cfg_write8 = npu_cfg_write8, - .cfg_write16 = npu_cfg_write16, - .cfg_write32 = npu_cfg_write32, + .cfg_read8 = pci_virt_cfg_read8, + .cfg_read16 = pci_virt_cfg_read16, + .cfg_read32 = pci_virt_cfg_read32, + .cfg_write8 = pci_virt_cfg_write8, + .cfg_write16 = pci_virt_cfg_write16, + .cfg_write32 = pci_virt_cfg_write32, .choose_bus = NULL, .get_reserved_pe_number = NULL, .device_init = NULL, @@ -1576,7 +1492,7 @@ static void npu_create_phb(struct dt_node *dn) npu_add_phb_properties(p); /* Create PHB slot */ - slot = npu_slot_create(&p->phb); + slot = virt_slot_create(&p->phb); if (!slot) { /** diff --git a/hw/npu2.c b/hw/npu2.c index 9f83fd046c4c..67e595960ece 100644 --- a/hw/npu2.c +++ b/hw/npu2.c @@ -399,37 +399,6 @@ static int64_t npu2_dev_cfg_bar(void *dev, struct pci_cfg_reg_filter *pcrf, return npu2_cfg_read_bar(ndev, pcrf, offset, len, data); } -#define NPU2_CFG_READ(size, type) \ -static int64_t npu2_cfg_read##size(struct phb *phb, uint32_t bdfn, \ - uint32_t offset, type *data) \ -{ \ - uint32_t val; \ - int64_t ret; \ - \ - ret = pci_virt_cfg_read(phb, bdfn, offset, \ - sizeof(*data), &val); \ - *data = (type)val; \ - return ret; \ -} -#define NPU2_CFG_WRITE(size, type) \ -static int64_t npu2_cfg_write##size(struct phb *phb, uint32_t bdfn, \ - uint32_t offset, type data) \ -{ \ - uint32_t val = data; \ - int64_t ret; \ - \ - ret = pci_virt_cfg_write(phb, bdfn, offset, \ - sizeof(data), val); \ - return ret; \ -} - -NPU2_CFG_READ(8, u8); -NPU2_CFG_READ(16, u16); -NPU2_CFG_READ(32, u32); -NPU2_CFG_WRITE(8, u8); -NPU2_CFG_WRITE(16, u16); -NPU2_CFG_WRITE(32, u32); - static struct dt_node *npu2_create_memory_dn(uint64_t addr, uint64_t size) { struct dt_node *mem; @@ -926,58 +895,6 @@ static int64_t npu2_set_pe(struct phb *phb, return OPAL_SUCCESS; } -static int64_t npu2_get_link_state(struct pci_slot *slot __unused, uint8_t *val) -{ - /* - * As we're emulating all PCI stuff, the link bandwidth - * isn't big deal anyway. - */ - *val = OPAL_SHPC_LINK_UP_x1; - return OPAL_SUCCESS; -} - -static int64_t npu2_get_power_state(struct pci_slot *slot __unused, uint8_t *val) -{ - *val = PCI_SLOT_POWER_ON; - return OPAL_SUCCESS; -} - -static int64_t npu2_hreset(struct pci_slot *slot __unused) -{ - return OPAL_SUCCESS; -} - -static int64_t npu2_freset(struct pci_slot *slot __unused) -{ - return OPAL_SUCCESS; -} - -static struct pci_slot *npu2_slot_create(struct phb *phb) -{ - struct pci_slot *slot; - - slot = pci_slot_alloc(phb, NULL); - if (!slot) - return slot; - - /* Elementary functions */ - slot->ops.get_presence_state = NULL; - slot->ops.get_link_state = npu2_get_link_state; - slot->ops.get_power_state = npu2_get_power_state; - slot->ops.get_attention_state = NULL; - slot->ops.get_latch_state = NULL; - slot->ops.set_power_state = NULL; - slot->ops.set_attention_state = NULL; - - slot->ops.prepare_link_change = NULL; - slot->ops.poll_link = NULL; - slot->ops.hreset = npu2_hreset; - slot->ops.freset = npu2_freset; - slot->ops.creset = NULL; - - return slot; -} - static int64_t npu2_freeze_status(struct phb *phb __unused, uint64_t pe_number __unused, uint8_t *freeze_state, @@ -1037,12 +954,12 @@ static int64_t npu2_tce_kill(struct phb *phb, uint32_t kill_type, } static const struct phb_ops npu_ops = { - .cfg_read8 = npu2_cfg_read8, - .cfg_read16 = npu2_cfg_read16, - .cfg_read32 = npu2_cfg_read32, - .cfg_write8 = npu2_cfg_write8, - .cfg_write16 = npu2_cfg_write16, - .cfg_write32 = npu2_cfg_write32, + .cfg_read8 = pci_virt_cfg_read8, + .cfg_read16 = pci_virt_cfg_read16, + .cfg_read32 = pci_virt_cfg_read32, + .cfg_write8 = pci_virt_cfg_write8, + .cfg_write16 = pci_virt_cfg_write16, + .cfg_write32 = pci_virt_cfg_write32, .choose_bus = NULL, .device_init = NULL, .phb_final_fixup = npu2_phb_final_fixup, @@ -1599,7 +1516,7 @@ static void npu2_create_phb(struct dt_node *dn) npu2_populate_devices(p, dn); npu2_add_phb_properties(p); - slot = npu2_slot_create(&p->phb); + slot = virt_slot_create(&p->phb); if (!slot) { /** diff --git a/include/pci-virt.h b/include/pci-virt.h index 7c787cf863a0..481d426011fc 100644 --- a/include/pci-virt.h +++ b/include/pci-virt.h @@ -59,7 +59,34 @@ extern struct pci_virt_device *pci_virt_add_device(struct phb *phb, uint32_t cfg_size, void *data); -/* Config space accessors */ +/* + * The virtual config spaces is made up of three arrays (spaces) for: + * + * Normal + * Read only (RO) + * Write 1 to clear (W1C) + * + * The normal space is the "real" config space and if you read from it directly + * you will see the contents of the PCI config space. The other two come into + * play when writing. Writes are masked against the contents of the RO space + * to ensure that any bits that were marked as read only when the virtual config + * space was initialised will remain the same. The W1C space works similarly, + * with it's contents being used to generate a mask of bits to be cleared. + * + * + * Legend: + * + * d - struct pci_virt_device + * o - byte offset to read/write from + * s - Size of the config space IO (1/2/4) + * v - Value to write or the pointer to read into + * + * r - value to write into the RO space + * w - value to write into the W1C space + * + * In general, when setting up a config space use the PCI_VIRT_CFG_*_*() macros. + */ + #define PCI_VIRT_CFG_NORMAL_RD(d, o, s, v) \ pci_virt_cfg_read_raw(d, PCI_VIRT_CFG_NORMAL, o, s, v) #define PCI_VIRT_CFG_NORMAL_WR(d, o, s, v) \ @@ -82,4 +109,15 @@ extern struct pci_virt_device *pci_virt_add_device(struct phb *phb, #define PCI_VIRT_CFG_INIT_RO(d, o, s, v) \ PCI_VIRT_CFG_INIT(d, o, s, v, 0xffffffff, 0) +/* templates for use with virtual PHBs */ +int64_t pci_virt_cfg_read8(struct phb *, uint32_t, uint32_t, uint8_t *); +int64_t pci_virt_cfg_read16(struct phb *, uint32_t, uint32_t, uint16_t *); +int64_t pci_virt_cfg_read32(struct phb *, uint32_t, uint32_t, uint32_t *); + +int64_t pci_virt_cfg_write8(struct phb *, uint32_t, uint32_t, uint8_t); +int64_t pci_virt_cfg_write16(struct phb *, uint32_t, uint32_t, uint16_t); +int64_t pci_virt_cfg_write32(struct phb *, uint32_t, uint32_t, uint32_t); + +struct pci_slot *virt_slot_create(struct phb *phb); + #endif /* __VIRT_PCI_H */