ipmit初始化smi_info添加到smi_infos

当通过hardcode_find_bmc以hardcode的方式确定有bmc后,后面就要判断是通过DMI还是ACPI的方式来初始化smi_info添加到smi_infos 这个list中。
例如在init_ipmi_si 根据dmi初始化smi_info的函数为dmi_find_bmc
static void dmi_find_bmc(void)
{
    const struct dmi_device *dev = NULL;
    struct dmi_ipmi_data data;
    int                  rv;

    while ((dev = dmi_find_device(DMI_DEV_TYPE_IPMI, NULL, dev))) {
        memset(&data, 0, sizeof(data));
        rv = decode_dmi((const struct dmi_header *) dev->device_data,
                &data);
        if (!rv)
            try_init_dmi(&data);
    }
}
可以看是通过dmi_find_device 来查找DMI_DEV_TYPE_IPMI,除此之外通过dmi_find_device 查找的其他设备如下:
enum dmi_device_type {
    DMI_DEV_TYPE_ANY = 0,
    DMI_DEV_TYPE_OTHER,
    DMI_DEV_TYPE_UNKNOWN,
    DMI_DEV_TYPE_VIDEO,
    DMI_DEV_TYPE_SCSI,
    DMI_DEV_TYPE_ETHERNET,
    DMI_DEV_TYPE_TOKENRING,
    DMI_DEV_TYPE_SOUND,
    DMI_DEV_TYPE_PATA,
    DMI_DEV_TYPE_SATA,
    DMI_DEV_TYPE_SAS,
    DMI_DEV_TYPE_IPMI = -1,
    DMI_DEV_TYPE_OEM_STRING = -2,
    DMI_DEV_TYPE_DEV_ONBOARD = -3,
    DMI_DEV_TYPE_DEV_SLOT = -4,
};
在dmi_find_bmc 中如果找到设备后,就通过decode_dmi 将DMI_DEV_TYPE_IPMI的信息存在struct dmi_ipmi_data data中,然后调用try_init_dmi 初始化smi_info添加到smi_infos 这个list中
static void try_init_dmi(struct dmi_ipmi_data *ipmi_data)
{
    struct smi_info *info;

    info = smi_info_alloc();
    if (!info) {
        printk(KERN_ERR PFX "Could not allocate SI data\n");
        return;
    }

    info->addr_source = SI_SMBIOS;
    printk(KERN_INFO PFX "probing via SMBIOS\n");

    switch (ipmi_data->type) {
    case 0x01: /* KCS */
        info->si_type = SI_KCS;
        break;
    case 0x02: /* SMIC */
        info->si_type = SI_SMIC;
        break;
    case 0x03: /* BT */
        info->si_type = SI_BT;
        break;
    default:
        kfree(info);
        return;
    }

    switch (ipmi_data->addr_space) {
    case IPMI_MEM_ADDR_SPACE:
        info->io_setup = mem_setup;
        info->io.addr_type = IPMI_MEM_ADDR_SPACE;
        break;

    case IPMI_IO_ADDR_SPACE:
        info->io_setup = port_setup;
        info->io.addr_type = IPMI_IO_ADDR_SPACE;
        break;

    default:
        kfree(info);
        printk(KERN_WARNING PFX "Unknown SMBIOS I/O Address type: %d\n",
               ipmi_data->addr_space);
        return;
    }
    info->io.addr_data = ipmi_data->base_addr;

    info->io.regspacing = ipmi_data->offset;
    if (!info->io.regspacing)
        info->io.regspacing = DEFAULT_REGSPACING;
    info->io.regsize = DEFAULT_REGSPACING;
    info->io.regshift = 0;

    info->slave_addr = ipmi_data->slave_addr;

    info->irq = ipmi_data->irq;
    if (info->irq)
        info->irq_setup = std_irq_setup;

    pr_info("ipmi_si: SMBIOS: %s %#lx regsize %d spacing %d irq %d\n",
         (info->io.addr_type == IPMI_IO_ADDR_SPACE) ? "io" : "mem",
         info->io.addr_data, info->io.regsize, info->io.regspacing,
         info->irq);
//前面是基本的赋值,这里调用add_smi添加到smi_infos 这个list中
    if (add_smi(info))
        kfree(info);
}
除了通过DMI外和可以通过APCI 其函数是spmi_find_bmc
static void spmi_find_bmc(void)
{
    acpi_status      status;
    struct SPMITable *spmi;
    int              i;

    if (acpi_disabled)
        return;

    if (acpi_failure)
        return;

    for (i = 0; ; i++) {
        status = acpi_get_table(ACPI_SIG_SPMI, i+1,
                    (struct acpi_table_header **)&spmi);
        if (status != AE_OK)
            return;

        try_init_spmi(spmi);
    }
}
在spmi_find_bmc 中通过acpi_get_table得到ACPI_SIG_SPMI 表后,就调用try_init_spmi 来初始化smi_info调用add_smi添加到smi_infos 这个list中
再通过add_smi 将smi_info *new_smi 添加到smi_infos中时,先通过is_new_interface 是否已经添加
static int add_smi(struct smi_info *new_smi)
{
    int rv = 0;

    printk(KERN_INFO PFX "Adding %s-specified %s state machine",
           ipmi_addr_src_to_str(new_smi->addr_source),
           si_to_str[new_smi->si_type]);
    mutex_lock(&smi_infos_lock);
    if (!is_new_interface(new_smi)) {
        printk(KERN_CONT " duplicate interface\n");
        rv = -EBUSY;
        goto out_err;
    }

    printk(KERN_CONT "\n");

    /* So we know not to free it unless we have allocated one. */
    new_smi->intf = NULL;
    new_smi->si_sm = NULL;
    new_smi->handlers = NULL;

    list_add_tail(&new_smi->link, &smi_infos);

out_err:
    mutex_unlock(&smi_infos_lock);
    return rv;
}
而is_new_interface 如下,可见主要是判断io的addr_type和addr_data
static int is_new_interface(struct smi_info *info)
{
    struct smi_info *e;

    list_for_each_entry(e, &smi_infos, link) {
        if (e->io.addr_type != info->io.addr_type)
            continue;
        if (e->io.addr_data == info->io.addr_data)
            return 0;
    }

    return 1;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值