Hi Philippe, Few comments,
Philippe Bergheaud <fe...@linux.vnet.ibm.com> writes: > diff --git a/drivers/misc/cxl/cxl.h b/drivers/misc/cxl/cxl.h > index 4fe5078..b0027e6 100644 > --- a/drivers/misc/cxl/cxl.h > +++ b/drivers/misc/cxl/cxl.h > @@ -24,6 +24,7 @@ > #include <asm/reg.h> > #include <misc/cxl-base.h> > > +#include <misc/cxl.h> > #include <uapi/misc/cxl.h> > > extern uint cxl_verbose; > @@ -34,7 +35,7 @@ extern uint cxl_verbose; > * Bump version each time a user API change is made, whether it is > * backwards compatible ot not. > */ > -#define CXL_API_VERSION 2 > +#define CXL_API_VERSION 3 > #define CXL_API_VERSION_COMPATIBLE 1 > > /* > @@ -522,6 +523,10 @@ struct cxl_context { > bool pending_fault; > bool pending_afu_err; > > + /* Used by AFU drivers for driver specific event delivery */ > + struct cxl_afu_driver_ops *afu_driver_ops; > + atomic_t afu_driver_events; If the afu_driver_ops.deliver_event is idempotent then instead of using a refcount we can simply call afu_driver_ops.deliver_event to see if there are any driver events queued. Since callback deliver_event is called in context of a spinlock and cannot sleep hence requirement of idempotency seems reasonable. > + > struct rcu_head rcu; > }; > > diff --git a/drivers/misc/cxl/file.c b/drivers/misc/cxl/file.c > index eec468f..6aebd0d 100644 > --- a/drivers/misc/cxl/file.c > +++ b/drivers/misc/cxl/file.c > @@ -293,6 +293,17 @@ int afu_mmap(struct file *file, struct vm_area_struct > *vm) > return cxl_context_iomap(ctx, vm); > } > > +static inline bool ctx_event_pending(struct cxl_context *ctx) > +{ > + if (ctx->pending_irq || ctx->pending_fault || ctx->pending_afu_err) > + return true; > + > + if (ctx->afu_driver_ops && atomic_read(&ctx->afu_driver_events)) > + return true; > + > + return false; > +} > + > unsigned int afu_poll(struct file *file, struct poll_table_struct *poll) > { > struct cxl_context *ctx = file->private_data; > @@ -305,8 +316,7 @@ unsigned int afu_poll(struct file *file, struct > poll_table_struct *poll) > pr_devel("afu_poll wait done pe: %i\n", ctx->pe); > > spin_lock_irqsave(&ctx->lock, flags); > - if (ctx->pending_irq || ctx->pending_fault || > - ctx->pending_afu_err) > + if (ctx_event_pending(ctx)) > mask |= POLLIN | POLLRDNORM; > else if (ctx->status == CLOSED) > /* Only error on closed when there are no futher events pending > @@ -319,16 +329,32 @@ unsigned int afu_poll(struct file *file, struct > poll_table_struct *poll) > return mask; > } > > -static inline int ctx_event_pending(struct cxl_context *ctx) > +static ssize_t afu_driver_event_copy(struct cxl_context *ctx, > + char __user *buf, Instead of using (char __user *buf) as an argument it would be better to use (struct cxl_event __user *buf) so that we dont have to use pointer arithmetic in this function body; which may break with future iterations of this struct. The struct cxl_event_afu_driver_reserved may simply be referred to as &(buf.afu_driver_event) > @@ -374,7 +400,14 @@ ssize_t afu_read(struct file *file, char __user *buf, > size_t count, > memset(&event, 0, sizeof(event)); > event.header.process_element = ctx->pe; > event.header.size = sizeof(struct cxl_event_header); > - if (ctx->pending_irq) { > + if (ctx->afu_driver_ops && atomic_read(&ctx->afu_driver_events)) { > + pr_devel("afu_read delivering AFU driver specific event\n"); > + pl = ctx->afu_driver_ops->deliver_event(ctx); > + atomic_dec(&ctx->afu_driver_events); > + WARN_ON(!pl || (pl->data_size > > CXL_MAX_EVENT_DATA_SIZE)); Should return an error to the driver via event_delivered(..,..,EOVERFLOW) > + event.header.size += pl->data_size; > + event.header.type = CXL_EVENT_AFU_DRIVER; > + } else if (ctx->pending_irq) { > pr_devel("afu_read delivering AFU interrupt\n"); > event.header.size += sizeof(struct cxl_event_afu_interrupt); > event.header.type = CXL_EVENT_AFU_INTERRUPT; > @@ -404,6 +437,9 @@ ssize_t afu_read(struct file *file, char __user *buf, > size_t count, > > spin_unlock_irqrestore(&ctx->lock, flags); > > + if (event.header.type == CXL_EVENT_AFU_DRIVER) > + return afu_driver_event_copy(ctx, buf, &event, pl); there should be check againt the count to see if driver event can fit into the buffer provided. If not then the driver/userspace should be notified. Otherwise it can result in corruption of userspace memory. Cheers, ~ Vaibhav _______________________________________________ Linuxppc-dev mailing list Linuxppc-dev@lists.ozlabs.org https://lists.ozlabs.org/listinfo/linuxppc-dev