Edward O'Callaghan has submitted this change. ( https://review.coreboot.org/c/flashrom/+/54861 )
Change subject: serprog.c: Separate shutdown from failed init cleanup ......................................................................
serprog.c: Separate shutdown from failed init cleanup
Shutdown function was covering two different jobs here: 1) the actual shutdown which is run at the end of the driver's lifecycle and 2) cleanup in cases when initialisation failed. Now, shutdown is only doing its main job (#1), and the driver itself is doing cleanup when init fails (#2).
The good thing is that now resources are released/closed immediately in cases when init fails (vs shutdown function which was run at some point later), and the driver leaves clean space after itself if init fails.
And very importantly this unlocks API change which plans to move register_shutdown inside register master API, see https://review.coreboot.org/c/flashrom/+/51761
BUG=b:185191942 TEST=builds
Change-Id: Idf4ed62c19667e18cc807913180c48cb8c978805 Signed-off-by: Anastasia Klimchuk aklm@chromium.org Reviewed-on: https://review.coreboot.org/c/flashrom/+/54861 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Angel Pons th3fanbus@gmail.com Reviewed-by: Edward O'Callaghan quasisec@chromium.org --- M serprog.c 1 file changed, 27 insertions(+), 22 deletions(-)
Approvals: build bot (Jenkins): Verified Angel Pons: Looks good to me, approved Edward O'Callaghan: Looks good to me, approved
diff --git a/serprog.c b/serprog.c index e6028aa..a70a289 100644 --- a/serprog.c +++ b/serprog.c @@ -635,33 +635,30 @@ return 1; }
- if (register_shutdown(serprog_shutdown, NULL)) - return 1; - msg_pdbg(MSGHEADER "connected - attempting to synchronize\n");
sp_check_avail_automatic = 0;
if (sp_synchronize()) - return 1; + goto init_err_cleanup_exit;
msg_pdbg(MSGHEADER "Synchronized\n");
if (sp_docommand(S_CMD_Q_IFACE, 0, NULL, 2, &iface)) { msg_perr("Error: NAK to query interface version\n"); - return 1; + goto init_err_cleanup_exit; }
if (iface != 1) { msg_perr("Error: Unknown interface version: %d\n", iface); - return 1; + goto init_err_cleanup_exit; }
msg_pdbg(MSGHEADER "Interface version ok.\n");
if (sp_docommand(S_CMD_Q_CMDMAP, 0, NULL, 32, sp_cmdmap)) { msg_perr("Error: query command map not supported\n"); - return 1; + goto init_err_cleanup_exit; }
sp_check_avail_automatic = 1; @@ -688,10 +685,10 @@ if (sp_check_commandavail(S_CMD_O_SPIOP) == 0) { msg_perr("Error: SPI operation not supported while the " "bustype is SPI\n"); - return 1; + goto init_err_cleanup_exit; } if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL)) - return 1; + goto init_err_cleanup_exit; /* Success of any of these commands is optional. We don't need the programmer to tell us its limits, but if it doesn't, we will assume stuff, so it's in the programmers best interest @@ -727,7 +724,7 @@ if (errno != 0 || spispeed == f_spi_suffix) { msg_perr("Error: Could not convert 'spispeed'.\n"); free(spispeed); - return 1; + goto init_err_cleanup_exit; } if (strlen(f_spi_suffix) == 1) { if (!strcasecmp(f_spi_suffix, "M")) @@ -737,12 +734,12 @@ else { msg_perr("Error: Garbage following 'spispeed' value.\n"); free(spispeed); - return 1; + goto init_err_cleanup_exit; } } else if (strlen(f_spi_suffix) > 1) { msg_perr("Error: Garbage following 'spispeed' value.\n"); free(spispeed); - return 1; + goto init_err_cleanup_exit; }
buf[0] = (f_spi_req >> (0 * 8)) & 0xFF; @@ -765,38 +762,38 @@ free(spispeed); bt = serprog_buses_supported; if (sp_docommand(S_CMD_S_BUSTYPE, 1, &bt, 0, NULL)) - return 1; + goto init_err_cleanup_exit; }
if (serprog_buses_supported & BUS_NONSPI) { if (sp_check_commandavail(S_CMD_O_INIT) == 0) { msg_perr("Error: Initialize operation buffer " "not supported\n"); - return 1; + goto init_err_cleanup_exit; }
if (sp_check_commandavail(S_CMD_O_DELAY) == 0) { msg_perr("Error: Write to opbuf: " "delay not supported\n"); - return 1; + goto init_err_cleanup_exit; }
/* S_CMD_O_EXEC availability checked later. */
if (sp_check_commandavail(S_CMD_R_BYTE) == 0) { msg_perr("Error: Single byte read not supported\n"); - return 1; + goto init_err_cleanup_exit; } /* This could be translated to single byte reads (if missing), * but now we don't support that. */ if (sp_check_commandavail(S_CMD_R_NBYTES) == 0) { msg_perr("Error: Read n bytes not supported\n"); - return 1; + goto init_err_cleanup_exit; } if (sp_check_commandavail(S_CMD_O_WRITEB) == 0) { msg_perr("Error: Write to opbuf: " "write byte not supported\n"); - return 1; + goto init_err_cleanup_exit; }
if (sp_docommand(S_CMD_Q_WRNMAXLEN, 0, NULL, 3, rbuf)) { @@ -815,7 +812,7 @@ if (!sp_write_n_buf) { msg_perr("Error: cannot allocate memory for " "Write-n buffer\n"); - return 1; + goto init_err_cleanup_exit; } sp_write_n_bytes = 0; } @@ -853,12 +850,12 @@ if (sp_check_commandavail(S_CMD_O_EXEC) == 0) { msg_perr("Error: Execute operation buffer not " "supported\n"); - return 1; + goto init_err_cleanup_exit; }
if (sp_docommand(S_CMD_O_INIT, 0, NULL, 0, NULL)) { msg_perr("Error: NAK to initialize operation buffer\n"); - return 1; + goto init_err_cleanup_exit; }
if (sp_docommand(S_CMD_Q_OPBUF, 0, NULL, 2, @@ -873,20 +870,28 @@ uint8_t en = 1; if (sp_docommand(S_CMD_S_PIN_STATE, 1, &en, 0, NULL) != 0) { msg_perr("Error: could not enable output buffers\n"); - return 1; + goto init_err_cleanup_exit; } else msg_pdbg(MSGHEADER "Output drivers enabled\n"); } else msg_pdbg(MSGHEADER "Warning: Programmer does not support toggling its output drivers\n"); + sp_prev_was_write = 0; sp_streamed_transmit_ops = 0; sp_streamed_transmit_bytes = 0; sp_opbuf_usage = 0; + + if (register_shutdown(serprog_shutdown, NULL)) + goto init_err_cleanup_exit; if (serprog_buses_supported & BUS_SPI) register_spi_master(&spi_master_serprog, NULL); if (serprog_buses_supported & BUS_NONSPI) register_par_master(&par_master_serprog, serprog_buses_supported & BUS_NONSPI, NULL); return 0; + +init_err_cleanup_exit: + serprog_shutdown(NULL); + return 1; }
void serprog_delay(unsigned int usecs)