-
Notifications
You must be signed in to change notification settings - Fork 6.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
drivers: mbox: add IVSHMEM based mbox driver
Add initial support of the mailbox driver based on the inter VM shared memory mechanism similar as the existing IPM driver. Signed-off-by: Felipe Neves <ryukokki.felipe@gmail.com>
- Loading branch information
Showing
5 changed files
with
199 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Copyright (c) 2024, Felipe Neves | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
config MBOX_IVSHMEM | ||
bool "MBOX driver based on IVSHMEM-Doorbell" | ||
default y | ||
depends on DT_HAS_LINARO_IVSHMEM_MBOX_ENABLED | ||
depends on IVSHMEM | ||
depends on IVSHMEM_DOORBELL | ||
help | ||
Mailbox driver using IVSHMEM Doorbell mechanism. | ||
|
||
if MBOX_IVSHMEM | ||
|
||
config MBOX_IVSHMEM_EVENT_LOOP_STACK_SIZE | ||
int "Stack size in bytes of IVSHMEM MBOX Event loop task" | ||
default 8192 | ||
help | ||
Adjust the stack size, in bytes of the ivshmem event loop task. | ||
|
||
config MBOX_IVSHMEM_EVENT_LOOP_PRIO | ||
int "Priority of IVSHMEM MBOX Event loop task" | ||
default 2 | ||
help | ||
Adjust the priority of the ivshmem event loop task. | ||
|
||
endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
/* | ||
* Copyright (c) 2024 Felipe Neves. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#define DT_DRV_COMPAT linaro_ivshmem_mbox | ||
|
||
#include <stdint.h> | ||
#include <string.h> | ||
#include <zephyr/device.h> | ||
#include <zephyr/drivers/mbox.h> | ||
#include <zephyr/drivers/virtualization/ivshmem.h> | ||
#include <zephyr/logging/log.h> | ||
LOG_MODULE_REGISTER(mbox_ivshmem, CONFIG_MBOX_LOG_LEVEL); | ||
|
||
K_THREAD_STACK_DEFINE(ivshmem_ev_loop_stack, CONFIG_MBOX_IVSHMEM_EVENT_LOOP_STACK_SIZE); | ||
static struct k_thread ivshmem_ev_loop_thread; | ||
|
||
struct ivshmem_mbox_data { | ||
mbox_callback_t cb; | ||
void *user_data; | ||
}; | ||
|
||
struct ivshmem_mbox_config { | ||
const struct device *ivshmem_dev; | ||
int peer_id; | ||
}; | ||
|
||
static void ivshmem_mbox_event_loop_thread(void *arg, void *p2, void *p3) | ||
{ | ||
ARG_UNUSED(p2); | ||
ARG_UNUSED(p3); | ||
|
||
unsigned int poll_signaled; | ||
int ivshmem_vector_rx; | ||
struct k_poll_signal sig; | ||
struct k_poll_event events[] = { | ||
K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &sig), | ||
}; | ||
|
||
const struct device *dev = (const struct device *)arg; | ||
struct ivshmem_mbox_data *dev_data = (struct ivshmem_mbox_data *)dev->data; | ||
struct ivshmem_mbox_config *dev_cfg = (struct ivshmem_mbox_config *)dev->config; | ||
|
||
k_poll_signal_init(&sig); | ||
int ret = ivshmem_register_handler(dev_cfg->ivshmem_dev, &sig, 0); | ||
|
||
if (ret < 0) { | ||
LOG_ERR("registering handlers must be supported: %d\n", ret); | ||
k_panic(); | ||
} | ||
|
||
while (1) { | ||
LOG_DBG("%s: waiting interrupt from client...\n", __func__); | ||
ret = k_poll(events, ARRAY_SIZE(events), K_FOREVER); | ||
|
||
k_poll_signal_check(&sig, &poll_signaled, &ivshmem_vector_rx); | ||
/* get ready for next signal */ | ||
k_poll_signal_reset(&sig); | ||
|
||
if (dev_data->cb) { | ||
dev_data->cb(dev, 0, dev_data->user_data, NULL); | ||
} | ||
} | ||
} | ||
|
||
static int ivshmem_mbox_send(const struct device *dev, mbox_channel_id_t channel, | ||
const struct mbox_msg *msg) | ||
{ | ||
ARG_UNUSED(msg); | ||
ARG_UNUSED(channel); | ||
|
||
struct ivshmem_mbox_config *dev_cfg = (struct ivshmem_mbox_config *)dev->config; | ||
|
||
LOG_DBG("sending notification to the peer id 0x%x\n", (int)channel); | ||
return ivshmem_int_peer(dev_cfg->ivshmem_dev, (int)channel, 0); | ||
} | ||
|
||
static int ivshmem_mbox_register_callback(const struct device *dev, mbox_channel_id_t channel, | ||
mbox_callback_t cb, void *user_data) | ||
{ | ||
ARG_UNUSED(channel); | ||
|
||
struct ivshmem_mbox_data *dev_data = (struct ivshmem_mbox_data *)dev->data; | ||
|
||
if (!cb) { | ||
LOG_ERR("Must provide a callback"); | ||
return -EINVAL; | ||
} | ||
|
||
dev_data->cb = cb; | ||
dev_data->user_data = user_data; | ||
|
||
return 0; | ||
} | ||
|
||
/* some subsystems needs those functions to be at least implemented, | ||
* returning some valid values instead of errors, just provide them. | ||
*/ | ||
|
||
static int ivshmem_mbox_mtu_get(const struct device *dev) | ||
{ | ||
ARG_UNUSED(dev); | ||
|
||
return 0; | ||
} | ||
|
||
static uint32_t ivshmem_mbox_max_channels_get(const struct device *dev) | ||
{ | ||
ARG_UNUSED(dev); | ||
|
||
return UINT16_MAX; | ||
} | ||
|
||
static int ivshmem_mbox_set_enabled(const struct device *dev, mbox_channel_id_t channel, | ||
bool enable) | ||
{ | ||
ARG_UNUSED(dev); | ||
ARG_UNUSED(channel); | ||
ARG_UNUSED(enable); | ||
|
||
return 0; | ||
} | ||
|
||
static int ivshmem_mbox_init(const struct device *dev) | ||
{ | ||
k_thread_create(&ivshmem_ev_loop_thread, ivshmem_ev_loop_stack, | ||
CONFIG_MBOX_IVSHMEM_EVENT_LOOP_STACK_SIZE, ivshmem_mbox_event_loop_thread, | ||
(void *)dev, NULL, NULL, CONFIG_MBOX_IVSHMEM_EVENT_LOOP_PRIO, 0, K_NO_WAIT); | ||
|
||
return 0; | ||
} | ||
|
||
static const struct mbox_driver_api ivshmem_mbox_driver_api = { | ||
.send = ivshmem_mbox_send, | ||
.register_callback = ivshmem_mbox_register_callback, | ||
.mtu_get = ivshmem_mbox_mtu_get, | ||
.max_channels_get = ivshmem_mbox_max_channels_get, | ||
.set_enabled = ivshmem_mbox_set_enabled, | ||
}; | ||
|
||
#define MBOX_IVSHMEM_INIT(inst) \ | ||
static const struct ivshmem_mbox_config ivshmem_mbox_cfg_##inst = { \ | ||
.ivshmem_dev = DEVICE_DT_GET(DT_INST_PHANDLE(inst, ivshmem)), \ | ||
}; \ | ||
static struct ivshmem_mbox_data ivshmem_mbox_data_##inst = { \ | ||
.cb = NULL, \ | ||
.user_data = NULL, \ | ||
}; \ | ||
DEVICE_DT_INST_DEFINE(inst, ivshmem_mbox_init, NULL, &ivshmem_mbox_data_##inst, \ | ||
&ivshmem_mbox_cfg_##inst, POST_KERNEL, \ | ||
CONFIG_APPLICATION_INIT_PRIORITY, &ivshmem_mbox_driver_api); | ||
Check notice on line 153 in drivers/mbox/mbox_ivshmem.c GitHub Actions / Run compliance checks on patch series (PR)You may want to run clang-format on this change
|
||
|
||
DT_INST_FOREACH_STATUS_OKAY(MBOX_IVSHMEM_INIT); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Copyright (c) 2024 Felipe Neves | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
description: Inter VM shared memory based mailbox binding | ||
|
||
compatible: "linaro,ivshmem-mbox" | ||
|
||
include: base.yaml | ||
|
||
properties: | ||
|
||
ivshmem: | ||
type: phandle | ||
required: true | ||
description: ivshmem device node |