bool is_registered;
bool releasing;
bool strobe_state;
+ bool active;
+ struct mutex lock;
};
struct gb_light {
struct gb_lights_set_brightness_request req;
struct gb_connection *connection = get_conn_from_channel(channel);
struct gb_bundle *bundle = connection->bundle;
+ bool old_active;
int ret;
+ mutex_lock(&channel->lock);
ret = gb_pm_runtime_get_sync(bundle);
if (ret < 0)
- return ret;
+ goto out_unlock;
+
+ old_active = channel->active;
req.light_id = channel->light->id;
req.channel_id = channel->id;
ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BRIGHTNESS,
&req, sizeof(req), NULL, 0);
+ if (ret < 0)
+ goto out_pm_put;
+
+ if (channel->led->brightness)
+ channel->active = true;
+ else
+ channel->active = false;
+ /* we need to keep module alive when turning to active state */
+ if (!old_active && channel->active)
+ goto out_unlock;
+
+ /*
+ * on the other hand if going to inactive we still hold a reference and
+ * need to put it, so we could go to suspend.
+ */
+ if (old_active && !channel->active)
+ gb_pm_runtime_put_autosuspend(bundle);
+
+out_pm_put:
gb_pm_runtime_put_autosuspend(bundle);
+out_unlock:
+ mutex_unlock(&channel->lock);
return ret;
}
struct gb_connection *connection = get_conn_from_channel(channel);
struct gb_bundle *bundle = connection->bundle;
struct gb_lights_blink_request req;
+ bool old_active;
int ret;
if (channel->releasing)
return -ESHUTDOWN;
+ mutex_lock(&channel->lock);
ret = gb_pm_runtime_get_sync(bundle);
if (ret < 0)
- return ret;
+ goto out_unlock;
+
+ old_active = channel->active;
req.light_id = channel->light->id;
req.channel_id = channel->id;
ret = gb_operation_sync(connection, GB_LIGHTS_TYPE_SET_BLINK, &req,
sizeof(req), NULL, 0);
+ if (ret < 0)
+ goto out_pm_put;
+
+ if (delay_on)
+ channel->active = true;
+ else
+ channel->active = false;
+
+ /* we need to keep module alive when turning to active state */
+ if (!old_active && channel->active)
+ goto out_unlock;
+ /*
+ * on the other hand if going to inactive we still hold a reference and
+ * need to put it, so we could go to suspend.
+ */
+ if (old_active && !channel->active)
+ gb_pm_runtime_put_autosuspend(bundle);
+
+out_pm_put:
gb_pm_runtime_put_autosuspend(bundle);
+out_unlock:
+ mutex_unlock(&channel->lock);
return ret;
}
ret = gb_lights_channel_register(&light->channels[i]);
if (ret < 0)
return ret;
+
+ mutex_init(&light->channels[i].lock);
}
light->ready = true;
kfree(channel->attr_groups);
kfree(channel->color_name);
kfree(channel->mode_name);
+ mutex_destroy(&channel->lock);
}
static void gb_lights_channel_release(struct gb_channel *channel)