前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一文搞懂 | Linux互连子系统

一文搞懂 | Linux互连子系统

作者头像
刘盼
发布2021-11-15 17:30:58
8870
发布2021-11-15 17:30:58
举报
文章被收录于专栏:人人都是极客人人都是极客

该框架旨在提供标准内核接口来控制 SoC 上的互连设置。这些设置可以是多个互连设备或功能块之间的吞吐量、延迟和优先级。这可以动态控制以节省功率或提供最大性能

互连总线是具有可配置参数的硬件,可以根据从各种驱动程序接收到的请求在数据路径上设置这些参数。互连总线的一个例子是芯片组中各种组件或功能块之间的互连。一个 SoC 上可以有多个互连,这些互连可以是多层的。

下面是 SoC 互连总线拓扑的简化图。

互连子系统的设计

互连子系统用以下几个概念抽象硬件的实现。

Interconnect provider

以软件的方式定义互连硬件模块,比如上图中的 M NoC、S NoC、C NoC、P NoC 和 Mem NoC。

代码语言:javascript
复制
struct icc_provider {
        //注册互连供应商名单
        struct list_head        provider_list;
        //互连供应商节点的内部列表
        struct list_head        nodes;
        //指向设备特定设置操作函数的指针
        int (*set)(struct icc_node *src, struct icc_node *dst);
        //指向设备特定聚合操作函数的指针
        int (*aggregate)(struct icc_node *node, u32 tag, u32 avg_bw,
                         u32 peak_bw, u32 *agg_avg, u32 *agg_peak);
        //指向在聚合开始之前调用的特定于设备的函数的指针
        void (*pre_aggregate)(struct icc_node *node);
        //指向设备特定函数的指针以获取当前带宽
        int (*get_bw)(struct icc_node *node, u32 *avg, u32 *peak);
        //用于从 phandle 参数映射节点的特定于提供程序的回调
        struct icc_node* (*xlate)(struct of_phandle_args *spec, void *data);
        //用于从 phandle 参数映射节点数据的供应商特定回调
        struct icc_node_data* (*xlate_extended)(struct of_phandle_args *spec, void *data);
        //此互连提供程序所属的设备
        struct device           *dev;
        //活跃用户数
        int                     users;
        //是否将使用set配置提供商间对
        bool                    inter_set;
        //指向私有数据的指针
        void                    *data;
};
代码语言:javascript
复制
struct icc_onecell_data {
        /此设备中的节点数
        unsigned int num_nodes;
        //指向此设备中节点的指针数组
        struct icc_node *nodes[];
};

Interconnect provider 提供的相关 API 如下所示:

代码语言:javascript
复制
//#include <linux/interconnect-provider.h>
int icc_std_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
                      u32 peak_bw, u32 *agg_avg, u32 *agg_peak);
struct icc_node *icc_node_create(int id);
void icc_node_destroy(int id);
int icc_link_create(struct icc_node *node, const int dst_id);
int icc_link_destroy(struct icc_node *src, struct icc_node *dst);
void icc_node_add(struct icc_node *node, struct icc_provider *provider);
void icc_node_del(struct icc_node *node);
int icc_nodes_remove(struct icc_provider *provider);
int icc_provider_add(struct icc_provider *provider);
int icc_provider_del(struct icc_provider *provider);
struct icc_node_data *of_icc_get_from_provider(struct of_phandle_args *spec);
void icc_sync_state(struct device *dev);

Interconnect node

互连节点定义这些互连硬件的端口。比如图中 CPU 连接到内存的点称为互连节点,属于 Mem NoC 模块。

代码语言:javascript
复制
struct icc_node {
        //平台特定的节点 ID
        int                     id;
        //debugfs 中使用的节点名称
        const char              *name;
        //指向我们在遍历时下一步可以去哪里的目标列表
        struct icc_node         **links;
        //到其他互连节点的链接数
        size_t                  num_links;

        //指向此节点的互连供应商
        struct icc_provider     *provider;
        //父提供者的“节点”列表中的列表条目
        struct list_head        node_list;
        //遍历节点图时使用的列表
        struct list_head        search_list;
        //遍历节点图时指向前一个节点的指针
        struct icc_node         *reverse;
        //遍历节点图时使用的标志
        u8                      is_traversed:1;
        //与此节点关联的 QoS 约束请求列表
        struct hlist_head       req_list;
        //来自所有消费者的平均带宽请求的总和
        u32                     avg_bw;
        //来自所有消费者的峰值带宽请求的总和
        u32                     peak_bw;
        //在初始化期间从硬件读取的平均带宽值
        u32                     init_avg;
        //在初始化期间从硬件读取的峰值带宽值
        u32                     init_peak;
        //指向私有数据的指针
        void                    *data;
};

Interconnect endpoints

互连端点是路径的第一个或最后一个元素。每个端点都是一个节点,但并非每个节点都是一个端点。

Interconnect path

互连路径是两个端点之间的一切,包括从源节点到达目标节点必须遍历的所有节点。

代码语言:javascript
复制
struct icc_path {
        const char *name;
        size_t num_nodes;
        struct icc_req reqs[];
};

Interconnect consumers

向 provider 发送请求,请求各种吞吐量、延迟和优先级。通常是设备驱动程序,根据他们的需要发送请求。

Interconnect consumers 提供的相关 API 如下所示:

代码语言:javascript
复制
//include/linux/interconnect.h
struct icc_path *icc_get(struct device *dev, const int src_id,
                         const int dst_id);
struct icc_path *of_icc_get(struct device *dev, const char *name);
struct icc_path *devm_of_icc_get(struct device *dev, const char *name);
struct icc_path *of_icc_get_by_index(struct device *dev, int idx);
void icc_put(struct icc_path *path);
int icc_enable(struct icc_path *path);
int icc_disable(struct icc_path *path);
int icc_set_bw(struct icc_path *path, u32 avg_bw, u32 peak_bw);
void icc_set_tag(struct icc_path *path, u32 tag);
const char *icc_get_name(struct icc_path *path);

互连子系统的 debugfs 接口

在用户态可以通过 debugfs 的接口去调试互联子系统的信息。

  • /sys/kernel/debug/interconnect/interconnect_graph
  • /sys/kernel/debug/interconnect/interconnect_summary

结果如下所示:

互连子系统的软件流程

最后我们用一张图总结下互连子系统的软件架构。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-11-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 人人都是极客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 互连子系统的设计
    • Interconnect provider
      • Interconnect node
        • Interconnect endpoints
          • Interconnect path
            • Interconnect consumers
            • 互连子系统的 debugfs 接口
            • 互连子系统的软件流程
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档