[PATCH v2] cxl: Export AFU error buffer via sysfs

2015-05-20 Thread Vaibhav Jain
Export the AFU Error Buffer via sysfs attribute (afu_err_buf). AFU
error buffer is used by the AFU to report application specific
errors. The contents of this buffer are AFU specific and are intended to
be interpreted by the application interacting with the afu.

Testing:
- Build against pseries le/be configs.
- Run testing with a special version of memcpy afu on a 'be'
kernel.

Change-log:
v1 - v2
- Simplified cxl_afu_read_err_buffer to handle unaligned reads
by performing a short read.

Signed-off-by: Vaibhav Jain vaib...@linux.vnet.ibm.com
---
 Documentation/ABI/testing/sysfs-class-cxl | 11 ++
 drivers/misc/cxl/cxl.h|  7 
 drivers/misc/cxl/pci.c| 60 +++
 drivers/misc/cxl/sysfs.c  | 33 +
 4 files changed, 111 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-class-cxl 
b/Documentation/ABI/testing/sysfs-class-cxl
index d46bba8..45e9ce3 100644
--- a/Documentation/ABI/testing/sysfs-class-cxl
+++ b/Documentation/ABI/testing/sysfs-class-cxl
@@ -6,6 +6,17 @@ Example: The real path of the attribute 
/sys/class/cxl/afu0.0s/irqs_max is
 
 Slave contexts (eg. /sys/class/cxl/afu0.0s):
 
+What:   /sys/class/cxl/afu/afu_err_buf
+Date:   September 2014
+Contact:linuxppc-dev@lists.ozlabs.org
+Description:read only
+AFU Error Buffer contents. The contents of this file are
+   application specific and depends on the AFU being used.
+   Applications interacting with the AFU can use this attribute
+   to know about the current error condition and take appropriate
+   action like logging the event etc.
+
+
 What:   /sys/class/cxl/afu/irqs_max
 Date:   September 2014
 Contact:linuxppc-dev@lists.ozlabs.org
diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
index a1cee47..789f077 100644
--- a/drivers/misc/cxl/cxl.h
+++ b/drivers/misc/cxl/cxl.h
@@ -362,6 +362,10 @@ struct cxl_afu {
struct mutex spa_mutex;
spinlock_t afu_cntl_lock;
 
+   /* AFU error buffer fields and bin attribute for sysfs */
+   u64 eb_len, eb_offset;
+   struct bin_attribute attr_eb;
+
/*
 * Only the first part of the SPA is used for the process element
 * linked list. The only other part that software needs to worry about
@@ -563,6 +567,9 @@ static inline void __iomem *_cxl_p2n_addr(struct cxl_afu 
*afu, cxl_p2n_reg_t reg
 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);
 
+ssize_t cxl_afu_read_err_buffer(struct cxl_afu *afu, char *buf,
+   loff_t off, size_t count);
+
 
 struct cxl_calls {
void (*cxl_slbia)(struct mm_struct *mm);
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
index 1ef0164..162a8fc 100644
--- a/drivers/misc/cxl/pci.c
+++ b/drivers/misc/cxl/pci.c
@@ -593,6 +593,22 @@ static int cxl_read_afu_descriptor(struct cxl_afu *afu)
afu-crs_len = AFUD_CR_LEN(val) * 256;
afu-crs_offset = AFUD_READ_CR_OFF(afu);
 
+
+   /* eb_len is in multiple of 4K */
+   afu-eb_len = AFUD_EB_LEN(AFUD_READ_EB(afu)) * 4096;
+   afu-eb_offset = AFUD_READ_EB_OFF(afu);
+
+   /* eb_off is 4K aligned so lower 12 bits are always zero */
+   if (EXTRACT_PPC_BITS(afu-eb_offset, 0, 11) != 0) {
+   dev_warn(afu-dev,
+Invalid AFU error buffer offset %Lx\n,
+afu-eb_offset);
+   dev_info(afu-dev,
+Ignoring AFU error buffer in the descriptor\n);
+   /* indicate that no afu buffer exists */
+   afu-eb_len = 0;
+   }
+
return 0;
 }
 
@@ -672,6 +688,50 @@ static int sanitise_afu_regs(struct cxl_afu *afu)
return 0;
 }
 
+/*
+ * afu_eb_read:
+ * Called from sysfs and reads the afu error info buffer. The h/w only supports
+ * 4/8 bytes aligned access. So most of the code tries to get around this by
+ * reading full 8 bytes aligned chunks, copying it to a temp buffer and 
dropping
+ * unneeded bytes at the beginning  the end of the requested region.
+ */
+ssize_t cxl_afu_read_err_buffer(struct cxl_afu *afu, char *buf,
+   loff_t off, size_t count)
+{
+   u8 tbuff[8];
+   const void __iomem *ebuf = afu-afu_desc_mmio + afu-eb_offset;
+
+   count = min((size_t)(afu-eb_len - off), count);
+
+   if (unlikely(count = 0)) {
+   /* handle case where no ebuf exists or offset out of bound */
+   count = 0;
+
+   } else if ((count = 8)  IS_ALIGNED(off, 8)) {
+   /* read all the intermediate aligned words */
+
+   count = round_down(off + count, 8) - off;
+   _memcpy_fromio(buf,
+  ebuf + off, count);
+
+   } else if (!IS_ALIGNED(off, 8)) {
+ 

Re: [PATCH v2] cxl: Export AFU error buffer via sysfs

2015-05-20 Thread Michael Neuling
On Wed, 2015-05-20 at 16:26 +0530, Vaibhav Jain wrote:
 Export the AFU Error Buffer via sysfs attribute (afu_err_buf). AFU
 error buffer is used by the AFU to report application specific
 errors. The contents of this buffer are AFU specific and are intended to
 be interpreted by the application interacting with the afu.
 
 Testing:
   - Build against pseries le/be configs.
   - Run testing with a special version of memcpy afu on a 'be'
   kernel.
 
 Change-log:
 v1 - v2
   - Simplified cxl_afu_read_err_buffer to handle unaligned reads
   by performing a short read.
 
 Signed-off-by: Vaibhav Jain vaib...@linux.vnet.ibm.com
 ---
  Documentation/ABI/testing/sysfs-class-cxl | 11 ++
  drivers/misc/cxl/cxl.h|  7 
  drivers/misc/cxl/pci.c| 60 
 +++
  drivers/misc/cxl/sysfs.c  | 33 +
  4 files changed, 111 insertions(+)
 
 diff --git a/Documentation/ABI/testing/sysfs-class-cxl 
 b/Documentation/ABI/testing/sysfs-class-cxl
 index d46bba8..45e9ce3 100644
 --- a/Documentation/ABI/testing/sysfs-class-cxl
 +++ b/Documentation/ABI/testing/sysfs-class-cxl
 @@ -6,6 +6,17 @@ Example: The real path of the attribute 
 /sys/class/cxl/afu0.0s/irqs_max is
  
  Slave contexts (eg. /sys/class/cxl/afu0.0s):
  
 +What:   /sys/class/cxl/afu/afu_err_buf
 +Date:   September 2014
 +Contact:linuxppc-dev@lists.ozlabs.org
 +Description:read only
 +AFU Error Buffer contents. The contents of this file are
 + application specific and depends on the AFU being used.
 + Applications interacting with the AFU can use this attribute
 + to know about the current error condition and take appropriate
 + action like logging the event etc.
 +
 +
  What:   /sys/class/cxl/afu/irqs_max
  Date:   September 2014
  Contact:linuxppc-dev@lists.ozlabs.org
 diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
 index a1cee47..789f077 100644
 --- a/drivers/misc/cxl/cxl.h
 +++ b/drivers/misc/cxl/cxl.h
 @@ -362,6 +362,10 @@ struct cxl_afu {
   struct mutex spa_mutex;
   spinlock_t afu_cntl_lock;
  
 + /* AFU error buffer fields and bin attribute for sysfs */
 + u64 eb_len, eb_offset;
 + struct bin_attribute attr_eb;
 +
   /*
* Only the first part of the SPA is used for the process element
* linked list. The only other part that software needs to worry about
 @@ -563,6 +567,9 @@ static inline void __iomem *_cxl_p2n_addr(struct cxl_afu 
 *afu, cxl_p2n_reg_t reg
  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);
  
 +ssize_t cxl_afu_read_err_buffer(struct cxl_afu *afu, char *buf,
 + loff_t off, size_t count);
 +
  
  struct cxl_calls {
   void (*cxl_slbia)(struct mm_struct *mm);
 diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
 index 1ef0164..162a8fc 100644
 --- a/drivers/misc/cxl/pci.c
 +++ b/drivers/misc/cxl/pci.c
 @@ -593,6 +593,22 @@ static int cxl_read_afu_descriptor(struct cxl_afu *afu)
   afu-crs_len = AFUD_CR_LEN(val) * 256;
   afu-crs_offset = AFUD_READ_CR_OFF(afu);
  
 +
 + /* eb_len is in multiple of 4K */
 + afu-eb_len = AFUD_EB_LEN(AFUD_READ_EB(afu)) * 4096;
 + afu-eb_offset = AFUD_READ_EB_OFF(afu);
 +
 + /* eb_off is 4K aligned so lower 12 bits are always zero */
 + if (EXTRACT_PPC_BITS(afu-eb_offset, 0, 11) != 0) {
 + dev_warn(afu-dev,
 +  Invalid AFU error buffer offset %Lx\n,
 +  afu-eb_offset);
 + dev_info(afu-dev,
 +  Ignoring AFU error buffer in the descriptor\n);
 + /* indicate that no afu buffer exists */
 + afu-eb_len = 0;
 + }
 +
   return 0;
  }
  
 @@ -672,6 +688,50 @@ static int sanitise_afu_regs(struct cxl_afu *afu)
   return 0;
  }
  
 +/*
 + * afu_eb_read:
 + * Called from sysfs and reads the afu error info buffer. The h/w only 
 supports
 + * 4/8 bytes aligned access. So most of the code tries to get around this by
 + * reading full 8 bytes aligned chunks, copying it to a temp buffer and 
 dropping
 + * unneeded bytes at the beginning  the end of the requested region.
 + */
 +ssize_t cxl_afu_read_err_buffer(struct cxl_afu *afu, char *buf,
 + loff_t off, size_t count)
 +{
 + u8 tbuff[8];
 + const void __iomem *ebuf = afu-afu_desc_mmio + afu-eb_offset;
 +
 + count = min((size_t)(afu-eb_len - off), count);
 +
 + if (unlikely(count = 0)) {
 + /* handle case where no ebuf exists or offset out of bound */
 + count = 0;
 +
 + } else if ((count = 8)  IS_ALIGNED(off, 8)) {
 + /* read all the intermediate aligned words */
 +
 + count = round_down(off + count, 8) - off;
 + _memcpy_fromio(buf,
 + 

Re: [PATCH v2] cxl: Export AFU error buffer via sysfs

2015-05-20 Thread Michael Neuling
On Wed, 2015-05-20 at 22:31 +1000, Michael Neuling wrote:
 On Wed, 2015-05-20 at 22:12 +1000, Michael Neuling wrote:
  On Wed, 2015-05-20 at 16:26 +0530, Vaibhav Jain wrote:
   Export the AFU Error Buffer via sysfs attribute (afu_err_buf). AFU
   error buffer is used by the AFU to report application specific
   errors. The contents of this buffer are AFU specific and are intended to
   be interpreted by the application interacting with the afu.
   
   Testing:
 - Build against pseries le/be configs.
 - Run testing with a special version of memcpy afu on a 'be'
 kernel.
   
   Change-log:
   v1 - v2
 - Simplified cxl_afu_read_err_buffer to handle unaligned reads
 by performing a short read.
   
   Signed-off-by: Vaibhav Jain vaib...@linux.vnet.ibm.com
   ---
Documentation/ABI/testing/sysfs-class-cxl | 11 ++
drivers/misc/cxl/cxl.h|  7 
drivers/misc/cxl/pci.c| 60 
   +++
drivers/misc/cxl/sysfs.c  | 33 +
4 files changed, 111 insertions(+)
   
   diff --git a/Documentation/ABI/testing/sysfs-class-cxl 
   b/Documentation/ABI/testing/sysfs-class-cxl
   index d46bba8..45e9ce3 100644
   --- a/Documentation/ABI/testing/sysfs-class-cxl
   +++ b/Documentation/ABI/testing/sysfs-class-cxl
   @@ -6,6 +6,17 @@ Example: The real path of the attribute 
   /sys/class/cxl/afu0.0s/irqs_max is

Slave contexts (eg. /sys/class/cxl/afu0.0s):

   +What:   /sys/class/cxl/afu/afu_err_buf
   +Date:   September 2014
   +Contact:linuxppc-dev@lists.ozlabs.org
   +Description:read only
   +AFU Error Buffer contents. The contents of this file are
   + application specific and depends on the AFU being used.
   + Applications interacting with the AFU can use this attribute
   + to know about the current error condition and take appropriate
   + action like logging the event etc.
   +
   +
What:   /sys/class/cxl/afu/irqs_max
Date:   September 2014
Contact:linuxppc-dev@lists.ozlabs.org
   diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
   index a1cee47..789f077 100644
   --- a/drivers/misc/cxl/cxl.h
   +++ b/drivers/misc/cxl/cxl.h
   @@ -362,6 +362,10 @@ struct cxl_afu {
 struct mutex spa_mutex;
 spinlock_t afu_cntl_lock;

   + /* AFU error buffer fields and bin attribute for sysfs */
   + u64 eb_len, eb_offset;
   + struct bin_attribute attr_eb;
   +
 /*
  * Only the first part of the SPA is used for the process element
  * linked list. The only other part that software needs to worry about
   @@ -563,6 +567,9 @@ static inline void __iomem *_cxl_p2n_addr(struct 
   cxl_afu *afu, cxl_p2n_reg_t reg
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);

   +ssize_t cxl_afu_read_err_buffer(struct cxl_afu *afu, char *buf,
   + loff_t off, size_t count);
   +

struct cxl_calls {
 void (*cxl_slbia)(struct mm_struct *mm);
   diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
   index 1ef0164..162a8fc 100644
   --- a/drivers/misc/cxl/pci.c
   +++ b/drivers/misc/cxl/pci.c
   @@ -593,6 +593,22 @@ static int cxl_read_afu_descriptor(struct cxl_afu 
   *afu)
 afu-crs_len = AFUD_CR_LEN(val) * 256;
 afu-crs_offset = AFUD_READ_CR_OFF(afu);

   +
   + /* eb_len is in multiple of 4K */
   + afu-eb_len = AFUD_EB_LEN(AFUD_READ_EB(afu)) * 4096;
   + afu-eb_offset = AFUD_READ_EB_OFF(afu);
   +
   + /* eb_off is 4K aligned so lower 12 bits are always zero */
   + if (EXTRACT_PPC_BITS(afu-eb_offset, 0, 11) != 0) {
   + dev_warn(afu-dev,
   +  Invalid AFU error buffer offset %Lx\n,
   +  afu-eb_offset);
   + dev_info(afu-dev,
   +  Ignoring AFU error buffer in the descriptor\n);
   + /* indicate that no afu buffer exists */
   + afu-eb_len = 0;
   + }
   +
 return 0;
}

   @@ -672,6 +688,50 @@ static int sanitise_afu_regs(struct cxl_afu *afu)
 return 0;
}

   +/*
   + * afu_eb_read:
   + * Called from sysfs and reads the afu error info buffer. The h/w only 
   supports
   + * 4/8 bytes aligned access. So most of the code tries to get around 
   this by
   + * reading full 8 bytes aligned chunks, copying it to a temp buffer and 
   dropping
   + * unneeded bytes at the beginning  the end of the requested region.
   + */
   +ssize_t cxl_afu_read_err_buffer(struct cxl_afu *afu, char *buf,
   + loff_t off, size_t count)
   +{
   + u8 tbuff[8];
   + const void __iomem *ebuf = afu-afu_desc_mmio + afu-eb_offset;
   +
   + count = min((size_t)(afu-eb_len - off), count);
   +
   + if (unlikely(count = 0)) {
   + /* handle case where no ebuf exists or offset out of bound */
   + count = 0;
   +
   + 

Re: [PATCH v2] cxl: Export AFU error buffer via sysfs

2015-05-20 Thread Michael Neuling
On Wed, 2015-05-20 at 22:12 +1000, Michael Neuling wrote:
 On Wed, 2015-05-20 at 16:26 +0530, Vaibhav Jain wrote:
  Export the AFU Error Buffer via sysfs attribute (afu_err_buf). AFU
  error buffer is used by the AFU to report application specific
  errors. The contents of this buffer are AFU specific and are intended to
  be interpreted by the application interacting with the afu.
  
  Testing:
  - Build against pseries le/be configs.
  - Run testing with a special version of memcpy afu on a 'be'
  kernel.
  
  Change-log:
  v1 - v2
  - Simplified cxl_afu_read_err_buffer to handle unaligned reads
  by performing a short read.
  
  Signed-off-by: Vaibhav Jain vaib...@linux.vnet.ibm.com
  ---
   Documentation/ABI/testing/sysfs-class-cxl | 11 ++
   drivers/misc/cxl/cxl.h|  7 
   drivers/misc/cxl/pci.c| 60 
  +++
   drivers/misc/cxl/sysfs.c  | 33 +
   4 files changed, 111 insertions(+)
  
  diff --git a/Documentation/ABI/testing/sysfs-class-cxl 
  b/Documentation/ABI/testing/sysfs-class-cxl
  index d46bba8..45e9ce3 100644
  --- a/Documentation/ABI/testing/sysfs-class-cxl
  +++ b/Documentation/ABI/testing/sysfs-class-cxl
  @@ -6,6 +6,17 @@ Example: The real path of the attribute 
  /sys/class/cxl/afu0.0s/irqs_max is
   
   Slave contexts (eg. /sys/class/cxl/afu0.0s):
   
  +What:   /sys/class/cxl/afu/afu_err_buf
  +Date:   September 2014
  +Contact:linuxppc-dev@lists.ozlabs.org
  +Description:read only
  +AFU Error Buffer contents. The contents of this file are
  +   application specific and depends on the AFU being used.
  +   Applications interacting with the AFU can use this attribute
  +   to know about the current error condition and take appropriate
  +   action like logging the event etc.
  +
  +
   What:   /sys/class/cxl/afu/irqs_max
   Date:   September 2014
   Contact:linuxppc-dev@lists.ozlabs.org
  diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h
  index a1cee47..789f077 100644
  --- a/drivers/misc/cxl/cxl.h
  +++ b/drivers/misc/cxl/cxl.h
  @@ -362,6 +362,10 @@ struct cxl_afu {
  struct mutex spa_mutex;
  spinlock_t afu_cntl_lock;
   
  +   /* AFU error buffer fields and bin attribute for sysfs */
  +   u64 eb_len, eb_offset;
  +   struct bin_attribute attr_eb;
  +
  /*
   * Only the first part of the SPA is used for the process element
   * linked list. The only other part that software needs to worry about
  @@ -563,6 +567,9 @@ static inline void __iomem *_cxl_p2n_addr(struct 
  cxl_afu *afu, cxl_p2n_reg_t reg
   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);
   
  +ssize_t cxl_afu_read_err_buffer(struct cxl_afu *afu, char *buf,
  +   loff_t off, size_t count);
  +
   
   struct cxl_calls {
  void (*cxl_slbia)(struct mm_struct *mm);
  diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c
  index 1ef0164..162a8fc 100644
  --- a/drivers/misc/cxl/pci.c
  +++ b/drivers/misc/cxl/pci.c
  @@ -593,6 +593,22 @@ static int cxl_read_afu_descriptor(struct cxl_afu *afu)
  afu-crs_len = AFUD_CR_LEN(val) * 256;
  afu-crs_offset = AFUD_READ_CR_OFF(afu);
   
  +
  +   /* eb_len is in multiple of 4K */
  +   afu-eb_len = AFUD_EB_LEN(AFUD_READ_EB(afu)) * 4096;
  +   afu-eb_offset = AFUD_READ_EB_OFF(afu);
  +
  +   /* eb_off is 4K aligned so lower 12 bits are always zero */
  +   if (EXTRACT_PPC_BITS(afu-eb_offset, 0, 11) != 0) {
  +   dev_warn(afu-dev,
  +Invalid AFU error buffer offset %Lx\n,
  +afu-eb_offset);
  +   dev_info(afu-dev,
  +Ignoring AFU error buffer in the descriptor\n);
  +   /* indicate that no afu buffer exists */
  +   afu-eb_len = 0;
  +   }
  +
  return 0;
   }
   
  @@ -672,6 +688,50 @@ static int sanitise_afu_regs(struct cxl_afu *afu)
  return 0;
   }
   
  +/*
  + * afu_eb_read:
  + * Called from sysfs and reads the afu error info buffer. The h/w only 
  supports
  + * 4/8 bytes aligned access. So most of the code tries to get around this 
  by
  + * reading full 8 bytes aligned chunks, copying it to a temp buffer and 
  dropping
  + * unneeded bytes at the beginning  the end of the requested region.
  + */
  +ssize_t cxl_afu_read_err_buffer(struct cxl_afu *afu, char *buf,
  +   loff_t off, size_t count)
  +{
  +   u8 tbuff[8];
  +   const void __iomem *ebuf = afu-afu_desc_mmio + afu-eb_offset;
  +
  +   count = min((size_t)(afu-eb_len - off), count);
  +
  +   if (unlikely(count = 0)) {
  +   /* handle case where no ebuf exists or offset out of bound */
  +   count = 0;
  +
  +   } else if ((count = 8)  IS_ALIGNED(off, 8)) {
  +   /* read all the intermediate aligned words