aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/npu-hw-procedures.c32
-rw-r--r--hw/npu.c450
-rw-r--r--include/npu.h22
3 files changed, 157 insertions, 347 deletions
diff --git a/hw/npu-hw-procedures.c b/hw/npu-hw-procedures.c
index cc3dcad..85f09a1 100644
--- a/hw/npu-hw-procedures.c
+++ b/hw/npu-hw-procedures.c
@@ -17,6 +17,7 @@
#include <io.h>
#include <timebase.h>
#include <pci.h>
+#include <pci-virt.h>
#include <interrupts.h>
#include <npu-regs.h>
#include <npu.h>
@@ -506,12 +507,9 @@ static uint32_t get_procedure_status(struct npu_dev *dev)
return dev->procedure_status;
}
-int64_t npu_dev_procedure_read(struct npu_dev_trap *trap,
- uint32_t offset,
- uint32_t size,
- uint32_t *data)
+static int64_t npu_dev_procedure_read(struct npu_dev *dev, uint32_t offset,
+ uint32_t size, uint32_t *data)
{
- struct npu_dev *dev = trap->dev;
int64_t rc = OPAL_SUCCESS;
if (size != 4) {
@@ -520,7 +518,6 @@ int64_t npu_dev_procedure_read(struct npu_dev_trap *trap,
return OPAL_PARAMETER;
}
- offset -= trap->start;
*data = 0;
switch (offset) {
@@ -546,12 +543,9 @@ int64_t npu_dev_procedure_read(struct npu_dev_trap *trap,
return rc;
}
-int64_t npu_dev_procedure_write(struct npu_dev_trap *trap,
- uint32_t offset,
- uint32_t size,
- uint32_t data)
+static int64_t npu_dev_procedure_write(struct npu_dev *dev, uint32_t offset,
+ uint32_t size, uint32_t data)
{
- struct npu_dev *dev = trap->dev;
const char *name;
int64_t rc = OPAL_SUCCESS;
@@ -562,8 +556,6 @@ int64_t npu_dev_procedure_write(struct npu_dev_trap *trap,
return OPAL_PARAMETER;
}
- offset -= trap->start;
-
switch (offset) {
case 0:
/* We ignore writes to the status register */
@@ -600,3 +592,17 @@ int64_t npu_dev_procedure_write(struct npu_dev_trap *trap,
return rc;
}
+
+int64_t npu_dev_procedure(void *dev, struct pci_cfg_reg_filter *pcrf,
+ uint32_t offset, uint32_t len, uint32_t *data,
+ bool write)
+{
+ struct pci_virt_device *pvd = dev;
+ struct npu_dev *ndev = pvd->data;
+
+ if (write)
+ return npu_dev_procedure_write(ndev, offset - pcrf->start,
+ len, *data);
+
+ return npu_dev_procedure_read(ndev, offset - pcrf->start, len, data);
+}
diff --git a/hw/npu.c b/hw/npu.c
index a9a167e..54f9085 100644
--- a/hw/npu.c
+++ b/hw/npu.c
@@ -18,6 +18,7 @@
#include <timebase.h>
#include <pci.h>
#include <pci-cfg.h>
+#include <pci-virt.h>
#include <pci-slot.h>
#include <interrupts.h>
#include <opal.h>
@@ -122,63 +123,6 @@ static struct npu_dev_cap *npu_dev_find_capability(struct npu_dev *dev,
#define VENDOR_CAP_PCI_DEV_OFFSET 0x0d
-/* PCI config raw accessors */
-#define NPU_DEV_CFG_NORMAL_RD(d, o, s, v) \
- npu_dev_cfg_read_raw(d, NPU_DEV_CFG_NORMAL, o, s, v)
-#define NPU_DEV_CFG_NORMAL_WR(d, o, s, v) \
- npu_dev_cfg_write_raw(d, NPU_DEV_CFG_NORMAL, o, s, v)
-#define NPU_DEV_CFG_RDONLY_RD(d, o, s, v) \
- npu_dev_cfg_read_raw(d, NPU_DEV_CFG_RDONLY, o, s, v)
-#define NPU_DEV_CFG_RDONLY_WR(d, o, s, v) \
- npu_dev_cfg_write_raw(d, NPU_DEV_CFG_RDONLY, o, s, v)
-#define NPU_DEV_CFG_W1CLR_RD(d, o, s, v) \
- npu_dev_cfg_read_raw(d, NPU_DEV_CFG_W1CLR, o, s, v)
-#define NPU_DEV_CFG_W1CLR_WR(d, o, s, v) \
- npu_dev_cfg_write_raw(d, NPU_DEV_CFG_W1CLR, o, s, v)
-
-#define NPU_DEV_CFG_INIT(d, o, s, v, ro, w1) \
- do { \
- NPU_DEV_CFG_NORMAL_WR(d, o, s, v); \
- NPU_DEV_CFG_RDONLY_WR(d, o, s, ro); \
- NPU_DEV_CFG_W1CLR_WR(d, o, s, w1); \
- } while(0)
-
-#define NPU_DEV_CFG_INIT_RO(d, o, s, v) \
- NPU_DEV_CFG_INIT(d, o, s, v, 0xffffffff, 0)
-
-static void npu_dev_cfg_read_raw(struct npu_dev *dev,
- uint32_t index,
- uint32_t offset,
- uint32_t size,
- uint32_t *val)
-{
- uint8_t *pcfg = dev->config[index];
- uint32_t r, t, i;
-
- r = 0;
- for (i = 0; i < size; i++) {
- t = pcfg[offset + i];
- r |= (t << (i * 8));
- }
-
- *val = r;
-}
-
-static void npu_dev_cfg_write_raw(struct npu_dev *dev,
- uint32_t index,
- uint32_t offset,
- uint32_t size,
- uint32_t val)
-{
- uint8_t *pcfg = dev->config[index];
- uint32_t i;
-
- for (i = offset; i < (offset + size); i++) {
- pcfg[i] = val;
- val = (val >> 8);
- }
-}
-
/* Returns the scom base for the given link index */
static uint64_t npu_link_scom_base(struct dt_node *dn, uint32_t scom_base,
int index)
@@ -216,14 +160,18 @@ static void npu_dev_bar_update(uint32_t gcid, struct npu_dev_bar *bar,
}
/* Trap for PCI command (0x4) to enable or disable device's BARs */
-static int64_t npu_dev_cfg_write_cmd(struct npu_dev_trap *trap,
- uint32_t offset,
- uint32_t size,
- uint32_t data)
+static int64_t npu_dev_cfg_write_cmd(void *dev,
+ struct pci_cfg_reg_filter *pcrf __unused,
+ uint32_t offset, uint32_t size,
+ uint32_t *data, bool write)
{
- struct npu_dev *dev = trap->dev;
+ struct pci_virt_device *pvd = dev;
+ struct npu_dev *ndev = pvd->data;
bool enable;
+ if (!write)
+ return OPAL_PARTIAL;
+
if (offset != PCI_CFG_CMD)
return OPAL_PARAMETER;
if (size != 1 && size != 2 && size != 4)
@@ -232,30 +180,30 @@ static int64_t npu_dev_cfg_write_cmd(struct npu_dev_trap *trap,
/* Update device BARs and link BARs will be syncrhonized
* with hardware automatically.
*/
- enable = !!(data & PCI_CFG_CMD_MEM_EN);
- npu_dev_bar_update(dev->npu->chip_id, &dev->bar, enable);
+ enable = !!(*data & PCI_CFG_CMD_MEM_EN);
+ npu_dev_bar_update(ndev->npu->chip_id, &ndev->bar, enable);
/* Normal path to update PCI config buffer */
- return OPAL_PARAMETER;
+ return OPAL_PARTIAL;
}
/*
* Trap for memory BARs: 0xFF's should be written to BAR register
* prior to getting its size.
*/
-static int64_t npu_dev_cfg_read_bar(struct npu_dev_trap *trap,
- uint32_t offset,
- uint32_t size,
+static int64_t npu_dev_cfg_bar_read(struct npu_dev *dev __unused,
+ struct pci_cfg_reg_filter *pcrf,
+ uint32_t offset, uint32_t size,
uint32_t *data)
{
- struct npu_dev_bar *bar = trap->data;
+ struct npu_dev_bar *bar = (struct npu_dev_bar *)(pcrf->data);
/* Revert to normal path if we weren't trapped for BAR size */
if (!bar->trapped)
- return OPAL_PARAMETER;
+ return OPAL_PARTIAL;
- if (offset != trap->start &&
- offset != trap->start + 4)
+ if (offset != pcrf->start &&
+ offset != pcrf->start + 4)
return OPAL_PARAMETER;
if (size != 4)
return OPAL_PARAMETER;
@@ -265,17 +213,17 @@ static int64_t npu_dev_cfg_read_bar(struct npu_dev_trap *trap,
return OPAL_SUCCESS;
}
-static int64_t npu_dev_cfg_write_bar(struct npu_dev_trap *trap,
- uint32_t offset,
- uint32_t size,
+static int64_t npu_dev_cfg_bar_write(struct npu_dev *dev,
+ struct pci_cfg_reg_filter *pcrf,
+ uint32_t offset, uint32_t size,
uint32_t data)
{
- struct npu_dev_bar *bar = trap->data;
- struct npu_dev *dev = container_of(bar, struct npu_dev, bar);
+ struct pci_virt_device *pvd = dev->pvd;
+ struct npu_dev_bar *bar = (struct npu_dev_bar *)(pcrf->data);
uint32_t pci_cmd;
- if (offset != trap->start &&
- offset != trap->start + 4)
+ if (offset != pcrf->start &&
+ offset != pcrf->start + 4)
return OPAL_PARAMETER;
if (size != 4)
return OPAL_PARAMETER;
@@ -283,7 +231,7 @@ static int64_t npu_dev_cfg_write_bar(struct npu_dev_trap *trap,
/* Return BAR size on next read */
if (data == 0xffffffff) {
bar->trapped = true;
- if (offset == trap->start)
+ if (offset == pcrf->start)
bar->bar_sz = (bar->size & 0xffffffff);
else
bar->bar_sz = (bar->size >> 32);
@@ -292,14 +240,14 @@ static int64_t npu_dev_cfg_write_bar(struct npu_dev_trap *trap,
}
/* Update BAR base address */
- if (offset == trap->start) {
+ if (offset == pcrf->start) {
bar->base &= 0xffffffff00000000;
bar->base |= (data & 0xfffffff0);
} else {
bar->base &= 0x00000000ffffffff;
bar->base |= ((uint64_t)data << 32);
- NPU_DEV_CFG_NORMAL_RD(dev, PCI_CFG_CMD, 4, &pci_cmd);
+ PCI_VIRT_CFG_NORMAL_RD(pvd, PCI_CFG_CMD, 4, &pci_cmd);
npu_dev_bar_update(dev->npu->chip_id, bar,
!!(pci_cmd & PCI_CFG_CMD_MEM_EN));
}
@@ -310,194 +258,60 @@ static int64_t npu_dev_cfg_write_bar(struct npu_dev_trap *trap,
return OPAL_PARAMETER;
}
-static struct npu_dev *bdfn_to_npu_dev(struct npu *p, uint32_t bdfn)
+static int64_t npu_dev_cfg_bar(void *dev, struct pci_cfg_reg_filter *pcrf,
+ uint32_t offset, uint32_t len, uint32_t *data,
+ bool write)
{
- int i;
-
- /* Sanity check */
- if (bdfn & ~0xff)
- return NULL;
-
- for(i = 0; i < p->total_devices; i++) {
- if (p->devices[i].bdfn == bdfn)
- return &p->devices[i];
- }
+ struct pci_virt_device *pvd = dev;
+ struct npu_dev *ndev = pvd->data;
- return NULL;
+ if (write)
+ return npu_dev_cfg_bar_write(ndev, pcrf, offset, len, *data);
+ return npu_dev_cfg_bar_read(ndev, pcrf, offset, len, data);
}
-static struct npu_dev *npu_dev_cfg_check(struct npu *p,
- uint32_t bdfn,
- uint32_t offset,
- uint32_t size)
+static struct npu_dev *bdfn_to_npu_dev(struct npu *p, uint32_t bdfn)
{
+ struct pci_virt_device *pvd;
+
/* Sanity check */
- if (offset >= NPU_DEV_CFG_SIZE)
- return NULL;
- if (offset & (size - 1))
+ if (bdfn & ~0xff)
return NULL;
- return bdfn_to_npu_dev(p, bdfn);
-}
-
-static struct npu_dev_trap *npu_dev_trap_check(struct npu_dev *dev,
- uint32_t offset,
- uint32_t size,
- bool read)
-{
- struct npu_dev_trap *trap;
-
- list_for_each(&dev->traps, trap, link) {
- if (read && !trap->read)
- continue;
- if (!read && !trap->write)
- continue;
-
- /* The requested region is overlapped with the one
- * specified by the trap, to pick the trap and let it
- * handle the request
- */
- if (offset <= trap->end &&
- (offset + size - 1) >= trap->start)
- return trap;
- }
+ pvd = pci_virt_find_device(&p->phb, bdfn);
+ if (pvd)
+ return pvd->data;
return NULL;
}
-static int64_t _npu_dev_cfg_read(struct phb *phb, uint32_t bdfn,
- uint32_t offset, uint32_t *data,
- size_t size)
-{
- struct npu *p = phb_to_npu(phb);
- struct npu_dev *dev;
- struct npu_dev_trap *trap;
- int64_t ret;
-
- /* Data returned upon errors */
- *data = 0xffffffff;
-
- /* If fenced, we want to return all 1s, so we're done. */
- if (p->fenced)
- return OPAL_SUCCESS;
-
- /* Retrieve NPU device */
- dev = npu_dev_cfg_check(p, bdfn, offset, size);
- if (!dev)
- return OPAL_PARAMETER;
-
- /* Retrieve trap */
- trap = npu_dev_trap_check(dev, offset, size, true);
- if (trap) {
- ret = trap->read(trap, offset,
- size, (uint32_t *)data);
- if (ret == OPAL_SUCCESS)
- return ret;
- }
-
- NPU_DEV_CFG_NORMAL_RD(dev, offset, size, data);
-
- return OPAL_SUCCESS;
-}
-
-#define NPU_DEV_CFG_READ(size, type) \
-static int64_t npu_dev_cfg_read##size(struct phb *phb, uint32_t bdfn, \
- uint32_t offset, type *data) \
-{ \
- int64_t rc; \
- uint32_t val; \
- \
- /* Data returned upon errors */ \
- rc = _npu_dev_cfg_read(phb, bdfn, offset, &val, sizeof(*data)); \
- *data = (type)val; \
- return rc; \
-}
-
-static int64_t _npu_dev_cfg_write(struct phb *phb, uint32_t bdfn,
- uint32_t offset, uint32_t data,
- size_t size)
-{
- struct npu *p = phb_to_npu(phb);
- struct npu_dev *dev;
- struct npu_dev_trap *trap;
- uint32_t val, v, r, c, i;
- int64_t ret;
-
- /* Retrieve NPU device */
- dev = npu_dev_cfg_check(p, bdfn, offset, size);
- if (!dev)
- return OPAL_PARAMETER;
-
- /* Retrieve trap */
- trap = npu_dev_trap_check(dev, offset, size, false);
- if (trap) {
- ret = trap->write(trap, offset,
- size, (uint32_t)data);
- if (ret == OPAL_SUCCESS)
- return ret;
- }
-
- /* Handle read-only and W1C bits */
- val = data;
- for (i = 0; i < size; i++) {
- v = dev->config[NPU_DEV_CFG_NORMAL][offset + i];
- r = dev->config[NPU_DEV_CFG_RDONLY][offset + i];
- c = dev->config[NPU_DEV_CFG_W1CLR][offset + i];
-
- /* Drop read-only bits */
- val &= ~(r << (i * 8));
- val |= (r & v) << (i * 8);
-
- /* Drop W1C bits */
- val &= ~(val & ((c & v) << (i * 8)));
- }
-
- NPU_DEV_CFG_NORMAL_WR(dev, offset, size, val);
- return OPAL_SUCCESS;
+#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_DEV_CFG_WRITE(size, type) \
-static int64_t npu_dev_cfg_write##size(struct phb *phb, uint32_t bdfn, \
- uint32_t offset, type data) \
-{ \
- return _npu_dev_cfg_write(phb, bdfn, offset, \
- data, sizeof(data)); \
+#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_DEV_CFG_READ(8, u8)
-NPU_DEV_CFG_READ(16, u16)
-NPU_DEV_CFG_READ(32, u32)
-NPU_DEV_CFG_WRITE(8, u8)
-NPU_DEV_CFG_WRITE(16, u16)
-NPU_DEV_CFG_WRITE(32, u32)
-
-/*
- * Add calls to trap reads and writes to a NPU config space.
- */
-static void npu_dev_add_cfg_trap(struct npu_dev *dev, uint32_t start,
- uint32_t size, void *data,
- int64_t (*read)(struct npu_dev_trap *,
- uint32_t,
- uint32_t,
- uint32_t *),
- int64_t (*write)(struct npu_dev_trap *,
- uint32_t,
- uint32_t,
- uint32_t))
-{
- struct npu_dev_trap *trap;
-
- trap = zalloc(sizeof(struct npu_dev_trap));
- assert(trap);
- trap->dev = dev;
- trap->start = start;
- trap->end = start + size - 1;
- trap->read = read;
- trap->write = write;
- trap->data = data;
- list_add_tail(&dev->traps, &trap->link);
-}
+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);
static int __npu_dev_bind_pci_dev(struct phb *phb __unused,
struct pci_device *pd,
@@ -550,7 +364,7 @@ static void npu_dev_bind_pci_dev(struct npu_dev *dev)
if (dev->pd) {
dev->phb = phb;
/* Found the device, set the bit in config space */
- NPU_DEV_CFG_INIT_RO(dev, VENDOR_CAP_START +
+ PCI_VIRT_CFG_INIT_RO(dev->pvd, VENDOR_CAP_START +
VENDOR_CAP_PCI_DEV_OFFSET, 1, 0x01);
return;
}
@@ -1151,12 +965,12 @@ static int64_t npu_err_inject(struct phb *phb, uint64_t pe_number,
}
static const struct phb_ops npu_ops = {
- .cfg_read8 = npu_dev_cfg_read8,
- .cfg_read16 = npu_dev_cfg_read16,
- .cfg_read32 = npu_dev_cfg_read32,
- .cfg_write8 = npu_dev_cfg_write8,
- .cfg_write16 = npu_dev_cfg_write16,
- .cfg_write32 = npu_dev_cfg_write32,
+ .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,
.choose_bus = NULL,
.get_reserved_pe_number = NULL,
.device_init = NULL,
@@ -1321,32 +1135,35 @@ static void npu_probe_phb(struct dt_node *dn)
static void npu_dev_populate_vendor_cap(struct npu_dev_cap *cap)
{
struct npu_dev *dev = cap->dev;
+ struct pci_virt_device *pvd = dev->pvd;
uint32_t offset = cap->start;
uint8_t val;
/* Add length and version information */
val = cap->end - cap->start;
- NPU_DEV_CFG_INIT_RO(dev, offset + 2, 1, val);
- NPU_DEV_CFG_INIT_RO(dev, offset + 3, 1, OPAL_NPU_VERSION);
+ PCI_VIRT_CFG_INIT_RO(pvd, offset + 2, 1, val);
+ PCI_VIRT_CFG_INIT_RO(pvd, offset + 3, 1, OPAL_NPU_VERSION);
offset += 4;
/* Defaults when the trap can't handle the read/write (eg. due
* to reading/writing less than 4 bytes). */
val = 0x0;
- NPU_DEV_CFG_INIT_RO(dev, offset, 4, val);
- NPU_DEV_CFG_INIT_RO(dev, offset + 4, 4, val);
+ PCI_VIRT_CFG_INIT_RO(pvd, offset, 4, val);
+ PCI_VIRT_CFG_INIT_RO(pvd, offset + 4, 4, val);
/* Create a trap for AT/PL procedures */
- npu_dev_add_cfg_trap(dev, offset, 8, NULL, npu_dev_procedure_read,
- npu_dev_procedure_write);
+ pci_virt_add_filter(pvd, offset, 8,
+ PCI_REG_FLAG_READ | PCI_REG_FLAG_WRITE,
+ npu_dev_procedure, NULL);
offset += 8;
- NPU_DEV_CFG_INIT_RO(dev, offset, 1, dev->index);
+ PCI_VIRT_CFG_INIT_RO(pvd, offset, 1, dev->index);
}
static void npu_dev_populate_pcie_cap(struct npu_dev_cap *cap)
{
struct npu_dev *dev = cap->dev;
+ struct pci_virt_device *pvd = dev->pvd;
uint32_t base = cap->start;
uint32_t val;
@@ -1367,7 +1184,7 @@ static void npu_dev_populate_pcie_cap(struct npu_dev_cap *cap)
/* 0x00 - ID/PCIE capability */
val = cap->id;
val |= ((0x2 << 16) | (PCIE_TYPE_ENDPOINT << 20));
- NPU_DEV_CFG_INIT_RO(dev, base, 4, val);
+ PCI_VIRT_CFG_INIT_RO(pvd, base, 4, val);
/* 0x04 - Device capability
*
@@ -1380,53 +1197,53 @@ static void npu_dev_populate_pcie_cap(struct npu_dev_cap *cap)
(PCIE_L0SL_MAX_NO_LIMIT << 6) |
(PCIE_L1L_MAX_NO_LIMIT << 9) |
(PCICAP_EXP_DEVCAP_FUNC_RESET));
- NPU_DEV_CFG_INIT_RO(dev, base + PCICAP_EXP_DEVCAP, 4, val);
+ PCI_VIRT_CFG_INIT_RO(pvd, base + PCICAP_EXP_DEVCAP, 4, val);
/* 0x08 - Device control and status */
- NPU_DEV_CFG_INIT(dev, base + PCICAP_EXP_DEVCTL, 4, 0x00002810,
+ PCI_VIRT_CFG_INIT(pvd, base + PCICAP_EXP_DEVCTL, 4, 0x00002810,
0xffff0000, 0x000f0000);
/* 0x0c - Link capability */
val = (PCIE_LSPEED_VECBIT_2 | (PCIE_LWIDTH_1X << 4));
- NPU_DEV_CFG_INIT_RO(dev, base + PCICAP_EXP_LCAP, 4, val);
+ PCI_VIRT_CFG_INIT_RO(pvd, base + PCICAP_EXP_LCAP, 4, val);
/* 0x10 - Link control and status */
- NPU_DEV_CFG_INIT(dev, base + PCICAP_EXP_LCTL, 4, 0x00130000,
+ PCI_VIRT_CFG_INIT(pvd, base + PCICAP_EXP_LCTL, 4, 0x00130000,
0xfffff000, 0xc0000000);
/* 0x14 - Slot capability */
- NPU_DEV_CFG_INIT_RO(dev, base + PCICAP_EXP_SLOTCAP, 4, 0x00000000);
+ PCI_VIRT_CFG_INIT_RO(pvd, base + PCICAP_EXP_SLOTCAP, 4, 0x00000000);
/* 0x18 - Slot control and status */
- NPU_DEV_CFG_INIT_RO(dev, base + PCICAP_EXP_SLOTCTL, 4, 0x00000000);
+ PCI_VIRT_CFG_INIT_RO(pvd, base + PCICAP_EXP_SLOTCTL, 4, 0x00000000);
/* 0x1c - Root control and capability */
- NPU_DEV_CFG_INIT(dev, base + PCICAP_EXP_RC, 4, 0x00000000,
+ PCI_VIRT_CFG_INIT(pvd, base + PCICAP_EXP_RC, 4, 0x00000000,
0xffffffe0, 0x00000000);
/* 0x20 - Root status */
- NPU_DEV_CFG_INIT(dev, base + PCICAP_EXP_RSTAT, 4, 0x00000000,
+ PCI_VIRT_CFG_INIT(pvd, base + PCICAP_EXP_RSTAT, 4, 0x00000000,
0xffffffff, 0x00010000);
/* 0x24 - Device capability 2 */
- NPU_DEV_CFG_INIT_RO(dev, base + PCIECAP_EXP_DCAP2, 4, 0x00000000);
+ PCI_VIRT_CFG_INIT_RO(pvd, base + PCIECAP_EXP_DCAP2, 4, 0x00000000);
/* 0x28 - Device Control and status 2 */
- NPU_DEV_CFG_INIT(dev, base + PCICAP_EXP_DCTL2, 4, 0x00070000,
+ PCI_VIRT_CFG_INIT(pvd, base + PCICAP_EXP_DCTL2, 4, 0x00070000,
0xffff0000, 0x00000000);
/* 0x2c - Link capability 2 */
- NPU_DEV_CFG_INIT_RO(dev, base + PCICAP_EXP_LCAP2, 4, 0x00000007);
+ PCI_VIRT_CFG_INIT_RO(pvd, base + PCICAP_EXP_LCAP2, 4, 0x00000007);
/* 0x30 - Link control and status 2 */
- NPU_DEV_CFG_INIT(dev, base + PCICAP_EXP_LCTL2, 4, 0x00000003,
+ PCI_VIRT_CFG_INIT(pvd, base + PCICAP_EXP_LCTL2, 4, 0x00000003,
0xffff0000, 0x00200000);
/* 0x34 - Slot capability 2 */
- NPU_DEV_CFG_INIT_RO(dev, base + PCICAP_EXP_SCAP2, 4, 0x00000000);
+ PCI_VIRT_CFG_INIT_RO(pvd, base + PCICAP_EXP_SCAP2, 4, 0x00000000);
/* 0x38 - Slot control and status 2 */
- NPU_DEV_CFG_INIT_RO(dev, base + PCICAP_EXP_SCTL2, 4, 0x00000000);
+ PCI_VIRT_CFG_INIT_RO(pvd, base + PCICAP_EXP_SCTL2, 4, 0x00000000);
}
static struct npu_dev_cap *npu_dev_create_capability(struct npu_dev *dev,
@@ -1492,31 +1309,29 @@ static void npu_dev_create_capabilities(struct npu_dev *dev)
static void npu_dev_create_cfg(struct npu_dev *dev)
{
+ struct pci_virt_device *pvd = dev->pvd;
struct npu_dev_cap *cap;
uint32_t offset;
uint32_t last_cap_offset;
- /* Initialize config traps */
- list_head_init(&dev->traps);
-
/* 0x00 - Vendor/Device ID */
- NPU_DEV_CFG_INIT_RO(dev, PCI_CFG_VENDOR_ID, 4, 0x04ea1014);
+ PCI_VIRT_CFG_INIT_RO(pvd, PCI_CFG_VENDOR_ID, 4, 0x04ea1014);
/* 0x04 - Command/Status
*
* Create one trap to trace toggling memory BAR enable bit
*/
- NPU_DEV_CFG_INIT(dev, PCI_CFG_CMD, 4, 0x00100000, 0xffb802b8,
+ PCI_VIRT_CFG_INIT(pvd, PCI_CFG_CMD, 4, 0x00100000, 0xffb802b8,
0xf9000000);
- npu_dev_add_cfg_trap(dev, PCI_CFG_CMD, 1, NULL, NULL,
- npu_dev_cfg_write_cmd);
+ pci_virt_add_filter(pvd, PCI_CFG_CMD, 1, PCI_REG_FLAG_WRITE,
+ npu_dev_cfg_write_cmd, NULL);
/* 0x08 - Rev/Class/Cache */
- NPU_DEV_CFG_INIT_RO(dev, PCI_CFG_REV_ID, 4, 0x06800100);
+ PCI_VIRT_CFG_INIT_RO(pvd, PCI_CFG_REV_ID, 4, 0x06800100);
/* 0x0c - CLS/Latency Timer/Header/BIST */
- NPU_DEV_CFG_INIT_RO(dev, PCI_CFG_CACHE_LINE_SIZE, 4, 0x00800000);
+ PCI_VIRT_CFG_INIT_RO(pvd, PCI_CFG_CACHE_LINE_SIZE, 4, 0x00800000);
/* 0x10 - BARs, always 64-bits non-prefetchable
*
@@ -1525,49 +1340,50 @@ static void npu_dev_create_cfg(struct npu_dev *dev)
*/
/* Low 32-bits */
- NPU_DEV_CFG_INIT(dev, PCI_CFG_BAR0, 4,
+ PCI_VIRT_CFG_INIT(pvd, PCI_CFG_BAR0, 4,
(dev->bar.base & 0xfffffff0) | dev->bar.flags,
0x0000000f, 0x00000000);
/* High 32-bits */
- NPU_DEV_CFG_INIT(dev, PCI_CFG_BAR1, 4, (dev->bar.base >> 32),
+ PCI_VIRT_CFG_INIT(pvd, PCI_CFG_BAR1, 4, (dev->bar.base >> 32),
0x00000000, 0x00000000);
/*
* Create trap. Writting 0xFF's to BAR registers should be
* trapped and return size on next read
*/
- npu_dev_add_cfg_trap(dev, PCI_CFG_BAR0, 8, &dev->bar,
- npu_dev_cfg_read_bar, npu_dev_cfg_write_bar);
+ pci_virt_add_filter(pvd, PCI_CFG_BAR0, 8,
+ PCI_REG_FLAG_READ | PCI_REG_FLAG_WRITE,
+ npu_dev_cfg_bar, &dev->bar);
/* 0x18/1c/20/24 - Disabled BAR#2/3/4/5
*
* Mark those BARs readonly so that 0x0 will be returned when
* probing the length and the BARs will be skipped.
*/
- NPU_DEV_CFG_INIT_RO(dev, PCI_CFG_BAR2, 4, 0x00000000);
- NPU_DEV_CFG_INIT_RO(dev, PCI_CFG_BAR3, 4, 0x00000000);
- NPU_DEV_CFG_INIT_RO(dev, PCI_CFG_BAR4, 4, 0x00000000);
- NPU_DEV_CFG_INIT_RO(dev, PCI_CFG_BAR5, 4, 0x00000000);
+ PCI_VIRT_CFG_INIT_RO(pvd, PCI_CFG_BAR2, 4, 0x00000000);
+ PCI_VIRT_CFG_INIT_RO(pvd, PCI_CFG_BAR3, 4, 0x00000000);
+ PCI_VIRT_CFG_INIT_RO(pvd, PCI_CFG_BAR4, 4, 0x00000000);
+ PCI_VIRT_CFG_INIT_RO(pvd, PCI_CFG_BAR5, 4, 0x00000000);
/* 0x28 - Cardbus CIS pointer */
- NPU_DEV_CFG_INIT_RO(dev, PCI_CFG_CARDBUS_CIS, 4, 0x00000000);
+ PCI_VIRT_CFG_INIT_RO(pvd, PCI_CFG_CARDBUS_CIS, 4, 0x00000000);
/* 0x2c - Subsystem ID */
- NPU_DEV_CFG_INIT_RO(dev, PCI_CFG_SUBSYS_VENDOR_ID, 4, 0x00000000);
+ PCI_VIRT_CFG_INIT_RO(pvd, PCI_CFG_SUBSYS_VENDOR_ID, 4, 0x00000000);
/* 0x30 - ROM BAR
*
* Force its size to be zero so that the kernel will skip
* probing the ROM BAR. We needn't emulate ROM BAR.
*/
- NPU_DEV_CFG_INIT_RO(dev, PCI_CFG_ROMBAR, 4, 0xffffffff);
+ PCI_VIRT_CFG_INIT_RO(pvd, PCI_CFG_ROMBAR, 4, 0xffffffff);
/* 0x34 - PCI Capability
*
* By default, we don't have any capabilities
*/
- NPU_DEV_CFG_INIT_RO(dev, PCI_CFG_CAP, 4, 0x00000000);
+ PCI_VIRT_CFG_INIT_RO(pvd, PCI_CFG_CAP, 4, 0x00000000);
last_cap_offset = PCI_CFG_CAP - 1;
list_for_each(&dev->capabilities, cap, link) {
@@ -1578,22 +1394,22 @@ static void npu_dev_create_cfg(struct npu_dev *dev)
cap->populate(cap);
/* Add capability header */
- NPU_DEV_CFG_INIT_RO(dev, offset, 2, cap->id);
+ PCI_VIRT_CFG_INIT_RO(pvd, offset, 2, cap->id);
/* Update the next capability pointer */
- NPU_DEV_CFG_NORMAL_WR(dev, last_cap_offset + 1, 1, offset);
+ PCI_VIRT_CFG_NORMAL_WR(pvd, last_cap_offset + 1, 1, offset);
last_cap_offset = offset;
}
/* 0x38 - Reserved */
- NPU_DEV_CFG_INIT_RO(dev, 0x38, 4, 0x00000000);
+ PCI_VIRT_CFG_INIT_RO(pvd, 0x38, 4, 0x00000000);
/* 0x3c - INT line/pin/Minimal grant/Maximal latency */
if (!(dev->index % 2))
- NPU_DEV_CFG_INIT_RO(dev, PCI_CFG_INT_LINE, 4, 0x00000100);
+ PCI_VIRT_CFG_INIT_RO(pvd, PCI_CFG_INT_LINE, 4, 0x00000100);
else
- NPU_DEV_CFG_INIT_RO(dev, PCI_CFG_INT_LINE, 4, 0x00000200);
+ PCI_VIRT_CFG_INIT_RO(pvd, PCI_CFG_INT_LINE, 4, 0x00000200);
}
static uint32_t npu_allocate_bdfn(struct npu *p, uint32_t group)
@@ -1602,7 +1418,7 @@ static uint32_t npu_allocate_bdfn(struct npu *p, uint32_t group)
int bdfn = (group << 3);
for (i = 0; i < p->total_devices; i++) {
- if (p->devices[i].bdfn == bdfn) {
+ if (p->devices[i].pvd->bdfn == bdfn) {
bdfn++;
break;
}
@@ -1615,7 +1431,7 @@ static void npu_create_devices(struct dt_node *dn, struct npu *p)
{
struct npu_dev *dev;
struct dt_node *npu_dn, *link;
- uint32_t npu_phandle, index = 0;
+ uint32_t bdfn, npu_phandle, index = 0;
uint64_t buid_reg;
uint64_t lsisrcid;
uint64_t buid;
@@ -1640,11 +1456,11 @@ static void npu_create_devices(struct dt_node *dn, struct npu *p)
/* Walk the link@x nodes to initialize devices */
p->total_devices = 0;
p->phb.scan_map = 0;
+ list_head_init(&p->phb.virt_devices);
dt_for_each_compatible(npu_dn, link, "ibm,npu-link") {
struct npu_dev_bar *bar;
uint32_t group_id;
uint64_t val;
- uint32_t j;
dev = &p->devices[index];
dev->index = dt_prop_get_u32(link, "ibm,npu-link-index");
@@ -1658,12 +1474,12 @@ static void npu_create_devices(struct dt_node *dn, struct npu *p)
dev->pl_base = NULL;
group_id = dt_prop_get_u32(link, "ibm,npu-group-id");
- dev->bdfn = npu_allocate_bdfn(p, group_id);
+ bdfn = npu_allocate_bdfn(p, group_id);
/* This must be done after calling
* npu_allocate_bdfn() */
p->total_devices++;
- p->phb.scan_map |= 0x1 << ((dev->bdfn & 0xf8) >> 3);
+ p->phb.scan_map |= 0x1 << ((bdfn & 0xf8) >> 3);
dev->pl_xscom_base = dt_prop_get_u64(link, "ibm,npu-phy");
dev->lane_mask = dt_prop_get_u32(link, "ibm,npu-lane-mask");
@@ -1671,9 +1487,9 @@ static void npu_create_devices(struct dt_node *dn, struct npu *p)
/* Setup BUID/ISRN */
xscom_write(p->chip_id, dev->xscom + NX_NP_BUID, buid_reg);
- /* Setup emulated config space */
- for (j = 0; j < NPU_DEV_CFG_MAX; j++)
- dev->config[j] = zalloc(NPU_DEV_CFG_SIZE);
+ /* Create PCI virtual device */
+ dev->pvd = pci_virt_add_device(&p->phb, bdfn, NPU_DEV_CFG_SIZE, dev);
+ assert(dev->pvd);
bar = &dev->bar;
bar->flags = (PCI_CFG_BAR_TYPE_MEM |
PCI_CFG_BAR_MEM64);
diff --git a/include/npu.h b/include/npu.h
index d92d3ed..0768155 100644
--- a/include/npu.h
+++ b/include/npu.h
@@ -113,20 +113,14 @@ struct npu_dev {
struct npu_dev_bar bar;
struct phb *phb;
- /* Device and function numbers are allocated based on GPU
- * association */
- uint32_t bdfn;
-
/* The link@x node */
struct dt_node *dt_node;
- /* The GPU PCI device this NPU device is associated with */
+ /* PCI virtual device and the associated GPU device */
+ struct pci_virt_device *pvd;
struct pci_device *pd;
-
struct npu *npu;
- uint8_t *config[NPU_DEV_CFG_MAX];
struct list_head capabilities;
- struct list_head traps;
/* Which PHY lanes this device is associated with */
uint16_t lane_mask;
@@ -194,15 +188,9 @@ static inline void npu_ioda_sel(struct npu *p, uint32_t table,
void npu_scom_init(struct npu_dev *dev);
-int64_t npu_dev_procedure_read(struct npu_dev_trap *trap,
- uint32_t offset,
- uint32_t size,
- uint32_t *data);
-
-int64_t npu_dev_procedure_write(struct npu_dev_trap *trap,
- uint32_t offset,
- uint32_t size,
- uint32_t data);
+int64_t npu_dev_procedure(void *dev, struct pci_cfg_reg_filter *pcrf,
+ uint32_t offset, uint32_t len, uint32_t *data,
+ bool write);
void npu_set_fence_state(struct npu *p, bool fence);