1 From 83beece5aff75879bdfc6df8ba84ea88fd93050e Mon Sep 17 00:00:00 2001
2 From: Conor Dooley <conor.dooley@microchip.com>
3 Date: Wed, 16 Oct 2024 17:35:06 +0100
4 Subject: firmware: microchip: auto-update: fix poll_complete() to not report spurious timeout errors
6 From: Conor Dooley <conor.dooley@microchip.com>
8 commit 83beece5aff75879bdfc6df8ba84ea88fd93050e upstream.
10 fw_upload's poll_complete() is really intended for use with
11 asynchronous write() implementations - or at least those where the
12 write() loop may terminate without the kernel yet being aware of whether
13 or not the firmware upload has succeeded. For auto-update, write() is
14 only ever called once and will only return when uploading has completed,
15 be that by passing or failing. The core fw_upload code only calls
16 poll_complete() after the final call to write() has returned.
18 However, the poll_complete() implementation in the auto-update driver
19 was written to expect poll_complete() to be called from another context,
20 and it waits for a completion signalled from write(). Since
21 poll_complete() is actually called from the same context, after the
22 write() loop has terminated, wait_for_completion() never sees the
23 completion get signalled and always times out, causing programming to
24 always report a failing.
26 Since write() is full synchronous, and its return value will indicate
27 whether or not programming passed or failed, poll_complete() serves no
28 purpose and can be cut down to simply return FW_UPLOAD_ERR_NONE.
30 Cc: stable@vger.kernel.org
31 Fixes: ec5b0f1193ad4 ("firmware: microchip: add PolarFire SoC Auto Update support")
32 Reported-by: Jamie Gibbons <jamie.gibbons@microchip.com>
33 Tested-by: Jamie Gibbons <jamie.gibbons@microchip.com>
34 Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
35 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
37 drivers/firmware/microchip/mpfs-auto-update.c | 42 ++++----------------------
38 1 file changed, 7 insertions(+), 35 deletions(-)
40 --- a/drivers/firmware/microchip/mpfs-auto-update.c
41 +++ b/drivers/firmware/microchip/mpfs-auto-update.c
43 #define AUTO_UPDATE_INFO_SIZE SZ_1M
44 #define AUTO_UPDATE_BITSTREAM_BASE (AUTO_UPDATE_DIRECTORY_SIZE + AUTO_UPDATE_INFO_SIZE)
46 -#define AUTO_UPDATE_TIMEOUT_MS 60000
48 struct mpfs_auto_update_priv {
49 struct mpfs_sys_controller *sys_controller;
51 struct mtd_info *flash;
52 struct fw_upload *fw_uploader;
53 - struct completion programming_complete;
54 size_t size_per_bitstream;
57 @@ -156,19 +153,6 @@ static void mpfs_auto_update_cancel(stru
59 static enum fw_upload_err mpfs_auto_update_poll_complete(struct fw_upload *fw_uploader)
61 - struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;
65 - * There is no meaningful way to get the status of the programming while
66 - * it is in progress, so attempting anything other than waiting for it
67 - * to complete would be misplaced.
69 - ret = wait_for_completion_timeout(&priv->programming_complete,
70 - msecs_to_jiffies(AUTO_UPDATE_TIMEOUT_MS));
72 - return FW_UPLOAD_ERR_TIMEOUT;
74 return FW_UPLOAD_ERR_NONE;
77 @@ -349,33 +333,23 @@ static enum fw_upload_err mpfs_auto_upda
78 u32 offset, u32 size, u32 *written)
80 struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;
81 - enum fw_upload_err err = FW_UPLOAD_ERR_NONE;
84 - reinit_completion(&priv->programming_complete);
86 ret = mpfs_auto_update_write_bitstream(fw_uploader, data, offset, size, written);
88 - err = FW_UPLOAD_ERR_RW_ERROR;
92 + return FW_UPLOAD_ERR_RW_ERROR;
94 - if (priv->cancel_request) {
95 - err = FW_UPLOAD_ERR_CANCELED;
98 + if (priv->cancel_request)
99 + return FW_UPLOAD_ERR_CANCELED;
101 if (mpfs_auto_update_is_bitstream_info(data, size))
103 + return FW_UPLOAD_ERR_NONE;
105 ret = mpfs_auto_update_verify_image(fw_uploader);
107 - err = FW_UPLOAD_ERR_FW_INVALID;
108 + return FW_UPLOAD_ERR_FW_INVALID;
111 - complete(&priv->programming_complete);
114 + return FW_UPLOAD_ERR_NONE;
117 static const struct fw_upload_ops mpfs_auto_update_ops = {
118 @@ -461,8 +435,6 @@ static int mpfs_auto_update_probe(struct
119 return dev_err_probe(dev, ret,
120 "The current bitstream does not support auto-update\n");
122 - init_completion(&priv->programming_complete);
124 fw_uploader = firmware_upload_register(THIS_MODULE, dev, "mpfs-auto-update",
125 &mpfs_auto_update_ops, priv);
126 if (IS_ERR(fw_uploader))