summaryrefslogtreecommitdiff
path: root/drivers/misc/cxl/native.c
diff options
context:
space:
mode:
authorFrederic Barrat <fbarrat@linux.vnet.ibm.com>2016-03-04 12:26:40 +0100
committerMichael Ellerman <mpe@ellerman.id.au>2016-03-09 23:40:00 +1100
commitd601ea918b878582e60b773f2f943d8d292b2abf (patch)
treed2bba34d1bc92b685d21c668c3abbde2c292a464 /drivers/misc/cxl/native.c
parentb40844aa55bb325de7509003c7529c75b0532412 (diff)
cxl: Support the cxl kernel API from a guest
Like on bare-metal, the cxl driver creates a virtual PHB and a pci device for the AFU. The configuration space of the device is mapped to the configuration record of the AFU. Reuse the code defined in afu_cr_read8|16|32() when reading the configuration space of the AFU device. Even though the (virtual) AFU device is a pci device, the adapter is not. So a driver using the cxl kernel API cannot read the VPD of the adapter through the usual PCI interface. Therefore, we add a call to the cxl kernel API: ssize_t cxl_read_adapter_vpd(struct pci_dev *dev, void *buf, size_t count); Co-authored-by: Christophe Lombard <clombard@linux.vnet.ibm.com> Signed-off-by: Frederic Barrat <fbarrat@linux.vnet.ibm.com> Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com> Reviewed-by: Manoj Kumar <manoj@linux.vnet.ibm.com> Acked-by: Ian Munsie <imunsie@au1.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'drivers/misc/cxl/native.c')
-rw-r--r--drivers/misc/cxl/native.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/drivers/misc/cxl/native.c b/drivers/misc/cxl/native.c
index 0e289c22cdec..e564ae657584 100644
--- a/drivers/misc/cxl/native.c
+++ b/drivers/misc/cxl/native.c
@@ -1019,6 +1019,52 @@ static int native_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off, u8 *out)
return rc;
}
+static int native_afu_cr_write32(struct cxl_afu *afu, int cr, u64 off, u32 in)
+{
+ if (unlikely(!cxl_ops->link_ok(afu->adapter)))
+ return -EIO;
+ if (unlikely(off >= afu->crs_len))
+ return -ERANGE;
+ out_le32(afu->native->afu_desc_mmio + afu->crs_offset +
+ (cr * afu->crs_len) + off, in);
+ return 0;
+}
+
+static int native_afu_cr_write16(struct cxl_afu *afu, int cr, u64 off, u16 in)
+{
+ u64 aligned_off = off & ~0x3L;
+ u32 val32, mask, shift;
+ int rc;
+
+ rc = native_afu_cr_read32(afu, cr, aligned_off, &val32);
+ if (rc)
+ return rc;
+ shift = (off & 0x3) * 8;
+ WARN_ON(shift == 24);
+ mask = 0xffff << shift;
+ val32 = (val32 & ~mask) | (in << shift);
+
+ rc = native_afu_cr_write32(afu, cr, aligned_off, val32);
+ return rc;
+}
+
+static int native_afu_cr_write8(struct cxl_afu *afu, int cr, u64 off, u8 in)
+{
+ u64 aligned_off = off & ~0x3L;
+ u32 val32, mask, shift;
+ int rc;
+
+ rc = native_afu_cr_read32(afu, cr, aligned_off, &val32);
+ if (rc)
+ return rc;
+ shift = (off & 0x3) * 8;
+ mask = 0xff << shift;
+ val32 = (val32 & ~mask) | (in << shift);
+
+ rc = native_afu_cr_write32(afu, cr, aligned_off, val32);
+ return rc;
+}
+
const struct cxl_backend_ops cxl_native_ops = {
.module = THIS_MODULE,
.adapter_reset = cxl_pci_reset,
@@ -1044,4 +1090,8 @@ const struct cxl_backend_ops cxl_native_ops = {
.afu_cr_read16 = native_afu_cr_read16,
.afu_cr_read32 = native_afu_cr_read32,
.afu_cr_read64 = native_afu_cr_read64,
+ .afu_cr_write8 = native_afu_cr_write8,
+ .afu_cr_write16 = native_afu_cr_write16,
+ .afu_cr_write32 = native_afu_cr_write32,
+ .read_adapter_vpd = cxl_pci_read_adapter_vpd,
};