drivers/char/ipmi/ipmi_si_intf.c

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

File Facts

System
Linux kernel
Corpus path
drivers/char/ipmi/ipmi_si_intf.c
Extension
.c
Size
63578 bytes
Lines
2426
Domain
Driver Families
Bucket
drivers/char
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

module_init(init_ipmi_si);

static void wait_msg_processed(struct smi_info *smi_info)
{
	unsigned long jiffies_now;
	long time_diff;

	while (smi_info->si_state != SI_HOSED &&
		    (smi_info->curr_msg || (smi_info->si_state != SI_NORMAL))) {
		jiffies_now = jiffies;
		time_diff = (((long)jiffies_now - (long)smi_info->last_timeout_jiffies)
		     * SI_USEC_PER_JIFFY);
		smi_event_handler(smi_info, time_diff);
		schedule_timeout_uninterruptible(1);
	}
}

static void shutdown_smi(void *send_info)
{
	struct smi_info *smi_info = send_info;

	if (smi_info->dev_group_added) {
		device_remove_group(smi_info->io.dev, &ipmi_si_dev_attr_group);
		smi_info->dev_group_added = false;
	}
	if (smi_info->io.dev)
		dev_set_drvdata(smi_info->io.dev, NULL);

	/*
	 * Make sure that interrupts, the timer and the thread are
	 * stopped and will not run again.
	 */
	smi_info->interrupt_disabled = true;
	if (smi_info->io.irq_cleanup) {
		smi_info->io.irq_cleanup(&smi_info->io);
		smi_info->io.irq_cleanup = NULL;
	}
	stop_timer_and_thread(smi_info);

	/*
	 * Wait until we know that we are out of any interrupt
	 * handlers might have been running before we freed the
	 * interrupt.
	 */
	synchronize_rcu();

	/*
	 * Timeouts are stopped, now make sure the interrupts are off
	 * in the BMC.  Note that timers and CPU interrupts are off,
	 * so no need for locks.
	 */
	wait_msg_processed(smi_info);

	if (smi_info->handlers)
		disable_si_irq(smi_info);

	wait_msg_processed(smi_info);

	if (smi_info->handlers)
		smi_info->handlers->cleanup(smi_info->si_sm);

	if (smi_info->io.io_cleanup) {
		smi_info->io.io_cleanup(&smi_info->io);
		smi_info->io.io_cleanup = NULL;
	}

	kfree(smi_info->si_sm);
	smi_info->si_sm = NULL;

	smi_info->intf = NULL;
}

/*
 * Must be called with smi_infos_lock held, to serialize the
 * smi_info->intf check.
 */
static void cleanup_one_si(struct smi_info *smi_info)
{
	if (!smi_info)
		return;

	list_del(&smi_info->link);
	ipmi_unregister_smi(smi_info->intf);
	kfree(smi_info);
}

void ipmi_si_remove_by_dev(struct device *dev)
{
	struct smi_info *e;

Annotation

Implementation Notes