Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc46b45a authored by Alexander Usyskin's avatar Alexander Usyskin Committed by Greg Kroah-Hartman
Browse files

mei: bus: call mei_cl_read_start under device lock



Ensure that mei_cl_read_start is called under the device lock
also in the bus layer. The function updates global ctrl_wr_list
which should be locked.

Cc: <stable@vger.kernel.org> #4.4+
Signed-off-by: default avatarAlexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent bedffda8
Loading
Loading
Loading
Loading
+12 −3
Original line number Diff line number Diff line
@@ -220,17 +220,23 @@ EXPORT_SYMBOL_GPL(mei_cldev_recv);
static void mei_cl_bus_event_work(struct work_struct *work)
{
	struct mei_cl_device *cldev;
	struct mei_device *bus;

	cldev = container_of(work, struct mei_cl_device, event_work);

	bus = cldev->bus;

	if (cldev->event_cb)
		cldev->event_cb(cldev, cldev->events, cldev->event_context);

	cldev->events = 0;

	/* Prepare for the next read */
	if (cldev->events_mask & BIT(MEI_CL_EVENT_RX))
	if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) {
		mutex_lock(&bus->device_lock);
		mei_cl_read_start(cldev->cl, 0, NULL);
		mutex_unlock(&bus->device_lock);
	}
}

/**
@@ -304,6 +310,7 @@ int mei_cldev_register_event_cb(struct mei_cl_device *cldev,
				unsigned long events_mask,
				mei_cldev_event_cb_t event_cb, void *context)
{
	struct mei_device *bus = cldev->bus;
	int ret;

	if (cldev->event_cb)
@@ -316,15 +323,17 @@ int mei_cldev_register_event_cb(struct mei_cl_device *cldev,
	INIT_WORK(&cldev->event_work, mei_cl_bus_event_work);

	if (cldev->events_mask & BIT(MEI_CL_EVENT_RX)) {
		mutex_lock(&bus->device_lock);
		ret = mei_cl_read_start(cldev->cl, 0, NULL);
		mutex_unlock(&bus->device_lock);
		if (ret && ret != -EBUSY)
			return ret;
	}

	if (cldev->events_mask & BIT(MEI_CL_EVENT_NOTIF)) {
		mutex_lock(&cldev->cl->dev->device_lock);
		mutex_lock(&bus->device_lock);
		ret = mei_cl_notify_request(cldev->cl, NULL, event_cb ? 1 : 0);
		mutex_unlock(&cldev->cl->dev->device_lock);
		mutex_unlock(&bus->device_lock);
		if (ret)
			return ret;
	}