[PATCH 1/2] cxl: Export optional AFU configuration record in sysfs

2015-02-04 Thread Ian Munsie
From: Ian Munsie 

An AFU may optionally contain one or more PCIe like configuration
records, which can be used to identify the AFU.

This patch adds support for exposing the raw config space and the
vendor, device and class code under sysfs. These will appear in a
subdirectory of the AFU device corresponding with the configuration
record number, e.g.

cat /sys/class/cxl/afu0.0/cr0/vendor
0x1014

cat /sys/class/cxl/afu0.0/cr0/device
0x4350

cat /sys/class/cxl/afu0.0/cr0/class
0x12

hexdump -C /sys/class/cxl/afu0.0/cr0/config
  14 10 50 43 00 00 00 00  06 00 00 12 00 00 00 00  |..PC|
0010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ||
*
0100

These files behave in much the same way as the equivalent files for PCI
devices, with one exception being that the config file is currently
read-only and restricted to the root user. It is not necessarily
required to be this strict, but we currently do not have a compelling
use-case to make it writable and/or world-readable, so I erred on the
side of being restrictive.

Signed-off-by: Ian Munsie 
---
 Documentation/ABI/testing/sysfs-class-cxl |  37 ++
 drivers/misc/cxl/cxl.h|  13 +++
 drivers/misc/cxl/pci.c|  23 
 drivers/misc/cxl/sysfs.c  | 179 --
 4 files changed, 242 insertions(+), 10 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-cxl 
b/Documentation/ABI/testing/sysfs-class-cxl
index db31176..23aad38 100644
--- a/Documentation/ABI/testing/sysfs-class-cxl
+++ b/Documentation/ABI/testing/sysfs-class-cxl
@@ -76,6 +76,43 @@ Description:read only
 
 
 
+AFU configuration records (eg. /sys/class/cxl/afu0.0/cr0):
+
+An AFU may optionally export one or more PCIe like configuration records, known
+as AFU configuration records, which will show up here (if present).
+
+What:   /sys/class/cxl//cr/vendor
+Date:   February 2015
+Contact:linuxppc-...@lists.ozlabs.org
+Description:read only
+   Hexadecimal value of the vendor ID found in this AFU
+   configuration record.
+
+What:   /sys/class/cxl//cr/device
+Date:   February 2015
+Contact:linuxppc-...@lists.ozlabs.org
+Description:read only
+   Hexadecimal value of the device ID found in this AFU
+   configuration record.
+
+What:   /sys/class/cxl//cr/vendor
+Date:   February 2015
+Contact:linuxppc-...@lists.ozlabs.org
+Description:read only
+   Hexadecimal value of the class code found in this AFU
+   configuration record.
+
+What:   /sys/class/cxl//cr/config
+Date:   February 2015
+Contact:linuxppc-...@lists.ozlabs.org
+Description:read only
+   This binary file provides raw access to the AFU configuration
+   record. The format is expected to match the either the standard
+   or extended configuration space defined by the PCIe
+   specification.
+
+
+
 Master contexts (eg. /sys/class/cxl/afu0.0m)
 
 What:   /sys/class/cxl/m/mmio_size
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index 6a6a487..a1cee47 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -382,6 +382,10 @@ struct cxl_afu {
int slice;
int modes_supported;
int current_mode;
+   int crs_num;
+   u64 crs_len;
+   u64 crs_offset;
+   struct list_head crs;
enum prefault_modes prefault_mode;
bool psa;
bool pp_psa;
@@ -551,6 +555,15 @@ static inline void __iomem *_cxl_p2n_addr(struct cxl_afu 
*afu, cxl_p2n_reg_t reg
 #define cxl_p2n_read(afu, reg) \
in_be64(_cxl_p2n_addr(afu, reg))
 
+
+#define cxl_afu_cr_read64(afu, cr, off) \
+   in_le64((afu)->afu_desc_mmio + (afu)->crs_offset + ((cr) * 
(afu)->crs_len) + (off))
+#define cxl_afu_cr_read32(afu, cr, off) \
+   in_le32((afu)->afu_desc_mmio + (afu)->crs_offset + ((cr) * 
(afu)->crs_len) + (off))
+u16 cxl_afu_cr_read16(struct cxl_afu *afu, int cr, u64 off);
+u8 cxl_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off);
+
+
 struct cxl_calls {
void (*cxl_slbia)(struct mm_struct *mm);
struct module *owner;
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
index 5137ee5..128481e 100644
--- a/drivers/misc/cxl/pci.c
+++ b/drivers/misc/cxl/pci.c
@@ -114,6 +114,24 @@
 #define   AFUD_EB_LEN(val) EXTRACT_PPC_BITS(val, 8, 63)
 #define AFUD_READ_EB_OFF(afu)  AFUD_READ(afu, 0x48)
 
+u16 cxl_afu_cr_read16(struct cxl_afu *afu, int cr, u64 off)
+{
+   u64 aligned_off = off & ~0x3L;
+   u32 val;
+
+   val = cxl_afu_cr_read32(afu, cr, aligned_off);
+   return (val >> ((off & 0x2) * 8)) & 0x;
+}
+
+u8 cxl_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off)
+{
+   u64 aligned_off = off & ~0x3L;
+   u32 val;
+
+   val = cxl_afu_cr_read32(afu, cr, 

[PATCH 1/2] cxl: Export optional AFU configuration record in sysfs

2015-02-04 Thread Ian Munsie
From: Ian Munsie imun...@au1.ibm.com

An AFU may optionally contain one or more PCIe like configuration
records, which can be used to identify the AFU.

This patch adds support for exposing the raw config space and the
vendor, device and class code under sysfs. These will appear in a
subdirectory of the AFU device corresponding with the configuration
record number, e.g.

cat /sys/class/cxl/afu0.0/cr0/vendor
0x1014

cat /sys/class/cxl/afu0.0/cr0/device
0x4350

cat /sys/class/cxl/afu0.0/cr0/class
0x12

hexdump -C /sys/class/cxl/afu0.0/cr0/config
  14 10 50 43 00 00 00 00  06 00 00 12 00 00 00 00  |..PC|
0010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ||
*
0100

These files behave in much the same way as the equivalent files for PCI
devices, with one exception being that the config file is currently
read-only and restricted to the root user. It is not necessarily
required to be this strict, but we currently do not have a compelling
use-case to make it writable and/or world-readable, so I erred on the
side of being restrictive.

Signed-off-by: Ian Munsie imun...@au1.ibm.com
---
 Documentation/ABI/testing/sysfs-class-cxl |  37 ++
 drivers/misc/cxl/cxl.h|  13 +++
 drivers/misc/cxl/pci.c|  23 
 drivers/misc/cxl/sysfs.c  | 179 --
 4 files changed, 242 insertions(+), 10 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-class-cxl 
b/Documentation/ABI/testing/sysfs-class-cxl
index db31176..23aad38 100644
--- a/Documentation/ABI/testing/sysfs-class-cxl
+++ b/Documentation/ABI/testing/sysfs-class-cxl
@@ -76,6 +76,43 @@ Description:read only
 
 
 
+AFU configuration records (eg. /sys/class/cxl/afu0.0/cr0):
+
+An AFU may optionally export one or more PCIe like configuration records, known
+as AFU configuration records, which will show up here (if present).
+
+What:   /sys/class/cxl/afu/crconfig num/vendor
+Date:   February 2015
+Contact:linuxppc-...@lists.ozlabs.org
+Description:read only
+   Hexadecimal value of the vendor ID found in this AFU
+   configuration record.
+
+What:   /sys/class/cxl/afu/crconfig num/device
+Date:   February 2015
+Contact:linuxppc-...@lists.ozlabs.org
+Description:read only
+   Hexadecimal value of the device ID found in this AFU
+   configuration record.
+
+What:   /sys/class/cxl/afu/crconfig num/vendor
+Date:   February 2015
+Contact:linuxppc-...@lists.ozlabs.org
+Description:read only
+   Hexadecimal value of the class code found in this AFU
+   configuration record.
+
+What:   /sys/class/cxl/afu/crconfig num/config
+Date:   February 2015
+Contact:linuxppc-...@lists.ozlabs.org
+Description:read only
+   This binary file provides raw access to the AFU configuration
+   record. The format is expected to match the either the standard
+   or extended configuration space defined by the PCIe
+   specification.
+
+
+
 Master contexts (eg. /sys/class/cxl/afu0.0m)
 
 What:   /sys/class/cxl/afum/mmio_size
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index 6a6a487..a1cee47 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -382,6 +382,10 @@ struct cxl_afu {
int slice;
int modes_supported;
int current_mode;
+   int crs_num;
+   u64 crs_len;
+   u64 crs_offset;
+   struct list_head crs;
enum prefault_modes prefault_mode;
bool psa;
bool pp_psa;
@@ -551,6 +555,15 @@ static inline void __iomem *_cxl_p2n_addr(struct cxl_afu 
*afu, cxl_p2n_reg_t reg
 #define cxl_p2n_read(afu, reg) \
in_be64(_cxl_p2n_addr(afu, reg))
 
+
+#define cxl_afu_cr_read64(afu, cr, off) \
+   in_le64((afu)-afu_desc_mmio + (afu)-crs_offset + ((cr) * 
(afu)-crs_len) + (off))
+#define cxl_afu_cr_read32(afu, cr, off) \
+   in_le32((afu)-afu_desc_mmio + (afu)-crs_offset + ((cr) * 
(afu)-crs_len) + (off))
+u16 cxl_afu_cr_read16(struct cxl_afu *afu, int cr, u64 off);
+u8 cxl_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off);
+
+
 struct cxl_calls {
void (*cxl_slbia)(struct mm_struct *mm);
struct module *owner;
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
index 5137ee5..128481e 100644
--- a/drivers/misc/cxl/pci.c
+++ b/drivers/misc/cxl/pci.c
@@ -114,6 +114,24 @@
 #define   AFUD_EB_LEN(val) EXTRACT_PPC_BITS(val, 8, 63)
 #define AFUD_READ_EB_OFF(afu)  AFUD_READ(afu, 0x48)
 
+u16 cxl_afu_cr_read16(struct cxl_afu *afu, int cr, u64 off)
+{
+   u64 aligned_off = off  ~0x3L;
+   u32 val;
+
+   val = cxl_afu_cr_read32(afu, cr, aligned_off);
+   return (val  ((off  0x2) * 8))  0x;
+}
+
+u8 cxl_afu_cr_read8(struct cxl_afu *afu, int cr, u64 off)
+{
+   u64 aligned_off =