Skip to content

Commit 23c9f7b

Browse files
jacksonc-xlnxcarlescufi
authored andcommitted
ipc_service: Add ipc_service_close_instance function
This function allows the application to close an ipc_service instance. It is intended for use when the remote agent it is communicating with has gone down and allows for cleanup. It first checks that the endpoints have been separately deregistered with the instance using the deregister_endpoint function before calling into previously added functions in ipc_static_vrings.c and ipc_rpmsg.c to close those instances. Signed-off-by: Jackson Cooper-Driver <[email protected]>
1 parent e69d131 commit 23c9f7b

File tree

4 files changed

+134
-0
lines changed

4 files changed

+134
-0
lines changed

include/zephyr/ipc/ipc_service.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,24 @@ struct ipc_ept_cfg {
203203
*/
204204
int ipc_service_open_instance(const struct device *instance);
205205

206+
/** @brief Close an instance
207+
*
208+
* Function to be used to close an instance. All endpoints must be
209+
* deregistered using ipc_service_deregister_endpoint before this
210+
* is called.
211+
*
212+
* @param[in] instance Instance to close.
213+
*
214+
* @retval -EINVAL when instance configuration is invalid.
215+
* @retval -EIO when no backend is registered.
216+
* @retval -EALREADY when the instance is not already opened.
217+
* @retval -EBUSY when an endpoint exists that hasn't been
218+
* deregistered
219+
*
220+
* @retval 0 on success or when not implemented on the backend (not needed).
221+
* @retval other errno codes depending on the implementation of the backend.
222+
*/
223+
int ipc_service_close_instance(const struct device *instance);
206224

207225
/** @brief Register IPC endpoint onto an instance.
208226
*

include/zephyr/ipc/ipc_service_backend.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ struct ipc_service_backend {
3737
*/
3838
int (*open_instance)(const struct device *instance);
3939

40+
/** @brief Pointer to the function that will be used to close an instance
41+
*
42+
* @param[in] instance Instance pointer.
43+
*
44+
* @retval -EALREADY when the instance is not already inited.
45+
*
46+
* @retval 0 on success
47+
* @retval other errno codes depending on the implementation of the
48+
* backend.
49+
*/
50+
int (*close_instance)(const struct device *instance);
51+
4052
/** @brief Pointer to the function that will be used to send data to the endpoint.
4153
*
4254
* @param[in] instance Instance pointer.

subsys/ipc/ipc_service/backends/ipc_rpmsg_static_vrings.c

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,21 @@ static struct ipc_rpmsg_ept *get_available_ept_slot(struct ipc_rpmsg_instance *r
8888
return get_ept_slot_with_name(rpmsg_inst, "");
8989
}
9090

91+
static bool check_endpoints_freed(struct ipc_rpmsg_instance *rpmsg_inst)
92+
{
93+
struct ipc_rpmsg_ept *rpmsg_ept;
94+
95+
for (size_t i = 0; i < NUM_ENDPOINTS; i++) {
96+
rpmsg_ept = &rpmsg_inst->endpoint[i];
97+
98+
if (strcmp("", rpmsg_ept->name) != 0) {
99+
return false;
100+
}
101+
}
102+
103+
return true;
104+
}
105+
91106
/*
92107
* Returns:
93108
* - true: when the endpoint was already cached / registered
@@ -299,6 +314,26 @@ static int mbox_init(const struct device *instance)
299314
return mbox_set_enabled(&conf->mbox_rx, 1);
300315
}
301316

317+
static int mbox_deinit(const struct device *instance)
318+
{
319+
const struct backend_config_t *conf = instance->config;
320+
struct backend_data_t *data = instance->data;
321+
k_tid_t wq_thread;
322+
int err;
323+
324+
err = mbox_set_enabled(&conf->mbox_rx, 0);
325+
if (err != 0) {
326+
return err;
327+
}
328+
329+
k_work_queue_drain(&data->mbox_wq, 1);
330+
331+
wq_thread = k_work_queue_thread_get(&data->mbox_wq);
332+
k_thread_abort(wq_thread);
333+
334+
return 0;
335+
}
336+
302337
static struct ipc_rpmsg_ept *register_ept_on_host(struct ipc_rpmsg_instance *rpmsg_inst,
303338
const struct ipc_ept_cfg *cfg)
304339
{
@@ -539,6 +574,50 @@ static int open(const struct device *instance)
539574

540575
}
541576

577+
static int close(const struct device *instance)
578+
{
579+
const struct backend_config_t *conf = instance->config;
580+
struct backend_data_t *data = instance->data;
581+
struct ipc_rpmsg_instance *rpmsg_inst;
582+
int err;
583+
584+
if (!atomic_cas(&data->state, STATE_INITED, STATE_BUSY)) {
585+
return -EALREADY;
586+
}
587+
588+
rpmsg_inst = &data->rpmsg_inst;
589+
590+
if (!check_endpoints_freed(rpmsg_inst)) {
591+
return -EBUSY;
592+
}
593+
594+
err = ipc_rpmsg_deinit(rpmsg_inst, data->role);
595+
if (err != 0) {
596+
goto error;
597+
}
598+
599+
err = mbox_deinit(instance);
600+
if (err != 0) {
601+
goto error;
602+
}
603+
604+
err = ipc_static_vrings_deinit(&data->vr, conf->role);
605+
if (err != 0) {
606+
goto error;
607+
}
608+
609+
memset(&data->vr, 0, sizeof(struct ipc_static_vrings));
610+
memset(rpmsg_inst, 0, sizeof(struct ipc_rpmsg_instance));
611+
612+
atomic_set(&data->state, STATE_READY);
613+
return 0;
614+
615+
error:
616+
/* Back to the inited state */
617+
atomic_set(&data->state, STATE_INITED);
618+
return err;
619+
}
620+
542621
static int get_tx_buffer_size(const struct device *instance, void *token)
543622
{
544623
struct backend_data_t *data = instance->data;
@@ -638,6 +717,7 @@ static int drop_tx_buffer(const struct device *instance, void *token,
638717

639718
const static struct ipc_service_backend backend_ops = {
640719
.open_instance = open,
720+
.close_instance = close,
641721
.register_endpoint = register_ept,
642722
.deregister_endpoint = deregister_ept,
643723
.send = send,

subsys/ipc/ipc_service/ipc_service.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,30 @@ int ipc_service_open_instance(const struct device *instance)
3838
return backend->open_instance(instance);
3939
}
4040

41+
int ipc_service_close_instance(const struct device *instance)
42+
{
43+
const struct ipc_service_backend *backend;
44+
45+
if (!instance) {
46+
LOG_ERR("Invalid instance");
47+
return -EINVAL;
48+
}
49+
50+
backend = (const struct ipc_service_backend *) instance->api;
51+
52+
if (!backend) {
53+
LOG_ERR("Invalid backend configuration");
54+
return -EIO;
55+
}
56+
57+
if (!backend->close_instance) {
58+
/* maybe not needed on backend */
59+
return 0;
60+
}
61+
62+
return backend->close_instance(instance);
63+
}
64+
4165
int ipc_service_register_endpoint(const struct device *instance,
4266
struct ipc_ept *ept,
4367
const struct ipc_ept_cfg *cfg)

0 commit comments

Comments
 (0)