Commit 32b0707a authored by Tingwei Zhang's avatar Tingwei Zhang Committed by Greg Kroah-Hartman
Browse files

coresight: Add try_get_module() in coresight_grab_device()



When coresight device is in an active session, driver module of
that device should not be removed. Use try_get_module() in
coresight_grab_device() to prevent module to be unloaded.
Use get_device()/put_device() to protect device data
in the middle of active session.

Suggested-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
Tested-by: default avatarMike Leach <mike.leach@linaro.org>
Reviewed-by: default avatarSuzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: default avatarTingwei Zhang <tingwei@codeaurora.org>
Signed-off-by: default avatarMathieu Poirier <mathieu.poirier@linaro.org>
Link: https://lore.kernel.org/r/20200928163513.70169-7-mathieu.poirier@linaro.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d735d925
Loading
Loading
Loading
Loading
+53 −7
Original line number Diff line number Diff line
@@ -629,13 +629,45 @@ struct coresight_device *coresight_get_sink_by_id(u32 id)
	return dev ? to_coresight_device(dev) : NULL;
}

/**
 * coresight_get_ref- Helper function to increase reference count to module
 * and device.
 * Return true in successful case and power up the device.
 * Return false when failed to get reference of module.
 */
static inline bool coresight_get_ref(struct coresight_device *csdev)
{
	struct device *dev = csdev->dev.parent;

	/* Make sure the driver can't be removed */
	if (!try_module_get(dev->driver->owner))
		return false;
	/* Make sure the device can't go away */
	get_device(dev);
	pm_runtime_get_sync(dev);
	return true;
}

/**
 * coresight_put_ref- Helper function to decrease reference count to module
 * and device. Power off the device.
 */
static inline void coresight_put_ref(struct coresight_device *csdev)
{
	struct device *dev = csdev->dev.parent;

	pm_runtime_put(dev);
	put_device(dev);
	module_put(dev->driver->owner);
}

/*
 * coresight_grab_device - Power up this device and any of the helper
 * devices connected to it for trace operation. Since the helper devices
 * don't appear on the trace path, they should be handled along with the
 * the master device.
 */
static void coresight_grab_device(struct coresight_device *csdev)
static int coresight_grab_device(struct coresight_device *csdev)
{
	int i;

@@ -644,9 +676,20 @@ static void coresight_grab_device(struct coresight_device *csdev)

		child  = csdev->pdata->conns[i].child_dev;
		if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
			pm_runtime_get_sync(child->dev.parent);
			if (!coresight_get_ref(child))
				goto err;
	}
	pm_runtime_get_sync(csdev->dev.parent);
	if (coresight_get_ref(csdev))
		return 0;
err:
	for (i--; i >= 0; i--) {
		struct coresight_device *child;

		child  = csdev->pdata->conns[i].child_dev;
		if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
			coresight_put_ref(child);
	}
	return -ENODEV;
}

/*
@@ -657,13 +700,13 @@ static void coresight_drop_device(struct coresight_device *csdev)
{
	int i;

	pm_runtime_put(csdev->dev.parent);
	coresight_put_ref(csdev);
	for (i = 0; i < csdev->pdata->nr_outport; i++) {
		struct coresight_device *child;

		child  = csdev->pdata->conns[i].child_dev;
		if (child && child->type == CORESIGHT_DEV_TYPE_HELPER)
			pm_runtime_put(child->dev.parent);
			coresight_put_ref(child);
	}
}

@@ -682,7 +725,7 @@ static int _coresight_build_path(struct coresight_device *csdev,
				 struct coresight_device *sink,
				 struct list_head *path)
{
	int i;
	int i, ret;
	bool found = false;
	struct coresight_node *node;

@@ -712,11 +755,14 @@ out:
	 * is tell the PM runtime core we need this element and add a node
	 * for it.
	 */
	ret = coresight_grab_device(csdev);
	if (ret)
		return ret;

	node = kzalloc(sizeof(struct coresight_node), GFP_KERNEL);
	if (!node)
		return -ENOMEM;

	coresight_grab_device(csdev);
	node->csdev = csdev;
	list_add(&node->link, path);