@@ -18,8 +18,9 @@ open
An fpga_image_load device is opened exclusively to control an image upload.
The device must remain open throughout the duration of the image upload.
-An attempt to close the device while an upload is in progress will block
-until the image upload is complete.
+An attempt to close the device while an upload is in progress will cause
+the upload to be cancelled. If unable to cancel the image upload, the close
+system call will block until the image upload is complete.
ioctl
-----
@@ -39,3 +40,11 @@ FPGA_IMAGE_LOAD_STATUS:
Collect status for an on-going image upload. The status returned includes
how much data remains to be transferred, the progress of the image upload,
and error information in the case of a failure.
+
+FPGA_IMAGE_LOAD_CANCEL:
+
+Request that an on-going image upload be cancelled. This IOCTL will return
+ENODEV if there is no update in progress. Depending on the implementation
+of the lower-level driver, the cancellation may take affect immediately.
+In other cases, the cancellation request may be blocked until a critical
+operation such as a FLASH is safely completed.
@@ -159,7 +159,6 @@ static int fpga_image_load_ioctl_write(struct fpga_image_load *imgld,
imgld->err_code = 0;
imgld->progress = FPGA_IMAGE_PROG_STARTING;
queue_work(system_long_wq, &imgld->work);
-
return 0;
exit_free:
@@ -184,11 +183,21 @@ static int fpga_image_load_ioctl_status(struct fpga_image_load *imgld,
return 0;
}
+static int fpga_image_load_ioctl_cancel(struct fpga_image_load *imgld,
+ unsigned long arg)
+{
+ if (imgld->progress == FPGA_IMAGE_PROG_IDLE)
+ return -ENODEV;
+
+ imgld->ops->cancel(imgld);
+ return 0;
+}
+
static long fpga_image_load_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
struct fpga_image_load *imgld = filp->private_data;
- int ret = -ENOTTY;
+ int ret = 0;
mutex_lock(&imgld->lock);
@@ -199,6 +208,12 @@ static long fpga_image_load_ioctl(struct file *filp, unsigned int cmd,
case FPGA_IMAGE_LOAD_STATUS:
ret = fpga_image_load_ioctl_status(imgld, arg);
break;
+ case FPGA_IMAGE_LOAD_CANCEL:
+ ret = fpga_image_load_ioctl_cancel(imgld, arg);
+ break;
+ default:
+ ret = -ENOTTY;
+ break;
}
mutex_unlock(&imgld->lock);
@@ -229,6 +244,8 @@ static int fpga_image_load_release(struct inode *inode, struct file *filp)
goto close_exit;
}
+ imgld->ops->cancel(imgld);
+
mutex_unlock(&imgld->lock);
flush_work(&imgld->work);
@@ -263,7 +280,8 @@ fpga_image_load_register(struct device *parent,
struct fpga_image_load *imgld;
int ret;
- if (!ops || !ops->prepare || !ops->write || !ops->poll_complete) {
+ if (!ops || !ops->cancel || !ops->prepare ||
+ !ops->write || !ops->poll_complete) {
dev_err(parent, "Attempt to register without all required ops\n");
return ERR_PTR(-ENOMEM);
}
@@ -342,6 +360,8 @@ void fpga_image_load_unregister(struct fpga_image_load *imgld)
goto unregister;
}
+ imgld->ops->cancel(imgld);
+
mutex_unlock(&imgld->lock);
flush_work(&imgld->work);
@@ -26,6 +26,9 @@ struct fpga_image_load;
* written.
* @poll_complete: Required: Check for the completion of the
* HW authentication/programming process.
+ * @cancel: Required: Request cancellation of update. This op
+ * is called from the context of a different kernel
+ * thread, so race conditions need to be considered.
* @cleanup: Optional: Complements the prepare()
* function and is called at the completion
* of the update, whether success or failure,
@@ -36,6 +39,7 @@ struct fpga_image_load_ops {
s32 (*write)(struct fpga_image_load *imgld, const u8 *data,
u32 offset, u32 size);
u32 (*poll_complete)(struct fpga_image_load *imgld);
+ void (*cancel)(struct fpga_image_load *imgld);
void (*cleanup)(struct fpga_image_load *imgld);
};
@@ -69,4 +69,6 @@ struct fpga_image_status {
#define FPGA_IMAGE_LOAD_STATUS _IOR(FPGA_IMAGE_LOAD_MAGIC, 1, struct fpga_image_status)
+#define FPGA_IMAGE_LOAD_CANCEL _IO(FPGA_IMAGE_LOAD_MAGIC, 2)
+
#endif /* _UAPI_LINUX_FPGA_IMAGE_LOAD_H */
Extend the FPGA Image Load framework to include a cancel IOCTL that can be used to request that an image upload be canceled. The IOCTL may return EBUSY if it cannot be canceled by software or ENODEV if there is no update in progress. Signed-off-by: Russ Weight <russell.h.weight@intel.com> --- v17: - Documentation cleanup for cancelling. - Removed the request_cancel flag and handling from the class driver including the fpga_image_prog_transition() function. - The cancel system call now directly calls the cancel() op of the lower-level driver. - Changed the cancel() op to return void. v16: - This was previously patch 6/6 - Amend fpga_image_load_release() to request cancellation of an ongoing update when possible. v15: - Compare to previous patch: [PATCH v14 6/6] fpga: sec-mgr: enable cancel of secure update - Changed file, symbol, and config names to reflect the new driver name - Cancel is now initiated by IOCT instead of sysfs - Removed signed-off/reviewed-by tags v14: - Updated ABI documentation date and kernel version v13: - No change v12: - Updated Date and KernelVersion fields in ABI documentation v11: - No change v10: - Rebased to 5.12-rc2 next - Updated Date and KernelVersion in ABI documentation v9: - Updated Date and KernelVersion in ABI documentation v8: - No change v7: - Changed Date in documentation file to December 2020 v6: - No change v5: - No change v4: - Changed from "Intel FPGA Security Manager" to FPGA Security Manager" and removed unnecessary references to "Intel". - Changed: iops -> sops, imgr -> smgr, IFPGA_ -> FPGA_, ifpga_ to fpga_ v3: - No change v2: - Bumped documentation date and version - Minor code cleanup per review comments --- Documentation/fpga/fpga-image-load.rst | 13 +++++++++++-- drivers/fpga/fpga-image-load.c | 26 +++++++++++++++++++++++--- include/linux/fpga/fpga-image-load.h | 4 ++++ include/uapi/linux/fpga-image-load.h | 2 ++ 4 files changed, 40 insertions(+), 5 deletions(-)