drivers/char/ipmi/ipmi_msghandler.c

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

File Facts

System
Linux kernel
Corpus path
drivers/char/ipmi/ipmi_msghandler.c
Extension
.c
Size
148156 bytes
Lines
5700
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 struct bmc_device *ipmi_find_bmc_guid(struct device_driver *drv,
					     guid_t *guid)
{
	struct device *dev;
	struct bmc_device *bmc = NULL;

	dev = driver_find_device(drv, NULL, guid, __find_bmc_guid);
	if (dev) {
		bmc = to_bmc_device(dev);
		put_device(dev);
	}
	return bmc;
}

struct prod_dev_id {
	unsigned int  product_id;
	unsigned char device_id;
};

static int __find_bmc_prod_dev_id(struct device *dev, const void *data)
{
	const struct prod_dev_id *cid = data;
	struct bmc_device *bmc;
	int rv;

	if (dev->type != &bmc_device_type)
		return 0;

	bmc = to_bmc_device(dev);
	rv = (bmc->id.product_id == cid->product_id
	      && bmc->id.device_id == cid->device_id);
	if (rv)
		rv = kref_get_unless_zero(&bmc->usecount);
	return rv;
}

/*
 * Returns with the bmc's usecount incremented, if it is non-NULL.
 */
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;
	struct bmc_device *bmc = NULL;

	dev = driver_find_device(drv, NULL, &id, __find_bmc_prod_dev_id);
	if (dev) {
		bmc = to_bmc_device(dev);
		put_device(dev);
	}
	return bmc;
}

static DEFINE_IDA(ipmi_bmc_ida);

static void
release_bmc_device(struct device *dev)
{
	kfree(to_bmc_device(dev));
}

static void cleanup_bmc_work(struct work_struct *work)
{
	struct bmc_device *bmc = container_of(work, struct bmc_device,
					      remove_work);
	int id = bmc->pdev.id; /* Unregister overwrites id */

	platform_device_unregister(&bmc->pdev);
	ida_free(&ipmi_bmc_ida, id);
}

static void
cleanup_bmc_device(struct kref *ref)
{
	struct bmc_device *bmc = container_of(ref, struct bmc_device, usecount);

	/*
	 * Remove the platform device in a work queue to avoid issues
	 * with removing the device attributes while reading a device
	 * attribute.
	 */
	queue_work(bmc_remove_work_wq, &bmc->remove_work);
}

/*

Annotation

Implementation Notes