Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc: qcom: apr: make code more reuseable

APR and other packet routers like GPR are pretty much same and
interact with other drivers in similar way.

Ex: GPR ports can be considered as APR services, only difference
is they are allocated dynamically.

Other difference is packet layout, which should not matter
with the apis abstracted. Apart from this the rest of the
functionality is pretty much identical across APR and GPR.

Make the apr code more reusable by abstracting it service level,
rather than device level so that we do not need to write
new drivers for other new packet routers like GPR.

This patch is in preparation to add GPR support to this driver.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Link: https://lore.kernel.org/r/20210927135559.738-4-srinivas.kandagatla@linaro.org

authored by

Srinivas Kandagatla and committed by
Bjorn Andersson
99139b80 1ff63d54

+90 -51
+79 -50
drivers/soc/qcom/apr.c
··· 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; ··· 49 44 */ 50 45 int apr_send_pkt(struct apr_device *adev, struct apr_pkt *pkt) 51 46 { 52 - struct apr *apr = dev_get_drvdata(adev->dev.parent); 47 + struct packet_router *apr = dev_get_drvdata(adev->dev.parent); 53 48 struct apr_hdr *hdr; 54 49 unsigned long flags; 55 50 int ret; 56 51 57 - spin_lock_irqsave(&adev->lock, flags); 52 + spin_lock_irqsave(&adev->svc.lock, flags); 58 53 59 54 hdr = &pkt->hdr; 60 55 hdr->src_domain = APR_DOMAIN_APPS; 61 - hdr->src_svc = adev->svc_id; 56 + hdr->src_svc = adev->svc.id; 62 57 hdr->dest_domain = adev->domain_id; 63 - hdr->dest_svc = adev->svc_id; 58 + hdr->dest_svc = adev->svc.id; 64 59 65 60 ret = rpmsg_trysend(apr->ch, pkt, hdr->pkt_size); 66 - spin_unlock_irqrestore(&adev->lock, flags); 61 + spin_unlock_irqrestore(&adev->svc.lock, flags); 67 62 68 63 return ret ? ret : hdr->pkt_size; 69 64 } ··· 79 74 static int apr_callback(struct rpmsg_device *rpdev, void *buf, 80 75 int len, void *priv, u32 addr) 81 76 { 82 - struct apr *apr = dev_get_drvdata(&rpdev->dev); 77 + struct packet_router *apr = dev_get_drvdata(&rpdev->dev); 83 78 struct apr_rx_buf *abuf; 84 79 unsigned long flags; 85 80 ··· 105 100 return 0; 106 101 } 107 102 108 - 109 - static int apr_do_rx_callback(struct apr *apr, struct apr_rx_buf *abuf) 103 + static int apr_do_rx_callback(struct packet_router *apr, struct apr_rx_buf *abuf) 110 104 { 111 105 uint16_t hdr_size, msg_type, ver, svc_id; 112 - struct apr_device *svc = NULL; 106 + struct pkt_router_svc *svc; 107 + struct apr_device *adev; 113 108 struct apr_driver *adrv = NULL; 114 109 struct apr_resp_pkt resp; 115 110 struct apr_hdr *hdr; ··· 150 145 svc_id = hdr->dest_svc; 151 146 spin_lock_irqsave(&apr->svcs_lock, flags); 152 147 svc = idr_find(&apr->svcs_idr, svc_id); 153 - if (svc && svc->dev.driver) 154 - adrv = to_apr_driver(svc->dev.driver); 148 + if (svc && svc->dev->driver) { 149 + adev = svc_to_apr_device(svc); 150 + adrv = to_apr_driver(adev->dev.driver); 151 + } 155 152 spin_unlock_irqrestore(&apr->svcs_lock, flags); 156 153 157 - if (!adrv) { 158 - dev_err(apr->dev, "APR: service is not registered\n"); 154 + if (!adrv || !adev) { 155 + dev_err(apr->dev, "APR: service is not registered (%d)\n", 156 + svc_id); 159 157 return -EINVAL; 160 158 } 161 159 ··· 172 164 if (resp.payload_size > 0) 173 165 resp.payload = buf + hdr_size; 174 166 175 - adrv->callback(svc, &resp); 167 + adrv->callback(adev, &resp); 176 168 177 169 return 0; 178 170 } 179 171 180 172 static void apr_rxwq(struct work_struct *work) 181 173 { 182 - struct apr *apr = container_of(work, struct apr, rx_work); 174 + struct packet_router *apr = container_of(work, struct packet_router, rx_work); 183 175 struct apr_rx_buf *abuf, *b; 184 176 unsigned long flags; 185 177 186 178 if (!list_empty(&apr->rx_list)) { 187 179 list_for_each_entry_safe(abuf, b, &apr->rx_list, node) { 188 - apr_do_rx_callback(apr, abuf); 180 + switch (apr->type) { 181 + case PR_TYPE_APR: 182 + apr_do_rx_callback(apr, abuf); 183 + break; 184 + default: 185 + break; 186 + } 189 187 spin_lock_irqsave(&apr->rx_lock, flags); 190 188 list_del(&abuf->node); 191 189 spin_unlock_irqrestore(&apr->rx_lock, flags); ··· 215 201 216 202 while (id->domain_id != 0 || id->svc_id != 0) { 217 203 if (id->domain_id == adev->domain_id && 218 - id->svc_id == adev->svc_id) 204 + id->svc_id == adev->svc.id) 219 205 return 1; 220 206 id++; 221 207 } ··· 235 221 { 236 222 struct apr_device *adev = to_apr_device(dev); 237 223 struct apr_driver *adrv; 238 - struct apr *apr = dev_get_drvdata(adev->dev.parent); 224 + struct packet_router *apr = dev_get_drvdata(adev->dev.parent); 239 225 240 226 if (dev->driver) { 241 227 adrv = to_apr_driver(dev->driver); 242 228 if (adrv->remove) 243 229 adrv->remove(adev); 244 230 spin_lock(&apr->svcs_lock); 245 - idr_remove(&apr->svcs_idr, adev->svc_id); 231 + idr_remove(&apr->svcs_idr, adev->svc.id); 246 232 spin_unlock(&apr->svcs_lock); 247 233 } 248 234 } ··· 269 255 EXPORT_SYMBOL_GPL(aprbus); 270 256 271 257 static int apr_add_device(struct device *dev, struct device_node *np, 272 - const struct apr_device_id *id) 258 + u32 svc_id, u32 domain_id) 273 259 { 274 - struct apr *apr = dev_get_drvdata(dev); 260 + struct packet_router *apr = dev_get_drvdata(dev); 275 261 struct apr_device *adev = NULL; 262 + struct pkt_router_svc *svc; 276 263 int ret; 277 264 278 265 adev = kzalloc(sizeof(*adev), GFP_KERNEL); 279 266 if (!adev) 280 267 return -ENOMEM; 281 268 282 - spin_lock_init(&adev->lock); 269 + adev->svc_id = svc_id; 270 + svc = &adev->svc; 283 271 284 - adev->svc_id = id->svc_id; 285 - adev->domain_id = id->domain_id; 286 - adev->version = id->svc_version; 272 + svc->id = svc_id; 273 + svc->pr = apr; 274 + svc->priv = adev; 275 + svc->dev = dev; 276 + spin_lock_init(&svc->lock); 277 + 278 + adev->domain_id = domain_id; 279 + 287 280 if (np) 288 281 snprintf(adev->name, APR_NAME_SIZE, "%pOFn", np); 289 - else 290 - strscpy(adev->name, id->name, APR_NAME_SIZE); 291 282 292 - dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, 293 - id->domain_id, id->svc_id); 283 + switch (apr->type) { 284 + case PR_TYPE_APR: 285 + dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, 286 + domain_id, svc_id); 287 + break; 288 + default: 289 + break; 290 + } 294 291 295 292 adev->dev.bus = &aprbus; 296 293 adev->dev.parent = dev; ··· 310 285 adev->dev.driver = NULL; 311 286 312 287 spin_lock(&apr->svcs_lock); 313 - idr_alloc(&apr->svcs_idr, adev, id->svc_id, 314 - id->svc_id + 1, GFP_ATOMIC); 288 + idr_alloc(&apr->svcs_idr, svc, svc_id, svc_id + 1, GFP_ATOMIC); 315 289 spin_unlock(&apr->svcs_lock); 316 290 317 291 of_property_read_string_index(np, "qcom,protection-domain", ··· 330 306 static int of_apr_add_pd_lookups(struct device *dev) 331 307 { 332 308 const char *service_name, *service_path; 333 - struct apr *apr = dev_get_drvdata(dev); 309 + struct packet_router *apr = dev_get_drvdata(dev); 334 310 struct device_node *node; 335 311 struct pdr_service *pds; 336 312 int ret; ··· 360 336 361 337 static void of_register_apr_devices(struct device *dev, const char *svc_path) 362 338 { 363 - struct apr *apr = dev_get_drvdata(dev); 339 + struct packet_router *apr = dev_get_drvdata(dev); 364 340 struct device_node *node; 365 341 const char *service_path; 366 342 int ret; 367 343 368 344 for_each_child_of_node(dev->of_node, node) { 369 - struct apr_device_id id = { {0} }; 345 + u32 svc_id; 346 + u32 domain_id; 370 347 371 348 /* 372 349 * This function is called with svc_path NULL during ··· 397 372 continue; 398 373 } 399 374 400 - if (of_property_read_u32(node, "reg", &id.svc_id)) 375 + if (of_property_read_u32(node, "reg", &svc_id)) 401 376 continue; 402 377 403 - id.domain_id = apr->dest_domain_id; 378 + domain_id = apr->dest_domain_id; 404 379 405 - if (apr_add_device(dev, node, &id)) 406 - dev_err(dev, "Failed to add apr %d svc\n", id.svc_id); 380 + if (apr_add_device(dev, node, svc_id, domain_id)) 381 + dev_err(dev, "Failed to add apr %d svc\n", svc_id); 407 382 } 408 383 } 409 384 ··· 423 398 424 399 static void apr_pd_status(int state, char *svc_path, void *priv) 425 400 { 426 - struct apr *apr = (struct apr *)priv; 401 + struct packet_router *apr = (struct packet_router *)priv; 427 402 428 403 switch (state) { 429 404 case SERVREG_SERVICE_STATE_UP: ··· 438 413 static int apr_probe(struct rpmsg_device *rpdev) 439 414 { 440 415 struct device *dev = &rpdev->dev; 441 - struct apr *apr; 416 + struct packet_router *apr; 442 417 int ret; 443 418 444 419 apr = devm_kzalloc(dev, sizeof(*apr), GFP_KERNEL); 445 420 if (!apr) 446 421 return -ENOMEM; 447 422 448 - ret = of_property_read_u32(dev->of_node, "qcom,apr-domain", &apr->dest_domain_id); 423 + ret = of_property_read_u32(dev->of_node, "qcom,domain", &apr->dest_domain_id); 424 + if (ret) /* try deprecated apr-domain property */ 425 + ret = of_property_read_u32(dev->of_node, "qcom,apr-domain", 426 + &apr->dest_domain_id); 427 + apr->type = PR_TYPE_APR; 449 428 if (ret) { 450 - dev_err(dev, "APR Domain ID not specified in DT\n"); 429 + dev_err(dev, "Domain ID not specified in DT\n"); 451 430 return ret; 452 431 } 453 432 ··· 494 465 495 466 static void apr_remove(struct rpmsg_device *rpdev) 496 467 { 497 - struct apr *apr = dev_get_drvdata(&rpdev->dev); 468 + struct packet_router *apr = dev_get_drvdata(&rpdev->dev); 498 469 499 470 pdr_handle_release(apr->pdr); 500 471 device_for_each_child(&rpdev->dev, NULL, apr_remove_device); ··· 531 502 } 532 503 EXPORT_SYMBOL_GPL(apr_driver_unregister); 533 504 534 - static const struct of_device_id apr_of_match[] = { 505 + static const struct of_device_id pkt_router_of_match[] = { 535 506 { .compatible = "qcom,apr"}, 536 507 { .compatible = "qcom,apr-v2"}, 537 508 {} 538 509 }; 539 - MODULE_DEVICE_TABLE(of, apr_of_match); 510 + MODULE_DEVICE_TABLE(of, pkt_router_of_match); 540 511 541 - static struct rpmsg_driver apr_driver = { 512 + static struct rpmsg_driver packet_router_driver = { 542 513 .probe = apr_probe, 543 514 .remove = apr_remove, 544 515 .callback = apr_callback, 545 516 .drv = { 546 517 .name = "qcom,apr", 547 - .of_match_table = apr_of_match, 518 + .of_match_table = pkt_router_of_match, 548 519 }, 549 520 }; 550 521 ··· 554 525 555 526 ret = bus_register(&aprbus); 556 527 if (!ret) 557 - ret = register_rpmsg_driver(&apr_driver); 528 + ret = register_rpmsg_driver(&packet_router_driver); 558 529 else 559 530 bus_unregister(&aprbus); 560 531 ··· 564 535 static void __exit apr_exit(void) 565 536 { 566 537 bus_unregister(&aprbus); 567 - unregister_rpmsg_driver(&apr_driver); 538 + unregister_rpmsg_driver(&packet_router_driver); 568 539 } 569 540 570 541 subsys_initcall(apr_init);
+11 -1
include/linux/soc/qcom/apr.h
··· 79 79 #define APR_SVC_MAJOR_VERSION(v) ((v >> 16) & 0xFF) 80 80 #define APR_SVC_MINOR_VERSION(v) (v & 0xFF) 81 81 82 + struct packet_router; 83 + struct pkt_router_svc { 84 + struct device *dev; 85 + struct packet_router *pr; 86 + spinlock_t lock; 87 + int id; 88 + void *priv; 89 + }; 90 + 82 91 struct apr_device { 83 92 struct device dev; 84 93 uint16_t svc_id; ··· 95 86 uint32_t version; 96 87 char name[APR_NAME_SIZE]; 97 88 const char *service_path; 98 - spinlock_t lock; 89 + struct pkt_router_svc svc; 99 90 struct list_head node; 100 91 }; 101 92 102 93 #define to_apr_device(d) container_of(d, struct apr_device, dev) 94 + #define svc_to_apr_device(d) container_of(d, struct apr_device, svc) 103 95 104 96 struct apr_driver { 105 97 int (*probe)(struct apr_device *sl);