ipmi_msghandler.c
来自「linux 内核源代码」· C语言 代码 · 共 2,407 行 · 第 1/5 页
C
2,407 行
smi, THIS_MODULE);#endif /* CONFIG_PROC_FS */ return rv;}static void remove_proc_entries(ipmi_smi_t smi){#ifdef CONFIG_PROC_FS struct ipmi_proc_entry *entry; mutex_lock(&smi->proc_entry_lock); while (smi->proc_entries) { entry = smi->proc_entries; smi->proc_entries = entry->next; remove_proc_entry(entry->name, smi->proc_dir); kfree(entry->name); kfree(entry); } mutex_unlock(&smi->proc_entry_lock); remove_proc_entry(smi->proc_dir_name, proc_ipmi_root);#endif /* CONFIG_PROC_FS */}static int __find_bmc_guid(struct device *dev, void *data){ unsigned char *id = data; struct bmc_device *bmc = dev_get_drvdata(dev); return memcmp(bmc->guid, id, 16) == 0;}static struct bmc_device *ipmi_find_bmc_guid(struct device_driver *drv, unsigned char *guid){ struct device *dev; dev = driver_find_device(drv, NULL, guid, __find_bmc_guid); if (dev) return dev_get_drvdata(dev); else return NULL;}struct prod_dev_id { unsigned int product_id; unsigned char device_id;};static int __find_bmc_prod_dev_id(struct device *dev, void *data){ struct prod_dev_id *id = data; struct bmc_device *bmc = dev_get_drvdata(dev); return (bmc->id.product_id == id->product_id && bmc->id.device_id == id->device_id);}static struct bmc_device *ipmi_find_bmc_prod_dev_id( struct device_driver *drv, unsigned int product_id, unsigned char device_id){ struct prod_dev_id id = { .product_id = product_id, .device_id = device_id, }; struct device *dev; dev = driver_find_device(drv, NULL, &id, __find_bmc_prod_dev_id); if (dev) return dev_get_drvdata(dev); else return NULL;}static ssize_t device_id_show(struct device *dev, struct device_attribute *attr, char *buf){ struct bmc_device *bmc = dev_get_drvdata(dev); return snprintf(buf, 10, "%u\n", bmc->id.device_id);}static ssize_t provides_dev_sdrs_show(struct device *dev, struct device_attribute *attr, char *buf){ struct bmc_device *bmc = dev_get_drvdata(dev); return snprintf(buf, 10, "%u\n", (bmc->id.device_revision & 0x80) >> 7);}static ssize_t revision_show(struct device *dev, struct device_attribute *attr, char *buf){ struct bmc_device *bmc = dev_get_drvdata(dev); return snprintf(buf, 20, "%u\n", bmc->id.device_revision & 0x0F);}static ssize_t firmware_rev_show(struct device *dev, struct device_attribute *attr, char *buf){ struct bmc_device *bmc = dev_get_drvdata(dev); return snprintf(buf, 20, "%u.%x\n", bmc->id.firmware_revision_1, bmc->id.firmware_revision_2);}static ssize_t ipmi_version_show(struct device *dev, struct device_attribute *attr, char *buf){ struct bmc_device *bmc = dev_get_drvdata(dev); return snprintf(buf, 20, "%u.%u\n", ipmi_version_major(&bmc->id), ipmi_version_minor(&bmc->id));}static ssize_t add_dev_support_show(struct device *dev, struct device_attribute *attr, char *buf){ struct bmc_device *bmc = dev_get_drvdata(dev); return snprintf(buf, 10, "0x%02x\n", bmc->id.additional_device_support);}static ssize_t manufacturer_id_show(struct device *dev, struct device_attribute *attr, char *buf){ struct bmc_device *bmc = dev_get_drvdata(dev); return snprintf(buf, 20, "0x%6.6x\n", bmc->id.manufacturer_id);}static ssize_t product_id_show(struct device *dev, struct device_attribute *attr, char *buf){ struct bmc_device *bmc = dev_get_drvdata(dev); return snprintf(buf, 10, "0x%4.4x\n", bmc->id.product_id);}static ssize_t aux_firmware_rev_show(struct device *dev, struct device_attribute *attr, char *buf){ struct bmc_device *bmc = dev_get_drvdata(dev); return snprintf(buf, 21, "0x%02x 0x%02x 0x%02x 0x%02x\n", bmc->id.aux_firmware_revision[3], bmc->id.aux_firmware_revision[2], bmc->id.aux_firmware_revision[1], bmc->id.aux_firmware_revision[0]);}static ssize_t guid_show(struct device *dev, struct device_attribute *attr, char *buf){ struct bmc_device *bmc = dev_get_drvdata(dev); return snprintf(buf, 100, "%Lx%Lx\n", (long long) bmc->guid[0], (long long) bmc->guid[8]);}static void remove_files(struct bmc_device *bmc){ if (!bmc->dev) return; device_remove_file(&bmc->dev->dev, &bmc->device_id_attr); device_remove_file(&bmc->dev->dev, &bmc->provides_dev_sdrs_attr); device_remove_file(&bmc->dev->dev, &bmc->revision_attr); device_remove_file(&bmc->dev->dev, &bmc->firmware_rev_attr); device_remove_file(&bmc->dev->dev, &bmc->version_attr); device_remove_file(&bmc->dev->dev, &bmc->add_dev_support_attr); device_remove_file(&bmc->dev->dev, &bmc->manufacturer_id_attr); device_remove_file(&bmc->dev->dev, &bmc->product_id_attr); if (bmc->id.aux_firmware_revision_set) device_remove_file(&bmc->dev->dev, &bmc->aux_firmware_rev_attr); if (bmc->guid_set) device_remove_file(&bmc->dev->dev, &bmc->guid_attr);}static voidcleanup_bmc_device(struct kref *ref){ struct bmc_device *bmc; bmc = container_of(ref, struct bmc_device, refcount); remove_files(bmc); platform_device_unregister(bmc->dev); kfree(bmc);}static void ipmi_bmc_unregister(ipmi_smi_t intf){ struct bmc_device *bmc = intf->bmc; if (intf->sysfs_name) { sysfs_remove_link(&intf->si_dev->kobj, intf->sysfs_name); kfree(intf->sysfs_name); intf->sysfs_name = NULL; } if (intf->my_dev_name) { sysfs_remove_link(&bmc->dev->dev.kobj, intf->my_dev_name); kfree(intf->my_dev_name); intf->my_dev_name = NULL; } mutex_lock(&ipmidriver_mutex); kref_put(&bmc->refcount, cleanup_bmc_device); intf->bmc = NULL; mutex_unlock(&ipmidriver_mutex);}static int create_files(struct bmc_device *bmc){ int err; bmc->device_id_attr.attr.name = "device_id"; bmc->device_id_attr.attr.mode = S_IRUGO; bmc->device_id_attr.show = device_id_show; bmc->provides_dev_sdrs_attr.attr.name = "provides_device_sdrs"; bmc->provides_dev_sdrs_attr.attr.mode = S_IRUGO; bmc->provides_dev_sdrs_attr.show = provides_dev_sdrs_show; bmc->revision_attr.attr.name = "revision"; bmc->revision_attr.attr.mode = S_IRUGO; bmc->revision_attr.show = revision_show; bmc->firmware_rev_attr.attr.name = "firmware_revision"; bmc->firmware_rev_attr.attr.mode = S_IRUGO; bmc->firmware_rev_attr.show = firmware_rev_show; bmc->version_attr.attr.name = "ipmi_version"; bmc->version_attr.attr.mode = S_IRUGO; bmc->version_attr.show = ipmi_version_show; bmc->add_dev_support_attr.attr.name = "additional_device_support"; bmc->add_dev_support_attr.attr.mode = S_IRUGO; bmc->add_dev_support_attr.show = add_dev_support_show; bmc->manufacturer_id_attr.attr.name = "manufacturer_id"; bmc->manufacturer_id_attr.attr.mode = S_IRUGO; bmc->manufacturer_id_attr.show = manufacturer_id_show; bmc->product_id_attr.attr.name = "product_id"; bmc->product_id_attr.attr.mode = S_IRUGO; bmc->product_id_attr.show = product_id_show; bmc->guid_attr.attr.name = "guid"; bmc->guid_attr.attr.mode = S_IRUGO; bmc->guid_attr.show = guid_show; bmc->aux_firmware_rev_attr.attr.name = "aux_firmware_revision"; bmc->aux_firmware_rev_attr.attr.mode = S_IRUGO; bmc->aux_firmware_rev_attr.show = aux_firmware_rev_show; err = device_create_file(&bmc->dev->dev, &bmc->device_id_attr); if (err) goto out; err = device_create_file(&bmc->dev->dev, &bmc->provides_dev_sdrs_attr); if (err) goto out_devid; err = device_create_file(&bmc->dev->dev, &bmc->revision_attr); if (err) goto out_sdrs; err = device_create_file(&bmc->dev->dev, &bmc->firmware_rev_attr); if (err) goto out_rev; err = device_create_file(&bmc->dev->dev, &bmc->version_attr); if (err) goto out_firm; err = device_create_file(&bmc->dev->dev, &bmc->add_dev_support_attr); if (err) goto out_version; err = device_create_file(&bmc->dev->dev, &bmc->manufacturer_id_attr); if (err) goto out_add_dev; err = device_create_file(&bmc->dev->dev, &bmc->product_id_attr); if (err) goto out_manu; if (bmc->id.aux_firmware_revision_set) { err = device_create_file(&bmc->dev->dev, &bmc->aux_firmware_rev_attr); if (err) goto out_prod_id; } if (bmc->guid_set) { err = device_create_file(&bmc->dev->dev, &bmc->guid_attr); if (err) goto out_aux_firm; } return 0;out_aux_firm: if (bmc->id.aux_firmware_revision_set) device_remove_file(&bmc->dev->dev, &bmc->aux_firmware_rev_attr);out_prod_id: device_remove_file(&bmc->dev->dev, &bmc->product_id_attr);out_manu: device_remove_file(&bmc->dev->dev, &bmc->manufacturer_id_attr);out_add_dev: device_remove_file(&bmc->dev->dev, &bmc->add_dev_support_attr);out_version: device_remove_file(&bmc->dev->dev, &bmc->version_attr);out_firm: device_remove_file(&bmc->dev->dev, &bmc->firmware_rev_attr);out_rev: device_remove_file(&bmc->dev->dev, &bmc->revision_attr);out_sdrs: device_remove_file(&bmc->dev->dev, &bmc->provides_dev_sdrs_attr);out_devid: device_remove_file(&bmc->dev->dev, &bmc->device_id_attr);out: return err;}static int ipmi_bmc_register(ipmi_smi_t intf, int ifnum, const char *sysfs_name){ int rv; struct bmc_device *bmc = intf->bmc; struct bmc_device *old_bmc; int size; char dummy[1]; mutex_lock(&ipmidriver_mutex); /* * Try to find if there is an bmc_device struct * representing the interfaced BMC already */ if (bmc->guid_set) old_bmc = ipmi_find_bmc_guid(&ipmidriver, bmc->guid); else old_bmc = ipmi_find_bmc_prod_dev_id(&ipmidriver, bmc->id.product_id, bmc->id.device_id); /* * If there is already an bmc_device, free the new one, * otherwise register the new BMC device */ if (old_bmc) { kfree(bmc); intf->bmc = old_bmc; bmc = old_bmc; kref_get(&bmc->refcount); mutex_unlock(&ipmidriver_mutex); printk(KERN_INFO "ipmi: interfacing existing BMC (man_id: 0x%6.6x," " prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n", bmc->id.manufacturer_id, bmc->id.product_id, bmc->id.device_id); } else { char name[14]; unsigned char orig_dev_id = bmc->id.device_id; int warn_printed = 0; snprintf(name, sizeof(name), "ipmi_bmc.%4.4x", bmc->id.product_id); while (ipmi_find_bmc_prod_dev_id(&ipmidriver, bmc->id.product_id, bmc->id.device_id)) { if (!warn_printed) { printk(KERN_WARNING PFX "This machine has two different BMCs" " with the same product id and device" " id. This is an error in the" " firmware, but incrementing the" " device id to work around the problem." " Prod ID = 0x%x, Dev ID = 0x%x\n", bmc->id.product_id, bmc->id.device_id); warn_printed = 1; } bmc->id.device_id++; /* Wraps at 255 */ if (bmc->id.device_id == orig_dev_id) { printk(KERN_ERR PFX "Out of device ids!\n"); break; } } bmc->dev = platform_device_alloc(name, bmc->id.device_id); if (!bmc->dev) { mutex_unlock(&ipmidriver_mutex); printk(KERN_ERR "ipmi_msghandler:" " Unable to allocate platform device\n"); return -ENOMEM; } bmc->dev->dev.driver = &ipmidriver; dev_set_drvdata(&bmc->dev->dev, bmc); kref_init(&bmc->refcount); rv = platform_device_add(bmc->dev); mutex_unlock(&ipmidriver_mutex); if (rv) { platform_device_put(bmc->dev); bmc->dev = NULL; printk(KERN_ERR "ipmi_msghandler:" " Unable to register bmc device: %d\n", rv); /* Don't go to out_err, you can only do that if the device is registered already. */ return rv; } rv = create_files(bmc); if (rv) { mutex_lock(&ipmidriver_mutex); platform_device_unregister(bmc->dev); mutex_unlock(&ipmidriver_mutex); return rv; } printk(KERN_INFO "ipmi: Found new BMC (man_id: 0x%6.6x, " " prod_id: 0x%4.4x, dev_id: 0x%2.2x)\n", bmc->id.manufacturer_id, bmc->id.product_id, bmc->id.device_id); } /* * create symlink from system interface device to bmc device * and back. */ intf->sysfs_name = kstrdup(sysfs_name, GFP_KERNEL); if (!intf->sysfs_name) { rv = -ENOMEM; printk(KERN_ERR "ipmi_msghandler: allocate link to BMC: %d\n", rv); goto out_err; } rv = sysfs_create_link(&intf->si_dev->kobj, &bmc->dev->dev.k
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?