Skip to content

Commit 9f51147

Browse files
committed
Merge tag 'riscv-firmware-for-v6.11' of https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux into soc/drivers
RISC-V firmware drivers for v6.11 Microchip: Support for writing "bitstream info" to the flash using the auto-update driver. At this point the "bitstream info" is a glorified dtbo wrapper, but there's plans to add more info there in the future. Additionally, rework some allocations in the driver and use scope-based cleanup on them. Signed-off-by: Conor Dooley <[email protected]> * tag 'riscv-firmware-for-v6.11' of https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux: firmware: microchip: use scope-based cleanup where possible firmware: microchip: move buffer allocation into mpfs_auto_update_set_image_address() firmware: microchip: support writing bitstream info to flash Link: https://lore.kernel.org/r/20240707-lukewarm-film-8a9da40a1c27@spud Signed-off-by: Arnd Bergmann <[email protected]>
2 parents 9e6b815 + d930eb4 commit 9f51147

File tree

1 file changed

+67
-69
lines changed

1 file changed

+67
-69
lines changed

drivers/firmware/microchip/mpfs-auto-update.c

Lines changed: 67 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
*
1010
* Author: Conor Dooley <[email protected]>
1111
*/
12+
#include <linux/cleanup.h>
1213
#include <linux/debugfs.h>
1314
#include <linux/firmware.h>
1415
#include <linux/math.h>
@@ -71,8 +72,9 @@
7172
#define AUTO_UPDATE_UPGRADE_DIRECTORY (AUTO_UPDATE_DIRECTORY_WIDTH * AUTO_UPDATE_UPGRADE_INDEX)
7273
#define AUTO_UPDATE_BLANK_DIRECTORY (AUTO_UPDATE_DIRECTORY_WIDTH * AUTO_UPDATE_BLANK_INDEX)
7374
#define AUTO_UPDATE_DIRECTORY_SIZE SZ_1K
74-
#define AUTO_UPDATE_RESERVED_SIZE SZ_1M
75-
#define AUTO_UPDATE_BITSTREAM_BASE (AUTO_UPDATE_DIRECTORY_SIZE + AUTO_UPDATE_RESERVED_SIZE)
75+
#define AUTO_UPDATE_INFO_BASE AUTO_UPDATE_DIRECTORY_SIZE
76+
#define AUTO_UPDATE_INFO_SIZE SZ_1M
77+
#define AUTO_UPDATE_BITSTREAM_BASE (AUTO_UPDATE_DIRECTORY_SIZE + AUTO_UPDATE_INFO_SIZE)
7678

7779
#define AUTO_UPDATE_TIMEOUT_MS 60000
7880

@@ -86,6 +88,17 @@ struct mpfs_auto_update_priv {
8688
bool cancel_request;
8789
};
8890

91+
static bool mpfs_auto_update_is_bitstream_info(const u8 *data, u32 size)
92+
{
93+
if (size < 4)
94+
return false;
95+
96+
if (data[0] == 0x4d && data[1] == 0x43 && data[2] == 0x48 && data[3] == 0x50)
97+
return true;
98+
99+
return false;
100+
}
101+
89102
static enum fw_upload_err mpfs_auto_update_prepare(struct fw_upload *fw_uploader, const u8 *data,
90103
u32 size)
91104
{
@@ -162,28 +175,17 @@ static enum fw_upload_err mpfs_auto_update_poll_complete(struct fw_upload *fw_up
162175
static int mpfs_auto_update_verify_image(struct fw_upload *fw_uploader)
163176
{
164177
struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;
165-
struct mpfs_mss_response *response;
166-
struct mpfs_mss_msg *message;
167-
u32 *response_msg;
178+
u32 *response_msg __free(kfree) =
179+
kzalloc(AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg), GFP_KERNEL);
180+
struct mpfs_mss_response *response __free(kfree) =
181+
kzalloc(sizeof(struct mpfs_mss_response), GFP_KERNEL);
182+
struct mpfs_mss_msg *message __free(kfree) =
183+
kzalloc(sizeof(struct mpfs_mss_msg), GFP_KERNEL);
168184
int ret;
169185

170-
response_msg = devm_kzalloc(priv->dev, AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg),
171-
GFP_KERNEL);
172-
if (!response_msg)
186+
if (!response_msg || !response || !message)
173187
return -ENOMEM;
174188

175-
response = devm_kzalloc(priv->dev, sizeof(struct mpfs_mss_response), GFP_KERNEL);
176-
if (!response) {
177-
ret = -ENOMEM;
178-
goto free_response_msg;
179-
}
180-
181-
message = devm_kzalloc(priv->dev, sizeof(struct mpfs_mss_msg), GFP_KERNEL);
182-
if (!message) {
183-
ret = -ENOMEM;
184-
goto free_response;
185-
}
186-
187189
/*
188190
* The system controller can verify that an image in the flash is valid.
189191
* Rather than duplicate the check in this driver, call the relevant
@@ -205,31 +207,25 @@ static int mpfs_auto_update_verify_image(struct fw_upload *fw_uploader)
205207
ret = mpfs_blocking_transaction(priv->sys_controller, message);
206208
if (ret | response->resp_status) {
207209
dev_warn(priv->dev, "Verification of Upgrade Image failed!\n");
208-
ret = ret ? ret : -EBADMSG;
209-
goto free_message;
210+
return ret ? ret : -EBADMSG;
210211
}
211212

212213
dev_info(priv->dev, "Verification of Upgrade Image passed!\n");
213214

214-
free_message:
215-
devm_kfree(priv->dev, message);
216-
free_response:
217-
devm_kfree(priv->dev, response);
218-
free_response_msg:
219-
devm_kfree(priv->dev, response_msg);
220-
221-
return ret;
215+
return 0;
222216
}
223217

224-
static int mpfs_auto_update_set_image_address(struct mpfs_auto_update_priv *priv, char *buffer,
218+
static int mpfs_auto_update_set_image_address(struct mpfs_auto_update_priv *priv,
225219
u32 image_address, loff_t directory_address)
226220
{
227221
struct erase_info erase;
228-
size_t erase_size = AUTO_UPDATE_DIRECTORY_SIZE;
222+
size_t erase_size = round_up(AUTO_UPDATE_DIRECTORY_SIZE, (u64)priv->flash->erasesize);
229223
size_t bytes_written = 0, bytes_read = 0;
224+
char *buffer __free(kfree) = kzalloc(erase_size, GFP_KERNEL);
230225
int ret;
231226

232-
erase_size = round_up(erase_size, (u64)priv->flash->erasesize);
227+
if (!buffer)
228+
return -ENOMEM;
233229

234230
erase.addr = AUTO_UPDATE_DIRECTORY_BASE;
235231
erase.len = erase_size;
@@ -275,7 +271,7 @@ static int mpfs_auto_update_set_image_address(struct mpfs_auto_update_priv *priv
275271
return ret;
276272

277273
if (bytes_written != erase_size)
278-
return ret;
274+
return -EIO;
279275

280276
return 0;
281277
}
@@ -285,26 +281,36 @@ static int mpfs_auto_update_write_bitstream(struct fw_upload *fw_uploader, const
285281
{
286282
struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle;
287283
struct erase_info erase;
288-
char *buffer;
289284
loff_t directory_address = AUTO_UPDATE_UPGRADE_DIRECTORY;
290285
size_t erase_size = AUTO_UPDATE_DIRECTORY_SIZE;
291286
size_t bytes_written = 0;
287+
bool is_info = mpfs_auto_update_is_bitstream_info(data, size);
292288
u32 image_address;
293289
int ret;
294290

295291
erase_size = round_up(erase_size, (u64)priv->flash->erasesize);
296292

297-
image_address = AUTO_UPDATE_BITSTREAM_BASE +
298-
AUTO_UPDATE_UPGRADE_INDEX * priv->size_per_bitstream;
299-
300-
buffer = devm_kzalloc(priv->dev, erase_size, GFP_KERNEL);
301-
if (!buffer)
302-
return -ENOMEM;
293+
if (is_info)
294+
image_address = AUTO_UPDATE_INFO_BASE;
295+
else
296+
image_address = AUTO_UPDATE_BITSTREAM_BASE +
297+
AUTO_UPDATE_UPGRADE_INDEX * priv->size_per_bitstream;
303298

304-
ret = mpfs_auto_update_set_image_address(priv, buffer, image_address, directory_address);
305-
if (ret) {
306-
dev_err(priv->dev, "failed to set image address in the SPI directory: %d\n", ret);
307-
goto out;
299+
/*
300+
* For bitstream info, the descriptor is written to a fixed offset,
301+
* so there is no need to set the image address.
302+
*/
303+
if (!is_info) {
304+
ret = mpfs_auto_update_set_image_address(priv, image_address, directory_address);
305+
if (ret) {
306+
dev_err(priv->dev, "failed to set image address in the SPI directory: %d\n", ret);
307+
return ret;
308+
}
309+
} else {
310+
if (size > AUTO_UPDATE_INFO_SIZE) {
311+
dev_err(priv->dev, "bitstream info exceeds permitted size\n");
312+
return -ENOSPC;
313+
}
308314
}
309315

310316
/*
@@ -318,7 +324,7 @@ static int mpfs_auto_update_write_bitstream(struct fw_upload *fw_uploader, const
318324
dev_info(priv->dev, "Erasing the flash at address (0x%x)\n", image_address);
319325
ret = mtd_erase(priv->flash, &erase);
320326
if (ret)
321-
goto out;
327+
return ret;
322328

323329
/*
324330
* No parsing etc of the bitstream is required. The system controller
@@ -328,18 +334,15 @@ static int mpfs_auto_update_write_bitstream(struct fw_upload *fw_uploader, const
328334
dev_info(priv->dev, "Writing the image to the flash at address (0x%x)\n", image_address);
329335
ret = mtd_write(priv->flash, (loff_t)image_address, size, &bytes_written, data);
330336
if (ret)
331-
goto out;
337+
return ret;
332338

333-
if (bytes_written != size) {
334-
ret = -EIO;
335-
goto out;
336-
}
339+
if (bytes_written != size)
340+
return -EIO;
337341

338342
*written = bytes_written;
343+
dev_info(priv->dev, "Wrote 0x%zx bytes to the flash\n", bytes_written);
339344

340-
out:
341-
devm_kfree(priv->dev, buffer);
342-
return ret;
345+
return 0;
343346
}
344347

345348
static enum fw_upload_err mpfs_auto_update_write(struct fw_upload *fw_uploader, const u8 *data,
@@ -362,6 +365,9 @@ static enum fw_upload_err mpfs_auto_update_write(struct fw_upload *fw_uploader,
362365
goto out;
363366
}
364367

368+
if (mpfs_auto_update_is_bitstream_info(data, size))
369+
goto out;
370+
365371
ret = mpfs_auto_update_verify_image(fw_uploader);
366372
if (ret)
367373
err = FW_UPLOAD_ERR_FW_INVALID;
@@ -381,23 +387,15 @@ static const struct fw_upload_ops mpfs_auto_update_ops = {
381387

382388
static int mpfs_auto_update_available(struct mpfs_auto_update_priv *priv)
383389
{
384-
struct mpfs_mss_response *response;
385-
struct mpfs_mss_msg *message;
386-
u32 *response_msg;
390+
u32 *response_msg __free(kfree) =
391+
kzalloc(AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg), GFP_KERNEL);
392+
struct mpfs_mss_response *response __free(kfree) =
393+
kzalloc(sizeof(struct mpfs_mss_response), GFP_KERNEL);
394+
struct mpfs_mss_msg *message __free(kfree) =
395+
kzalloc(sizeof(struct mpfs_mss_msg), GFP_KERNEL);
387396
int ret;
388397

389-
response_msg = devm_kzalloc(priv->dev,
390-
AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg),
391-
GFP_KERNEL);
392-
if (!response_msg)
393-
return -ENOMEM;
394-
395-
response = devm_kzalloc(priv->dev, sizeof(struct mpfs_mss_response), GFP_KERNEL);
396-
if (!response)
397-
return -ENOMEM;
398-
399-
message = devm_kzalloc(priv->dev, sizeof(struct mpfs_mss_msg), GFP_KERNEL);
400-
if (!message)
398+
if (!response_msg || !response || !message)
401399
return -ENOMEM;
402400

403401
/*

0 commit comments

Comments
 (0)