1 概述
(1)mailbox是一种框架,通过消息队列和中断驱动信号处理多处理器间的通讯;
(2)mailbox的实现分为contoller和client。简单的说就是client 可以通过controller提供的channel发送信息给controller;
(3)在drivers/mailbox下实现的都是controller的源码;
具体到某个厂商的硬件,则描述如下:
Kconfig文件:内核开关,用于配置mbox模块是否编译到内核;
config ARM_MHU
tristate "ARM MHU Mailbox"
depends on ARM_AMBA help
Say Y here if you want to build the ARM MHU controller driver. The controller has 3 mailbox channels, the last of which can be used in Secure mode only.
Makefile文件:根据Kconfig编译相应的模块;
我们知道要实现mailbox的源文件其实只有两个
obj-$(CONFIG_MAILBOX) += mailbox.o
obj-$(CONFIG_ARM_MHU) += arm_mhu.o
其中,mailbox.c 是kernel提供的framework,arm_mhu.c 则是具体厂商的实现
(4)client 通过mbox_send_message给controller发送数据的时候必须指定channel;
int mbox_send_message(struct mbox_chan *chan, void *mssg)
(5)client 在通过mbox_send_message给controller发送数据的时候必须指定channel,channel可以通过以下方式获得。
目前kernel提供了两种方法得到mailbox的channel
struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl,const char *name);
struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index);
使用完成后调用mbox_free_channel 释放channel,这样别人就可以继续使用这个channel;
void mbox_free_channel(struct mbox_chan *chan); /* may sleep */
其中,mbox_request_channel_byname是mbox_request_channel的一个封装。
2 基本框架
目录:
drivers/mailbox
mailbox.c/mailbox.h/mailbox-test.c/-mailbox.c
3 关键数据结构
struct mbox_controller {
struct device *dev; // 特定mailbox驱动probe时赋值 dev = &pdev->dev
const struct mbox_chan_ops *ops; // mailbox channel需要实现的功能函数
struct mbox_chan *chans; // mailbox channel指针数组
int num_chans; // mailbox channel个数
bool txdone_irq; // 通过中断来判断上次传输是否完成
bool txdone_poll; // 通过poll机制来判断上次传输是否完成
unsigned txpoll_period; // POLL 周期, 以ms计
struct mbox_chan *(*of_xlate)(struct mbox_controller *mbox,
const struct of_phandle_args *sp); // 获取特定channel的回调函数
/* Internal to API */
struct hrtimer poll_hrt;
struct list_head node;
};
struct mbox_chan {
struct mbox_controller *mbox; // contronller指针
unsigned txdone_method;
struct mbox_client *cl; // client指针
struct completion tx_complete; //
void *active_req;
unsigned msg_count, msg_free;
void *msg_data[MBOX_TX_QUEUE_LEN];
spinlock_t lock; /* Serialise access to the channel */
void *con_priv;
};
struct mbox_chan_ops {
int (*send_data)(struct mbox_chan *chan, void *data); // 发送数据(需要last data sent)
int (*startup)(struct mbox_chan *chan); // 特定mailbox 启动
void (*shutdown)(struct mbox_chan *chan); // 特定mailbox 关闭
bool (*last_tx_done)(struct mbox_chan *chan); // 如果TXDONE_BY_POLL 该回调会被使用
bool (*peek_data)(struct mbox_chan *chan); // 检测是否有数据
};
struct mbox_client {
struct device *dev; // client 设备
bool tx_block; // block until last data is all transmitted
unsigned long tx_tout; // max block period for timeout
bool knows_txdone; // txdone 回调,如果controller已经有txdone,则该配置无效
void (*rx_callback)(struct mbox_client *cl, void *mssg); // 收到数据
void (*tx_prepare)(struct mbox_client *cl, void *mssg); // 准备数据
void (*tx_done)(struct mbox_client *cl, void *mssg, int r); // 检测txdone
};
4 函数接口
4.1 mailbox controller api
文件:kernel/include/linux/mailbox_controller.h
(1)注册、注销控制器
int mbox_controller_register(struct mbox_controller *mbox); /* can sleep */--------probe中调用
void mbox_controller_unregister(struct mbox_controller *mbox); /* can sleep */-------probe中调用
(2)(对外接口)将底层收到的数据回调给上层应用
void mbox_chan_received_data(struct mbox_chan *chan, void *data); /* atomic */
(3)通知上层当前数据已经发送完成
void mbox_chan_txdone(struct mbox_chan *chan, int r); /* atomic */
4.2 mailbox client api
文件:kernel/include/linux/mailbox_client.h
(1)发送数据前,申请通道
struct mbox_chan *mbox_request_channel_byname(struct mbox_client *cl,
const char *name);
struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index);
(2)数据发送
int mbox_send_message(struct mbox_chan *chan, void *mssg);
v