Skip to content

Commit 4177fe2

Browse files
ahasztagtomchy
authored andcommitted
mgmt: suit: Fix starting new candidate upload before ending previous
This commit fixes the issue with starting a new envelope transfer while the old one has not yet finished its cleanup. This is done interrupting any image fetching which was in progress and waiting until the cleanup has finished. Signed-off-by: Artur Hadasz <[email protected]>
1 parent 31c42e4 commit 4177fe2

File tree

4 files changed

+82
-7
lines changed

4 files changed

+82
-7
lines changed

subsys/mgmt/suitfu/src/suitfu_mgmt.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ struct system_update_work {
3131

3232
static struct k_work_q system_update_work_queue;
3333

34+
/* Timeout duration for the semaphore which waits for envelope processing
35+
* to complete. This needs to be quite long because, in cases
36+
* where partitions in external memory are modified, the cleanup process
37+
* involves erasing them, which can be time-consuming.
38+
*/
39+
#define ENVELOPE_PROCESSING_STOPPING_TIMEOUT K_SECONDS(20)
40+
41+
K_SEM_DEFINE(envelope_processing_finished_sem, 0, 1);
42+
static atomic_t envelope_processing_in_progress;
43+
3444
static void update_failure(void)
3545
{
3646
if (suit_dfu_cleanup() < 0) {
@@ -42,23 +52,64 @@ static void schedule_envelope_processing(struct k_work *item)
4252
{
4353
int ret = suit_dfu_candidate_preprocess();
4454

55+
56+
if (atomic_get(&envelope_processing_in_progress) == 0) {
57+
LOG_INF("Envelope processing has been interrupted");
58+
ret = -ECANCELED;
59+
}
60+
4561
if (ret < 0) {
4662
LOG_ERR("Envelope processing error");
4763
update_failure();
64+
atomic_set(&envelope_processing_in_progress, 0);
65+
k_sem_give(&envelope_processing_finished_sem);
4866
return;
4967
}
68+
5069
k_msleep(CONFIG_MGMT_SUITFU_TRIGGER_UPDATE_RESET_DELAY_MS);
5170

71+
LOG_INF("Rebooting to start firmware upgrade");
5272
ret = suit_dfu_update_start();
5373
if (ret < 0) {
5474
LOG_ERR("Failed to start firmware upgrade!");
5575
update_failure();
76+
atomic_set(&envelope_processing_in_progress, 0);
77+
k_sem_give(&envelope_processing_finished_sem);
5678
return;
5779
}
80+
81+
atomic_set(&envelope_processing_in_progress, 0);
82+
k_sem_give(&envelope_processing_finished_sem);
83+
}
84+
85+
static void stop_current_envelope_processing(void)
86+
{
87+
if (atomic_get(&envelope_processing_in_progress) == 0) {
88+
return;
89+
}
90+
LOG_INF("Stopping old envelope processing");
91+
92+
#ifdef CONFIG_MGMT_SUITFU_GRP_SUIT_IMAGE_FETCH
93+
suitfu_mgmt_suit_image_fetch_stop();
94+
#endif
95+
/* Wait for the envelope processing to finish.
96+
* Note: If we have already finished envelope processing with success
97+
* and we are just waiting to send the response to the host,
98+
* this function will not stop the update anymore - the device will
99+
* reboot and start the update.
100+
*/
101+
atomic_set(&envelope_processing_in_progress, 0);
102+
if (k_sem_take(&envelope_processing_finished_sem,
103+
ENVELOPE_PROCESSING_STOPPING_TIMEOUT) == 0) {
104+
LOG_INF("Envelope processing stopped successfully");
105+
} else {
106+
LOG_WRN("Stopping envelope processing timed out");
107+
}
58108
}
59109

60110
int suitfu_mgmt_cleanup(void)
61111
{
112+
stop_current_envelope_processing();
62113
if (suit_dfu_cleanup() < 0) {
63114
return MGMT_ERR_EUNKNOWN;
64115
}
@@ -86,6 +137,12 @@ int suitfu_mgmt_candidate_envelope_process(void)
86137
LOG_INF("Schedule envelope processing");
87138
k_work_init_delayable(&suw.work, schedule_envelope_processing);
88139

140+
if (atomic_get(&envelope_processing_in_progress) == 1) {
141+
LOG_WRN("Current envelope processing is already in progress, new request rejected");
142+
return MGMT_ERR_EBUSY;
143+
}
144+
atomic_set(&envelope_processing_in_progress, 1);
145+
k_sem_reset(&envelope_processing_finished_sem);
89146
int ret = k_work_schedule_for_queue(&system_update_work_queue, &suw.work, K_NO_WAIT);
90147

91148
if (ret < 0) {
@@ -103,6 +160,8 @@ int suitfu_mgmt_erase(struct suit_nvm_device_info *device_info, size_t num_bytes
103160
return MGMT_ERR_EINVAL;
104161
}
105162

163+
stop_current_envelope_processing();
164+
106165
size_t erase_size = DIV_ROUND_UP(num_bytes, device_info->erase_block_size) *
107166
device_info->erase_block_size;
108167

@@ -133,6 +192,8 @@ int suitfu_mgmt_write(struct suit_nvm_device_info *device_info, size_t req_img_o
133192

134193
int rc;
135194

195+
stop_current_envelope_processing();
196+
136197
if (device_info == NULL || device_info->fdev == NULL || chunk == NULL) {
137198
LOG_ERR("Wrong parameters");
138199
return MGMT_ERR_EINVAL;
@@ -252,6 +313,7 @@ int suitfu_mgmt_write(struct suit_nvm_device_info *device_info, size_t req_img_o
252313

253314
int suitfu_mgmt_init(void)
254315
{
316+
atomic_set(&envelope_processing_in_progress, 0);
255317
k_work_queue_init(&system_update_work_queue);
256318
k_work_queue_start(&system_update_work_queue, system_update_stack_area,
257319
K_THREAD_STACK_SIZEOF(system_update_stack_area), K_HIGHEST_THREAD_PRIO,

subsys/mgmt/suitfu/src/suitfu_mgmt_priv.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,11 @@ int suitfu_mgmt_suit_envelope_upload(struct smp_streamer *ctx);
120120
*/
121121
void suitfu_mgmt_suit_image_fetch_init(void);
122122

123+
/**
124+
* @brief Stops Image fetching if it is in progress
125+
*/
126+
void suitfu_mgmt_suit_image_fetch_stop(void);
127+
123128
/**
124129
* @brief Process Get Missing Image State Request.
125130
*

subsys/mgmt/suitfu/src/suitfu_mgmt_suit_cand_env_upload.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ int suitfu_mgmt_suit_envelope_upload(struct smp_streamer *ctx)
9494
}
9595

9696
/* Erases dfu_partition and dfu_cache_partition_0, leaves
97-
* dfu_partition_1..dfu_partition_n intact. suitfu_mgmt_claenup() may be used
97+
* dfu_partition_1..dfu_partition_n intact. suitfu_mgmt_cleanup() may be used
9898
* instead.
9999
*/
100100
int rc = suitfu_mgmt_erase(&device_info, req.size);

subsys/mgmt/suitfu/src/suitfu_mgmt_suit_image_fetch.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ int suitfu_mgmt_suit_missing_image_upload(struct smp_streamer *ctx)
211211

212212
session->last_notify_ts = k_uptime_get();
213213

214-
component_unlock();
215214
} else {
216215
component_unlock();
217216
return MGMT_ERR_EBADSTATE;
@@ -228,7 +227,6 @@ int suitfu_mgmt_suit_missing_image_upload(struct smp_streamer *ctx)
228227
offset_in_image += req.img_data.len;
229228
}
230229

231-
component_lock();
232230
if (session->transfer_completed_cvar && session->uri && session->uri_length &&
233231
session->session_id == req.stream_session_id) {
234232
if (rc != 0) {
@@ -243,14 +241,11 @@ int suitfu_mgmt_suit_missing_image_upload(struct smp_streamer *ctx)
243241
session->return_code = SUIT_PLAT_SUCCESS;
244242
k_condvar_signal(session->transfer_completed_cvar);
245243
}
246-
247-
component_unlock();
248-
249244
} else {
250-
component_unlock();
251245
image_size = 0;
252246
return MGMT_ERR_EBADSTATE;
253247
}
248+
component_unlock();
254249

255250
rc = MGMT_ERR_EOK;
256251
if (zcbor_tstr_put_lit(zse, "rc") && zcbor_int32_put(zse, rc) &&
@@ -294,3 +289,16 @@ void suitfu_mgmt_suit_image_fetch_init(void)
294289
{
295290
suit_dfu_fetch_source_register(suitfu_mgmt_suit_missing_image_request);
296291
}
292+
293+
void suitfu_mgmt_suit_image_fetch_stop(void)
294+
{
295+
component_lock();
296+
stream_session_t *session = &stream_session;
297+
298+
if (session->uri) {
299+
/* Stop fetching by signaling the transfer completion with error */
300+
session->return_code = SUIT_PLAT_ERR_BUSY;
301+
k_condvar_signal(session->transfer_completed_cvar);
302+
}
303+
component_unlock();
304+
}

0 commit comments

Comments
 (0)