drivers/char/ipmi/ipmi_devintf.c

Source file repositories/reference/linux-study-clean/drivers/char/ipmi/ipmi_devintf.c

File Facts

System
Linux kernel
Corpus path
drivers/char/ipmi/ipmi_devintf.c
Extension
.c
Size
19588 bytes
Lines
908
Domain
Driver Families
Bucket
drivers/char
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations ipmi_fops = {
	.owner		= THIS_MODULE,
	.unlocked_ioctl	= ipmi_ioctl,
#ifdef CONFIG_COMPAT
	.compat_ioctl   = compat_ipmi_ioctl,
#endif
	.open		= ipmi_open,
	.release	= ipmi_release,
	.fasync		= ipmi_fasync,
	.poll		= ipmi_poll,
	.llseek		= noop_llseek,
};

#define DEVICE_NAME     "ipmidev"

static int ipmi_major;
module_param(ipmi_major, int, 0);
MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device.  By"
		 " default, or if you set it to zero, it will choose the next"
		 " available device.  Setting it to -1 will disable the"
		 " interface.  Other values will set the major device number"
		 " to that value.");

/* Keep track of the devices that are registered. */
struct ipmi_reg_list {
	dev_t            dev;
	struct list_head link;
};
static LIST_HEAD(reg_list);
static DEFINE_MUTEX(reg_list_mutex);

static const struct class ipmi_class = {
	.name = "ipmi",
};

static void ipmi_new_smi(int if_num, struct device *device)
{
	dev_t dev = MKDEV(ipmi_major, if_num);
	struct ipmi_reg_list *entry;

	entry = kmalloc_obj(*entry);
	if (!entry) {
		pr_err("ipmi_devintf: Unable to create the ipmi class device link\n");
		return;
	}
	entry->dev = dev;

	mutex_lock(&reg_list_mutex);
	device_create(&ipmi_class, device, dev, NULL, "ipmi%d", if_num);
	list_add(&entry->link, &reg_list);
	mutex_unlock(&reg_list_mutex);
}

static void ipmi_smi_gone(int if_num)
{
	dev_t dev = MKDEV(ipmi_major, if_num);
	struct ipmi_reg_list *entry;

	mutex_lock(&reg_list_mutex);
	list_for_each_entry(entry, &reg_list, link) {
		if (entry->dev == dev) {
			list_del(&entry->link);
			kfree(entry);
			break;
		}
	}
	device_destroy(&ipmi_class, dev);
	mutex_unlock(&reg_list_mutex);
}

static struct ipmi_smi_watcher smi_watcher =
{
	.owner    = THIS_MODULE,
	.new_smi  = ipmi_new_smi,
	.smi_gone = ipmi_smi_gone,
};

static int __init init_ipmi_devintf(void)
{
	int rv;

	if (ipmi_major < 0)
		return -EINVAL;

	pr_info("ipmi device interface\n");

	rv = class_register(&ipmi_class);
	if (rv)
		return rv;

Annotation

Implementation Notes