in qcom_smd.c [1272:1331]
static void qcom_channel_state_worker(struct work_struct *work)
{
struct qcom_smd_channel *channel;
struct qcom_smd_edge *edge = container_of(work,
struct qcom_smd_edge,
state_work);
struct rpmsg_channel_info chinfo;
unsigned remote_state;
unsigned long flags;
/*
* Register a device for any closed channel where the remote processor
* is showing interest in opening the channel.
*/
spin_lock_irqsave(&edge->channels_lock, flags);
list_for_each_entry(channel, &edge->channels, list) {
if (channel->state != SMD_CHANNEL_CLOSED)
continue;
remote_state = GET_RX_CHANNEL_INFO(channel, state);
if (remote_state != SMD_CHANNEL_OPENING &&
remote_state != SMD_CHANNEL_OPENED)
continue;
if (channel->registered)
continue;
spin_unlock_irqrestore(&edge->channels_lock, flags);
qcom_smd_create_device(channel);
channel->registered = true;
spin_lock_irqsave(&edge->channels_lock, flags);
channel->registered = true;
}
/*
* Unregister the device for any channel that is opened where the
* remote processor is closing the channel.
*/
list_for_each_entry(channel, &edge->channels, list) {
if (channel->state != SMD_CHANNEL_OPENING &&
channel->state != SMD_CHANNEL_OPENED)
continue;
remote_state = GET_RX_CHANNEL_INFO(channel, state);
if (remote_state == SMD_CHANNEL_OPENING ||
remote_state == SMD_CHANNEL_OPENED)
continue;
spin_unlock_irqrestore(&edge->channels_lock, flags);
strncpy(chinfo.name, channel->name, sizeof(chinfo.name));
chinfo.src = RPMSG_ADDR_ANY;
chinfo.dst = RPMSG_ADDR_ANY;
rpmsg_unregister_device(&edge->dev, &chinfo);
channel->registered = false;
spin_lock_irqsave(&edge->channels_lock, flags);
}
spin_unlock_irqrestore(&edge->channels_lock, flags);
}