Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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 <conor.dooley@microchip.com>

* 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 <arnd@arndb.de>

+67 -69
+67 -69
drivers/firmware/microchip/mpfs-auto-update.c
··· 9 9 * 10 10 * Author: Conor Dooley <conor.dooley@microchip.com> 11 11 */ 12 + #include <linux/cleanup.h> 12 13 #include <linux/debugfs.h> 13 14 #include <linux/firmware.h> 14 15 #include <linux/math.h> ··· 72 71 #define AUTO_UPDATE_UPGRADE_DIRECTORY (AUTO_UPDATE_DIRECTORY_WIDTH * AUTO_UPDATE_UPGRADE_INDEX) 73 72 #define AUTO_UPDATE_BLANK_DIRECTORY (AUTO_UPDATE_DIRECTORY_WIDTH * AUTO_UPDATE_BLANK_INDEX) 74 73 #define AUTO_UPDATE_DIRECTORY_SIZE SZ_1K 75 - #define AUTO_UPDATE_RESERVED_SIZE SZ_1M 76 - #define AUTO_UPDATE_BITSTREAM_BASE (AUTO_UPDATE_DIRECTORY_SIZE + AUTO_UPDATE_RESERVED_SIZE) 74 + #define AUTO_UPDATE_INFO_BASE AUTO_UPDATE_DIRECTORY_SIZE 75 + #define AUTO_UPDATE_INFO_SIZE SZ_1M 76 + #define AUTO_UPDATE_BITSTREAM_BASE (AUTO_UPDATE_DIRECTORY_SIZE + AUTO_UPDATE_INFO_SIZE) 77 77 78 78 #define AUTO_UPDATE_TIMEOUT_MS 60000 79 79 ··· 87 85 size_t size_per_bitstream; 88 86 bool cancel_request; 89 87 }; 88 + 89 + static bool mpfs_auto_update_is_bitstream_info(const u8 *data, u32 size) 90 + { 91 + if (size < 4) 92 + return false; 93 + 94 + if (data[0] == 0x4d && data[1] == 0x43 && data[2] == 0x48 && data[3] == 0x50) 95 + return true; 96 + 97 + return false; 98 + } 90 99 91 100 static enum fw_upload_err mpfs_auto_update_prepare(struct fw_upload *fw_uploader, const u8 *data, 92 101 u32 size) ··· 175 162 static int mpfs_auto_update_verify_image(struct fw_upload *fw_uploader) 176 163 { 177 164 struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle; 178 - struct mpfs_mss_response *response; 179 - struct mpfs_mss_msg *message; 180 - u32 *response_msg; 165 + u32 *response_msg __free(kfree) = 166 + kzalloc(AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg), GFP_KERNEL); 167 + struct mpfs_mss_response *response __free(kfree) = 168 + kzalloc(sizeof(struct mpfs_mss_response), GFP_KERNEL); 169 + struct mpfs_mss_msg *message __free(kfree) = 170 + kzalloc(sizeof(struct mpfs_mss_msg), GFP_KERNEL); 181 171 int ret; 182 172 183 - response_msg = devm_kzalloc(priv->dev, AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg), 184 - GFP_KERNEL); 185 - if (!response_msg) 173 + if (!response_msg || !response || !message) 186 174 return -ENOMEM; 187 - 188 - response = devm_kzalloc(priv->dev, sizeof(struct mpfs_mss_response), GFP_KERNEL); 189 - if (!response) { 190 - ret = -ENOMEM; 191 - goto free_response_msg; 192 - } 193 - 194 - message = devm_kzalloc(priv->dev, sizeof(struct mpfs_mss_msg), GFP_KERNEL); 195 - if (!message) { 196 - ret = -ENOMEM; 197 - goto free_response; 198 - } 199 175 200 176 /* 201 177 * The system controller can verify that an image in the flash is valid. ··· 207 205 ret = mpfs_blocking_transaction(priv->sys_controller, message); 208 206 if (ret | response->resp_status) { 209 207 dev_warn(priv->dev, "Verification of Upgrade Image failed!\n"); 210 - ret = ret ? ret : -EBADMSG; 211 - goto free_message; 208 + return ret ? ret : -EBADMSG; 212 209 } 213 210 214 211 dev_info(priv->dev, "Verification of Upgrade Image passed!\n"); 215 212 216 - free_message: 217 - devm_kfree(priv->dev, message); 218 - free_response: 219 - devm_kfree(priv->dev, response); 220 - free_response_msg: 221 - devm_kfree(priv->dev, response_msg); 222 - 223 - return ret; 213 + return 0; 224 214 } 225 215 226 - static int mpfs_auto_update_set_image_address(struct mpfs_auto_update_priv *priv, char *buffer, 216 + static int mpfs_auto_update_set_image_address(struct mpfs_auto_update_priv *priv, 227 217 u32 image_address, loff_t directory_address) 228 218 { 229 219 struct erase_info erase; 230 - size_t erase_size = AUTO_UPDATE_DIRECTORY_SIZE; 220 + size_t erase_size = round_up(AUTO_UPDATE_DIRECTORY_SIZE, (u64)priv->flash->erasesize); 231 221 size_t bytes_written = 0, bytes_read = 0; 222 + char *buffer __free(kfree) = kzalloc(erase_size, GFP_KERNEL); 232 223 int ret; 233 224 234 - erase_size = round_up(erase_size, (u64)priv->flash->erasesize); 225 + if (!buffer) 226 + return -ENOMEM; 235 227 236 228 erase.addr = AUTO_UPDATE_DIRECTORY_BASE; 237 229 erase.len = erase_size; ··· 271 275 return ret; 272 276 273 277 if (bytes_written != erase_size) 274 - return ret; 278 + return -EIO; 275 279 276 280 return 0; 277 281 } ··· 281 285 { 282 286 struct mpfs_auto_update_priv *priv = fw_uploader->dd_handle; 283 287 struct erase_info erase; 284 - char *buffer; 285 288 loff_t directory_address = AUTO_UPDATE_UPGRADE_DIRECTORY; 286 289 size_t erase_size = AUTO_UPDATE_DIRECTORY_SIZE; 287 290 size_t bytes_written = 0; 291 + bool is_info = mpfs_auto_update_is_bitstream_info(data, size); 288 292 u32 image_address; 289 293 int ret; 290 294 291 295 erase_size = round_up(erase_size, (u64)priv->flash->erasesize); 292 296 293 - image_address = AUTO_UPDATE_BITSTREAM_BASE + 294 - AUTO_UPDATE_UPGRADE_INDEX * priv->size_per_bitstream; 297 + if (is_info) 298 + image_address = AUTO_UPDATE_INFO_BASE; 299 + else 300 + image_address = AUTO_UPDATE_BITSTREAM_BASE + 301 + AUTO_UPDATE_UPGRADE_INDEX * priv->size_per_bitstream; 295 302 296 - buffer = devm_kzalloc(priv->dev, erase_size, GFP_KERNEL); 297 - if (!buffer) 298 - return -ENOMEM; 299 - 300 - ret = mpfs_auto_update_set_image_address(priv, buffer, image_address, directory_address); 301 - if (ret) { 302 - dev_err(priv->dev, "failed to set image address in the SPI directory: %d\n", ret); 303 - goto out; 303 + /* 304 + * For bitstream info, the descriptor is written to a fixed offset, 305 + * so there is no need to set the image address. 306 + */ 307 + if (!is_info) { 308 + ret = mpfs_auto_update_set_image_address(priv, image_address, directory_address); 309 + if (ret) { 310 + dev_err(priv->dev, "failed to set image address in the SPI directory: %d\n", ret); 311 + return ret; 312 + } 313 + } else { 314 + if (size > AUTO_UPDATE_INFO_SIZE) { 315 + dev_err(priv->dev, "bitstream info exceeds permitted size\n"); 316 + return -ENOSPC; 317 + } 304 318 } 305 319 306 320 /* ··· 324 318 dev_info(priv->dev, "Erasing the flash at address (0x%x)\n", image_address); 325 319 ret = mtd_erase(priv->flash, &erase); 326 320 if (ret) 327 - goto out; 321 + return ret; 328 322 329 323 /* 330 324 * No parsing etc of the bitstream is required. The system controller ··· 334 328 dev_info(priv->dev, "Writing the image to the flash at address (0x%x)\n", image_address); 335 329 ret = mtd_write(priv->flash, (loff_t)image_address, size, &bytes_written, data); 336 330 if (ret) 337 - goto out; 331 + return ret; 338 332 339 - if (bytes_written != size) { 340 - ret = -EIO; 341 - goto out; 342 - } 333 + if (bytes_written != size) 334 + return -EIO; 343 335 344 336 *written = bytes_written; 337 + dev_info(priv->dev, "Wrote 0x%zx bytes to the flash\n", bytes_written); 345 338 346 - out: 347 - devm_kfree(priv->dev, buffer); 348 - return ret; 339 + return 0; 349 340 } 350 341 351 342 static enum fw_upload_err mpfs_auto_update_write(struct fw_upload *fw_uploader, const u8 *data, ··· 365 362 goto out; 366 363 } 367 364 365 + if (mpfs_auto_update_is_bitstream_info(data, size)) 366 + goto out; 367 + 368 368 ret = mpfs_auto_update_verify_image(fw_uploader); 369 369 if (ret) 370 370 err = FW_UPLOAD_ERR_FW_INVALID; ··· 387 381 388 382 static int mpfs_auto_update_available(struct mpfs_auto_update_priv *priv) 389 383 { 390 - struct mpfs_mss_response *response; 391 - struct mpfs_mss_msg *message; 392 - u32 *response_msg; 384 + u32 *response_msg __free(kfree) = 385 + kzalloc(AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg), GFP_KERNEL); 386 + struct mpfs_mss_response *response __free(kfree) = 387 + kzalloc(sizeof(struct mpfs_mss_response), GFP_KERNEL); 388 + struct mpfs_mss_msg *message __free(kfree) = 389 + kzalloc(sizeof(struct mpfs_mss_msg), GFP_KERNEL); 393 390 int ret; 394 391 395 - response_msg = devm_kzalloc(priv->dev, 396 - AUTO_UPDATE_FEATURE_RESP_SIZE * sizeof(*response_msg), 397 - GFP_KERNEL); 398 - if (!response_msg) 399 - return -ENOMEM; 400 - 401 - response = devm_kzalloc(priv->dev, sizeof(struct mpfs_mss_response), GFP_KERNEL); 402 - if (!response) 403 - return -ENOMEM; 404 - 405 - message = devm_kzalloc(priv->dev, sizeof(struct mpfs_mss_msg), GFP_KERNEL); 406 - if (!message) 392 + if (!response_msg || !response || !message) 407 393 return -ENOMEM; 408 394 409 395 /*