Lines Matching +full:channel +full:-

1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2016-2017, Linaro Ltd
48 * struct glink_defer_cmd - deferred incoming control message
64 * struct glink_core_rx_intent - RX intent
67 * @data: pointer to the data (may be NULL for zero-copy)
71 * @in_use: To mark if intent is already in use for the channel
87 * struct qcom_glink - driver context, relates to one remote subsystem
97 * @lcids: idr of all channels with a known local channel id
98 * @rcids: idr of all channels with a known remote channel id
139 * struct glink_channel - internal representation of a channel
141 * @ept: rpmsg endpoint this channel is associated with
143 * @refcount: refcount for the channel object
145 * @name: unique channel name/identifier
146 * @lcid: channel id, in local space
147 * @rcid: channel id, in remote space
156 * @open_ack: completed once remote has acked the open-request
157 * @open_req: completed once open-request has been received
228 struct glink_channel *channel; in qcom_glink_alloc_channel() local
230 channel = kzalloc(sizeof(*channel), GFP_KERNEL); in qcom_glink_alloc_channel()
231 if (!channel) in qcom_glink_alloc_channel()
232 return ERR_PTR(-ENOMEM); in qcom_glink_alloc_channel()
235 spin_lock_init(&channel->recv_lock); in qcom_glink_alloc_channel()
236 spin_lock_init(&channel->intent_lock); in qcom_glink_alloc_channel()
237 mutex_init(&channel->intent_req_lock); in qcom_glink_alloc_channel()
239 channel->glink = glink; in qcom_glink_alloc_channel()
240 channel->name = kstrdup(name, GFP_KERNEL); in qcom_glink_alloc_channel()
241 if (!channel->name) { in qcom_glink_alloc_channel()
242 kfree(channel); in qcom_glink_alloc_channel()
243 return ERR_PTR(-ENOMEM); in qcom_glink_alloc_channel()
246 init_completion(&channel->open_req); in qcom_glink_alloc_channel()
247 init_completion(&channel->open_ack); in qcom_glink_alloc_channel()
248 init_waitqueue_head(&channel->intent_req_wq); in qcom_glink_alloc_channel()
250 INIT_LIST_HEAD(&channel->done_intents); in qcom_glink_alloc_channel()
251 INIT_WORK(&channel->intent_work, qcom_glink_rx_done_work); in qcom_glink_alloc_channel()
253 idr_init(&channel->liids); in qcom_glink_alloc_channel()
254 idr_init(&channel->riids); in qcom_glink_alloc_channel()
255 kref_init(&channel->refcount); in qcom_glink_alloc_channel()
257 return channel; in qcom_glink_alloc_channel()
262 struct glink_channel *channel = container_of(ref, struct glink_channel, in qcom_glink_channel_release() local
270 cancel_work_sync(&channel->intent_work); in qcom_glink_channel_release()
272 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_channel_release()
273 /* Free all non-reuse intents pending rx_done work */ in qcom_glink_channel_release()
274 list_for_each_entry_safe(intent, tmp, &channel->done_intents, node) { in qcom_glink_channel_release()
275 if (!intent->reuse) { in qcom_glink_channel_release()
276 kfree(intent->data); in qcom_glink_channel_release()
281 idr_for_each_entry(&channel->liids, tmp, iid) { in qcom_glink_channel_release()
282 kfree(tmp->data); in qcom_glink_channel_release()
285 idr_destroy(&channel->liids); in qcom_glink_channel_release()
287 idr_for_each_entry(&channel->riids, tmp, iid) in qcom_glink_channel_release()
289 idr_destroy(&channel->riids); in qcom_glink_channel_release()
290 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_channel_release()
292 kfree(channel->name); in qcom_glink_channel_release()
293 kfree(channel); in qcom_glink_channel_release()
298 return glink->rx_pipe->avail(glink->rx_pipe); in qcom_glink_rx_avail()
304 glink->rx_pipe->peek(glink->rx_pipe, data, offset, count); in qcom_glink_rx_peek()
309 glink->rx_pipe->advance(glink->rx_pipe, count); in qcom_glink_rx_advance()
314 return glink->tx_pipe->avail(glink->tx_pipe); in qcom_glink_tx_avail()
321 glink->tx_pipe->write(glink->tx_pipe, hdr, hlen, data, dlen); in qcom_glink_tx_write()
326 glink->tx_pipe->kick(glink->tx_pipe); in qcom_glink_tx_kick()
351 if (tlen >= glink->tx_pipe->length) in qcom_glink_tx()
352 return -EINVAL; in qcom_glink_tx()
354 spin_lock_irqsave(&glink->tx_lock, flags); in qcom_glink_tx()
356 if (glink->abort_tx) { in qcom_glink_tx()
357 ret = -EIO; in qcom_glink_tx()
363 ret = -EAGAIN; in qcom_glink_tx()
367 if (glink->abort_tx) { in qcom_glink_tx()
368 ret = -EIO; in qcom_glink_tx()
372 if (!glink->sent_read_notify) { in qcom_glink_tx()
373 glink->sent_read_notify = true; in qcom_glink_tx()
378 spin_unlock_irqrestore(&glink->tx_lock, flags); in qcom_glink_tx()
380 wait_event_timeout(glink->tx_avail_notify, in qcom_glink_tx()
383 spin_lock_irqsave(&glink->tx_lock, flags); in qcom_glink_tx()
386 glink->sent_read_notify = false; in qcom_glink_tx()
393 spin_unlock_irqrestore(&glink->tx_lock, flags); in qcom_glink_tx()
404 msg.param2 = cpu_to_le32(glink->features); in qcom_glink_send_version()
406 trace_qcom_glink_cmd_version_tx(glink->label, GLINK_VERSION_1, glink->features); in qcom_glink_send_version()
417 msg.param2 = cpu_to_le32(glink->features); in qcom_glink_send_version_ack()
419 trace_qcom_glink_cmd_version_ack_tx(glink->label, msg.param1, msg.param2); in qcom_glink_send_version_ack()
425 struct glink_channel *channel) in qcom_glink_send_open_ack() argument
430 msg.param1 = cpu_to_le16(channel->rcid); in qcom_glink_send_open_ack()
433 trace_qcom_glink_cmd_open_ack_tx(glink->label, channel->name, in qcom_glink_send_open_ack()
434 channel->lcid, channel->rcid); in qcom_glink_send_open_ack()
442 struct glink_channel *channel; in qcom_glink_handle_intent_req_ack() local
447 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_handle_intent_req_ack()
448 channel = idr_find(&glink->rcids, cid); in qcom_glink_handle_intent_req_ack()
449 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_handle_intent_req_ack()
451 trace_qcom_glink_cmd_rx_intent_req_ack_rx(glink->label, in qcom_glink_handle_intent_req_ack()
452 channel ? channel->name : NULL, in qcom_glink_handle_intent_req_ack()
453 channel ? channel->lcid : 0, in qcom_glink_handle_intent_req_ack()
455 if (!channel) { in qcom_glink_handle_intent_req_ack()
456 dev_err(glink->dev, "unable to find channel\n"); in qcom_glink_handle_intent_req_ack()
460 WRITE_ONCE(channel->intent_req_result, granted); in qcom_glink_handle_intent_req_ack()
461 wake_up_all(&channel->intent_req_wq); in qcom_glink_handle_intent_req_ack()
464 static void qcom_glink_intent_req_abort(struct glink_channel *channel) in qcom_glink_intent_req_abort() argument
466 WRITE_ONCE(channel->intent_req_result, 0); in qcom_glink_intent_req_abort()
467 wake_up_all(&channel->intent_req_wq); in qcom_glink_intent_req_abort()
471 * qcom_glink_send_open_req() - send a GLINK_CMD_OPEN request to the remote
473 * @channel: Ptr to the channel that the open req is sent
475 * Allocates a local channel id and sends a GLINK_CMD_OPEN message to the remote.
481 struct glink_channel *channel) in qcom_glink_send_open_req() argument
484 int name_len = strlen(channel->name) + 1; in qcom_glink_send_open_req()
489 kref_get(&channel->refcount); in qcom_glink_send_open_req()
491 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_send_open_req()
492 ret = idr_alloc_cyclic(&glink->lcids, channel, in qcom_glink_send_open_req()
495 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_send_open_req()
499 channel->lcid = ret; in qcom_glink_send_open_req()
501 req->cmd = cpu_to_le16(GLINK_CMD_OPEN); in qcom_glink_send_open_req()
502 req->param1 = cpu_to_le16(channel->lcid); in qcom_glink_send_open_req()
503 req->param2 = cpu_to_le32(name_len); in qcom_glink_send_open_req()
504 strcpy(req->data, channel->name); in qcom_glink_send_open_req()
506 trace_qcom_glink_cmd_open_tx(glink->label, channel->name, in qcom_glink_send_open_req()
507 channel->lcid, channel->rcid); in qcom_glink_send_open_req()
516 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_send_open_req()
517 idr_remove(&glink->lcids, channel->lcid); in qcom_glink_send_open_req()
518 channel->lcid = 0; in qcom_glink_send_open_req()
519 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_send_open_req()
525 struct glink_channel *channel) in qcom_glink_send_close_req() argument
530 req.param1 = cpu_to_le16(channel->lcid); in qcom_glink_send_close_req()
533 trace_qcom_glink_cmd_close_tx(glink->label, channel->name, in qcom_glink_send_close_req()
534 channel->lcid, channel->rcid); in qcom_glink_send_close_req()
540 struct glink_channel *channel) in qcom_glink_send_close_ack() argument
545 req.param1 = cpu_to_le16(channel->rcid); in qcom_glink_send_close_ack()
548 trace_qcom_glink_cmd_close_ack_tx(glink->label, channel->name, in qcom_glink_send_close_ack()
549 channel->lcid, channel->rcid); in qcom_glink_send_close_ack()
556 struct glink_channel *channel = container_of(work, struct glink_channel, in qcom_glink_rx_done_work() local
558 struct qcom_glink *glink = channel->glink; in qcom_glink_rx_done_work()
566 unsigned int cid = channel->lcid; in qcom_glink_rx_done_work()
571 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_rx_done_work()
572 list_for_each_entry_safe(intent, tmp, &channel->done_intents, node) { in qcom_glink_rx_done_work()
573 list_del(&intent->node); in qcom_glink_rx_done_work()
574 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_rx_done_work()
575 iid = intent->id; in qcom_glink_rx_done_work()
576 reuse = intent->reuse; in qcom_glink_rx_done_work()
582 trace_qcom_glink_cmd_rx_done_tx(glink->label, channel->name, in qcom_glink_rx_done_work()
583 channel->lcid, channel->rcid, cmd.liid, reuse); in qcom_glink_rx_done_work()
587 kfree(intent->data); in qcom_glink_rx_done_work()
590 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_rx_done_work()
592 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_rx_done_work()
596 struct glink_channel *channel, in qcom_glink_rx_done() argument
600 if (glink->intentless) { in qcom_glink_rx_done()
601 kfree(intent->data); in qcom_glink_rx_done()
607 if (!intent->reuse) { in qcom_glink_rx_done()
608 spin_lock(&channel->intent_lock); in qcom_glink_rx_done()
609 idr_remove(&channel->liids, intent->id); in qcom_glink_rx_done()
610 spin_unlock(&channel->intent_lock); in qcom_glink_rx_done()
614 spin_lock(&channel->intent_lock); in qcom_glink_rx_done()
615 list_add_tail(&intent->node, &channel->done_intents); in qcom_glink_rx_done()
616 spin_unlock(&channel->intent_lock); in qcom_glink_rx_done()
618 schedule_work(&channel->intent_work); in qcom_glink_rx_done()
622 * qcom_glink_receive_version() - receive version/features from remote system
628 * This function is called in response to a remote-initiated version/feature
635 trace_qcom_glink_cmd_version_rx(glink->label, version, features); in qcom_glink_receive_version()
641 glink->features &= features; in qcom_glink_receive_version()
650 * qcom_glink_receive_version_ack() - receive negotiation ack from remote system
656 * This function is called in response to a local-initiated version/feature
657 * negotiation sequence and is the counter-offer from the remote side based
664 trace_qcom_glink_cmd_version_ack_rx(glink->label, version, features); in qcom_glink_receive_version_ack()
671 if (features == glink->features) in qcom_glink_receive_version_ack()
674 glink->features &= features; in qcom_glink_receive_version_ack()
683 * qcom_glink_send_intent_req_ack() - convert an rx intent request ack cmd to
686 * @channel: The glink channel
692 struct glink_channel *channel, in qcom_glink_send_intent_req_ack() argument
697 trace_qcom_glink_cmd_rx_intent_req_ack_tx(glink->label, channel->name, in qcom_glink_send_intent_req_ack()
698 channel->lcid, channel->rcid, in qcom_glink_send_intent_req_ack()
702 msg.param1 = cpu_to_le16(channel->lcid); in qcom_glink_send_intent_req_ack()
711 * qcom_glink_advertise_intent - convert an rx intent cmd to wire format and
714 * @channel: The local channel
720 struct glink_channel *channel, in qcom_glink_advertise_intent() argument
733 cmd.lcid = cpu_to_le16(channel->lcid); in qcom_glink_advertise_intent()
735 cmd.size = cpu_to_le32(intent->size); in qcom_glink_advertise_intent()
736 cmd.liid = cpu_to_le32(intent->id); in qcom_glink_advertise_intent()
738 trace_qcom_glink_cmd_intent_tx(glink->label, channel->name, in qcom_glink_advertise_intent()
739 channel->lcid, channel->rcid, in qcom_glink_advertise_intent()
749 struct glink_channel *channel, in qcom_glink_alloc_intent() argument
761 intent->data = kzalloc(size, GFP_KERNEL); in qcom_glink_alloc_intent()
762 if (!intent->data) in qcom_glink_alloc_intent()
765 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_alloc_intent()
766 ret = idr_alloc_cyclic(&channel->liids, intent, 1, -1, GFP_ATOMIC); in qcom_glink_alloc_intent()
768 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_alloc_intent()
771 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_alloc_intent()
773 intent->id = ret; in qcom_glink_alloc_intent()
774 intent->size = size; in qcom_glink_alloc_intent()
775 intent->reuse = reuseable; in qcom_glink_alloc_intent()
780 kfree(intent->data); in qcom_glink_alloc_intent()
791 struct glink_channel *channel; in qcom_glink_handle_rx_done() local
796 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_handle_rx_done()
797 channel = idr_find(&glink->rcids, cid); in qcom_glink_handle_rx_done()
798 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_handle_rx_done()
800 trace_qcom_glink_cmd_rx_done_rx(glink->label, channel ? channel->name : NULL, in qcom_glink_handle_rx_done()
801 channel ? channel->lcid : 0, cid, iid, reuse); in qcom_glink_handle_rx_done()
802 if (!channel) { in qcom_glink_handle_rx_done()
803 dev_err(glink->dev, "invalid channel id received\n"); in qcom_glink_handle_rx_done()
807 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_handle_rx_done()
808 intent = idr_find(&channel->riids, iid); in qcom_glink_handle_rx_done()
811 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_handle_rx_done()
812 dev_err(glink->dev, "invalid intent id received\n"); in qcom_glink_handle_rx_done()
816 intent->in_use = false; in qcom_glink_handle_rx_done()
819 idr_remove(&channel->riids, intent->id); in qcom_glink_handle_rx_done()
822 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_handle_rx_done()
825 WRITE_ONCE(channel->intent_received, true); in qcom_glink_handle_rx_done()
826 wake_up_all(&channel->intent_req_wq); in qcom_glink_handle_rx_done()
831 * qcom_glink_handle_intent_req() - Receive a request for rx_intent
834 * @cid: Remote channel ID
837 * The function searches for the local channel to which the request for
844 struct glink_channel *channel; in qcom_glink_handle_intent_req() local
847 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_handle_intent_req()
848 channel = idr_find(&glink->rcids, cid); in qcom_glink_handle_intent_req()
849 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_handle_intent_req()
851 trace_qcom_glink_cmd_rx_intent_req_rx(glink->label, in qcom_glink_handle_intent_req()
852 channel ? channel->name : NULL, in qcom_glink_handle_intent_req()
853 channel ? channel->lcid : 0, in qcom_glink_handle_intent_req()
855 if (!channel) { in qcom_glink_handle_intent_req()
856 pr_err("%s channel not found for cid %d\n", __func__, cid); in qcom_glink_handle_intent_req()
860 intent = qcom_glink_alloc_intent(glink, channel, size, false); in qcom_glink_handle_intent_req()
862 qcom_glink_advertise_intent(glink, channel, intent); in qcom_glink_handle_intent_req()
864 qcom_glink_send_intent_req_ack(glink, channel, !!intent); in qcom_glink_handle_intent_req()
874 dev_dbg(glink->dev, "Insufficient data in rx fifo"); in qcom_glink_rx_defer()
875 return -ENXIO; in qcom_glink_rx_defer()
880 return -ENOMEM; in qcom_glink_rx_defer()
882 INIT_LIST_HEAD(&dcmd->node); in qcom_glink_rx_defer()
885 container_of(&dcmd->msg, struct glink_msg, hdr), 0, in qcom_glink_rx_defer()
886 sizeof(dcmd->msg) + extra); in qcom_glink_rx_defer()
888 spin_lock(&glink->rx_lock); in qcom_glink_rx_defer()
889 list_add_tail(&dcmd->node, &glink->rx_queue); in qcom_glink_rx_defer()
890 spin_unlock(&glink->rx_lock); in qcom_glink_rx_defer()
892 schedule_work(&glink->rx_work); in qcom_glink_rx_defer()
893 qcom_glink_rx_advance(glink, sizeof(dcmd->msg) + extra); in qcom_glink_rx_defer()
901 struct glink_channel *channel; in qcom_glink_rx_data() local
915 dev_dbg(glink->dev, "Not enough data in fifo\n"); in qcom_glink_rx_data()
916 return -EAGAIN; in qcom_glink_rx_data()
924 dev_dbg(glink->dev, "Payload not yet in fifo\n"); in qcom_glink_rx_data()
925 return -EAGAIN; in qcom_glink_rx_data()
930 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_data()
931 channel = idr_find(&glink->rcids, rcid); in qcom_glink_rx_data()
932 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_data()
934 trace_qcom_glink_cmd_tx_data_rx(glink->label, channel ? channel->name : NULL, in qcom_glink_rx_data()
935 channel ? channel->lcid : 0, rcid, in qcom_glink_rx_data()
938 if (!channel) { in qcom_glink_rx_data()
939 dev_dbg(glink->dev, "Data on non-existing channel\n"); in qcom_glink_rx_data()
945 if (glink->intentless) { in qcom_glink_rx_data()
947 if (!channel->buf) { in qcom_glink_rx_data()
950 return -ENOMEM; in qcom_glink_rx_data()
952 intent->data = kmalloc(chunk_size + left_size, in qcom_glink_rx_data()
954 if (!intent->data) { in qcom_glink_rx_data()
956 return -ENOMEM; in qcom_glink_rx_data()
959 intent->id = 0xbabababa; in qcom_glink_rx_data()
960 intent->size = chunk_size + left_size; in qcom_glink_rx_data()
961 intent->offset = 0; in qcom_glink_rx_data()
963 channel->buf = intent; in qcom_glink_rx_data()
965 intent = channel->buf; in qcom_glink_rx_data()
968 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_rx_data()
969 intent = idr_find(&channel->liids, liid); in qcom_glink_rx_data()
970 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_rx_data()
973 dev_err(glink->dev, in qcom_glink_rx_data()
974 "no intent found for channel %s intent %d", in qcom_glink_rx_data()
975 channel->name, liid); in qcom_glink_rx_data()
976 ret = -ENOENT; in qcom_glink_rx_data()
981 if (intent->size - intent->offset < chunk_size) { in qcom_glink_rx_data()
982 dev_err(glink->dev, "Insufficient space in intent\n"); in qcom_glink_rx_data()
988 qcom_glink_rx_peek(glink, intent->data + intent->offset, in qcom_glink_rx_data()
990 intent->offset += chunk_size; in qcom_glink_rx_data()
994 spin_lock(&channel->recv_lock); in qcom_glink_rx_data()
995 if (channel->ept.cb) { in qcom_glink_rx_data()
996 channel->ept.cb(channel->ept.rpdev, in qcom_glink_rx_data()
997 intent->data, in qcom_glink_rx_data()
998 intent->offset, in qcom_glink_rx_data()
999 channel->ept.priv, in qcom_glink_rx_data()
1002 spin_unlock(&channel->recv_lock); in qcom_glink_rx_data()
1004 intent->offset = 0; in qcom_glink_rx_data()
1005 channel->buf = NULL; in qcom_glink_rx_data()
1007 qcom_glink_rx_done(glink, channel, intent); in qcom_glink_rx_data()
1018 trace_qcom_glink_cmd_read_notif_rx(glink->label); in qcom_glink_rx_read_notif()
1030 struct glink_channel *channel; in qcom_glink_handle_intent() local
1047 dev_dbg(glink->dev, "Not enough data in fifo\n"); in qcom_glink_handle_intent()
1051 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_handle_intent()
1052 channel = idr_find(&glink->rcids, cid); in qcom_glink_handle_intent()
1053 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_handle_intent()
1054 if (!channel) { in qcom_glink_handle_intent()
1055 trace_qcom_glink_cmd_intent_rx(glink->label, NULL, 0, cid, count, 0, 0); in qcom_glink_handle_intent()
1056 dev_err(glink->dev, "intents for non-existing channel\n"); in qcom_glink_handle_intent()
1067 trace_qcom_glink_cmd_intent_rx(glink->label, channel->name, in qcom_glink_handle_intent()
1068 channel->lcid, cid, count, in qcom_glink_handle_intent()
1069 count > 0 ? msg->intents[0].size : 0, in qcom_glink_handle_intent()
1070 count > 0 ? msg->intents[0].iid : 0); in qcom_glink_handle_intent()
1077 intent->id = le32_to_cpu(msg->intents[i].iid); in qcom_glink_handle_intent()
1078 intent->size = le32_to_cpu(msg->intents[i].size); in qcom_glink_handle_intent()
1080 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_handle_intent()
1081 ret = idr_alloc(&channel->riids, intent, in qcom_glink_handle_intent()
1082 intent->id, intent->id + 1, GFP_ATOMIC); in qcom_glink_handle_intent()
1083 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_handle_intent()
1086 dev_err(glink->dev, "failed to store remote intent\n"); in qcom_glink_handle_intent()
1089 WRITE_ONCE(channel->intent_received, true); in qcom_glink_handle_intent()
1090 wake_up_all(&channel->intent_req_wq); in qcom_glink_handle_intent()
1098 struct glink_channel *channel; in qcom_glink_rx_open_ack() local
1102 spin_lock(&glink->idr_lock); in qcom_glink_rx_open_ack()
1103 channel = idr_find(&glink->lcids, lcid); in qcom_glink_rx_open_ack()
1104 spin_unlock(&glink->idr_lock); in qcom_glink_rx_open_ack()
1106 trace_qcom_glink_cmd_open_ack_rx(glink->label, channel ? channel->name : NULL, in qcom_glink_rx_open_ack()
1107 lcid, channel ? channel->rcid : 0); in qcom_glink_rx_open_ack()
1108 if (!channel) { in qcom_glink_rx_open_ack()
1109 dev_err(glink->dev, "Invalid open ack packet\n"); in qcom_glink_rx_open_ack()
1110 return -EINVAL; in qcom_glink_rx_open_ack()
1113 complete_all(&channel->open_ack); in qcom_glink_rx_open_ack()
1119 * qcom_glink_set_flow_control() - convert a signal cmd to wire format and transmit
1120 * @ept: Rpmsg endpoint for channel.
1128 struct glink_channel *channel = to_glink_channel(ept); in qcom_glink_set_flow_control() local
1129 struct qcom_glink *glink = channel->glink; in qcom_glink_set_flow_control()
1137 msg.param1 = cpu_to_le16(channel->lcid); in qcom_glink_set_flow_control()
1140 trace_qcom_glink_cmd_signal_tx(glink->label, channel->name, in qcom_glink_set_flow_control()
1141 channel->lcid, channel->rcid, sigs); in qcom_glink_set_flow_control()
1149 struct glink_channel *channel; in qcom_glink_handle_signals() local
1155 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_handle_signals()
1156 channel = idr_find(&glink->rcids, rcid); in qcom_glink_handle_signals()
1157 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_handle_signals()
1159 trace_qcom_glink_cmd_signal_rx(glink->label, channel ? channel->name : NULL, in qcom_glink_handle_signals()
1160 channel ? channel->lcid : 0, rcid, sigs); in qcom_glink_handle_signals()
1161 if (!channel) { in qcom_glink_handle_signals()
1162 dev_err(glink->dev, "signal for non-existing channel\n"); in qcom_glink_handle_signals()
1168 if (channel->ept.flow_cb) in qcom_glink_handle_signals()
1169 channel->ept.flow_cb(channel->ept.rpdev, channel->ept.priv, enable); in qcom_glink_handle_signals()
1182 wake_up_all(&glink->tx_avail_notify); in qcom_glink_native_rx()
1232 dev_err(glink->dev, "unhandled rx cmd: %d\n", cmd); in qcom_glink_native_rx()
1233 ret = -EINVAL; in qcom_glink_native_rx()
1247 struct glink_channel *channel; in qcom_glink_create_local() local
1251 channel = qcom_glink_alloc_channel(glink, name); in qcom_glink_create_local()
1252 if (IS_ERR(channel)) in qcom_glink_create_local()
1253 return ERR_CAST(channel); in qcom_glink_create_local()
1255 ret = qcom_glink_send_open_req(glink, channel); in qcom_glink_create_local()
1259 ret = wait_for_completion_timeout(&channel->open_ack, 5 * HZ); in qcom_glink_create_local()
1263 ret = wait_for_completion_timeout(&channel->open_req, 5 * HZ); in qcom_glink_create_local()
1267 qcom_glink_send_open_ack(glink, channel); in qcom_glink_create_local()
1269 return channel; in qcom_glink_create_local()
1272 /* qcom_glink_send_open_req() did register the channel in lcids*/ in qcom_glink_create_local()
1273 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_create_local()
1274 idr_remove(&glink->lcids, channel->lcid); in qcom_glink_create_local()
1275 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_create_local()
1279 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_create_local()
1281 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_create_local()
1283 return ERR_PTR(-ETIMEDOUT); in qcom_glink_create_local()
1288 struct glink_channel *channel) in qcom_glink_create_remote() argument
1292 qcom_glink_send_open_ack(glink, channel); in qcom_glink_create_remote()
1294 ret = qcom_glink_send_open_req(glink, channel); in qcom_glink_create_remote()
1298 ret = wait_for_completion_timeout(&channel->open_ack, 5 * HZ); in qcom_glink_create_remote()
1300 ret = -ETIMEDOUT; in qcom_glink_create_remote()
1308 * Send a close request to "undo" our open-ack. The close-ack will in qcom_glink_create_remote()
1313 qcom_glink_send_close_req(glink, channel); in qcom_glink_create_remote()
1324 struct glink_channel *parent = to_glink_channel(rpdev->ept); in qcom_glink_create_ept()
1325 struct glink_channel *channel; in qcom_glink_create_ept() local
1326 struct qcom_glink *glink = parent->glink; in qcom_glink_create_ept()
1333 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_create_ept()
1334 idr_for_each_entry(&glink->rcids, channel, cid) { in qcom_glink_create_ept()
1335 if (!strcmp(channel->name, name)) in qcom_glink_create_ept()
1338 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_create_ept()
1340 if (!channel) { in qcom_glink_create_ept()
1341 channel = qcom_glink_create_local(glink, name); in qcom_glink_create_ept()
1342 if (IS_ERR(channel)) in qcom_glink_create_ept()
1345 ret = qcom_glink_create_remote(glink, channel); in qcom_glink_create_ept()
1350 ept = &channel->ept; in qcom_glink_create_ept()
1351 ept->rpdev = rpdev; in qcom_glink_create_ept()
1352 ept->cb = cb; in qcom_glink_create_ept()
1353 ept->priv = priv; in qcom_glink_create_ept()
1354 ept->ops = &glink_endpoint_ops; in qcom_glink_create_ept()
1361 struct glink_channel *channel = to_glink_channel(rpdev->ept); in qcom_glink_announce_create() local
1362 struct device_node *np = rpdev->dev.of_node; in qcom_glink_announce_create()
1363 struct qcom_glink *glink = channel->glink; in qcom_glink_announce_create()
1372 if (glink->intentless || !completion_done(&channel->open_ack)) in qcom_glink_announce_create()
1377 val = prop->value; in qcom_glink_announce_create()
1378 num_groups = prop->length / sizeof(u32) / 2; in qcom_glink_announce_create()
1381 /* Channel is now open, advertise base set of intents */ in qcom_glink_announce_create()
1382 while (num_groups--) { in qcom_glink_announce_create()
1385 while (num_intents--) { in qcom_glink_announce_create()
1386 intent = qcom_glink_alloc_intent(glink, channel, size, in qcom_glink_announce_create()
1391 qcom_glink_advertise_intent(glink, channel, intent); in qcom_glink_announce_create()
1399 struct glink_channel *channel = to_glink_channel(ept); in qcom_glink_destroy_ept() local
1400 struct qcom_glink *glink = channel->glink; in qcom_glink_destroy_ept()
1403 spin_lock_irqsave(&channel->recv_lock, flags); in qcom_glink_destroy_ept()
1404 channel->ept.cb = NULL; in qcom_glink_destroy_ept()
1405 spin_unlock_irqrestore(&channel->recv_lock, flags); in qcom_glink_destroy_ept()
1407 /* Decouple the potential rpdev from the channel */ in qcom_glink_destroy_ept()
1408 channel->rpdev = NULL; in qcom_glink_destroy_ept()
1410 qcom_glink_send_close_req(glink, channel); in qcom_glink_destroy_ept()
1414 struct glink_channel *channel, in qcom_glink_request_intent() argument
1425 mutex_lock(&channel->intent_req_lock); in qcom_glink_request_intent()
1427 WRITE_ONCE(channel->intent_req_result, -1); in qcom_glink_request_intent()
1428 WRITE_ONCE(channel->intent_received, false); in qcom_glink_request_intent()
1431 cmd.cid = channel->lcid; in qcom_glink_request_intent()
1434 trace_qcom_glink_cmd_rx_intent_req_tx(glink->label, channel->name, in qcom_glink_request_intent()
1435 channel->lcid, channel->rcid, in qcom_glink_request_intent()
1442 ret = wait_event_timeout(channel->intent_req_wq, in qcom_glink_request_intent()
1443 READ_ONCE(channel->intent_req_result) == 0 || in qcom_glink_request_intent()
1444 (READ_ONCE(channel->intent_req_result) > 0 && in qcom_glink_request_intent()
1445 READ_ONCE(channel->intent_received)) || in qcom_glink_request_intent()
1446 glink->abort_tx, in qcom_glink_request_intent()
1449 dev_err(glink->dev, "intent request timed out\n"); in qcom_glink_request_intent()
1450 ret = -ETIMEDOUT; in qcom_glink_request_intent()
1451 } else if (glink->abort_tx) { in qcom_glink_request_intent()
1452 ret = -ECANCELED; in qcom_glink_request_intent()
1454 ret = READ_ONCE(channel->intent_req_result) ? 0 : -EAGAIN; in qcom_glink_request_intent()
1458 mutex_unlock(&channel->intent_req_lock); in qcom_glink_request_intent()
1462 static int __qcom_glink_send(struct glink_channel *channel, in __qcom_glink_send() argument
1465 struct qcom_glink *glink = channel->glink; in __qcom_glink_send()
1479 if (!glink->intentless) { in __qcom_glink_send()
1481 spin_lock_irqsave(&channel->intent_lock, flags); in __qcom_glink_send()
1482 idr_for_each_entry(&channel->riids, tmp, iid) { in __qcom_glink_send()
1483 if (tmp->size >= len && !tmp->in_use) { in __qcom_glink_send()
1486 else if (intent->size > tmp->size) in __qcom_glink_send()
1488 if (intent->size == len) in __qcom_glink_send()
1493 intent->in_use = true; in __qcom_glink_send()
1494 spin_unlock_irqrestore(&channel->intent_lock, flags); in __qcom_glink_send()
1501 return -EBUSY; in __qcom_glink_send()
1503 ret = qcom_glink_request_intent(glink, channel, len); in __qcom_glink_send()
1508 iid = intent->id; in __qcom_glink_send()
1512 chunk_size = len - offset; in __qcom_glink_send()
1517 req.msg.param1 = cpu_to_le16(channel->lcid); in __qcom_glink_send()
1520 req.left_size = cpu_to_le32(len - offset - chunk_size); in __qcom_glink_send()
1522 trace_qcom_glink_cmd_tx_data_tx(glink->label, channel->name, in __qcom_glink_send()
1523 channel->lcid, channel->rcid, in __qcom_glink_send()
1525 len - offset - chunk_size, in __qcom_glink_send()
1532 intent->in_use = false; in __qcom_glink_send()
1544 struct glink_channel *channel = to_glink_channel(ept); in qcom_glink_send() local
1546 return __qcom_glink_send(channel, data, len, true); in qcom_glink_send()
1551 struct glink_channel *channel = to_glink_channel(ept); in qcom_glink_trysend() local
1553 return __qcom_glink_send(channel, data, len, false); in qcom_glink_trysend()
1558 struct glink_channel *channel = to_glink_channel(ept); in qcom_glink_sendto() local
1560 return __qcom_glink_send(channel, data, len, true); in qcom_glink_sendto()
1565 struct glink_channel *channel = to_glink_channel(ept); in qcom_glink_trysendto() local
1567 return __qcom_glink_send(channel, data, len, false); in qcom_glink_trysendto()
1571 * Finds the device_node for the glink child interested in this channel.
1574 const char *channel) in qcom_glink_match_channel() argument
1582 key = "qcom,glink-channels"; in qcom_glink_match_channel()
1587 if (strcmp(name, channel) == 0) in qcom_glink_match_channel()
1612 kfree(rpdev->driver_override); in qcom_glink_rpdev_release()
1619 struct glink_channel *channel; in qcom_glink_rx_open() local
1627 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_open()
1628 idr_for_each_entry(&glink->lcids, channel, lcid) { in qcom_glink_rx_open()
1629 if (!strcmp(channel->name, name)) in qcom_glink_rx_open()
1632 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_open()
1634 if (!channel) { in qcom_glink_rx_open()
1635 channel = qcom_glink_alloc_channel(glink, name); in qcom_glink_rx_open()
1636 if (IS_ERR(channel)) in qcom_glink_rx_open()
1637 return PTR_ERR(channel); in qcom_glink_rx_open()
1643 trace_qcom_glink_cmd_open_rx(glink->label, name, channel->lcid, rcid); in qcom_glink_rx_open()
1645 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_open()
1646 ret = idr_alloc(&glink->rcids, channel, rcid, rcid + 1, GFP_ATOMIC); in qcom_glink_rx_open()
1648 dev_err(glink->dev, "Unable to insert channel into rcid list\n"); in qcom_glink_rx_open()
1649 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_open()
1652 channel->rcid = ret; in qcom_glink_rx_open()
1653 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_open()
1655 complete_all(&channel->open_req); in qcom_glink_rx_open()
1660 ret = -ENOMEM; in qcom_glink_rx_open()
1664 rpdev->ept = &channel->ept; in qcom_glink_rx_open()
1665 strscpy_pad(rpdev->id.name, name, RPMSG_NAME_SIZE); in qcom_glink_rx_open()
1666 rpdev->src = RPMSG_ADDR_ANY; in qcom_glink_rx_open()
1667 rpdev->dst = RPMSG_ADDR_ANY; in qcom_glink_rx_open()
1668 rpdev->ops = &glink_device_ops; in qcom_glink_rx_open()
1670 node = qcom_glink_match_channel(glink->dev->of_node, name); in qcom_glink_rx_open()
1671 rpdev->dev.of_node = node; in qcom_glink_rx_open()
1672 rpdev->dev.parent = glink->dev; in qcom_glink_rx_open()
1673 rpdev->dev.release = qcom_glink_rpdev_release; in qcom_glink_rx_open()
1679 channel->rpdev = rpdev; in qcom_glink_rx_open()
1685 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_open()
1686 idr_remove(&glink->rcids, channel->rcid); in qcom_glink_rx_open()
1687 channel->rcid = 0; in qcom_glink_rx_open()
1688 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_open()
1692 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_rx_open()
1700 struct glink_channel *channel; in qcom_glink_rx_close() local
1703 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_close()
1704 channel = idr_find(&glink->rcids, rcid); in qcom_glink_rx_close()
1705 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_close()
1707 trace_qcom_glink_cmd_close_rx(glink->label, channel ? channel->name : NULL, in qcom_glink_rx_close()
1708 channel ? channel->lcid : 0, rcid); in qcom_glink_rx_close()
1709 if (WARN(!channel, "close request on unknown channel\n")) in qcom_glink_rx_close()
1713 cancel_work_sync(&channel->intent_work); in qcom_glink_rx_close()
1715 if (channel->rpdev) { in qcom_glink_rx_close()
1716 strscpy_pad(chinfo.name, channel->name, sizeof(chinfo.name)); in qcom_glink_rx_close()
1720 rpmsg_unregister_device(glink->dev, &chinfo); in qcom_glink_rx_close()
1722 channel->rpdev = NULL; in qcom_glink_rx_close()
1724 qcom_glink_send_close_ack(glink, channel); in qcom_glink_rx_close()
1726 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_close()
1727 idr_remove(&glink->rcids, channel->rcid); in qcom_glink_rx_close()
1728 channel->rcid = 0; in qcom_glink_rx_close()
1729 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_close()
1731 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_rx_close()
1737 struct glink_channel *channel; in qcom_glink_rx_close_ack() local
1741 wake_up_all(&glink->tx_avail_notify); in qcom_glink_rx_close_ack()
1743 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_close_ack()
1744 channel = idr_find(&glink->lcids, lcid); in qcom_glink_rx_close_ack()
1746 trace_qcom_glink_cmd_close_ack_rx(glink->label, channel ? channel->name : NULL, in qcom_glink_rx_close_ack()
1747 lcid, channel ? channel->rcid : 0); in qcom_glink_rx_close_ack()
1748 if (WARN(!channel, "close ack on unknown channel\n")) { in qcom_glink_rx_close_ack()
1749 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_close_ack()
1753 idr_remove(&glink->lcids, channel->lcid); in qcom_glink_rx_close_ack()
1754 channel->lcid = 0; in qcom_glink_rx_close_ack()
1755 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_close_ack()
1757 /* Decouple the potential rpdev from the channel */ in qcom_glink_rx_close_ack()
1758 if (channel->rpdev) { in qcom_glink_rx_close_ack()
1759 strscpy(chinfo.name, channel->name, sizeof(chinfo.name)); in qcom_glink_rx_close_ack()
1763 rpmsg_unregister_device(glink->dev, &chinfo); in qcom_glink_rx_close_ack()
1765 channel->rpdev = NULL; in qcom_glink_rx_close_ack()
1767 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_rx_close_ack()
1782 spin_lock_irqsave(&glink->rx_lock, flags); in qcom_glink_work()
1783 if (list_empty(&glink->rx_queue)) { in qcom_glink_work()
1784 spin_unlock_irqrestore(&glink->rx_lock, flags); in qcom_glink_work()
1787 dcmd = list_first_entry(&glink->rx_queue, in qcom_glink_work()
1789 list_del(&dcmd->node); in qcom_glink_work()
1790 spin_unlock_irqrestore(&glink->rx_lock, flags); in qcom_glink_work()
1792 msg = container_of(&dcmd->msg, struct glink_msg, hdr); in qcom_glink_work()
1793 cmd = le16_to_cpu(msg->cmd); in qcom_glink_work()
1794 param1 = le16_to_cpu(msg->param1); in qcom_glink_work()
1795 param2 = le32_to_cpu(msg->param2); in qcom_glink_work()
1805 qcom_glink_rx_open(glink, param1, msg->data); in qcom_glink_work()
1831 cancel_work_sync(&glink->rx_work); in qcom_glink_cancel_rx_work()
1833 list_for_each_entry_safe(dcmd, tmp, &glink->rx_queue, node) in qcom_glink_cancel_rx_work()
1843 ret = of_property_read_string(dev->of_node, "label", &name); in rpmsg_name_show()
1845 name = dev->of_node->name; in rpmsg_name_show()
1860 struct glink_channel *channel = to_glink_channel(rpdev->ept); in qcom_glink_device_release() local
1863 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_device_release()
1864 kfree(rpdev->driver_override); in qcom_glink_device_release()
1871 struct glink_channel *channel; in qcom_glink_create_chrdev() local
1875 return -ENOMEM; in qcom_glink_create_chrdev()
1877 channel = qcom_glink_alloc_channel(glink, "rpmsg_chrdev"); in qcom_glink_create_chrdev()
1878 if (IS_ERR(channel)) { in qcom_glink_create_chrdev()
1880 return PTR_ERR(channel); in qcom_glink_create_chrdev()
1882 channel->rpdev = rpdev; in qcom_glink_create_chrdev()
1884 rpdev->ept = &channel->ept; in qcom_glink_create_chrdev()
1885 rpdev->ops = &glink_device_ops; in qcom_glink_create_chrdev()
1886 rpdev->dev.parent = glink->dev; in qcom_glink_create_chrdev()
1887 rpdev->dev.release = qcom_glink_device_release; in qcom_glink_create_chrdev()
1903 return ERR_PTR(-ENOMEM); in qcom_glink_native_probe()
1905 glink->dev = dev; in qcom_glink_native_probe()
1906 glink->tx_pipe = tx; in qcom_glink_native_probe()
1907 glink->rx_pipe = rx; in qcom_glink_native_probe()
1909 glink->features = features; in qcom_glink_native_probe()
1910 glink->intentless = intentless; in qcom_glink_native_probe()
1912 spin_lock_init(&glink->tx_lock); in qcom_glink_native_probe()
1913 spin_lock_init(&glink->rx_lock); in qcom_glink_native_probe()
1914 INIT_LIST_HEAD(&glink->rx_queue); in qcom_glink_native_probe()
1915 INIT_WORK(&glink->rx_work, qcom_glink_work); in qcom_glink_native_probe()
1916 init_waitqueue_head(&glink->tx_avail_notify); in qcom_glink_native_probe()
1918 spin_lock_init(&glink->idr_lock); in qcom_glink_native_probe()
1919 idr_init(&glink->lcids); in qcom_glink_native_probe()
1920 idr_init(&glink->rcids); in qcom_glink_native_probe()
1922 ret = of_property_read_string(dev->of_node, "label", &glink->label); in qcom_glink_native_probe()
1924 glink->label = dev->of_node->name; in qcom_glink_native_probe()
1926 glink->dev->groups = qcom_glink_groups; in qcom_glink_native_probe()
1938 dev_err(glink->dev, "failed to register chrdev\n"); in qcom_glink_native_probe()
1953 struct glink_channel *channel; in qcom_glink_native_remove() local
1961 spin_lock_irqsave(&glink->tx_lock, flags); in qcom_glink_native_remove()
1962 glink->abort_tx = true; in qcom_glink_native_remove()
1963 wake_up_all(&glink->tx_avail_notify); in qcom_glink_native_remove()
1964 spin_unlock_irqrestore(&glink->tx_lock, flags); in qcom_glink_native_remove()
1967 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_native_remove()
1968 idr_for_each_entry(&glink->lcids, channel, cid) in qcom_glink_native_remove()
1969 qcom_glink_intent_req_abort(channel); in qcom_glink_native_remove()
1970 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_native_remove()
1972 ret = device_for_each_child(glink->dev, NULL, qcom_glink_remove_device); in qcom_glink_native_remove()
1974 dev_warn(glink->dev, "Can't remove GLINK devices: %d\n", ret); in qcom_glink_native_remove()
1976 /* Release any defunct local channels, waiting for close-ack */ in qcom_glink_native_remove()
1977 idr_for_each_entry(&glink->lcids, channel, cid) in qcom_glink_native_remove()
1978 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_native_remove()
1980 /* Release any defunct local channels, waiting for close-req */ in qcom_glink_native_remove()
1981 idr_for_each_entry(&glink->rcids, channel, cid) in qcom_glink_native_remove()
1982 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_native_remove()
1984 idr_destroy(&glink->lcids); in qcom_glink_native_remove()
1985 idr_destroy(&glink->rcids); in qcom_glink_native_remove()