Commit 7e18c89d authored by Mika Westerberg's avatar Mika Westerberg Committed by Lee Jones
Browse files

platform/x86: intel_scu_ipc: Add managed function to register SCU IPC



Drivers such as intel_pmc_ipc.c can be unloaded as well so in order to
support those in this driver add a new function that can be called to
unregister the SCU IPC when it is not needed anymore.

We also add a managed version of the intel_scu_ipc_register() that takes
care of calling intel_scu_ipc_unregister() automatically when the driver
is unbound.

Signed-off-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: default avatarLee Jones <lee.jones@linaro.org>
parent 663cc188
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -25,6 +25,16 @@ __intel_scu_ipc_register(struct device *parent,
#define intel_scu_ipc_register(parent, scu_data)  \
	__intel_scu_ipc_register(parent, scu_data, THIS_MODULE)

void intel_scu_ipc_unregister(struct intel_scu_ipc_dev *scu);

struct intel_scu_ipc_dev *
__devm_intel_scu_ipc_register(struct device *parent,
			      const struct intel_scu_ipc_data *scu_data,
			      struct module *owner);

#define devm_intel_scu_ipc_register(parent, scu_data)  \
	__devm_intel_scu_ipc_register(parent, scu_data, THIS_MODULE)

struct intel_scu_ipc_dev *intel_scu_ipc_dev_get(void);
void intel_scu_ipc_dev_put(struct intel_scu_ipc_dev *scu);
struct intel_scu_ipc_dev *devm_intel_scu_ipc_dev_get(struct device *dev);
+62 −0
Original line number Diff line number Diff line
@@ -637,6 +637,68 @@ err_unlock:
}
EXPORT_SYMBOL_GPL(__intel_scu_ipc_register);

/**
 * intel_scu_ipc_unregister() - Unregister SCU IPC
 * @scu: SCU IPC handle
 *
 * This unregisters the SCU IPC device and releases the acquired
 * resources once the refcount goes to zero.
 */
void intel_scu_ipc_unregister(struct intel_scu_ipc_dev *scu)
{
	mutex_lock(&ipclock);
	if (!WARN_ON(!ipcdev)) {
		ipcdev = NULL;
		device_unregister(&scu->dev);
	}
	mutex_unlock(&ipclock);
}
EXPORT_SYMBOL_GPL(intel_scu_ipc_unregister);

static void devm_intel_scu_ipc_unregister(struct device *dev, void *res)
{
	struct intel_scu_ipc_devres *dr = res;
	struct intel_scu_ipc_dev *scu = dr->scu;

	intel_scu_ipc_unregister(scu);
}

/**
 * __devm_intel_scu_ipc_register() - Register managed SCU IPC device
 * @parent: Parent device
 * @scu_data: Data used to configure SCU IPC
 * @owner: Module registering the SCU IPC device
 *
 * Call this function to register managed SCU IPC mechanism under
 * @parent. Returns pointer to the new SCU IPC device or ERR_PTR() in
 * case of failure. The caller may use the returned instance if it needs
 * to do SCU IPC calls itself.
 */
struct intel_scu_ipc_dev *
__devm_intel_scu_ipc_register(struct device *parent,
			      const struct intel_scu_ipc_data *scu_data,
			      struct module *owner)
{
	struct intel_scu_ipc_devres *dr;
	struct intel_scu_ipc_dev *scu;

	dr = devres_alloc(devm_intel_scu_ipc_unregister, sizeof(*dr), GFP_KERNEL);
	if (!dr)
		return NULL;

	scu = __intel_scu_ipc_register(parent, scu_data, owner);
	if (IS_ERR(scu)) {
		devres_free(dr);
		return scu;
	}

	dr->scu = scu;
	devres_add(parent, dr);

	return scu;
}
EXPORT_SYMBOL_GPL(__devm_intel_scu_ipc_register);

static int __init intel_scu_ipc_init(void)
{
	return class_register(&intel_scu_ipc_class);