.. | .. |
---|
15 | 15 | #include <linux/rpmsg.h> |
---|
16 | 16 | #include <linux/of.h> |
---|
17 | 17 | |
---|
18 | | -struct apr { |
---|
| 18 | +enum { |
---|
| 19 | + PR_TYPE_APR = 0, |
---|
| 20 | +}; |
---|
| 21 | + |
---|
| 22 | +struct packet_router { |
---|
19 | 23 | struct rpmsg_endpoint *ch; |
---|
20 | 24 | struct device *dev; |
---|
21 | 25 | spinlock_t svcs_lock; |
---|
22 | 26 | spinlock_t rx_lock; |
---|
23 | 27 | struct idr svcs_idr; |
---|
24 | 28 | int dest_domain_id; |
---|
| 29 | + int type; |
---|
25 | 30 | struct pdr_handle *pdr; |
---|
26 | 31 | struct workqueue_struct *rxwq; |
---|
27 | 32 | struct work_struct rx_work; |
---|
.. | .. |
---|
44 | 49 | */ |
---|
45 | 50 | int apr_send_pkt(struct apr_device *adev, struct apr_pkt *pkt) |
---|
46 | 51 | { |
---|
47 | | - struct apr *apr = dev_get_drvdata(adev->dev.parent); |
---|
| 52 | + struct packet_router *apr = dev_get_drvdata(adev->dev.parent); |
---|
48 | 53 | struct apr_hdr *hdr; |
---|
49 | 54 | unsigned long flags; |
---|
50 | 55 | int ret; |
---|
51 | 56 | |
---|
52 | | - spin_lock_irqsave(&adev->lock, flags); |
---|
| 57 | + spin_lock_irqsave(&adev->svc.lock, flags); |
---|
53 | 58 | |
---|
54 | 59 | hdr = &pkt->hdr; |
---|
55 | 60 | hdr->src_domain = APR_DOMAIN_APPS; |
---|
56 | | - hdr->src_svc = adev->svc_id; |
---|
| 61 | + hdr->src_svc = adev->svc.id; |
---|
57 | 62 | hdr->dest_domain = adev->domain_id; |
---|
58 | | - hdr->dest_svc = adev->svc_id; |
---|
| 63 | + hdr->dest_svc = adev->svc.id; |
---|
59 | 64 | |
---|
60 | 65 | ret = rpmsg_trysend(apr->ch, pkt, hdr->pkt_size); |
---|
61 | | - spin_unlock_irqrestore(&adev->lock, flags); |
---|
| 66 | + spin_unlock_irqrestore(&adev->svc.lock, flags); |
---|
62 | 67 | |
---|
63 | 68 | return ret ? ret : hdr->pkt_size; |
---|
64 | 69 | } |
---|
.. | .. |
---|
74 | 79 | static int apr_callback(struct rpmsg_device *rpdev, void *buf, |
---|
75 | 80 | int len, void *priv, u32 addr) |
---|
76 | 81 | { |
---|
77 | | - struct apr *apr = dev_get_drvdata(&rpdev->dev); |
---|
| 82 | + struct packet_router *apr = dev_get_drvdata(&rpdev->dev); |
---|
78 | 83 | struct apr_rx_buf *abuf; |
---|
79 | 84 | unsigned long flags; |
---|
80 | 85 | |
---|
.. | .. |
---|
100 | 105 | return 0; |
---|
101 | 106 | } |
---|
102 | 107 | |
---|
103 | | - |
---|
104 | | -static int apr_do_rx_callback(struct apr *apr, struct apr_rx_buf *abuf) |
---|
| 108 | +static int apr_do_rx_callback(struct packet_router *apr, struct apr_rx_buf *abuf) |
---|
105 | 109 | { |
---|
106 | 110 | uint16_t hdr_size, msg_type, ver, svc_id; |
---|
107 | | - struct apr_device *svc = NULL; |
---|
| 111 | + struct pkt_router_svc *svc; |
---|
| 112 | + struct apr_device *adev; |
---|
108 | 113 | struct apr_driver *adrv = NULL; |
---|
109 | 114 | struct apr_resp_pkt resp; |
---|
110 | 115 | struct apr_hdr *hdr; |
---|
.. | .. |
---|
145 | 150 | svc_id = hdr->dest_svc; |
---|
146 | 151 | spin_lock_irqsave(&apr->svcs_lock, flags); |
---|
147 | 152 | svc = idr_find(&apr->svcs_idr, svc_id); |
---|
148 | | - if (svc && svc->dev.driver) |
---|
149 | | - adrv = to_apr_driver(svc->dev.driver); |
---|
| 153 | + if (svc && svc->dev->driver) { |
---|
| 154 | + adev = svc_to_apr_device(svc); |
---|
| 155 | + adrv = to_apr_driver(adev->dev.driver); |
---|
| 156 | + } |
---|
150 | 157 | spin_unlock_irqrestore(&apr->svcs_lock, flags); |
---|
151 | 158 | |
---|
152 | | - if (!adrv) { |
---|
153 | | - dev_err(apr->dev, "APR: service is not registered\n"); |
---|
| 159 | + if (!adrv || !adev) { |
---|
| 160 | + dev_err(apr->dev, "APR: service is not registered (%d)\n", |
---|
| 161 | + svc_id); |
---|
154 | 162 | return -EINVAL; |
---|
155 | 163 | } |
---|
156 | 164 | |
---|
.. | .. |
---|
164 | 172 | if (resp.payload_size > 0) |
---|
165 | 173 | resp.payload = buf + hdr_size; |
---|
166 | 174 | |
---|
167 | | - adrv->callback(svc, &resp); |
---|
| 175 | + adrv->callback(adev, &resp); |
---|
168 | 176 | |
---|
169 | 177 | return 0; |
---|
170 | 178 | } |
---|
171 | 179 | |
---|
172 | 180 | static void apr_rxwq(struct work_struct *work) |
---|
173 | 181 | { |
---|
174 | | - struct apr *apr = container_of(work, struct apr, rx_work); |
---|
| 182 | + struct packet_router *apr = container_of(work, struct packet_router, rx_work); |
---|
175 | 183 | struct apr_rx_buf *abuf, *b; |
---|
176 | 184 | unsigned long flags; |
---|
177 | 185 | |
---|
178 | 186 | if (!list_empty(&apr->rx_list)) { |
---|
179 | 187 | list_for_each_entry_safe(abuf, b, &apr->rx_list, node) { |
---|
180 | | - apr_do_rx_callback(apr, abuf); |
---|
| 188 | + switch (apr->type) { |
---|
| 189 | + case PR_TYPE_APR: |
---|
| 190 | + apr_do_rx_callback(apr, abuf); |
---|
| 191 | + break; |
---|
| 192 | + default: |
---|
| 193 | + break; |
---|
| 194 | + } |
---|
181 | 195 | spin_lock_irqsave(&apr->rx_lock, flags); |
---|
182 | 196 | list_del(&abuf->node); |
---|
183 | 197 | spin_unlock_irqrestore(&apr->rx_lock, flags); |
---|
.. | .. |
---|
201 | 215 | |
---|
202 | 216 | while (id->domain_id != 0 || id->svc_id != 0) { |
---|
203 | 217 | if (id->domain_id == adev->domain_id && |
---|
204 | | - id->svc_id == adev->svc_id) |
---|
| 218 | + id->svc_id == adev->svc.id) |
---|
205 | 219 | return 1; |
---|
206 | 220 | id++; |
---|
207 | 221 | } |
---|
.. | .. |
---|
221 | 235 | { |
---|
222 | 236 | struct apr_device *adev = to_apr_device(dev); |
---|
223 | 237 | struct apr_driver *adrv; |
---|
224 | | - struct apr *apr = dev_get_drvdata(adev->dev.parent); |
---|
| 238 | + struct packet_router *apr = dev_get_drvdata(adev->dev.parent); |
---|
225 | 239 | |
---|
226 | 240 | if (dev->driver) { |
---|
227 | 241 | adrv = to_apr_driver(dev->driver); |
---|
228 | 242 | if (adrv->remove) |
---|
229 | 243 | adrv->remove(adev); |
---|
230 | 244 | spin_lock(&apr->svcs_lock); |
---|
231 | | - idr_remove(&apr->svcs_idr, adev->svc_id); |
---|
| 245 | + idr_remove(&apr->svcs_idr, adev->svc.id); |
---|
232 | 246 | spin_unlock(&apr->svcs_lock); |
---|
233 | 247 | } |
---|
234 | 248 | |
---|
.. | .. |
---|
257 | 271 | EXPORT_SYMBOL_GPL(aprbus); |
---|
258 | 272 | |
---|
259 | 273 | static int apr_add_device(struct device *dev, struct device_node *np, |
---|
260 | | - const struct apr_device_id *id) |
---|
| 274 | + u32 svc_id, u32 domain_id) |
---|
261 | 275 | { |
---|
262 | | - struct apr *apr = dev_get_drvdata(dev); |
---|
| 276 | + struct packet_router *apr = dev_get_drvdata(dev); |
---|
263 | 277 | struct apr_device *adev = NULL; |
---|
| 278 | + struct pkt_router_svc *svc; |
---|
264 | 279 | int ret; |
---|
265 | 280 | |
---|
266 | 281 | adev = kzalloc(sizeof(*adev), GFP_KERNEL); |
---|
267 | 282 | if (!adev) |
---|
268 | 283 | return -ENOMEM; |
---|
269 | 284 | |
---|
270 | | - spin_lock_init(&adev->lock); |
---|
| 285 | + adev->svc_id = svc_id; |
---|
| 286 | + svc = &adev->svc; |
---|
271 | 287 | |
---|
272 | | - adev->svc_id = id->svc_id; |
---|
273 | | - adev->domain_id = id->domain_id; |
---|
274 | | - adev->version = id->svc_version; |
---|
| 288 | + svc->id = svc_id; |
---|
| 289 | + svc->pr = apr; |
---|
| 290 | + svc->priv = adev; |
---|
| 291 | + svc->dev = dev; |
---|
| 292 | + spin_lock_init(&svc->lock); |
---|
| 293 | + |
---|
| 294 | + adev->domain_id = domain_id; |
---|
| 295 | + |
---|
275 | 296 | if (np) |
---|
276 | 297 | snprintf(adev->name, APR_NAME_SIZE, "%pOFn", np); |
---|
277 | | - else |
---|
278 | | - strscpy(adev->name, id->name, APR_NAME_SIZE); |
---|
279 | 298 | |
---|
280 | | - dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, |
---|
281 | | - id->domain_id, id->svc_id); |
---|
| 299 | + switch (apr->type) { |
---|
| 300 | + case PR_TYPE_APR: |
---|
| 301 | + dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, |
---|
| 302 | + domain_id, svc_id); |
---|
| 303 | + break; |
---|
| 304 | + default: |
---|
| 305 | + break; |
---|
| 306 | + } |
---|
282 | 307 | |
---|
283 | 308 | adev->dev.bus = &aprbus; |
---|
284 | 309 | adev->dev.parent = dev; |
---|
.. | .. |
---|
287 | 312 | adev->dev.driver = NULL; |
---|
288 | 313 | |
---|
289 | 314 | spin_lock(&apr->svcs_lock); |
---|
290 | | - idr_alloc(&apr->svcs_idr, adev, id->svc_id, |
---|
291 | | - id->svc_id + 1, GFP_ATOMIC); |
---|
| 315 | + ret = idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC); |
---|
292 | 316 | spin_unlock(&apr->svcs_lock); |
---|
| 317 | + if (ret < 0) { |
---|
| 318 | + dev_err(dev, "idr_alloc failed: %d\n", ret); |
---|
| 319 | + goto out; |
---|
| 320 | + } |
---|
293 | 321 | |
---|
294 | | - of_property_read_string_index(np, "qcom,protection-domain", |
---|
295 | | - 1, &adev->service_path); |
---|
| 322 | + /* Protection domain is optional, it does not exist on older platforms */ |
---|
| 323 | + ret = of_property_read_string_index(np, "qcom,protection-domain", |
---|
| 324 | + 1, &adev->service_path); |
---|
| 325 | + if (ret < 0 && ret != -EINVAL) { |
---|
| 326 | + dev_err(dev, "Failed to read second value of qcom,protection-domain\n"); |
---|
| 327 | + goto out; |
---|
| 328 | + } |
---|
296 | 329 | |
---|
297 | 330 | dev_info(dev, "Adding APR dev: %s\n", dev_name(&adev->dev)); |
---|
298 | 331 | |
---|
.. | .. |
---|
302 | 335 | put_device(&adev->dev); |
---|
303 | 336 | } |
---|
304 | 337 | |
---|
| 338 | +out: |
---|
305 | 339 | return ret; |
---|
306 | 340 | } |
---|
307 | 341 | |
---|
308 | 342 | static int of_apr_add_pd_lookups(struct device *dev) |
---|
309 | 343 | { |
---|
310 | 344 | const char *service_name, *service_path; |
---|
311 | | - struct apr *apr = dev_get_drvdata(dev); |
---|
| 345 | + struct packet_router *apr = dev_get_drvdata(dev); |
---|
312 | 346 | struct device_node *node; |
---|
313 | 347 | struct pdr_service *pds; |
---|
314 | 348 | int ret; |
---|
.. | .. |
---|
340 | 374 | |
---|
341 | 375 | static void of_register_apr_devices(struct device *dev, const char *svc_path) |
---|
342 | 376 | { |
---|
343 | | - struct apr *apr = dev_get_drvdata(dev); |
---|
| 377 | + struct packet_router *apr = dev_get_drvdata(dev); |
---|
344 | 378 | struct device_node *node; |
---|
345 | 379 | const char *service_path; |
---|
346 | 380 | int ret; |
---|
347 | 381 | |
---|
348 | 382 | for_each_child_of_node(dev->of_node, node) { |
---|
349 | | - struct apr_device_id id = { {0} }; |
---|
| 383 | + u32 svc_id; |
---|
| 384 | + u32 domain_id; |
---|
350 | 385 | |
---|
351 | 386 | /* |
---|
352 | 387 | * This function is called with svc_path NULL during |
---|
.. | .. |
---|
376 | 411 | continue; |
---|
377 | 412 | } |
---|
378 | 413 | |
---|
379 | | - if (of_property_read_u32(node, "reg", &id.svc_id)) |
---|
| 414 | + if (of_property_read_u32(node, "reg", &svc_id)) |
---|
380 | 415 | continue; |
---|
381 | 416 | |
---|
382 | | - id.domain_id = apr->dest_domain_id; |
---|
| 417 | + domain_id = apr->dest_domain_id; |
---|
383 | 418 | |
---|
384 | | - if (apr_add_device(dev, node, &id)) |
---|
385 | | - dev_err(dev, "Failed to add apr %d svc\n", id.svc_id); |
---|
| 419 | + if (apr_add_device(dev, node, svc_id, domain_id)) |
---|
| 420 | + dev_err(dev, "Failed to add apr %d svc\n", svc_id); |
---|
386 | 421 | } |
---|
387 | 422 | } |
---|
388 | 423 | |
---|
.. | .. |
---|
402 | 437 | |
---|
403 | 438 | static void apr_pd_status(int state, char *svc_path, void *priv) |
---|
404 | 439 | { |
---|
405 | | - struct apr *apr = (struct apr *)priv; |
---|
| 440 | + struct packet_router *apr = (struct packet_router *)priv; |
---|
406 | 441 | |
---|
407 | 442 | switch (state) { |
---|
408 | 443 | case SERVREG_SERVICE_STATE_UP: |
---|
.. | .. |
---|
417 | 452 | static int apr_probe(struct rpmsg_device *rpdev) |
---|
418 | 453 | { |
---|
419 | 454 | struct device *dev = &rpdev->dev; |
---|
420 | | - struct apr *apr; |
---|
| 455 | + struct packet_router *apr; |
---|
421 | 456 | int ret; |
---|
422 | 457 | |
---|
423 | 458 | apr = devm_kzalloc(dev, sizeof(*apr), GFP_KERNEL); |
---|
424 | 459 | if (!apr) |
---|
425 | 460 | return -ENOMEM; |
---|
426 | 461 | |
---|
427 | | - ret = of_property_read_u32(dev->of_node, "qcom,apr-domain", &apr->dest_domain_id); |
---|
| 462 | + ret = of_property_read_u32(dev->of_node, "qcom,domain", &apr->dest_domain_id); |
---|
| 463 | + if (ret) /* try deprecated apr-domain property */ |
---|
| 464 | + ret = of_property_read_u32(dev->of_node, "qcom,apr-domain", |
---|
| 465 | + &apr->dest_domain_id); |
---|
| 466 | + apr->type = PR_TYPE_APR; |
---|
428 | 467 | if (ret) { |
---|
429 | | - dev_err(dev, "APR Domain ID not specified in DT\n"); |
---|
| 468 | + dev_err(dev, "Domain ID not specified in DT\n"); |
---|
430 | 469 | return ret; |
---|
431 | 470 | } |
---|
432 | 471 | |
---|
.. | .. |
---|
469 | 508 | |
---|
470 | 509 | static void apr_remove(struct rpmsg_device *rpdev) |
---|
471 | 510 | { |
---|
472 | | - struct apr *apr = dev_get_drvdata(&rpdev->dev); |
---|
| 511 | + struct packet_router *apr = dev_get_drvdata(&rpdev->dev); |
---|
473 | 512 | |
---|
474 | 513 | pdr_handle_release(apr->pdr); |
---|
475 | 514 | device_for_each_child(&rpdev->dev, NULL, apr_remove_device); |
---|
.. | .. |
---|
506 | 545 | } |
---|
507 | 546 | EXPORT_SYMBOL_GPL(apr_driver_unregister); |
---|
508 | 547 | |
---|
509 | | -static const struct of_device_id apr_of_match[] = { |
---|
| 548 | +static const struct of_device_id pkt_router_of_match[] = { |
---|
510 | 549 | { .compatible = "qcom,apr"}, |
---|
511 | 550 | { .compatible = "qcom,apr-v2"}, |
---|
512 | 551 | {} |
---|
513 | 552 | }; |
---|
514 | | -MODULE_DEVICE_TABLE(of, apr_of_match); |
---|
| 553 | +MODULE_DEVICE_TABLE(of, pkt_router_of_match); |
---|
515 | 554 | |
---|
516 | | -static struct rpmsg_driver apr_driver = { |
---|
| 555 | +static struct rpmsg_driver packet_router_driver = { |
---|
517 | 556 | .probe = apr_probe, |
---|
518 | 557 | .remove = apr_remove, |
---|
519 | 558 | .callback = apr_callback, |
---|
520 | 559 | .drv = { |
---|
521 | 560 | .name = "qcom,apr", |
---|
522 | | - .of_match_table = apr_of_match, |
---|
| 561 | + .of_match_table = pkt_router_of_match, |
---|
523 | 562 | }, |
---|
524 | 563 | }; |
---|
525 | 564 | |
---|
.. | .. |
---|
529 | 568 | |
---|
530 | 569 | ret = bus_register(&aprbus); |
---|
531 | 570 | if (!ret) |
---|
532 | | - ret = register_rpmsg_driver(&apr_driver); |
---|
| 571 | + ret = register_rpmsg_driver(&packet_router_driver); |
---|
533 | 572 | else |
---|
534 | 573 | bus_unregister(&aprbus); |
---|
535 | 574 | |
---|
.. | .. |
---|
539 | 578 | static void __exit apr_exit(void) |
---|
540 | 579 | { |
---|
541 | 580 | bus_unregister(&aprbus); |
---|
542 | | - unregister_rpmsg_driver(&apr_driver); |
---|
| 581 | + unregister_rpmsg_driver(&packet_router_driver); |
---|
543 | 582 | } |
---|
544 | 583 | |
---|
545 | 584 | subsys_initcall(apr_init); |
---|