acpi_gbl_table_handler

在kernel中一般通过下面的的方式调用acpi_gbl_table_handler    
if (acpi_gbl_table_handler) {
        (void)acpi_gbl_table_handler(ACPI_TABLE_EVENT_LOAD, table,
                         acpi_gbl_table_handler_context);
    }

其中acpi_gbl_table_handler的第一个参数表示event。
event 主要有五种
/* Table Event Types */

#define ACPI_TABLE_EVENT_LOAD           0x0
#define ACPI_TABLE_EVENT_UNLOAD         0x1
#define ACPI_TABLE_EVENT_INSTALL        0x2
#define ACPI_TABLE_EVENT_UNINSTALL      0x3
#define ACPI_NUM_TABLE_EVENTS           4

在acpi/bus.c 中acpi_bus_init 会调用acpi_install_table_handler 来初始化acpi_gbl_table_handler
status = acpi_install_table_handler(acpi_bus_table_handler, NULL);
注意这时候acpi_gbl_table_handler_context 是等于NULL的,而是在调用的时候赋值的,就如上面调用的那样.
acpi_install_table_handler(acpi_table_handler handler, void *context)
{
    acpi_status status;

    ACPI_FUNCTION_TRACE(acpi_install_table_handler);

    if (!handler) {
        return_ACPI_STATUS(AE_BAD_PARAMETER);
    }

    status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
    if (ACPI_FAILURE(status)) {
        return_ACPI_STATUS(status);
    }

    /* Don't allow more than one handler */

    if (acpi_gbl_table_handler) {
        status = AE_ALREADY_EXISTS;
        goto cleanup;
    }

    /* Install the handler */

    acpi_gbl_table_handler = handler;
    acpi_gbl_table_handler_context = context;

cleanup:
    (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
    return_ACPI_STATUS(status);
}
acpi_bus_table_handler 的实现如下,只要分为两个函数,
static acpi_status acpi_bus_table_handler(u32 event, void *table, void *context)
{
    acpi_scan_table_handler(event, table, context);

    return acpi_sysfs_table_handler(event, table, context);
}
acpi_scan_table_handler 主要是为ACPI_TABLE_EVENT_LOAD申请一个acpi_table_events_work ,并初始化一个work。
void acpi_scan_table_handler(u32 event, void *table, void *context)
{
    struct acpi_table_events_work *tew;

    if (!acpi_scan_initialized)
        return;

    if (event != ACPI_TABLE_EVENT_LOAD)
        return;

    tew = kmalloc(sizeof(*tew), GFP_KERNEL);
    if (!tew)
        return;

    INIT_WORK(&tew->work, acpi_table_events_fn);
    tew->table = table;
    tew->event = event;

    schedule_work(&tew->work);
}



但是acpi_bus_table_handler 这个函数只处理ACPI_TABLE_EVENT_LOAD。
这个event的处理函数是acpi_table_events_fn
static void acpi_table_events_fn(struct work_struct *work)
{
    struct acpi_table_events_work *tew;

    tew = container_of(work, struct acpi_table_events_work, work);

    if (tew->event == ACPI_TABLE_EVENT_LOAD) {
        acpi_scan_lock_acquire();
        acpi_bus_scan(ACPI_ROOT_OBJECT);
        acpi_scan_lock_release();
    }

    kfree(tew);
}
从这个函数也看出只处理event函数。 acpi_table_events_fn 主要调用acpi_bus_scan 来将ACPI device node 加到namespace scope中
再来看看acpi_sysfs_table_handler
acpi_status acpi_sysfs_table_handler(u32 event, void *table, void *context)
{
    struct acpi_table_attr *table_attr;

    switch (event) {
    case ACPI_TABLE_EVENT_INSTALL:
        table_attr =
            kzalloc(sizeof(struct acpi_table_attr), GFP_KERNEL);
        if (!table_attr)
            return AE_NO_MEMORY;

        if (acpi_table_attr_init(dynamic_tables_kobj,
                     table_attr, table)) {
            kfree(table_attr);
            return AE_ERROR;
        }
        list_add_tail(&table_attr->node, &acpi_table_attr_list);
        break;
    case ACPI_TABLE_EVENT_LOAD:
    case ACPI_TABLE_EVENT_UNLOAD:
    case ACPI_TABLE_EVENT_UNINSTALL:
        /*
         * we do not need to do anything right now
         * because the table is not deleted from the
         * global table list when unloading it.
         */
        break;
    default:
        return AE_BAD_PARAMETER;
    }
    return AE_OK;
}
acpi_sysfs_table_handler 只处理ACPI_TABLE_EVENT_INSTALL ,主要调用acpi_table_attr_init 在下面的路径中生成二进制文件
/sys/firmware/acpi/tables/dynamic

static int acpi_table_attr_init(struct kobject *tables_obj,
                struct acpi_table_attr *table_attr,
                struct acpi_table_header *table_header)
{
    struct acpi_table_header *header = NULL;
    struct acpi_table_attr *attr = NULL;
    char instance_str[ACPI_INST_SIZE];

    sysfs_attr_init(&table_attr->attr.attr);
    ACPI_MOVE_NAME(table_attr->name, table_header->signature);

    list_for_each_entry(attr, &acpi_table_attr_list, node) {
        if (ACPI_COMPARE_NAME(table_attr->name, attr->name))
            if (table_attr->instance < attr->instance)
                table_attr->instance = attr->instance;
    }
    table_attr->instance++;
    if (table_attr->instance > ACPI_MAX_TABLE_INSTANCES) {
        pr_warn("%4.4s: too many table instances\n",
            table_attr->name);
        return -ERANGE;
    }

    ACPI_MOVE_NAME(table_attr->filename, table_header->signature);
    table_attr->filename[ACPI_NAME_SIZE] = '\0';
    if (table_attr->instance > 1 || (table_attr->instance == 1 &&
                     !acpi_get_table
                     (table_header->signature, 2, &header))) {
        snprintf(instance_str, sizeof(instance_str), "%u",
             table_attr->instance);
        strcat(table_attr->filename, instance_str);
    }

    table_attr->attr.size = table_header->length;
    table_attr->attr.read = acpi_table_show;
    table_attr->attr.attr.name = table_attr->filename;
    table_attr->attr.attr.mode = 0400;

    return sysfs_create_bin_file(tables_obj, &table_attr->attr);
}
可以看到最终调用sysfs_create_bin_file 来实现,并且这个/sys/firmware/acpi/tables/dynamic 路径下提供的文件是只读的
因为table_attr->attr.write是等于NULL的。所有就没有提供写函数.
为什么会是这个路径呢?
因为dynamic_tables_kobj的赋值如下:
static int acpi_tables_sysfs_init(void)
{
    struct acpi_table_attr *table_attr;
    struct acpi_table_header *table_header = NULL;
    int table_index;
    acpi_status status;
    int ret;

    tables_kobj = kobject_create_and_add("tables", acpi_kobj);
    if (!tables_kobj)
        goto err;

    dynamic_tables_kobj = kobject_create_and_add("dynamic", tables_kobj);
    if (!dynamic_tables_kobj)
        goto err_dynamic_tables;

}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值