Lines Matching +full:data +full:- +full:channel
1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2016-2017, Linaro Ltd
36 u8 data[]; member
40 * struct glink_defer_cmd - deferred incoming control message
43 * @data: payload of the message
52 u8 data[]; member
56 * struct glink_core_rx_intent - RX intent
59 * @data: pointer to the data (may be NULL for zero-copy)
63 * @in_use: To mark if intent is already in use for the channel
68 void *data; member
79 * struct qcom_glink - driver context, relates to one remote subsystem
82 * @mbox_chan: mailbox channel
91 * @lcids: idr of all channels with a known local channel id
92 * @rcids: idr of all channels with a known remote channel id
131 * struct glink_channel - internal representation of a channel
133 * @ept: rpmsg endpoint this channel is associated with
135 * @refcount: refcount for the channel object
137 * @name: unique channel name/identifier
138 * @lcid: channel id, in local space
139 * @rcid: channel id, in remote space
148 * @open_ack: completed once remote has acked the open-request
149 * @open_req: completed once open-request has been received
212 struct glink_channel *channel; in qcom_glink_alloc_channel() local
214 channel = kzalloc(sizeof(*channel), GFP_KERNEL); in qcom_glink_alloc_channel()
215 if (!channel) in qcom_glink_alloc_channel()
216 return ERR_PTR(-ENOMEM); in qcom_glink_alloc_channel()
218 /* Setup glink internal glink_channel data */ in qcom_glink_alloc_channel()
219 spin_lock_init(&channel->recv_lock); in qcom_glink_alloc_channel()
220 spin_lock_init(&channel->intent_lock); in qcom_glink_alloc_channel()
221 mutex_init(&channel->intent_req_lock); in qcom_glink_alloc_channel()
223 channel->glink = glink; in qcom_glink_alloc_channel()
224 channel->name = kstrdup(name, GFP_KERNEL); in qcom_glink_alloc_channel()
225 if (!channel->name) { in qcom_glink_alloc_channel()
226 kfree(channel); in qcom_glink_alloc_channel()
227 return ERR_PTR(-ENOMEM); in qcom_glink_alloc_channel()
230 init_completion(&channel->open_req); in qcom_glink_alloc_channel()
231 init_completion(&channel->open_ack); in qcom_glink_alloc_channel()
232 init_completion(&channel->intent_req_comp); in qcom_glink_alloc_channel()
234 INIT_LIST_HEAD(&channel->done_intents); in qcom_glink_alloc_channel()
235 INIT_WORK(&channel->intent_work, qcom_glink_rx_done_work); in qcom_glink_alloc_channel()
237 idr_init(&channel->liids); in qcom_glink_alloc_channel()
238 idr_init(&channel->riids); in qcom_glink_alloc_channel()
239 kref_init(&channel->refcount); in qcom_glink_alloc_channel()
241 return channel; in qcom_glink_alloc_channel()
246 struct glink_channel *channel = container_of(ref, struct glink_channel, in qcom_glink_channel_release() local
254 cancel_work_sync(&channel->intent_work); in qcom_glink_channel_release()
256 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_channel_release()
257 /* Free all non-reuse intents pending rx_done work */ in qcom_glink_channel_release()
258 list_for_each_entry_safe(intent, tmp, &channel->done_intents, node) { in qcom_glink_channel_release()
259 if (!intent->reuse) { in qcom_glink_channel_release()
260 kfree(intent->data); in qcom_glink_channel_release()
265 idr_for_each_entry(&channel->liids, tmp, iid) { in qcom_glink_channel_release()
266 kfree(tmp->data); in qcom_glink_channel_release()
269 idr_destroy(&channel->liids); in qcom_glink_channel_release()
271 idr_for_each_entry(&channel->riids, tmp, iid) in qcom_glink_channel_release()
273 idr_destroy(&channel->riids); in qcom_glink_channel_release()
274 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_channel_release()
276 kfree(channel->name); in qcom_glink_channel_release()
277 kfree(channel); in qcom_glink_channel_release()
282 return glink->rx_pipe->avail(glink->rx_pipe); in qcom_glink_rx_avail()
286 void *data, unsigned int offset, size_t count) in qcom_glink_rx_peak() argument
288 glink->rx_pipe->peak(glink->rx_pipe, data, offset, count); in qcom_glink_rx_peak()
293 glink->rx_pipe->advance(glink->rx_pipe, count); in qcom_glink_rx_advance()
298 return glink->tx_pipe->avail(glink->tx_pipe); in qcom_glink_tx_avail()
303 const void *data, size_t dlen) in qcom_glink_tx_write() argument
305 glink->tx_pipe->write(glink->tx_pipe, hdr, hlen, data, dlen); in qcom_glink_tx_write()
310 const void *data, size_t dlen, bool wait) in qcom_glink_tx() argument
317 if (tlen >= glink->tx_pipe->length) in qcom_glink_tx()
318 return -EINVAL; in qcom_glink_tx()
320 spin_lock_irqsave(&glink->tx_lock, flags); in qcom_glink_tx()
324 ret = -EAGAIN; in qcom_glink_tx()
329 spin_unlock_irqrestore(&glink->tx_lock, flags); in qcom_glink_tx()
333 spin_lock_irqsave(&glink->tx_lock, flags); in qcom_glink_tx()
336 qcom_glink_tx_write(glink, hdr, hlen, data, dlen); in qcom_glink_tx()
338 mbox_send_message(glink->mbox_chan, NULL); in qcom_glink_tx()
339 mbox_client_txdone(glink->mbox_chan, 0); in qcom_glink_tx()
342 spin_unlock_irqrestore(&glink->tx_lock, flags); in qcom_glink_tx()
353 msg.param2 = cpu_to_le32(glink->features); in qcom_glink_send_version()
364 msg.param2 = cpu_to_le32(glink->features); in qcom_glink_send_version_ack()
370 struct glink_channel *channel) in qcom_glink_send_open_ack() argument
375 msg.param1 = cpu_to_le16(channel->rcid); in qcom_glink_send_open_ack()
384 struct glink_channel *channel; in qcom_glink_handle_intent_req_ack() local
387 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_handle_intent_req_ack()
388 channel = idr_find(&glink->rcids, cid); in qcom_glink_handle_intent_req_ack()
389 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_handle_intent_req_ack()
390 if (!channel) { in qcom_glink_handle_intent_req_ack()
391 dev_err(glink->dev, "unable to find channel\n"); in qcom_glink_handle_intent_req_ack()
395 channel->intent_req_result = granted; in qcom_glink_handle_intent_req_ack()
396 complete(&channel->intent_req_comp); in qcom_glink_handle_intent_req_ack()
400 * qcom_glink_send_open_req() - send a RPM_CMD_OPEN request to the remote
402 * @channel: Ptr to the channel that the open req is sent
404 * Allocates a local channel id and sends a RPM_CMD_OPEN message to the remote.
410 struct glink_channel *channel) in qcom_glink_send_open_req() argument
416 int name_len = strlen(channel->name) + 1; in qcom_glink_send_open_req()
421 kref_get(&channel->refcount); in qcom_glink_send_open_req()
423 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_send_open_req()
424 ret = idr_alloc_cyclic(&glink->lcids, channel, in qcom_glink_send_open_req()
427 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_send_open_req()
431 channel->lcid = ret; in qcom_glink_send_open_req()
434 req.msg.param1 = cpu_to_le16(channel->lcid); in qcom_glink_send_open_req()
436 strcpy(req.name, channel->name); in qcom_glink_send_open_req()
445 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_send_open_req()
446 idr_remove(&glink->lcids, channel->lcid); in qcom_glink_send_open_req()
447 channel->lcid = 0; in qcom_glink_send_open_req()
448 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_send_open_req()
454 struct glink_channel *channel) in qcom_glink_send_close_req() argument
459 req.param1 = cpu_to_le16(channel->lcid); in qcom_glink_send_close_req()
479 struct glink_channel *channel = container_of(work, struct glink_channel, in qcom_glink_rx_done_work() local
481 struct qcom_glink *glink = channel->glink; in qcom_glink_rx_done_work()
489 unsigned int cid = channel->lcid; in qcom_glink_rx_done_work()
494 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_rx_done_work()
495 list_for_each_entry_safe(intent, tmp, &channel->done_intents, node) { in qcom_glink_rx_done_work()
496 list_del(&intent->node); in qcom_glink_rx_done_work()
497 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_rx_done_work()
498 iid = intent->id; in qcom_glink_rx_done_work()
499 reuse = intent->reuse; in qcom_glink_rx_done_work()
507 kfree(intent->data); in qcom_glink_rx_done_work()
510 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_rx_done_work()
512 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_rx_done_work()
516 struct glink_channel *channel, in qcom_glink_rx_done() argument
520 if (glink->intentless) { in qcom_glink_rx_done()
521 kfree(intent->data); in qcom_glink_rx_done()
527 if (!intent->reuse) { in qcom_glink_rx_done()
528 spin_lock(&channel->intent_lock); in qcom_glink_rx_done()
529 idr_remove(&channel->liids, intent->id); in qcom_glink_rx_done()
530 spin_unlock(&channel->intent_lock); in qcom_glink_rx_done()
534 spin_lock(&channel->intent_lock); in qcom_glink_rx_done()
535 list_add_tail(&intent->node, &channel->done_intents); in qcom_glink_rx_done()
536 spin_unlock(&channel->intent_lock); in qcom_glink_rx_done()
538 schedule_work(&channel->intent_work); in qcom_glink_rx_done()
542 * qcom_glink_receive_version() - receive version/features from remote system
548 * This function is called in response to a remote-initiated version/feature
559 glink->features &= features; in qcom_glink_receive_version()
568 * qcom_glink_receive_version_ack() - receive negotiation ack from remote system
574 * This function is called in response to a local-initiated version/feature
575 * negotiation sequence and is the counter-offer from the remote side based
587 if (features == glink->features) in qcom_glink_receive_version_ack()
590 glink->features &= features; in qcom_glink_receive_version_ack()
599 * qcom_glink_send_intent_req_ack() - convert an rx intent request ack cmd to
602 * @channel: The glink channel
608 struct glink_channel *channel, in qcom_glink_send_intent_req_ack() argument
614 msg.param1 = cpu_to_le16(channel->lcid); in qcom_glink_send_intent_req_ack()
623 * qcom_glink_advertise_intent - convert an rx intent cmd to wire format and
626 * @channel: The local channel
632 struct glink_channel *channel, in qcom_glink_advertise_intent() argument
645 cmd.lcid = cpu_to_le16(channel->lcid); in qcom_glink_advertise_intent()
647 cmd.size = cpu_to_le32(intent->size); in qcom_glink_advertise_intent()
648 cmd.liid = cpu_to_le32(intent->id); in qcom_glink_advertise_intent()
657 struct glink_channel *channel, in qcom_glink_alloc_intent() argument
669 intent->data = kzalloc(size, GFP_KERNEL); in qcom_glink_alloc_intent()
670 if (!intent->data) in qcom_glink_alloc_intent()
673 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_alloc_intent()
674 ret = idr_alloc_cyclic(&channel->liids, intent, 1, -1, GFP_ATOMIC); in qcom_glink_alloc_intent()
676 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_alloc_intent()
679 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_alloc_intent()
681 intent->id = ret; in qcom_glink_alloc_intent()
682 intent->size = size; in qcom_glink_alloc_intent()
683 intent->reuse = reuseable; in qcom_glink_alloc_intent()
688 kfree(intent->data); in qcom_glink_alloc_intent()
699 struct glink_channel *channel; in qcom_glink_handle_rx_done() local
702 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_handle_rx_done()
703 channel = idr_find(&glink->rcids, cid); in qcom_glink_handle_rx_done()
704 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_handle_rx_done()
705 if (!channel) { in qcom_glink_handle_rx_done()
706 dev_err(glink->dev, "invalid channel id received\n"); in qcom_glink_handle_rx_done()
710 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_handle_rx_done()
711 intent = idr_find(&channel->riids, iid); in qcom_glink_handle_rx_done()
714 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_handle_rx_done()
715 dev_err(glink->dev, "invalid intent id received\n"); in qcom_glink_handle_rx_done()
719 intent->in_use = false; in qcom_glink_handle_rx_done()
722 idr_remove(&channel->riids, intent->id); in qcom_glink_handle_rx_done()
725 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_handle_rx_done()
729 * qcom_glink_handle_intent_req() - Receive a request for rx_intent
732 * @cid: Remote channel ID
735 * The function searches for the local channel to which the request for
742 struct glink_channel *channel; in qcom_glink_handle_intent_req() local
745 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_handle_intent_req()
746 channel = idr_find(&glink->rcids, cid); in qcom_glink_handle_intent_req()
747 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_handle_intent_req()
749 if (!channel) { in qcom_glink_handle_intent_req()
750 pr_err("%s channel not found for cid %d\n", __func__, cid); in qcom_glink_handle_intent_req()
754 intent = qcom_glink_alloc_intent(glink, channel, size, false); in qcom_glink_handle_intent_req()
756 qcom_glink_advertise_intent(glink, channel, intent); in qcom_glink_handle_intent_req()
758 qcom_glink_send_intent_req_ack(glink, channel, !!intent); in qcom_glink_handle_intent_req()
768 dev_dbg(glink->dev, "Insufficient data in rx fifo"); in qcom_glink_rx_defer()
769 return -ENXIO; in qcom_glink_rx_defer()
774 return -ENOMEM; in qcom_glink_rx_defer()
776 INIT_LIST_HEAD(&dcmd->node); in qcom_glink_rx_defer()
778 qcom_glink_rx_peak(glink, &dcmd->msg, 0, sizeof(dcmd->msg) + extra); in qcom_glink_rx_defer()
780 spin_lock(&glink->rx_lock); in qcom_glink_rx_defer()
781 list_add_tail(&dcmd->node, &glink->rx_queue); in qcom_glink_rx_defer()
782 spin_unlock(&glink->rx_lock); in qcom_glink_rx_defer()
784 schedule_work(&glink->rx_work); in qcom_glink_rx_defer()
785 qcom_glink_rx_advance(glink, sizeof(dcmd->msg) + extra); in qcom_glink_rx_defer()
793 struct glink_channel *channel; in qcom_glink_rx_data() local
807 dev_dbg(glink->dev, "Not enough data in fifo\n"); in qcom_glink_rx_data()
808 return -EAGAIN; in qcom_glink_rx_data()
816 dev_dbg(glink->dev, "Payload not yet in fifo\n"); in qcom_glink_rx_data()
817 return -EAGAIN; in qcom_glink_rx_data()
821 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_data()
822 channel = idr_find(&glink->rcids, rcid); in qcom_glink_rx_data()
823 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_data()
824 if (!channel) { in qcom_glink_rx_data()
825 dev_dbg(glink->dev, "Data on non-existing channel\n"); in qcom_glink_rx_data()
831 if (glink->intentless) { in qcom_glink_rx_data()
833 if (!channel->buf) { in qcom_glink_rx_data()
836 return -ENOMEM; in qcom_glink_rx_data()
838 intent->data = kmalloc(chunk_size + left_size, in qcom_glink_rx_data()
840 if (!intent->data) { in qcom_glink_rx_data()
842 return -ENOMEM; in qcom_glink_rx_data()
845 intent->id = 0xbabababa; in qcom_glink_rx_data()
846 intent->size = chunk_size + left_size; in qcom_glink_rx_data()
847 intent->offset = 0; in qcom_glink_rx_data()
849 channel->buf = intent; in qcom_glink_rx_data()
851 intent = channel->buf; in qcom_glink_rx_data()
856 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_rx_data()
857 intent = idr_find(&channel->liids, liid); in qcom_glink_rx_data()
858 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_rx_data()
861 dev_err(glink->dev, in qcom_glink_rx_data()
862 "no intent found for channel %s intent %d", in qcom_glink_rx_data()
863 channel->name, liid); in qcom_glink_rx_data()
864 ret = -ENOENT; in qcom_glink_rx_data()
869 if (intent->size - intent->offset < chunk_size) { in qcom_glink_rx_data()
870 dev_err(glink->dev, "Insufficient space in intent\n"); in qcom_glink_rx_data()
876 qcom_glink_rx_peak(glink, intent->data + intent->offset, in qcom_glink_rx_data()
878 intent->offset += chunk_size; in qcom_glink_rx_data()
882 spin_lock(&channel->recv_lock); in qcom_glink_rx_data()
883 if (channel->ept.cb) { in qcom_glink_rx_data()
884 channel->ept.cb(channel->ept.rpdev, in qcom_glink_rx_data()
885 intent->data, in qcom_glink_rx_data()
886 intent->offset, in qcom_glink_rx_data()
887 channel->ept.priv, in qcom_glink_rx_data()
890 spin_unlock(&channel->recv_lock); in qcom_glink_rx_data()
892 intent->offset = 0; in qcom_glink_rx_data()
893 channel->buf = NULL; in qcom_glink_rx_data()
895 qcom_glink_rx_done(glink, channel, intent); in qcom_glink_rx_data()
910 struct glink_channel *channel; in qcom_glink_handle_intent() local
927 dev_dbg(glink->dev, "Not enough data in fifo\n"); in qcom_glink_handle_intent()
931 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_handle_intent()
932 channel = idr_find(&glink->rcids, cid); in qcom_glink_handle_intent()
933 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_handle_intent()
934 if (!channel) { in qcom_glink_handle_intent()
935 dev_err(glink->dev, "intents for non-existing channel\n"); in qcom_glink_handle_intent()
951 intent->id = le32_to_cpu(msg->intents[i].iid); in qcom_glink_handle_intent()
952 intent->size = le32_to_cpu(msg->intents[i].size); in qcom_glink_handle_intent()
954 spin_lock_irqsave(&channel->intent_lock, flags); in qcom_glink_handle_intent()
955 ret = idr_alloc(&channel->riids, intent, in qcom_glink_handle_intent()
956 intent->id, intent->id + 1, GFP_ATOMIC); in qcom_glink_handle_intent()
957 spin_unlock_irqrestore(&channel->intent_lock, flags); in qcom_glink_handle_intent()
960 dev_err(glink->dev, "failed to store remote intent\n"); in qcom_glink_handle_intent()
969 struct glink_channel *channel; in qcom_glink_rx_open_ack() local
971 spin_lock(&glink->idr_lock); in qcom_glink_rx_open_ack()
972 channel = idr_find(&glink->lcids, lcid); in qcom_glink_rx_open_ack()
973 spin_unlock(&glink->idr_lock); in qcom_glink_rx_open_ack()
974 if (!channel) { in qcom_glink_rx_open_ack()
975 dev_err(glink->dev, "Invalid open ack packet\n"); in qcom_glink_rx_open_ack()
976 return -EINVAL; in qcom_glink_rx_open_ack()
979 complete_all(&channel->open_ack); in qcom_glink_rx_open_ack()
984 static irqreturn_t qcom_glink_native_intr(int irq, void *data) in qcom_glink_native_intr() argument
986 struct qcom_glink *glink = data; in qcom_glink_native_intr()
1027 mbox_send_message(glink->mbox_chan, NULL); in qcom_glink_native_intr()
1028 mbox_client_txdone(glink->mbox_chan, 0); in qcom_glink_native_intr()
1046 dev_err(glink->dev, "unhandled rx cmd: %d\n", cmd); in qcom_glink_native_intr()
1047 ret = -EINVAL; in qcom_glink_native_intr()
1062 struct glink_channel *channel; in qcom_glink_create_local() local
1066 channel = qcom_glink_alloc_channel(glink, name); in qcom_glink_create_local()
1067 if (IS_ERR(channel)) in qcom_glink_create_local()
1068 return ERR_CAST(channel); in qcom_glink_create_local()
1070 ret = qcom_glink_send_open_req(glink, channel); in qcom_glink_create_local()
1074 ret = wait_for_completion_timeout(&channel->open_ack, 5 * HZ); in qcom_glink_create_local()
1078 ret = wait_for_completion_timeout(&channel->open_req, 5 * HZ); in qcom_glink_create_local()
1082 qcom_glink_send_open_ack(glink, channel); in qcom_glink_create_local()
1084 return channel; in qcom_glink_create_local()
1087 /* qcom_glink_send_open_req() did register the channel in lcids*/ in qcom_glink_create_local()
1088 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_create_local()
1089 idr_remove(&glink->lcids, channel->lcid); in qcom_glink_create_local()
1090 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_create_local()
1094 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_create_local()
1096 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_create_local()
1098 return ERR_PTR(-ETIMEDOUT); in qcom_glink_create_local()
1103 struct glink_channel *channel) in qcom_glink_create_remote() argument
1107 qcom_glink_send_open_ack(glink, channel); in qcom_glink_create_remote()
1109 ret = qcom_glink_send_open_req(glink, channel); in qcom_glink_create_remote()
1113 ret = wait_for_completion_timeout(&channel->open_ack, 5 * HZ); in qcom_glink_create_remote()
1115 ret = -ETIMEDOUT; in qcom_glink_create_remote()
1123 * Send a close request to "undo" our open-ack. The close-ack will in qcom_glink_create_remote()
1128 qcom_glink_send_close_req(glink, channel); in qcom_glink_create_remote()
1139 struct glink_channel *parent = to_glink_channel(rpdev->ept); in qcom_glink_create_ept()
1140 struct glink_channel *channel; in qcom_glink_create_ept() local
1141 struct qcom_glink *glink = parent->glink; in qcom_glink_create_ept()
1148 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_create_ept()
1149 idr_for_each_entry(&glink->rcids, channel, cid) { in qcom_glink_create_ept()
1150 if (!strcmp(channel->name, name)) in qcom_glink_create_ept()
1153 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_create_ept()
1155 if (!channel) { in qcom_glink_create_ept()
1156 channel = qcom_glink_create_local(glink, name); in qcom_glink_create_ept()
1157 if (IS_ERR(channel)) in qcom_glink_create_ept()
1160 ret = qcom_glink_create_remote(glink, channel); in qcom_glink_create_ept()
1165 ept = &channel->ept; in qcom_glink_create_ept()
1166 ept->rpdev = rpdev; in qcom_glink_create_ept()
1167 ept->cb = cb; in qcom_glink_create_ept()
1168 ept->priv = priv; in qcom_glink_create_ept()
1169 ept->ops = &glink_endpoint_ops; in qcom_glink_create_ept()
1176 struct glink_channel *channel = to_glink_channel(rpdev->ept); in qcom_glink_announce_create() local
1177 struct device_node *np = rpdev->dev.of_node; in qcom_glink_announce_create()
1178 struct qcom_glink *glink = channel->glink; in qcom_glink_announce_create()
1187 if (glink->intentless || !completion_done(&channel->open_ack)) in qcom_glink_announce_create()
1192 val = prop->value; in qcom_glink_announce_create()
1193 num_groups = prop->length / sizeof(u32) / 2; in qcom_glink_announce_create()
1196 /* Channel is now open, advertise base set of intents */ in qcom_glink_announce_create()
1197 while (num_groups--) { in qcom_glink_announce_create()
1200 while (num_intents--) { in qcom_glink_announce_create()
1201 intent = qcom_glink_alloc_intent(glink, channel, size, in qcom_glink_announce_create()
1206 qcom_glink_advertise_intent(glink, channel, intent); in qcom_glink_announce_create()
1214 struct glink_channel *channel = to_glink_channel(ept); in qcom_glink_destroy_ept() local
1215 struct qcom_glink *glink = channel->glink; in qcom_glink_destroy_ept()
1218 spin_lock_irqsave(&channel->recv_lock, flags); in qcom_glink_destroy_ept()
1219 channel->ept.cb = NULL; in qcom_glink_destroy_ept()
1220 spin_unlock_irqrestore(&channel->recv_lock, flags); in qcom_glink_destroy_ept()
1222 /* Decouple the potential rpdev from the channel */ in qcom_glink_destroy_ept()
1223 channel->rpdev = NULL; in qcom_glink_destroy_ept()
1225 qcom_glink_send_close_req(glink, channel); in qcom_glink_destroy_ept()
1229 struct glink_channel *channel, in qcom_glink_request_intent() argument
1240 mutex_lock(&channel->intent_req_lock); in qcom_glink_request_intent()
1242 reinit_completion(&channel->intent_req_comp); in qcom_glink_request_intent()
1245 cmd.cid = channel->lcid; in qcom_glink_request_intent()
1252 ret = wait_for_completion_timeout(&channel->intent_req_comp, 10 * HZ); in qcom_glink_request_intent()
1254 dev_err(glink->dev, "intent request timed out\n"); in qcom_glink_request_intent()
1255 ret = -ETIMEDOUT; in qcom_glink_request_intent()
1257 ret = channel->intent_req_result ? 0 : -ECANCELED; in qcom_glink_request_intent()
1261 mutex_unlock(&channel->intent_req_lock); in qcom_glink_request_intent()
1265 static int __qcom_glink_send(struct glink_channel *channel, in __qcom_glink_send() argument
1266 void *data, int len, bool wait) in __qcom_glink_send() argument
1268 struct qcom_glink *glink = channel->glink; in __qcom_glink_send()
1280 if (!glink->intentless) { in __qcom_glink_send()
1282 spin_lock_irqsave(&channel->intent_lock, flags); in __qcom_glink_send()
1283 idr_for_each_entry(&channel->riids, tmp, iid) { in __qcom_glink_send()
1284 if (tmp->size >= len && !tmp->in_use) { in __qcom_glink_send()
1287 else if (intent->size > tmp->size) in __qcom_glink_send()
1289 if (intent->size == len) in __qcom_glink_send()
1294 intent->in_use = true; in __qcom_glink_send()
1295 spin_unlock_irqrestore(&channel->intent_lock, flags); in __qcom_glink_send()
1302 return -EBUSY; in __qcom_glink_send()
1304 ret = qcom_glink_request_intent(glink, channel, len); in __qcom_glink_send()
1309 iid = intent->id; in __qcom_glink_send()
1313 req.msg.param1 = cpu_to_le16(channel->lcid); in __qcom_glink_send()
1318 ret = qcom_glink_tx(glink, &req, sizeof(req), data, len, wait); in __qcom_glink_send()
1322 intent->in_use = false; in __qcom_glink_send()
1327 static int qcom_glink_send(struct rpmsg_endpoint *ept, void *data, int len) in qcom_glink_send() argument
1329 struct glink_channel *channel = to_glink_channel(ept); in qcom_glink_send() local
1331 return __qcom_glink_send(channel, data, len, true); in qcom_glink_send()
1334 static int qcom_glink_trysend(struct rpmsg_endpoint *ept, void *data, int len) in qcom_glink_trysend() argument
1336 struct glink_channel *channel = to_glink_channel(ept); in qcom_glink_trysend() local
1338 return __qcom_glink_send(channel, data, len, false); in qcom_glink_trysend()
1342 * Finds the device_node for the glink child interested in this channel.
1345 const char *channel) in qcom_glink_match_channel() argument
1353 key = "qcom,glink-channels"; in qcom_glink_match_channel()
1358 if (strcmp(name, channel) == 0) in qcom_glink_match_channel()
1379 struct glink_channel *channel = to_glink_channel(rpdev->ept); in qcom_glink_rpdev_release() local
1381 channel->rpdev = NULL; in qcom_glink_rpdev_release()
1382 kfree(rpdev->driver_override); in qcom_glink_rpdev_release()
1389 struct glink_channel *channel; in qcom_glink_rx_open() local
1397 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_open()
1398 idr_for_each_entry(&glink->lcids, channel, lcid) { in qcom_glink_rx_open()
1399 if (!strcmp(channel->name, name)) in qcom_glink_rx_open()
1402 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_open()
1404 if (!channel) { in qcom_glink_rx_open()
1405 channel = qcom_glink_alloc_channel(glink, name); in qcom_glink_rx_open()
1406 if (IS_ERR(channel)) in qcom_glink_rx_open()
1407 return PTR_ERR(channel); in qcom_glink_rx_open()
1413 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_open()
1414 ret = idr_alloc(&glink->rcids, channel, rcid, rcid + 1, GFP_ATOMIC); in qcom_glink_rx_open()
1416 dev_err(glink->dev, "Unable to insert channel into rcid list\n"); in qcom_glink_rx_open()
1417 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_open()
1420 channel->rcid = ret; in qcom_glink_rx_open()
1421 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_open()
1423 complete_all(&channel->open_req); in qcom_glink_rx_open()
1428 ret = -ENOMEM; in qcom_glink_rx_open()
1432 rpdev->ept = &channel->ept; in qcom_glink_rx_open()
1433 strncpy(rpdev->id.name, name, RPMSG_NAME_SIZE); in qcom_glink_rx_open()
1434 rpdev->src = RPMSG_ADDR_ANY; in qcom_glink_rx_open()
1435 rpdev->dst = RPMSG_ADDR_ANY; in qcom_glink_rx_open()
1436 rpdev->ops = &glink_device_ops; in qcom_glink_rx_open()
1438 node = qcom_glink_match_channel(glink->dev->of_node, name); in qcom_glink_rx_open()
1439 rpdev->dev.of_node = node; in qcom_glink_rx_open()
1440 rpdev->dev.parent = glink->dev; in qcom_glink_rx_open()
1441 rpdev->dev.release = qcom_glink_rpdev_release; in qcom_glink_rx_open()
1447 channel->rpdev = rpdev; in qcom_glink_rx_open()
1453 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_open()
1454 idr_remove(&glink->rcids, channel->rcid); in qcom_glink_rx_open()
1455 channel->rcid = 0; in qcom_glink_rx_open()
1456 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_open()
1460 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_rx_open()
1468 struct glink_channel *channel; in qcom_glink_rx_close() local
1471 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_close()
1472 channel = idr_find(&glink->rcids, rcid); in qcom_glink_rx_close()
1473 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_close()
1474 if (WARN(!channel, "close request on unknown channel\n")) in qcom_glink_rx_close()
1478 cancel_work_sync(&channel->intent_work); in qcom_glink_rx_close()
1480 if (channel->rpdev) { in qcom_glink_rx_close()
1481 strscpy_pad(chinfo.name, channel->name, sizeof(chinfo.name)); in qcom_glink_rx_close()
1485 rpmsg_unregister_device(glink->dev, &chinfo); in qcom_glink_rx_close()
1488 qcom_glink_send_close_ack(glink, channel->rcid); in qcom_glink_rx_close()
1490 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_close()
1491 idr_remove(&glink->rcids, channel->rcid); in qcom_glink_rx_close()
1492 channel->rcid = 0; in qcom_glink_rx_close()
1493 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_close()
1495 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_rx_close()
1500 struct glink_channel *channel; in qcom_glink_rx_close_ack() local
1503 spin_lock_irqsave(&glink->idr_lock, flags); in qcom_glink_rx_close_ack()
1504 channel = idr_find(&glink->lcids, lcid); in qcom_glink_rx_close_ack()
1505 if (WARN(!channel, "close ack on unknown channel\n")) { in qcom_glink_rx_close_ack()
1506 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_close_ack()
1510 idr_remove(&glink->lcids, channel->lcid); in qcom_glink_rx_close_ack()
1511 channel->lcid = 0; in qcom_glink_rx_close_ack()
1512 spin_unlock_irqrestore(&glink->idr_lock, flags); in qcom_glink_rx_close_ack()
1514 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_rx_close_ack()
1529 spin_lock_irqsave(&glink->rx_lock, flags); in qcom_glink_work()
1530 if (list_empty(&glink->rx_queue)) { in qcom_glink_work()
1531 spin_unlock_irqrestore(&glink->rx_lock, flags); in qcom_glink_work()
1534 dcmd = list_first_entry(&glink->rx_queue, in qcom_glink_work()
1536 list_del(&dcmd->node); in qcom_glink_work()
1537 spin_unlock_irqrestore(&glink->rx_lock, flags); in qcom_glink_work()
1539 msg = &dcmd->msg; in qcom_glink_work()
1540 cmd = le16_to_cpu(msg->cmd); in qcom_glink_work()
1541 param1 = le16_to_cpu(msg->param1); in qcom_glink_work()
1542 param2 = le32_to_cpu(msg->param2); in qcom_glink_work()
1552 qcom_glink_rx_open(glink, param1, msg->data); in qcom_glink_work()
1578 cancel_work_sync(&glink->rx_work); in qcom_glink_cancel_rx_work()
1580 list_for_each_entry_safe(dcmd, tmp, &glink->rx_queue, node) in qcom_glink_cancel_rx_work()
1590 ret = of_property_read_string(dev->of_node, "label", &name); in rpmsg_name_show()
1592 name = dev->of_node->name; in rpmsg_name_show()
1607 struct glink_channel *channel = to_glink_channel(rpdev->ept); in qcom_glink_device_release() local
1610 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_device_release()
1611 kfree(rpdev->driver_override); in qcom_glink_device_release()
1618 struct glink_channel *channel; in qcom_glink_create_chrdev() local
1622 return -ENOMEM; in qcom_glink_create_chrdev()
1624 channel = qcom_glink_alloc_channel(glink, "rpmsg_chrdev"); in qcom_glink_create_chrdev()
1625 if (IS_ERR(channel)) { in qcom_glink_create_chrdev()
1627 return PTR_ERR(channel); in qcom_glink_create_chrdev()
1629 channel->rpdev = rpdev; in qcom_glink_create_chrdev()
1631 rpdev->ept = &channel->ept; in qcom_glink_create_chrdev()
1632 rpdev->ops = &glink_device_ops; in qcom_glink_create_chrdev()
1633 rpdev->dev.parent = glink->dev; in qcom_glink_create_chrdev()
1634 rpdev->dev.release = qcom_glink_device_release; in qcom_glink_create_chrdev()
1651 return ERR_PTR(-ENOMEM); in qcom_glink_native_probe()
1653 glink->dev = dev; in qcom_glink_native_probe()
1654 glink->tx_pipe = tx; in qcom_glink_native_probe()
1655 glink->rx_pipe = rx; in qcom_glink_native_probe()
1657 glink->features = features; in qcom_glink_native_probe()
1658 glink->intentless = intentless; in qcom_glink_native_probe()
1660 spin_lock_init(&glink->tx_lock); in qcom_glink_native_probe()
1661 spin_lock_init(&glink->rx_lock); in qcom_glink_native_probe()
1662 INIT_LIST_HEAD(&glink->rx_queue); in qcom_glink_native_probe()
1663 INIT_WORK(&glink->rx_work, qcom_glink_work); in qcom_glink_native_probe()
1665 spin_lock_init(&glink->idr_lock); in qcom_glink_native_probe()
1666 idr_init(&glink->lcids); in qcom_glink_native_probe()
1667 idr_init(&glink->rcids); in qcom_glink_native_probe()
1669 glink->dev->groups = qcom_glink_groups; in qcom_glink_native_probe()
1675 ret = of_property_read_string(dev->of_node, "label", &glink->name); in qcom_glink_native_probe()
1677 glink->name = dev->of_node->name; in qcom_glink_native_probe()
1679 glink->mbox_client.dev = dev; in qcom_glink_native_probe()
1680 glink->mbox_client.knows_txdone = true; in qcom_glink_native_probe()
1681 glink->mbox_chan = mbox_request_channel(&glink->mbox_client, 0); in qcom_glink_native_probe()
1682 if (IS_ERR(glink->mbox_chan)) { in qcom_glink_native_probe()
1683 if (PTR_ERR(glink->mbox_chan) != -EPROBE_DEFER) in qcom_glink_native_probe()
1684 dev_err(dev, "failed to acquire IPC channel\n"); in qcom_glink_native_probe()
1685 return ERR_CAST(glink->mbox_chan); in qcom_glink_native_probe()
1688 irq = of_irq_get(dev->of_node, 0); in qcom_glink_native_probe()
1692 "glink-native", glink); in qcom_glink_native_probe()
1698 glink->irq = irq; in qcom_glink_native_probe()
1706 dev_err(glink->dev, "failed to register chrdev\n"); in qcom_glink_native_probe()
1712 static int qcom_glink_remove_device(struct device *dev, void *data) in qcom_glink_remove_device() argument
1721 struct glink_channel *channel; in qcom_glink_native_remove() local
1725 disable_irq(glink->irq); in qcom_glink_native_remove()
1728 ret = device_for_each_child(glink->dev, NULL, qcom_glink_remove_device); in qcom_glink_native_remove()
1730 dev_warn(glink->dev, "Can't remove GLINK devices: %d\n", ret); in qcom_glink_native_remove()
1732 /* Release any defunct local channels, waiting for close-ack */ in qcom_glink_native_remove()
1733 idr_for_each_entry(&glink->lcids, channel, cid) in qcom_glink_native_remove()
1734 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_native_remove()
1736 /* Release any defunct local channels, waiting for close-req */ in qcom_glink_native_remove()
1737 idr_for_each_entry(&glink->rcids, channel, cid) in qcom_glink_native_remove()
1738 kref_put(&channel->refcount, qcom_glink_channel_release); in qcom_glink_native_remove()
1740 idr_destroy(&glink->lcids); in qcom_glink_native_remove()
1741 idr_destroy(&glink->rcids); in qcom_glink_native_remove()
1742 mbox_free_channel(glink->mbox_chan); in qcom_glink_native_remove()
1748 device_unregister(glink->dev); in qcom_glink_native_unregister()