diff --git a/libcxl.c b/libcxl.c index dadff07..b9a63c4 100644 --- a/libcxl.c +++ b/libcxl.c @@ -89,6 +89,8 @@ static struct cxl_afu_h * malloc_afu(void) afu->mmio_addr = NULL; afu->dev_name = NULL; afu->sysfs_path = NULL; + afu->fd_errbuff = -1; + afu->errbuff_size = -1; return afu; } @@ -205,6 +207,8 @@ static void _cxl_afu_free(struct cxl_afu_h *afu, int free_adapter) cxl_mmio_unmap(afu); if (afu->fd != -1) close(afu->fd); + if (afu->fd_errbuff != -1) + close(afu->fd_errbuff); free(afu); } diff --git a/libcxl.h b/libcxl.h index 5cccdc1..1e9c299 100644 --- a/libcxl.h +++ b/libcxl.h @@ -206,4 +206,26 @@ int cxl_mmio_read32(struct cxl_afu_h *afu, uint64_t offset, uint32_t *data); */ int cxl_mmio_install_sigbus_handler(); +/** + * Returns the size of afu_err_buff in bytes. + * @param afu Handle to the afu. + * @param valp Pointer to the location where size is copied to. + * @return In case of success '0' is returned. In case of an error or + * the afu_err_buff doesn't exist, -1 is returned and errno is set + * appropriately. + */ +int cxl_errinfo_size(struct cxl_afu_h *afu, size_t *valp); + +/** + * Read and copy the contents of afu_err_info buffer into the provided buffer. + * @param afu Handle to the afu + * @param dst Pointer to the buffer where data would be copied. + * @param off Start offset within the afu_err_info handle. + * @param len Number of bytes to be copied after the start offset. + * @return The number of bytes copied from the afu_err_buff to dst. In case of + * an error or the afu_err_buff doesn't exist, -1 is returned and errno is set + * appropriately. + */ +ssize_t cxl_errinfo_read(struct cxl_afu_h *afu, void *dst, off_t off, + size_t len); #endif diff --git a/libcxl_internal.h b/libcxl_internal.h index 45edf3b..72dab80 100644 --- a/libcxl_internal.h +++ b/libcxl_internal.h @@ -40,6 +40,8 @@ struct cxl_afu_h { void *mmio_addr; __u32 mmio_flags; size_t mmio_size; + int fd_errbuff; /* fd to the afu_err_buff */ + size_t errbuff_size; }; int cxl_get_dev(struct cxl_afu_h *afu, long *majorp, long *minorp); diff --git a/libcxl_sysfs.c b/libcxl_sysfs.c index ec843b5..8838714 100644 --- a/libcxl_sysfs.c +++ b/libcxl_sysfs.c @@ -514,3 +514,55 @@ int cxl_set_prefault_mode(struct cxl_afu_h *afu, enum cxl_prefault_mode value) } return write_sysfs_afu(afu, PREFAULT_MODE, str); } + +/* Returns the total size of the afu_err_buff in bytes */ +int cxl_errinfo_size(struct cxl_afu_h *afu, size_t *valp) +{ + /* check if we need to fetch the size of the buffer */ + if (afu->errbuff_size == -1) { + char * path; + struct stat st; + + path = sysfs_get_path(afu->sysfs_path, "afu_err_buff"); + if (path == NULL) + return -1; + + /* get the file size */ + if (stat(path, &st) < 0) { + free(path); + return -1; + } + + afu->errbuff_size = st.st_size; + free(path); + } + + *valp = afu->errbuff_size; + return 0; +} + +/* Read and copies contents to afu_err_buff to the provided buffer */ +ssize_t cxl_errinfo_read(struct cxl_afu_h *afu, void *dst, off_t off, + size_t len) +{ + /* check if we need to open the descriptor */ + if (afu->fd_errbuff == -1) { + char * path; + + path = sysfs_get_path(afu->sysfs_path, "afu_err_buff"); + if (path == NULL) + return -1; + + afu->fd_errbuff = open(path, O_RDONLY | O_CLOEXEC); + free(path); + + if (afu->fd_errbuff == -1) + return -1; + } + + /* seek to right offset and read contents */ + if (lseek(afu->fd_errbuff, off, SEEK_SET) < 0) + return -1; + + return read(afu->fd_errbuff, dst, len); +} diff --git a/man3/cxl.3 b/man3/cxl.3 index 7235b21..8c355cd 100644 --- a/man3/cxl.3 +++ b/man3/cxl.3 @@ -33,6 +33,8 @@ Jobs, described by AFU specific Work Element Descriptors (WEDs), can be submitted and executed by AFUs. AFU MMIO space can be mapped into the current process memory, and AFUs can be configured and controlled via MMIO reads and writes. +Also if an AFU exports an AFU Error Buffer (afu_err_buff), its contents +can be queried. .SS Constant macros .TS ; @@ -177,6 +179,16 @@ cxl_mmio_unmap unmap an AFU Problem State Area cxl_mmio_write32 write a 32-bit word to the mapped AFU Problem State Area cxl_mmio_write64 write a 32-bit word to the mapped AFU Problem State Area .TE +.SS AFU Error Buffer query functions +.TS +; +lb lb +lb l. +Function Description +_ +cxl_errinfo_size returns the size of afu_err_buff in bytes +cxl_errinfo_read read and copy the contents of afu_err_info buffer into the provided buffer +.TE .SH SEE ALSO .BR cxl_adapter_afu_next (3), .BR cxl_adapter_dev_name (3), @@ -194,6 +206,8 @@ cxl_mmio_write64 write a 32-bit word to the mapped AFU Problem State Area .BR cxl_afu_open_h (3), .BR cxl_afu_opened (3), .BR cxl_afu_sysfs_pci (3), +.BR cxl_errinfo_size (3), +.BR cxl_errinfo_read (3), .BR cxl_for_each_adapter (3), .BR cxl_for_each_adapter_afu (3), .BR cxl_for_each_afu (3), diff --git a/man3/cxl_errinfo_read.3 b/man3/cxl_errinfo_read.3 new file mode 100644 index 0000000..0f4ef19 --- /dev/null +++ b/man3/cxl_errinfo_read.3 @@ -0,0 +1,65 @@ +.\" Copyright 2015 IBM Corp. +.\" +.TH CXL_ERRINFO_READ 3 2015-02-27 "" "CXL Programmer's Manual" +.SH NAME +cxl_errinfo_read \- Read and copy the contents of afu_err_info buffer +.SH SYNOPSIS +.BR #include +.PP +.BI "ssize_t cxl_errinfo_read(struct cxl_afu_h " +.BI * afu ", void *" dst ", off_t " off ", size_t " len ); +.SH DESCRIPTION +.PP +.BR cxl_errinfo_read " attempts to read upto" +.IR len " bytes located at offset " off " in " +AFU Error Buffer and copy it to user provided buffer located at +.IR dst "." +.PP +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. +.SH RETURN VALUE +On success, returns the number of bytes copied from the afu_err_buff to +.IB dst . + +On error, -1 is returned, +.I errno +is set appropriately and the contents at +.I dst +are not touched. +.SH ERRORS +.TP +.B ENOENT +The AFU does not export afu_err_buff region. +.TP +.B EACCES +Permission to read the contents of AFU Error buffer is denied. +.TP +.B ENOMEM +Insufficient memory. +.TP +.B ENOSPC +No AFU context available. +.TP +.B EPROTO +Unsupported kernel CXL API version. +.SH FILES +.TP +.BI /dev/cxl/afu . d +AFU device in dedicated process mode. +.TP +.BI /dev/cxl/afu . m +AFU device in AFU directed mode, master context. +.TP +.BI /dev/cxl/afu . s +AFU device in AFU directed mode, slave context. +.TP +.BI /dev/cxl/afu . /afu_err_buff +AFU Error Buffer contents. The contents of this file are +application specific and depends on the AFU being used. + +.SH SEE ALSO +.BR cxl (3), +.BR cxl_errinfo_size (3), diff --git a/man3/cxl_errinfo_size.3 b/man3/cxl_errinfo_size.3 new file mode 100644 index 0000000..50f7b52 --- /dev/null +++ b/man3/cxl_errinfo_size.3 @@ -0,0 +1,66 @@ +.\" Copyright 2015 IBM Corp. +.\" +.TH CXL_ERRINFO_SIZE 3 2015-02-27 "" "CXL Programmer's Manual" +.SH NAME +cxl_errinfo_size \- returns the size of afu_err_buff in bytes +.SH SYNOPSIS +.BR #include +.PP +.BI "int cxl_errinfo_size(struct cxl_afu_h " +.BI * afu ", size_t *" valp ); +.SH DESCRIPTION +.PP +.BR cxl_errinfo_size +stores the size (in bytes) of the +.B AFU Error Buffer +associated with the provided +.IB afu +context handle at +.IB valp . +.PP +Applications can also use this function to determine if the afu_err_buff +exists for the attached +.IR afu . +.SH RETURN VALUE +On success, 0 is returned and size of the buffer is stored at +.I valp + +On error, -1 is returned, +.I errno +is set appropriately and the contents at +.I valp +are not touched +.SH ERRORS +.TP +.B ENOENT +The AFU does not export afu_err_buff region. +.TP +.B EACCES +Permission to read the contents of AFU Error buffer is denied. +.TP +.B ENOMEM +Insufficient memory. +.TP +.B ENOSPC +No AFU context available. +.TP +.B EPROTO +Unsupported kernel CXL API version. +.SH FILES +.TP +.BI /dev/cxl/afu . d +AFU device in dedicated process mode. +.TP +.BI /dev/cxl/afu . m +AFU device in AFU directed mode, master context. +.TP +.BI /dev/cxl/afu . s +AFU device in AFU directed mode, slave context. +.TP +.BI /dev/cxl/afu . /afu_err_buff +AFU Error Buffer contents. The contents of this file are +application specific and depends on the AFU being used. + +.SH SEE ALSO +.BR cxl (3), +.BR cxl_errinfo_read (3), diff --git a/symver.map b/symver.map index 9a191a9..de0b58d 100644 --- a/symver.map +++ b/symver.map @@ -58,6 +58,9 @@ LIBCXL_1 { cxl_mmio_install_sigbus_handler; + cxl_errinfo_size; + cxl_errinfo_read; + local: *; };