Lines Matching +full:rpmsg +full:- +full:out

1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2016-2017, Linaro Ltd
16 #include <linux/rpmsg.h>
40 * struct glink_defer_cmd - deferred incoming control message
56 * struct glink_core_rx_intent - RX intent
59 * @data: pointer to the data (may be NULL for zero-copy)
79 * struct qcom_glink - driver context, relates to one remote subsystem
128 * struct glink_channel - internal representation of a channel
130 * @ept: rpmsg endpoint this channel is associated with
145 * @open_ack: completed once remote has acked the open-request
146 * @open_req: completed once open-request has been received
221 return ERR_PTR(-ENOMEM); in qcom_glink_alloc_channel()
224 spin_lock_init(&channel->recv_lock); in qcom_glink_alloc_channel()
225 spin_lock_init(&channel->intent_lock); in qcom_glink_alloc_channel()
226 mutex_init(&channel->intent_req_lock); in qcom_glink_alloc_channel()
228 channel->glink = glink; in qcom_glink_alloc_channel()
229 channel->name = kstrdup(name, GFP_KERNEL); in qcom_glink_alloc_channel()
230 if (!channel->name) { in qcom_glink_alloc_channel()
232 return ERR_PTR(-ENOMEM); in qcom_glink_alloc_channel()
235 init_completion(&channel->open_req); in qcom_glink_alloc_channel()
236 init_completion(&channel->open_ack); in qcom_glink_alloc_channel()
237 init_waitqueue_head(&channel->intent_req_wq); in qcom_glink_alloc_channel()
239 INIT_LIST_HEAD(&channel->done_intents); in qcom_glink_alloc_channel()
240 INIT_WORK(&channel->intent_work, qcom_glink_rx_done_work); in qcom_glink_alloc_channel()
242 idr_init(&channel->liids); in qcom_glink_alloc_channel()
243 idr_init(&channel->riids); in qcom_glink_alloc_channel()
244 kref_init(&channel->refcount); in qcom_glink_alloc_channel()
259 cancel_work_sync(&channel->intent_work); in qcom_glink_channel_release()
261 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_channel_release()
262 /* Free all non-reuse intents pending rx_done work */ in qcom_glink_channel_release()
263 list_for_each_entry_safe(intent, tmp, &channel->done_intents, node) { in qcom_glink_channel_release()
264 if (!intent->reuse) { in qcom_glink_channel_release()
265 kfree(intent->data); in qcom_glink_channel_release()
270 idr_for_each_entry(&channel->liids, tmp, iid) { in qcom_glink_channel_release()
271 kfree(tmp->data); in qcom_glink_channel_release()
274 idr_destroy(&channel->liids); in qcom_glink_channel_release()
276 idr_for_each_entry(&channel->riids, tmp, iid) in qcom_glink_channel_release()
278 idr_destroy(&channel->riids); in qcom_glink_channel_release()
279 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_channel_release()
281 kfree(channel->name); in qcom_glink_channel_release()
287 return glink->rx_pipe->avail(glink->rx_pipe); in qcom_glink_rx_avail()
293 glink->rx_pipe->peek(glink->rx_pipe, data, offset, count); in qcom_glink_rx_peek()
298 glink->rx_pipe->advance(glink->rx_pipe, count); in qcom_glink_rx_advance()
303 return glink->tx_pipe->avail(glink->tx_pipe); in qcom_glink_tx_avail()
310 glink->tx_pipe->write(glink->tx_pipe, hdr, hlen, data, dlen); in qcom_glink_tx_write()
315 glink->tx_pipe->kick(glink->tx_pipe); in qcom_glink_tx_kick()
340 if (tlen >= glink->tx_pipe->length) in qcom_glink_tx()
341 return -EINVAL; in qcom_glink_tx()
343 spin_lock_irqsave(&glink->tx_lock, flags); in qcom_glink_tx()
345 if (glink->abort_tx) { in qcom_glink_tx()
346 ret = -EIO; in qcom_glink_tx()
347 goto out; in qcom_glink_tx()
352 ret = -EAGAIN; in qcom_glink_tx()
353 goto out; in qcom_glink_tx()
356 if (glink->abort_tx) { in qcom_glink_tx()
357 ret = -EIO; in qcom_glink_tx()
358 goto out; in qcom_glink_tx()
361 if (!glink->sent_read_notify) { in qcom_glink_tx()
362 glink->sent_read_notify = true; in qcom_glink_tx()
367 spin_unlock_irqrestore(&glink->tx_lock, flags); in qcom_glink_tx()
369 wait_event_timeout(glink->tx_avail_notify, in qcom_glink_tx()
372 spin_lock_irqsave(&glink->tx_lock, flags); in qcom_glink_tx()
375 glink->sent_read_notify = false; in qcom_glink_tx()
381 out: in qcom_glink_tx()
382 spin_unlock_irqrestore(&glink->tx_lock, flags); in qcom_glink_tx()
393 msg.param2 = cpu_to_le32(glink->features); in qcom_glink_send_version()
404 msg.param2 = cpu_to_le32(glink->features); in qcom_glink_send_version_ack()
415 msg.param1 = cpu_to_le16(channel->rcid); in qcom_glink_send_open_ack()
427 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_handle_intent_req_ack()
428 channel = idr_find(&glink->rcids, cid); in qcom_glink_handle_intent_req_ack()
429 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_handle_intent_req_ack()
431 dev_err(glink->dev, "unable to find channel\n"); in qcom_glink_handle_intent_req_ack()
435 WRITE_ONCE(channel->intent_req_result, granted); in qcom_glink_handle_intent_req_ack()
436 wake_up_all(&channel->intent_req_wq); in qcom_glink_handle_intent_req_ack()
441 WRITE_ONCE(channel->intent_req_result, 0); in qcom_glink_intent_req_abort()
442 wake_up_all(&channel->intent_req_wq); in qcom_glink_intent_req_abort()
446 * qcom_glink_send_open_req() - send a GLINK_CMD_OPEN request to the remote
462 int name_len = strlen(channel->name) + 1; in qcom_glink_send_open_req()
467 kref_get(&channel->refcount); in qcom_glink_send_open_req()
469 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_send_open_req()
470 ret = idr_alloc_cyclic(&glink->lcids, channel, in qcom_glink_send_open_req()
473 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_send_open_req()
477 channel->lcid = ret; in qcom_glink_send_open_req()
480 req.msg.param1 = cpu_to_le16(channel->lcid); in qcom_glink_send_open_req()
482 strcpy(req.name, channel->name); in qcom_glink_send_open_req()
491 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_send_open_req()
492 idr_remove(&glink->lcids, channel->lcid); in qcom_glink_send_open_req()
493 channel->lcid = 0; in qcom_glink_send_open_req()
494 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_send_open_req()
505 req.param1 = cpu_to_le16(channel->lcid); in qcom_glink_send_close_req()
527 struct qcom_glink *glink = channel->glink; in qcom_glink_rx_done_work()
535 unsigned int cid = channel->lcid; in qcom_glink_rx_done_work()
540 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_rx_done_work()
541 list_for_each_entry_safe(intent, tmp, &channel->done_intents, node) { in qcom_glink_rx_done_work()
542 list_del(&intent->node); in qcom_glink_rx_done_work()
543 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_rx_done_work()
544 iid = intent->id; in qcom_glink_rx_done_work()
545 reuse = intent->reuse; in qcom_glink_rx_done_work()
553 kfree(intent->data); in qcom_glink_rx_done_work()
556 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_rx_done_work()
558 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_rx_done_work()
566 if (glink->intentless) { in qcom_glink_rx_done()
567 kfree(intent->data); in qcom_glink_rx_done()
573 if (!intent->reuse) { in qcom_glink_rx_done()
574 spin_lock(&channel->intent_lock); in qcom_glink_rx_done()
575 idr_remove(&channel->liids, intent->id); in qcom_glink_rx_done()
576 spin_unlock(&channel->intent_lock); in qcom_glink_rx_done()
580 spin_lock(&channel->intent_lock); in qcom_glink_rx_done()
581 list_add_tail(&intent->node, &channel->done_intents); in qcom_glink_rx_done()
582 spin_unlock(&channel->intent_lock); in qcom_glink_rx_done()
584 schedule_work(&channel->intent_work); in qcom_glink_rx_done()
588 * qcom_glink_receive_version() - receive version/features from remote system
594 * This function is called in response to a remote-initiated version/feature
605 glink->features &= features; in qcom_glink_receive_version()
614 * qcom_glink_receive_version_ack() - receive negotiation ack from remote system
620 * This function is called in response to a local-initiated version/feature
621 * negotiation sequence and is the counter-offer from the remote side based
633 if (features == glink->features) in qcom_glink_receive_version_ack()
636 glink->features &= features; in qcom_glink_receive_version_ack()
645 * qcom_glink_send_intent_req_ack() - convert an rx intent request ack cmd to
660 msg.param1 = cpu_to_le16(channel->lcid); in qcom_glink_send_intent_req_ack()
669 * qcom_glink_advertise_intent - convert an rx intent cmd to wire format and
691 cmd.lcid = cpu_to_le16(channel->lcid); in qcom_glink_advertise_intent()
693 cmd.size = cpu_to_le32(intent->size); in qcom_glink_advertise_intent()
694 cmd.liid = cpu_to_le32(intent->id); in qcom_glink_advertise_intent()
715 intent->data = kzalloc(size, GFP_KERNEL); in qcom_glink_alloc_intent()
716 if (!intent->data) in qcom_glink_alloc_intent()
719 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_alloc_intent()
720 ret = idr_alloc_cyclic(&channel->liids, intent, 1, -1, GFP_ATOMIC); in qcom_glink_alloc_intent()
722 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_alloc_intent()
725 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_alloc_intent()
727 intent->id = ret; in qcom_glink_alloc_intent()
728 intent->size = size; in qcom_glink_alloc_intent()
729 intent->reuse = reuseable; in qcom_glink_alloc_intent()
734 kfree(intent->data); in qcom_glink_alloc_intent()
748 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_handle_rx_done()
749 channel = idr_find(&glink->rcids, cid); in qcom_glink_handle_rx_done()
750 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_handle_rx_done()
752 dev_err(glink->dev, "invalid channel id received\n"); in qcom_glink_handle_rx_done()
756 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_handle_rx_done()
757 intent = idr_find(&channel->riids, iid); in qcom_glink_handle_rx_done()
760 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_handle_rx_done()
761 dev_err(glink->dev, "invalid intent id received\n"); in qcom_glink_handle_rx_done()
765 intent->in_use = false; in qcom_glink_handle_rx_done()
768 idr_remove(&channel->riids, intent->id); in qcom_glink_handle_rx_done()
771 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_handle_rx_done()
774 WRITE_ONCE(channel->intent_received, true); in qcom_glink_handle_rx_done()
775 wake_up_all(&channel->intent_req_wq); in qcom_glink_handle_rx_done()
780 * qcom_glink_handle_intent_req() - Receive a request for rx_intent
796 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_handle_intent_req()
797 channel = idr_find(&glink->rcids, cid); in qcom_glink_handle_intent_req()
798 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_handle_intent_req()
819 dev_dbg(glink->dev, "Insufficient data in rx fifo"); in qcom_glink_rx_defer()
820 return -ENXIO; in qcom_glink_rx_defer()
825 return -ENOMEM; in qcom_glink_rx_defer()
827 INIT_LIST_HEAD(&dcmd->node); in qcom_glink_rx_defer()
829 qcom_glink_rx_peek(glink, &dcmd->msg, 0, sizeof(dcmd->msg) + extra); in qcom_glink_rx_defer()
831 spin_lock(&glink->rx_lock); in qcom_glink_rx_defer()
832 list_add_tail(&dcmd->node, &glink->rx_queue); in qcom_glink_rx_defer()
833 spin_unlock(&glink->rx_lock); in qcom_glink_rx_defer()
835 schedule_work(&glink->rx_work); in qcom_glink_rx_defer()
836 qcom_glink_rx_advance(glink, sizeof(dcmd->msg) + extra); in qcom_glink_rx_defer()
858 dev_dbg(glink->dev, "Not enough data in fifo\n"); in qcom_glink_rx_data()
859 return -EAGAIN; in qcom_glink_rx_data()
867 dev_dbg(glink->dev, "Payload not yet in fifo\n"); in qcom_glink_rx_data()
868 return -EAGAIN; in qcom_glink_rx_data()
872 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_data()
873 channel = idr_find(&glink->rcids, rcid); in qcom_glink_rx_data()
874 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_data()
876 dev_dbg(glink->dev, "Data on non-existing channel\n"); in qcom_glink_rx_data()
882 if (glink->intentless) { in qcom_glink_rx_data()
884 if (!channel->buf) { in qcom_glink_rx_data()
887 return -ENOMEM; in qcom_glink_rx_data()
889 intent->data = kmalloc(chunk_size + left_size, in qcom_glink_rx_data()
891 if (!intent->data) { in qcom_glink_rx_data()
893 return -ENOMEM; in qcom_glink_rx_data()
896 intent->id = 0xbabababa; in qcom_glink_rx_data()
897 intent->size = chunk_size + left_size; in qcom_glink_rx_data()
898 intent->offset = 0; in qcom_glink_rx_data()
900 channel->buf = intent; in qcom_glink_rx_data()
902 intent = channel->buf; in qcom_glink_rx_data()
907 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_rx_data()
908 intent = idr_find(&channel->liids, liid); in qcom_glink_rx_data()
909 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_rx_data()
912 dev_err(glink->dev, in qcom_glink_rx_data()
914 channel->name, liid); in qcom_glink_rx_data()
915 ret = -ENOENT; in qcom_glink_rx_data()
920 if (intent->size - intent->offset < chunk_size) { in qcom_glink_rx_data()
921 dev_err(glink->dev, "Insufficient space in intent\n"); in qcom_glink_rx_data()
927 qcom_glink_rx_peek(glink, intent->data + intent->offset, in qcom_glink_rx_data()
929 intent->offset += chunk_size; in qcom_glink_rx_data()
933 spin_lock(&channel->recv_lock); in qcom_glink_rx_data()
934 if (channel->ept.cb) { in qcom_glink_rx_data()
935 channel->ept.cb(channel->ept.rpdev, in qcom_glink_rx_data()
936 intent->data, in qcom_glink_rx_data()
937 intent->offset, in qcom_glink_rx_data()
938 channel->ept.priv, in qcom_glink_rx_data()
941 spin_unlock(&channel->recv_lock); in qcom_glink_rx_data()
943 intent->offset = 0; in qcom_glink_rx_data()
944 channel->buf = NULL; in qcom_glink_rx_data()
978 dev_dbg(glink->dev, "Not enough data in fifo\n"); in qcom_glink_handle_intent()
982 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_handle_intent()
983 channel = idr_find(&glink->rcids, cid); in qcom_glink_handle_intent()
984 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_handle_intent()
986 dev_err(glink->dev, "intents for non-existing channel\n"); in qcom_glink_handle_intent()
1002 intent->id = le32_to_cpu(msg->intents[i].iid); in qcom_glink_handle_intent()
1003 intent->size = le32_to_cpu(msg->intents[i].size); in qcom_glink_handle_intent()
1005 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_handle_intent()
1006 ret = idr_alloc(&channel->riids, intent, in qcom_glink_handle_intent()
1007 intent->id, intent->id + 1, GFP_ATOMIC); in qcom_glink_handle_intent()
1008 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_handle_intent()
1011 dev_err(glink->dev, "failed to store remote intent\n"); in qcom_glink_handle_intent()
1014 WRITE_ONCE(channel->intent_received, true); in qcom_glink_handle_intent()
1015 wake_up_all(&channel->intent_req_wq); in qcom_glink_handle_intent()
1025 spin_lock(&glink->idr_lock); in qcom_glink_rx_open_ack()
1026 channel = idr_find(&glink->lcids, lcid); in qcom_glink_rx_open_ack()
1027 spin_unlock(&glink->idr_lock); in qcom_glink_rx_open_ack()
1029 dev_err(glink->dev, "Invalid open ack packet\n"); in qcom_glink_rx_open_ack()
1030 return -EINVAL; in qcom_glink_rx_open_ack()
1033 complete_all(&channel->open_ack); in qcom_glink_rx_open_ack()
1039 * qcom_glink_set_flow_control() - convert a signal cmd to wire format and transmit
1040 * @ept: Rpmsg endpoint for channel.
1049 struct qcom_glink *glink = channel->glink; in qcom_glink_set_flow_control()
1057 msg.param1 = cpu_to_le16(channel->lcid); in qcom_glink_set_flow_control()
1070 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_handle_signals()
1071 channel = idr_find(&glink->rcids, rcid); in qcom_glink_handle_signals()
1072 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_handle_signals()
1074 dev_err(glink->dev, "signal for non-existing channel\n"); in qcom_glink_handle_signals()
1080 if (channel->ept.flow_cb) in qcom_glink_handle_signals()
1081 channel->ept.flow_cb(channel->ept.rpdev, channel->ept.priv, enable); in qcom_glink_handle_signals()
1094 wake_up_all(&glink->tx_avail_notify); in qcom_glink_native_rx()
1151 dev_err(glink->dev, "unhandled rx cmd: %d\n", cmd); in qcom_glink_native_rx()
1152 ret = -EINVAL; in qcom_glink_native_rx()
1178 ret = wait_for_completion_timeout(&channel->open_ack, 5 * HZ); in qcom_glink_create_local()
1182 ret = wait_for_completion_timeout(&channel->open_req, 5 * HZ); in qcom_glink_create_local()
1192 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_create_local()
1193 idr_remove(&glink->lcids, channel->lcid); in qcom_glink_create_local()
1194 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_create_local()
1198 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_create_local()
1200 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_create_local()
1202 return ERR_PTR(-ETIMEDOUT); in qcom_glink_create_local()
1217 ret = wait_for_completion_timeout(&channel->open_ack, 5 * HZ); in qcom_glink_create_remote()
1219 ret = -ETIMEDOUT; in qcom_glink_create_remote()
1227 * Send a close request to "undo" our open-ack. The close-ack will in qcom_glink_create_remote()
1243 struct glink_channel *parent = to_glink_channel(rpdev->ept); in qcom_glink_create_ept()
1245 struct qcom_glink *glink = parent->glink; in qcom_glink_create_ept()
1252 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_create_ept()
1253 idr_for_each_entry(&glink->rcids, channel, cid) { in qcom_glink_create_ept()
1254 if (!strcmp(channel->name, name)) in qcom_glink_create_ept()
1257 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_create_ept()
1269 ept = &channel->ept; in qcom_glink_create_ept()
1270 ept->rpdev = rpdev; in qcom_glink_create_ept()
1271 ept->cb = cb; in qcom_glink_create_ept()
1272 ept->priv = priv; in qcom_glink_create_ept()
1273 ept->ops = &glink_endpoint_ops; in qcom_glink_create_ept()
1280 struct glink_channel *channel = to_glink_channel(rpdev->ept); in qcom_glink_announce_create()
1281 struct device_node *np = rpdev->dev.of_node; in qcom_glink_announce_create()
1282 struct qcom_glink *glink = channel->glink; in qcom_glink_announce_create()
1291 if (glink->intentless || !completion_done(&channel->open_ack)) in qcom_glink_announce_create()
1296 val = prop->value; in qcom_glink_announce_create()
1297 num_groups = prop->length / sizeof(u32) / 2; in qcom_glink_announce_create()
1301 while (num_groups--) { in qcom_glink_announce_create()
1304 while (num_intents--) { in qcom_glink_announce_create()
1319 struct qcom_glink *glink = channel->glink; in qcom_glink_destroy_ept()
1322 spin_lock_irqsave(&channel->recv_lock, flags); in qcom_glink_destroy_ept()
1323 channel->ept.cb = NULL; in qcom_glink_destroy_ept()
1324 spin_unlock_irqrestore(&channel->recv_lock, flags); in qcom_glink_destroy_ept()
1327 channel->rpdev = NULL; in qcom_glink_destroy_ept()
1344 mutex_lock(&channel->intent_req_lock); in qcom_glink_request_intent()
1346 WRITE_ONCE(channel->intent_req_result, -1); in qcom_glink_request_intent()
1347 WRITE_ONCE(channel->intent_received, false); in qcom_glink_request_intent()
1350 cmd.cid = channel->lcid; in qcom_glink_request_intent()
1357 ret = wait_event_timeout(channel->intent_req_wq, in qcom_glink_request_intent()
1358 READ_ONCE(channel->intent_req_result) == 0 || in qcom_glink_request_intent()
1359 (READ_ONCE(channel->intent_req_result) > 0 && in qcom_glink_request_intent()
1360 READ_ONCE(channel->intent_received)) || in qcom_glink_request_intent()
1361 glink->abort_tx, in qcom_glink_request_intent()
1364 dev_err(glink->dev, "intent request timed out\n"); in qcom_glink_request_intent()
1365 ret = -ETIMEDOUT; in qcom_glink_request_intent()
1366 } else if (glink->abort_tx) { in qcom_glink_request_intent()
1367 ret = -ECANCELED; in qcom_glink_request_intent()
1369 ret = READ_ONCE(channel->intent_req_result) ? 0 : -EAGAIN; in qcom_glink_request_intent()
1373 mutex_unlock(&channel->intent_req_lock); in qcom_glink_request_intent()
1380 struct qcom_glink *glink = channel->glink; in __qcom_glink_send()
1394 if (!glink->intentless) { in __qcom_glink_send()
1396 spin_lock_irqsave(&channel->intent_lock, flags); in __qcom_glink_send()
1397 idr_for_each_entry(&channel->riids, tmp, iid) { in __qcom_glink_send()
1398 if (tmp->size >= len && !tmp->in_use) { in __qcom_glink_send()
1401 else if (intent->size > tmp->size) in __qcom_glink_send()
1403 if (intent->size == len) in __qcom_glink_send()
1408 intent->in_use = true; in __qcom_glink_send()
1409 spin_unlock_irqrestore(&channel->intent_lock, flags); in __qcom_glink_send()
1416 return -EBUSY; in __qcom_glink_send()
1423 iid = intent->id; in __qcom_glink_send()
1427 chunk_size = len - offset; in __qcom_glink_send()
1432 req.msg.param1 = cpu_to_le16(channel->lcid); in __qcom_glink_send()
1435 req.left_size = cpu_to_le32(len - offset - chunk_size); in __qcom_glink_send()
1441 intent->in_use = false; in __qcom_glink_send()
1491 key = "qcom,glink-channels"; in qcom_glink_match_channel()
1521 kfree(rpdev->driver_override); in qcom_glink_rpdev_release()
1536 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_open()
1537 idr_for_each_entry(&glink->lcids, channel, lcid) { in qcom_glink_rx_open()
1538 if (!strcmp(channel->name, name)) in qcom_glink_rx_open()
1541 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_open()
1552 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_open()
1553 ret = idr_alloc(&glink->rcids, channel, rcid, rcid + 1, GFP_ATOMIC); in qcom_glink_rx_open()
1555 dev_err(glink->dev, "Unable to insert channel into rcid list\n"); in qcom_glink_rx_open()
1556 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_open()
1559 channel->rcid = ret; in qcom_glink_rx_open()
1560 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_open()
1562 complete_all(&channel->open_req); in qcom_glink_rx_open()
1567 ret = -ENOMEM; in qcom_glink_rx_open()
1571 rpdev->ept = &channel->ept; in qcom_glink_rx_open()
1572 strscpy_pad(rpdev->id.name, name, RPMSG_NAME_SIZE); in qcom_glink_rx_open()
1573 rpdev->src = RPMSG_ADDR_ANY; in qcom_glink_rx_open()
1574 rpdev->dst = RPMSG_ADDR_ANY; in qcom_glink_rx_open()
1575 rpdev->ops = &glink_device_ops; in qcom_glink_rx_open()
1577 node = qcom_glink_match_channel(glink->dev->of_node, name); in qcom_glink_rx_open()
1578 rpdev->dev.of_node = node; in qcom_glink_rx_open()
1579 rpdev->dev.parent = glink->dev; in qcom_glink_rx_open()
1580 rpdev->dev.release = qcom_glink_rpdev_release; in qcom_glink_rx_open()
1586 channel->rpdev = rpdev; in qcom_glink_rx_open()
1592 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_open()
1593 idr_remove(&glink->rcids, channel->rcid); in qcom_glink_rx_open()
1594 channel->rcid = 0; in qcom_glink_rx_open()
1595 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_open()
1599 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_rx_open()
1610 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_close()
1611 channel = idr_find(&glink->rcids, rcid); in qcom_glink_rx_close()
1612 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_close()
1617 cancel_work_sync(&channel->intent_work); in qcom_glink_rx_close()
1619 if (channel->rpdev) { in qcom_glink_rx_close()
1620 strscpy_pad(chinfo.name, channel->name, sizeof(chinfo.name)); in qcom_glink_rx_close()
1624 rpmsg_unregister_device(glink->dev, &chinfo); in qcom_glink_rx_close()
1626 channel->rpdev = NULL; in qcom_glink_rx_close()
1628 qcom_glink_send_close_ack(glink, channel->rcid); in qcom_glink_rx_close()
1630 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_close()
1631 idr_remove(&glink->rcids, channel->rcid); in qcom_glink_rx_close()
1632 channel->rcid = 0; in qcom_glink_rx_close()
1633 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_close()
1635 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_rx_close()
1645 wake_up_all(&glink->tx_avail_notify); in qcom_glink_rx_close_ack()
1647 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_close_ack()
1648 channel = idr_find(&glink->lcids, lcid); in qcom_glink_rx_close_ack()
1650 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_close_ack()
1654 idr_remove(&glink->lcids, channel->lcid); in qcom_glink_rx_close_ack()
1655 channel->lcid = 0; in qcom_glink_rx_close_ack()
1656 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_close_ack()
1659 if (channel->rpdev) { in qcom_glink_rx_close_ack()
1660 strscpy(chinfo.name, channel->name, sizeof(chinfo.name)); in qcom_glink_rx_close_ack()
1664 rpmsg_unregister_device(glink->dev, &chinfo); in qcom_glink_rx_close_ack()
1666 channel->rpdev = NULL; in qcom_glink_rx_close_ack()
1668 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_rx_close_ack()
1683 spin_lock_irqsave(&glink->rx_lock, flags); in qcom_glink_work()
1684 if (list_empty(&glink->rx_queue)) { in qcom_glink_work()
1685 spin_unlock_irqrestore(&glink->rx_lock, flags); in qcom_glink_work()
1688 dcmd = list_first_entry(&glink->rx_queue, in qcom_glink_work()
1690 list_del(&dcmd->node); in qcom_glink_work()
1691 spin_unlock_irqrestore(&glink->rx_lock, flags); in qcom_glink_work()
1693 msg = &dcmd->msg; in qcom_glink_work()
1694 cmd = le16_to_cpu(msg->cmd); in qcom_glink_work()
1695 param1 = le16_to_cpu(msg->param1); in qcom_glink_work()
1696 param2 = le32_to_cpu(msg->param2); in qcom_glink_work()
1706 qcom_glink_rx_open(glink, param1, msg->data); in qcom_glink_work()
1732 cancel_work_sync(&glink->rx_work); in qcom_glink_cancel_rx_work()
1734 list_for_each_entry_safe(dcmd, tmp, &glink->rx_queue, node) in qcom_glink_cancel_rx_work()
1744 ret = of_property_read_string(dev->of_node, "label", &name); in rpmsg_name_show()
1746 name = dev->of_node->name; in rpmsg_name_show()
1761 struct glink_channel *channel = to_glink_channel(rpdev->ept); in qcom_glink_device_release()
1764 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_device_release()
1765 kfree(rpdev->driver_override); in qcom_glink_device_release()
1776 return -ENOMEM; in qcom_glink_create_chrdev()
1783 channel->rpdev = rpdev; in qcom_glink_create_chrdev()
1785 rpdev->ept = &channel->ept; in qcom_glink_create_chrdev()
1786 rpdev->ops = &glink_device_ops; in qcom_glink_create_chrdev()
1787 rpdev->dev.parent = glink->dev; in qcom_glink_create_chrdev()
1788 rpdev->dev.release = qcom_glink_device_release; in qcom_glink_create_chrdev()
1804 return ERR_PTR(-ENOMEM); in qcom_glink_native_probe()
1806 glink->dev = dev; in qcom_glink_native_probe()
1807 glink->tx_pipe = tx; in qcom_glink_native_probe()
1808 glink->rx_pipe = rx; in qcom_glink_native_probe()
1810 glink->features = features; in qcom_glink_native_probe()
1811 glink->intentless = intentless; in qcom_glink_native_probe()
1813 spin_lock_init(&glink->tx_lock); in qcom_glink_native_probe()
1814 spin_lock_init(&glink->rx_lock); in qcom_glink_native_probe()
1815 INIT_LIST_HEAD(&glink->rx_queue); in qcom_glink_native_probe()
1816 INIT_WORK(&glink->rx_work, qcom_glink_work); in qcom_glink_native_probe()
1817 init_waitqueue_head(&glink->tx_avail_notify); in qcom_glink_native_probe()
1819 spin_lock_init(&glink->idr_lock); in qcom_glink_native_probe()
1820 idr_init(&glink->lcids); in qcom_glink_native_probe()
1821 idr_init(&glink->rcids); in qcom_glink_native_probe()
1823 glink->dev->groups = qcom_glink_groups; in qcom_glink_native_probe()
1835 dev_err(glink->dev, "failed to register chrdev\n"); in qcom_glink_native_probe()
1858 spin_lock_irqsave(&glink->tx_lock, flags); in qcom_glink_native_remove()
1859 glink->abort_tx = true; in qcom_glink_native_remove()
1860 wake_up_all(&glink->tx_avail_notify); in qcom_glink_native_remove()
1861 spin_unlock_irqrestore(&glink->tx_lock, flags); in qcom_glink_native_remove()
1864 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_native_remove()
1865 idr_for_each_entry(&glink->lcids, channel, cid) in qcom_glink_native_remove()
1867 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_native_remove()
1869 ret = device_for_each_child(glink->dev, NULL, qcom_glink_remove_device); in qcom_glink_native_remove()
1871 dev_warn(glink->dev, "Can't remove GLINK devices: %d\n", ret); in qcom_glink_native_remove()
1873 /* Release any defunct local channels, waiting for close-ack */ in qcom_glink_native_remove()
1874 idr_for_each_entry(&glink->lcids, channel, cid) in qcom_glink_native_remove()
1875 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_native_remove()
1877 /* Release any defunct local channels, waiting for close-req */ in qcom_glink_native_remove()
1878 idr_for_each_entry(&glink->rcids, channel, cid) in qcom_glink_native_remove()
1879 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_native_remove()
1881 idr_destroy(&glink->lcids); in qcom_glink_native_remove()
1882 idr_destroy(&glink->rcids); in qcom_glink_native_remove()