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 + -
显示快捷键?