@@ -28,4 +28,6 @@ Start an image load with the provided image buffer. This IOCTL returns
immediately after starting a kernel worker thread to process the image load
which could take as long a 40 minutes depending on the actual device being
updated. This is an exclusive operation; an attempt to start concurrent image
-load for the same device will fail with EBUSY.
+load for the same device will fail with EBUSY. An eventfd file descriptor
+parameter is provided to this IOCTL, and it will be signalled at the
+completion of the image load.
@@ -33,6 +33,7 @@ static void fpga_image_prog_complete(struct fpga_image_load *imgld)
{
mutex_lock(&imgld->lock);
imgld->progress = FPGA_IMAGE_PROG_IDLE;
+ eventfd_signal(imgld->finished, 1);
complete_all(&imgld->update_done);
mutex_unlock(&imgld->lock);
}
@@ -92,6 +93,8 @@ static void fpga_image_do_load(struct work_struct *work)
imgld->data = NULL;
put_device(&imgld->dev);
fpga_image_prog_complete(imgld);
+ eventfd_ctx_put(imgld->finished);
+ imgld->finished = NULL;
}
static int fpga_image_load_ioctl_write(struct fpga_image_load *imgld,
@@ -99,6 +102,7 @@ static int fpga_image_load_ioctl_write(struct fpga_image_load *imgld,
{
struct fpga_image_write wb;
unsigned long minsz;
+ int ret;
u8 *buf;
if (imgld->driver_unload || imgld->progress != FPGA_IMAGE_PROG_IDLE)
@@ -115,13 +119,23 @@ static int fpga_image_load_ioctl_write(struct fpga_image_load *imgld,
if (wb.size & 0x3)
return -EINVAL;
+ if (wb.evtfd < 0)
+ return -EINVAL;
+
buf = vzalloc(wb.size);
if (!buf)
return -ENOMEM;
if (copy_from_user(buf, u64_to_user_ptr(wb.buf), wb.size)) {
- vfree(buf);
- return -EFAULT;
+ ret = -EFAULT;
+ goto exit_free;
+ }
+
+ imgld->finished = eventfd_ctx_fdget(wb.evtfd);
+ if (IS_ERR(imgld->finished)) {
+ ret = PTR_ERR(imgld->finished);
+ imgld->finished = NULL;
+ goto exit_free;
}
imgld->data = buf;
@@ -130,8 +144,11 @@ static int fpga_image_load_ioctl_write(struct fpga_image_load *imgld,
imgld->progress = FPGA_IMAGE_PROG_STARTING;
reinit_completion(&imgld->update_done);
schedule_work(&imgld->work);
-
return 0;
+
+exit_free:
+ vfree(buf);
+ return ret;
}
static long fpga_image_load_ioctl(struct file *filp, unsigned int cmd,
@@ -10,6 +10,7 @@
#include <linux/cdev.h>
#include <linux/completion.h>
#include <linux/device.h>
+#include <linux/eventfd.h>
#include <linux/mutex.h>
#include <linux/types.h>
#include <uapi/linux/fpga-image-load.h>
@@ -52,6 +53,7 @@ struct fpga_image_load {
enum fpga_image_prog err_progress; /* progress at time of failure */
enum fpga_image_err err_code; /* image load error code */
bool driver_unload;
+ struct eventfd_ctx *finished;
void *priv;
};
@@ -52,6 +52,7 @@ struct fpga_image_write {
/* Input */
__u32 flags; /* Zero for now */
__u32 size; /* Data size (in bytes) to be written */
+ __s32 evtfd; /* File descriptor for completion signal */
__u64 buf; /* User space address of source data */
};
Amend the FPGA_IMAGE_LOAD_WRITE IOCTL implementation to include and eventfd file descriptor as a parameter. The eventfd will be triggered when the image upload completes. Signed-off-by: Russ Weight <russell.h.weight@intel.com> --- v15: - This patch is new to the patch-set, and adds an eventfd to the FPGA_IMAGE_LOAD_WRITE IOCTL. The eventfd is signalled upon completion of an update. --- Documentation/fpga/fpga-image-load.rst | 4 +++- drivers/fpga/fpga-image-load.c | 23 ++++++++++++++++++++--- include/linux/fpga/fpga-image-load.h | 2 ++ include/uapi/linux/fpga-image-load.h | 1 + 4 files changed, 26 insertions(+), 4 deletions(-)