jlink_spi.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 this
https://review.coreboot.org/c/flashrom/+/51761
Change-Id: I71f64ed38154af670d4d28b8c7914d87fbc75679
Signed-off-by: Anastasia Klimchuk <aklm@chromium.org>
Original-Reviewed-on: https://review.coreboot.org/c/flashrom/+/52308
Original-Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Reviewed-on: https://review.coreboot.org/c/flashrom-stable/+/72170
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Nico Huber <nico.h@gmx.de>
diff --git a/jlink_spi.c b/jlink_spi.c
index eabc789..b163899 100644
--- a/jlink_spi.c
+++ b/jlink_spi.c
@@ -189,8 +189,6 @@
char *arg;
unsigned long speed = 0;
- register_shutdown(jlink_spi_shutdown, NULL);
-
arg = extract_programmer_param("spispeed");
if (arg) {
@@ -294,7 +292,7 @@
if (ret != JAYLINK_OK) {
msg_perr("jaylink_discovery_scan() failed: %s.\n", jaylink_strerror(ret));
- return 1;
+ goto init_err;
}
struct jaylink_device **devs;
@@ -303,7 +301,7 @@
if (ret != JAYLINK_OK) {
msg_perr("jaylink_get_devices() failed: %s.\n", jaylink_strerror(ret));
- return 1;
+ goto init_err;
}
if (!use_serial_number)
@@ -346,7 +344,7 @@
if (!device_found) {
msg_perr("No J-Link device found.\n");
- return 1;
+ goto init_err;
}
size_t length;
@@ -357,7 +355,7 @@
if (ret != JAYLINK_OK) {
msg_perr("jaylink_get_firmware_version() failed: %s.\n", jaylink_strerror(ret));
- return 1;
+ goto init_err;
} else if (length > 0) {
msg_pdbg("Firmware: %s\n", firmware_version);
free(firmware_version);
@@ -371,7 +369,7 @@
msg_pdbg("S/N: N/A\n");
} else {
msg_perr("jaylink_device_get_serial_number() failed: %s.\n", jaylink_strerror(ret));
- return 1;
+ goto init_err;
}
uint8_t caps[JAYLINK_DEV_EXT_CAPS_SIZE] = { 0 };
@@ -380,7 +378,7 @@
if (ret != JAYLINK_OK) {
msg_perr("jaylink_get_caps() failed: %s.\n", jaylink_strerror(ret));
- return 1;
+ goto init_err;
}
if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_EXT_CAPS)) {
@@ -388,14 +386,14 @@
if (ret != JAYLINK_OK) {
msg_perr("jaylink_get_extended_caps() failed: %s.\n", jaylink_strerror(ret));
- return 1;
+ goto init_err;
}
}
if (enable_target_power) {
if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_SET_TARGET_POWER)) {
msg_perr("Device does not support target power.\n");
- return 1;
+ goto init_err;
}
}
@@ -405,19 +403,19 @@
if (ret != JAYLINK_OK) {
msg_perr("jaylink_get_available_interfaces() failed: %s.\n", jaylink_strerror(ret));
- return 1;
+ goto init_err;
}
if (!(ifaces & (1 << JAYLINK_TIF_JTAG))) {
msg_perr("Device does not support JTAG interface.\n");
- return 1;
+ goto init_err;
}
ret = jaylink_select_interface(jaylink_devh, JAYLINK_TIF_JTAG, NULL);
if (ret != JAYLINK_OK) {
msg_perr("jaylink_select_interface() failed: %s.\n", jaylink_strerror(ret));
- return 1;
+ goto init_err;
}
if (enable_target_power) {
@@ -438,7 +436,7 @@
if (ret != JAYLINK_OK) {
msg_perr("jaylink_get_hardware_status() failed: %s.\n", jaylink_strerror(ret));
- return 1;
+ goto init_err;
}
msg_pdbg("VTarget: %u.%03u V\n", hwstat.target_voltage / 1000,
@@ -447,7 +445,7 @@
if (hwstat.target_voltage < MIN_TARGET_VOLTAGE) {
msg_perr("Target voltage is below %u.%03u V. You need to attach VTref to the I/O voltage of "
"the chip.\n", MIN_TARGET_VOLTAGE / 1000, MIN_TARGET_VOLTAGE % 1000);
- return 1;
+ goto init_err;
}
struct jaylink_speed device_speeds;
@@ -460,7 +458,7 @@
if (ret != JAYLINK_OK) {
msg_perr("jaylink_get_speeds() failed: %s.\n", jaylink_strerror(ret));
- return 1;
+ goto init_err;
}
}
@@ -476,25 +474,35 @@
if (speed > (device_speeds.freq / device_speeds.div)) {
msg_perr("Specified SPI speed of %lu kHz is too high. Maximum is %" PRIu32 " kHz.\n", speed,
device_speeds.freq / device_speeds.div);
- return 1;
+ goto init_err;
}
ret = jaylink_set_speed(jaylink_devh, speed);
if (ret != JAYLINK_OK) {
msg_perr("jaylink_set_speed() failed: %s.\n", jaylink_strerror(ret));
- return 1;
+ goto init_err;
}
msg_pdbg("SPI speed: %lu kHz\n", speed);
/* Ensure that the CS signal is not active initially. */
if (!deassert_cs())
- return 1;
+ goto init_err;
+ if (register_shutdown(jlink_spi_shutdown, NULL))
+ goto init_err;
register_spi_master(&spi_master_jlink_spi);
return 0;
+
+init_err:
+ if (jaylink_devh)
+ jaylink_close(jaylink_devh);
+
+ jaylink_exit(jaylink_ctx);
+
+ return 1;
}
const struct programmer_entry programmer_jlink_spi = {