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

1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
15 #include <linux/rpmsg.h>
48 * apr_send_pkt() - Send a apr message from apr device
57 struct packet_router *apr = dev_get_drvdata(adev->dev.parent); in apr_send_pkt()
62 spin_lock_irqsave(&adev->svc.lock, flags); in apr_send_pkt()
64 hdr = &pkt->hdr; in apr_send_pkt()
65 hdr->src_domain = APR_DOMAIN_APPS; in apr_send_pkt()
66 hdr->src_svc = adev->svc.id; in apr_send_pkt()
67 hdr->dest_domain = adev->domain_id; in apr_send_pkt()
68 hdr->dest_svc = adev->svc.id; in apr_send_pkt()
70 ret = rpmsg_trysend(apr->ch, pkt, hdr->pkt_size); in apr_send_pkt()
71 spin_unlock_irqrestore(&adev->svc.lock, flags); in apr_send_pkt()
73 return ret ? ret : hdr->pkt_size; in apr_send_pkt()
79 struct packet_router *gpr = port->pr; in gpr_free_port()
82 spin_lock_irqsave(&gpr->svcs_lock, flags); in gpr_free_port()
83 idr_remove(&gpr->svcs_idr, port->id); in gpr_free_port()
84 spin_unlock_irqrestore(&gpr->svcs_lock, flags); in gpr_free_port()
93 struct packet_router *pr = dev_get_drvdata(gdev->dev.parent); in gpr_alloc_port()
100 return ERR_PTR(-ENOMEM); in gpr_alloc_port()
103 svc->callback = cb; in gpr_alloc_port()
104 svc->pr = pr; in gpr_alloc_port()
105 svc->priv = priv; in gpr_alloc_port()
106 svc->dev = dev; in gpr_alloc_port()
107 spin_lock_init(&svc->lock); in gpr_alloc_port()
109 spin_lock(&pr->svcs_lock); in gpr_alloc_port()
110 id = idr_alloc_cyclic(&pr->svcs_idr, svc, GPR_DYNAMIC_PORT_START, in gpr_alloc_port()
115 spin_unlock(&pr->svcs_lock); in gpr_alloc_port()
119 svc->id = id; in gpr_alloc_port()
120 spin_unlock(&pr->svcs_lock); in gpr_alloc_port()
128 struct packet_router *pr = svc->pr; in pkt_router_send_svc_pkt()
133 hdr = &pkt->hdr; in pkt_router_send_svc_pkt()
135 spin_lock_irqsave(&svc->lock, flags); in pkt_router_send_svc_pkt()
136 ret = rpmsg_trysend(pr->ch, pkt, hdr->pkt_size); in pkt_router_send_svc_pkt()
137 spin_unlock_irqrestore(&svc->lock, flags); in pkt_router_send_svc_pkt()
139 return ret ? ret : hdr->pkt_size; in pkt_router_send_svc_pkt()
144 return pkt_router_send_svc_pkt(&gdev->svc, pkt); in gpr_send_pkt()
164 struct packet_router *apr = dev_get_drvdata(&rpdev->dev); in apr_callback()
169 dev_err(apr->dev, "APR: Improper apr pkt received:%p %d\n", in apr_callback()
171 return -EINVAL; in apr_callback()
176 return -ENOMEM; in apr_callback()
178 abuf->len = len; in apr_callback()
179 memcpy(abuf->buf, buf, len); in apr_callback()
181 spin_lock_irqsave(&apr->rx_lock, flags); in apr_callback()
182 list_add_tail(&abuf->node, &apr->rx_list); in apr_callback()
183 spin_unlock_irqrestore(&apr->rx_lock, flags); in apr_callback()
185 queue_work(apr->rxwq, &apr->rx_work); in apr_callback()
199 void *buf = abuf->buf; in apr_do_rx_callback()
200 int len = abuf->len; in apr_do_rx_callback()
203 ver = APR_HDR_FIELD_VER(hdr->hdr_field); in apr_do_rx_callback()
205 return -EINVAL; in apr_do_rx_callback()
207 hdr_size = APR_HDR_FIELD_SIZE_BYTES(hdr->hdr_field); in apr_do_rx_callback()
209 dev_err(apr->dev, "APR: Wrong hdr size:%d\n", hdr_size); in apr_do_rx_callback()
210 return -EINVAL; in apr_do_rx_callback()
213 if (hdr->pkt_size < APR_HDR_SIZE || hdr->pkt_size != len) { in apr_do_rx_callback()
214 dev_err(apr->dev, "APR: Wrong packet size\n"); in apr_do_rx_callback()
215 return -EINVAL; in apr_do_rx_callback()
218 msg_type = APR_HDR_FIELD_MT(hdr->hdr_field); in apr_do_rx_callback()
220 dev_err(apr->dev, "APR: Wrong message type: %d\n", msg_type); in apr_do_rx_callback()
221 return -EINVAL; in apr_do_rx_callback()
224 if (hdr->src_domain >= APR_DOMAIN_MAX || in apr_do_rx_callback()
225 hdr->dest_domain >= APR_DOMAIN_MAX || in apr_do_rx_callback()
226 hdr->src_svc >= APR_SVC_MAX || in apr_do_rx_callback()
227 hdr->dest_svc >= APR_SVC_MAX) { in apr_do_rx_callback()
228 dev_err(apr->dev, "APR: Wrong APR header\n"); in apr_do_rx_callback()
229 return -EINVAL; in apr_do_rx_callback()
232 svc_id = hdr->dest_svc; in apr_do_rx_callback()
233 spin_lock_irqsave(&apr->svcs_lock, flags); in apr_do_rx_callback()
234 svc = idr_find(&apr->svcs_idr, svc_id); in apr_do_rx_callback()
235 if (svc && svc->dev->driver) { in apr_do_rx_callback()
237 adrv = to_apr_driver(adev->dev.driver); in apr_do_rx_callback()
239 spin_unlock_irqrestore(&apr->svcs_lock, flags); in apr_do_rx_callback()
242 dev_err(apr->dev, "APR: service is not registered (%d)\n", in apr_do_rx_callback()
244 return -EINVAL; in apr_do_rx_callback()
248 resp.payload_size = hdr->pkt_size - hdr_size; in apr_do_rx_callback()
257 adrv->callback(adev, &resp); in apr_do_rx_callback()
269 void *buf = abuf->buf; in gpr_do_rx_callback()
270 int len = abuf->len; in gpr_do_rx_callback()
273 ver = hdr->version; in gpr_do_rx_callback()
275 return -EINVAL; in gpr_do_rx_callback()
277 hdr_size = hdr->hdr_size; in gpr_do_rx_callback()
279 dev_err(gpr->dev, "GPR: Wrong hdr size:%d\n", hdr_size); in gpr_do_rx_callback()
280 return -EINVAL; in gpr_do_rx_callback()
283 if (hdr->pkt_size < GPR_PKT_HEADER_BYTE_SIZE || hdr->pkt_size != len) { in gpr_do_rx_callback()
284 dev_err(gpr->dev, "GPR: Wrong packet size\n"); in gpr_do_rx_callback()
285 return -EINVAL; in gpr_do_rx_callback()
289 resp.payload_size = hdr->pkt_size - (hdr_size * 4); in gpr_do_rx_callback()
299 spin_lock_irqsave(&gpr->svcs_lock, flags); in gpr_do_rx_callback()
300 svc = idr_find(&gpr->svcs_idr, hdr->dest_port); in gpr_do_rx_callback()
301 spin_unlock_irqrestore(&gpr->svcs_lock, flags); in gpr_do_rx_callback()
304 dev_err(gpr->dev, "GPR: Port(%x) is not registered\n", in gpr_do_rx_callback()
305 hdr->dest_port); in gpr_do_rx_callback()
306 return -EINVAL; in gpr_do_rx_callback()
309 if (svc->callback) in gpr_do_rx_callback()
310 svc->callback(&resp, svc->priv, 0); in gpr_do_rx_callback()
321 if (!list_empty(&apr->rx_list)) { in apr_rxwq()
322 list_for_each_entry_safe(abuf, b, &apr->rx_list, node) { in apr_rxwq()
323 switch (apr->type) { in apr_rxwq()
333 spin_lock_irqsave(&apr->rx_lock, flags); in apr_rxwq()
334 list_del(&abuf->node); in apr_rxwq()
335 spin_unlock_irqrestore(&apr->rx_lock, flags); in apr_rxwq()
345 const struct apr_device_id *id = adrv->id_table; in apr_device_match()
354 while (id->domain_id != 0 || id->svc_id != 0) { in apr_device_match()
355 if (id->domain_id == adev->domain_id && in apr_device_match()
356 id->svc_id == adev->svc.id) in apr_device_match()
367 struct apr_driver *adrv = to_apr_driver(dev->driver); in apr_device_probe()
370 ret = adrv->probe(adev); in apr_device_probe()
372 adev->svc.callback = adrv->gpr_callback; in apr_device_probe()
380 struct apr_driver *adrv = to_apr_driver(dev->driver); in apr_device_remove()
381 struct packet_router *apr = dev_get_drvdata(adev->dev.parent); in apr_device_remove()
383 if (adrv->remove) in apr_device_remove()
384 adrv->remove(adev); in apr_device_remove()
385 spin_lock(&apr->svcs_lock); in apr_device_remove()
386 idr_remove(&apr->svcs_idr, adev->svc.id); in apr_device_remove()
387 spin_unlock(&apr->svcs_lock); in apr_device_remove()
396 if (ret != -ENODEV) in apr_uevent()
399 return add_uevent_var(env, "MODALIAS=apr:%s", adev->name); in apr_uevent()
421 return -ENOMEM; in apr_add_device()
423 adev->svc_id = svc_id; in apr_add_device()
424 svc = &adev->svc; in apr_add_device()
426 svc->id = svc_id; in apr_add_device()
427 svc->pr = apr; in apr_add_device()
428 svc->priv = adev; in apr_add_device()
429 svc->dev = dev; in apr_add_device()
430 spin_lock_init(&svc->lock); in apr_add_device()
432 adev->domain_id = domain_id; in apr_add_device()
435 snprintf(adev->name, APR_NAME_SIZE, "%pOFn", np); in apr_add_device()
437 switch (apr->type) { in apr_add_device()
439 dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, in apr_add_device()
443 dev_set_name(&adev->dev, "gprsvc:%s:%x:%x", adev->name, in apr_add_device()
450 adev->dev.bus = &aprbus; in apr_add_device()
451 adev->dev.parent = dev; in apr_add_device()
452 adev->dev.of_node = np; in apr_add_device()
453 adev->dev.release = apr_dev_release; in apr_add_device()
454 adev->dev.driver = NULL; in apr_add_device()
456 spin_lock(&apr->svcs_lock); in apr_add_device()
457 ret = idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC); in apr_add_device()
458 spin_unlock(&apr->svcs_lock); in apr_add_device()
461 goto out; in apr_add_device()
465 ret = of_property_read_string_index(np, "qcom,protection-domain", in apr_add_device()
466 1, &adev->service_path); in apr_add_device()
467 if (ret < 0 && ret != -EINVAL) { in apr_add_device()
468 dev_err(dev, "Failed to read second value of qcom,protection-domain\n"); in apr_add_device()
469 goto out; in apr_add_device()
472 dev_info(dev, "Adding APR/GPR dev: %s\n", dev_name(&adev->dev)); in apr_add_device()
474 ret = device_register(&adev->dev); in apr_add_device()
477 put_device(&adev->dev); in apr_add_device()
480 out: in apr_add_device()
491 for_each_child_of_node_scoped(dev->of_node, node) { in of_apr_add_pd_lookups()
492 ret = of_property_read_string_index(node, "qcom,protection-domain", in of_apr_add_pd_lookups()
497 ret = of_property_read_string_index(node, "qcom,protection-domain", in of_apr_add_pd_lookups()
504 pds = pdr_add_lookup(apr->pdr, service_name, service_path); in of_apr_add_pd_lookups()
505 if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) { in of_apr_add_pd_lookups()
521 for_each_child_of_node(dev->of_node, node) { in of_register_apr_devices()
528 * without a qcom,protection-domain specified. in of_register_apr_devices()
534 * qcom,protection-domain. in of_register_apr_devices()
537 ret = of_property_read_string_index(node, "qcom,protection-domain", in of_register_apr_devices()
556 domain_id = apr->dest_domain_id; in of_register_apr_devices()
567 if (svc_path && adev->service_path) { in apr_remove_device()
568 if (!strcmp(adev->service_path, (char *)svc_path)) in apr_remove_device()
569 device_unregister(&adev->dev); in apr_remove_device()
571 device_unregister(&adev->dev); in apr_remove_device()
583 of_register_apr_devices(apr->dev, svc_path); in apr_pd_status()
586 device_for_each_child(apr->dev, svc_path, apr_remove_device); in apr_pd_status()
593 struct device *dev = &rpdev->dev; in apr_probe()
599 return -ENOMEM; in apr_probe()
601 ret = of_property_read_u32(dev->of_node, "qcom,domain", &apr->dest_domain_id); in apr_probe()
603 if (of_device_is_compatible(dev->of_node, "qcom,gpr")) { in apr_probe()
604 apr->type = PR_TYPE_GPR; in apr_probe()
606 if (ret) /* try deprecated apr-domain property */ in apr_probe()
607 ret = of_property_read_u32(dev->of_node, "qcom,apr-domain", in apr_probe()
608 &apr->dest_domain_id); in apr_probe()
609 apr->type = PR_TYPE_APR; in apr_probe()
618 apr->ch = rpdev->ept; in apr_probe()
619 apr->dev = dev; in apr_probe()
620 apr->rxwq = create_singlethread_workqueue("qcom_apr_rx"); in apr_probe()
621 if (!apr->rxwq) { in apr_probe()
622 dev_err(apr->dev, "Failed to start Rx WQ\n"); in apr_probe()
623 return -ENOMEM; in apr_probe()
625 INIT_WORK(&apr->rx_work, apr_rxwq); in apr_probe()
627 apr->pdr = pdr_handle_alloc(apr_pd_status, apr); in apr_probe()
628 if (IS_ERR(apr->pdr)) { in apr_probe()
630 ret = PTR_ERR(apr->pdr); in apr_probe()
634 INIT_LIST_HEAD(&apr->rx_list); in apr_probe()
635 spin_lock_init(&apr->rx_lock); in apr_probe()
636 spin_lock_init(&apr->svcs_lock); in apr_probe()
637 idr_init(&apr->svcs_idr); in apr_probe()
648 pdr_handle_release(apr->pdr); in apr_probe()
650 destroy_workqueue(apr->rxwq); in apr_probe()
656 struct packet_router *apr = dev_get_drvdata(&rpdev->dev); in apr_remove()
658 pdr_handle_release(apr->pdr); in apr_remove()
659 device_for_each_child(&rpdev->dev, NULL, apr_remove_device); in apr_remove()
660 destroy_workqueue(apr->rxwq); in apr_remove()
664 * __apr_driver_register() - Client driver registration with aprbus
666 * @drv:Client driver to be associated with client-device.
670 * It is called from the driver's module-init function.
674 drv->driver.bus = &aprbus; in __apr_driver_register()
675 drv->driver.owner = owner; in __apr_driver_register()
677 return driver_register(&drv->driver); in __apr_driver_register()
682 * apr_driver_unregister() - Undo effect of apr_driver_register
688 driver_unregister(&drv->driver); in apr_driver_unregister()
694 { .compatible = "qcom,apr-v2"},