drivers/misc/mei/gsc-me.c

Source file repositories/reference/linux-study-clean/drivers/misc/mei/gsc-me.c

File Facts

System
Linux kernel
Corpus path
drivers/misc/mei/gsc-me.c
Extension
.c
Size
7044 bytes
Lines
304
Domain
Driver Families
Bucket
drivers/misc
Inferred role
Driver Families: implementation source
Status
source 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

if (IS_ERR(hw->polling_thread)) {
			ret = PTR_ERR(hw->polling_thread);
			dev_err(device, "unable to create kernel thread: %d\n", ret);
			goto err;
		}
	} else {
		ret = devm_request_threaded_irq(device, hw->irq,
						mei_me_irq_quick_handler,
						mei_me_irq_thread_handler,
						IRQF_ONESHOT, KBUILD_MODNAME, dev);
		if (ret) {
			dev_err(device, "irq register failed %d\n", ret);
			goto err;
		}
	}

	ret = mei_register(dev, device);
	if (ret)
		goto deinterrupt;

	pm_runtime_get_noresume(device);
	pm_runtime_set_active(device);
	pm_runtime_enable(device);

	/* Continue in spite of firmware handshake failure.
	 * In order to provide access to the firmware status registers to the user
	 * space via sysfs.
	 */
	if (mei_start(dev))
		dev_warn(device, "init hw failure.\n");

	pm_runtime_set_autosuspend_delay(device, MEI_GSC_RPM_TIMEOUT);
	pm_runtime_use_autosuspend(device);

	pm_runtime_put_noidle(device);
	return 0;

deinterrupt:
	if (!mei_me_hw_use_polling(hw))
		devm_free_irq(device, hw->irq, dev);
err:
	dev_err(device, "probe failed: %d\n", ret);
	dev_set_drvdata(device, NULL);
	return ret;
}

static void mei_gsc_remove(struct auxiliary_device *aux_dev)
{
	struct mei_device *dev;
	struct mei_me_hw *hw;

	dev = dev_get_drvdata(&aux_dev->dev);
	hw = to_me_hw(dev);

	mei_stop(dev);

	hw = to_me_hw(dev);
	if (mei_me_hw_use_polling(hw))
		kthread_stop(hw->polling_thread);

	pm_runtime_disable(&aux_dev->dev);

	mei_disable_interrupts(dev);
	if (!mei_me_hw_use_polling(hw))
		devm_free_irq(&aux_dev->dev, hw->irq, dev);

	mei_deregister(dev);
}

static int __maybe_unused mei_gsc_pm_suspend(struct device *device)
{
	struct mei_device *dev = dev_get_drvdata(device);

	mei_stop(dev);

	mei_disable_interrupts(dev);

	return 0;
}

static int __maybe_unused mei_gsc_pm_resume(struct device *device)
{
	struct mei_device *dev = dev_get_drvdata(device);
	struct auxiliary_device *aux_dev;
	struct mei_aux_device *adev;
	int err;
	struct mei_me_hw *hw;

	hw = to_me_hw(dev);
	aux_dev = to_auxiliary_dev(device);

Annotation

Implementation Notes