1 // SPDX-License-Identifier: GPL-2.0-only 2 // 3 // Copyright(c) 2022 Intel Corporation. All rights reserved. 4 // 5 // Authors: Ranjani Sridharan <ranjani.sridharan@linux.intel.com> 6 // Peter Ujfalusi <peter.ujfalusi@linux.intel.com> 7 // 8 9 #include <linux/debugfs.h> 10 #include <linux/errno.h> 11 #include <linux/list.h> 12 #include <linux/module.h> 13 #include <linux/mutex.h> 14 #include <linux/slab.h> 15 #include <sound/sof/ipc4/header.h> 16 #include "ops.h" 17 #include "sof-client.h" 18 #include "sof-priv.h" 19 #include "ipc3-priv.h" 20 #include "ipc4-priv.h" 21 22 /** 23 * struct sof_ipc_event_entry - IPC client event description 24 * @ipc_msg_type: IPC msg type of the event the client is interested 25 * @cdev: sof_client_dev of the requesting client 26 * @callback: Callback function of the client 27 * @list: item in SOF core client event list 28 */ 29 struct sof_ipc_event_entry { 30 u32 ipc_msg_type; 31 struct sof_client_dev *cdev; 32 sof_client_event_callback callback; 33 struct list_head list; 34 }; 35 36 /** 37 * struct sof_state_event_entry - DSP panic event subscription entry 38 * @cdev: sof_client_dev of the requesting client 39 * @callback: Callback function of the client 40 * @list: item in SOF core client event list 41 */ 42 struct sof_state_event_entry { 43 struct sof_client_dev *cdev; 44 sof_client_fw_state_callback callback; 45 struct list_head list; 46 }; 47 48 static void sof_client_auxdev_release(struct device *dev) 49 { 50 struct auxiliary_device *auxdev = to_auxiliary_dev(dev); 51 struct sof_client_dev *cdev = auxiliary_dev_to_sof_client_dev(auxdev); 52 53 kfree(cdev->auxdev.dev.platform_data); 54 kfree(cdev); 55 } 56 57 static int sof_client_dev_add_data(struct sof_client_dev *cdev, const void *data, 58 size_t size) 59 { 60 void *d = NULL; 61 62 if (data) { 63 d = kmemdup(data, size, GFP_KERNEL); 64 if (!d) 65 return -ENOMEM; 66 } 67 68 cdev->auxdev.dev.platform_data = d; 69 return 0; 70 } 71 72 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) 73 static int sof_register_ipc_flood_test(struct snd_sof_dev *sdev) 74 { 75 int ret = 0; 76 int i; 77 78 if (sdev->pdata->ipc_type != SOF_IPC) 79 return 0; 80 81 for (i = 0; i < CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_NUM; i++) { 82 ret = sof_client_dev_register(sdev, "ipc_flood", i, NULL, 0); 83 if (ret < 0) 84 break; 85 } 86 87 if (ret) { 88 for (; i >= 0; --i) 89 sof_client_dev_unregister(sdev, "ipc_flood", i); 90 } 91 92 return ret; 93 } 94 95 static void sof_unregister_ipc_flood_test(struct snd_sof_dev *sdev) 96 { 97 int i; 98 99 for (i = 0; i < CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST_NUM; i++) 100 sof_client_dev_unregister(sdev, "ipc_flood", i); 101 } 102 #else 103 static inline int sof_register_ipc_flood_test(struct snd_sof_dev *sdev) 104 { 105 return 0; 106 } 107 108 static inline void sof_unregister_ipc_flood_test(struct snd_sof_dev *sdev) {} 109 #endif /* CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST */ 110 111 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_MSG_INJECTOR) 112 static int sof_register_ipc_msg_injector(struct snd_sof_dev *sdev) 113 { 114 return sof_client_dev_register(sdev, "msg_injector", 0, NULL, 0); 115 } 116 117 static void sof_unregister_ipc_msg_injector(struct snd_sof_dev *sdev) 118 { 119 sof_client_dev_unregister(sdev, "msg_injector", 0); 120 } 121 #else 122 static inline int sof_register_ipc_msg_injector(struct snd_sof_dev *sdev) 123 { 124 return 0; 125 } 126 127 static inline void sof_unregister_ipc_msg_injector(struct snd_sof_dev *sdev) {} 128 #endif /* CONFIG_SND_SOC_SOF_DEBUG_IPC_MSG_INJECTOR */ 129 130 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_KERNEL_INJECTOR) 131 static int sof_register_ipc_kernel_injector(struct snd_sof_dev *sdev) 132 { 133 /* Only IPC3 supported right now */ 134 if (sdev->pdata->ipc_type != SOF_IPC) 135 return 0; 136 137 return sof_client_dev_register(sdev, "kernel_injector", 0, NULL, 0); 138 } 139 140 static void sof_unregister_ipc_kernel_injector(struct snd_sof_dev *sdev) 141 { 142 sof_client_dev_unregister(sdev, "kernel_injector", 0); 143 } 144 #else 145 static inline int sof_register_ipc_kernel_injector(struct snd_sof_dev *sdev) 146 { 147 return 0; 148 } 149 150 static inline void sof_unregister_ipc_kernel_injector(struct snd_sof_dev *sdev) {} 151 #endif /* CONFIG_SND_SOC_SOF_DEBUG_IPC_KERNEL_INJECTOR */ 152 153 int sof_register_clients(struct snd_sof_dev *sdev) 154 { 155 int ret; 156 157 if (sdev->dspless_mode_selected) 158 return 0; 159 160 /* Register platform independent client devices */ 161 ret = sof_register_ipc_flood_test(sdev); 162 if (ret) { 163 dev_err(sdev->dev, "IPC flood test client registration failed\n"); 164 return ret; 165 } 166 167 ret = sof_register_ipc_msg_injector(sdev); 168 if (ret) { 169 dev_err(sdev->dev, "IPC message injector client registration failed\n"); 170 goto err_msg_injector; 171 } 172 173 ret = sof_register_ipc_kernel_injector(sdev); 174 if (ret) { 175 dev_err(sdev->dev, "IPC kernel injector client registration failed\n"); 176 goto err_kernel_injector; 177 } 178 179 /* Platform depndent client device registration */ 180 181 if (sof_ops(sdev) && sof_ops(sdev)->register_ipc_clients) 182 ret = sof_ops(sdev)->register_ipc_clients(sdev); 183 184 if (!ret) 185 return 0; 186 187 sof_unregister_ipc_kernel_injector(sdev); 188 189 err_kernel_injector: 190 sof_unregister_ipc_msg_injector(sdev); 191 192 err_msg_injector: 193 sof_unregister_ipc_flood_test(sdev); 194 195 return ret; 196 } 197 198 void sof_unregister_clients(struct snd_sof_dev *sdev) 199 { 200 if (sof_ops(sdev) && sof_ops(sdev)->unregister_ipc_clients) 201 sof_ops(sdev)->unregister_ipc_clients(sdev); 202 203 sof_unregister_ipc_kernel_injector(sdev); 204 sof_unregister_ipc_msg_injector(sdev); 205 sof_unregister_ipc_flood_test(sdev); 206 } 207 208 int sof_client_dev_register(struct snd_sof_dev *sdev, const char *name, u32 id, 209 const void *data, size_t size) 210 { 211 struct auxiliary_device *auxdev; 212 struct sof_client_dev *cdev; 213 int ret; 214 215 cdev = kzalloc(sizeof(*cdev), GFP_KERNEL); 216 if (!cdev) 217 return -ENOMEM; 218 219 cdev->sdev = sdev; 220 auxdev = &cdev->auxdev; 221 auxdev->name = name; 222 auxdev->dev.parent = sdev->dev; 223 auxdev->dev.release = sof_client_auxdev_release; 224 auxdev->id = id; 225 226 ret = sof_client_dev_add_data(cdev, data, size); 227 if (ret < 0) 228 goto err_dev_add_data; 229 230 ret = auxiliary_device_init(auxdev); 231 if (ret < 0) { 232 dev_err(sdev->dev, "failed to initialize client dev %s.%d\n", name, id); 233 goto err_dev_init; 234 } 235 236 ret = auxiliary_device_add(&cdev->auxdev); 237 if (ret < 0) { 238 dev_err(sdev->dev, "failed to add client dev %s.%d\n", name, id); 239 /* 240 * sof_client_auxdev_release() will be invoked to free up memory 241 * allocations through put_device() 242 */ 243 auxiliary_device_uninit(&cdev->auxdev); 244 return ret; 245 } 246 247 /* add to list of SOF client devices */ 248 mutex_lock(&sdev->ipc_client_mutex); 249 list_add(&cdev->list, &sdev->ipc_client_list); 250 mutex_unlock(&sdev->ipc_client_mutex); 251 252 return 0; 253 254 err_dev_init: 255 kfree(cdev->auxdev.dev.platform_data); 256 257 err_dev_add_data: 258 kfree(cdev); 259 260 return ret; 261 } 262 EXPORT_SYMBOL_NS_GPL(sof_client_dev_register, SND_SOC_SOF_CLIENT); 263 264 void sof_client_dev_unregister(struct snd_sof_dev *sdev, const char *name, u32 id) 265 { 266 struct sof_client_dev *cdev; 267 268 mutex_lock(&sdev->ipc_client_mutex); 269 270 /* 271 * sof_client_auxdev_release() will be invoked to free up memory 272 * allocations through put_device() 273 */ 274 list_for_each_entry(cdev, &sdev->ipc_client_list, list) { 275 if (!strcmp(cdev->auxdev.name, name) && cdev->auxdev.id == id) { 276 list_del(&cdev->list); 277 auxiliary_device_delete(&cdev->auxdev); 278 auxiliary_device_uninit(&cdev->auxdev); 279 break; 280 } 281 } 282 283 mutex_unlock(&sdev->ipc_client_mutex); 284 } 285 EXPORT_SYMBOL_NS_GPL(sof_client_dev_unregister, SND_SOC_SOF_CLIENT); 286 287 int sof_client_ipc_tx_message(struct sof_client_dev *cdev, void *ipc_msg, 288 void *reply_data, size_t reply_bytes) 289 { 290 if (cdev->sdev->pdata->ipc_type == SOF_IPC) { 291 struct sof_ipc_cmd_hdr *hdr = ipc_msg; 292 293 return sof_ipc_tx_message(cdev->sdev->ipc, ipc_msg, hdr->size, 294 reply_data, reply_bytes); 295 } else if (cdev->sdev->pdata->ipc_type == SOF_INTEL_IPC4) { 296 struct sof_ipc4_msg *msg = ipc_msg; 297 298 return sof_ipc_tx_message(cdev->sdev->ipc, ipc_msg, msg->data_size, 299 reply_data, reply_bytes); 300 } 301 302 return -EINVAL; 303 } 304 EXPORT_SYMBOL_NS_GPL(sof_client_ipc_tx_message, SND_SOC_SOF_CLIENT); 305 306 int sof_client_ipc_rx_message(struct sof_client_dev *cdev, void *ipc_msg, void *msg_buf) 307 { 308 if (cdev->sdev->pdata->ipc_type == SOF_IPC) { 309 struct sof_ipc_cmd_hdr *hdr = ipc_msg; 310 311 if (hdr->size < sizeof(hdr)) { 312 dev_err(cdev->sdev->dev, "The received message size is invalid\n"); 313 return -EINVAL; 314 } 315 316 sof_ipc3_do_rx_work(cdev->sdev, ipc_msg, msg_buf); 317 return 0; 318 } 319 320 return -EOPNOTSUPP; 321 } 322 EXPORT_SYMBOL_NS_GPL(sof_client_ipc_rx_message, SND_SOC_SOF_CLIENT); 323 324 int sof_client_ipc_set_get_data(struct sof_client_dev *cdev, void *ipc_msg, 325 bool set) 326 { 327 if (cdev->sdev->pdata->ipc_type == SOF_IPC) { 328 struct sof_ipc_cmd_hdr *hdr = ipc_msg; 329 330 return sof_ipc_set_get_data(cdev->sdev->ipc, ipc_msg, hdr->size, 331 set); 332 } else if (cdev->sdev->pdata->ipc_type == SOF_INTEL_IPC4) { 333 struct sof_ipc4_msg *msg = ipc_msg; 334 335 return sof_ipc_set_get_data(cdev->sdev->ipc, ipc_msg, 336 msg->data_size, set); 337 } 338 339 return -EINVAL; 340 } 341 EXPORT_SYMBOL_NS_GPL(sof_client_ipc_set_get_data, SND_SOC_SOF_CLIENT); 342 343 #ifdef CONFIG_SND_SOC_SOF_INTEL_IPC4 344 struct sof_ipc4_fw_module *sof_client_ipc4_find_module(struct sof_client_dev *c, const guid_t *uuid) 345 { 346 struct snd_sof_dev *sdev = c->sdev; 347 348 if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) 349 return sof_ipc4_find_module_by_uuid(sdev, uuid); 350 dev_err(sdev->dev, "Only supported with IPC4\n"); 351 352 return NULL; 353 } 354 EXPORT_SYMBOL_NS_GPL(sof_client_ipc4_find_module, SND_SOC_SOF_CLIENT); 355 #endif 356 357 int sof_suspend_clients(struct snd_sof_dev *sdev, pm_message_t state) 358 { 359 struct auxiliary_driver *adrv; 360 struct sof_client_dev *cdev; 361 362 mutex_lock(&sdev->ipc_client_mutex); 363 364 list_for_each_entry(cdev, &sdev->ipc_client_list, list) { 365 /* Skip devices without loaded driver */ 366 if (!cdev->auxdev.dev.driver) 367 continue; 368 369 adrv = to_auxiliary_drv(cdev->auxdev.dev.driver); 370 if (adrv->suspend) 371 adrv->suspend(&cdev->auxdev, state); 372 } 373 374 mutex_unlock(&sdev->ipc_client_mutex); 375 376 return 0; 377 } 378 EXPORT_SYMBOL_NS_GPL(sof_suspend_clients, SND_SOC_SOF_CLIENT); 379 380 int sof_resume_clients(struct snd_sof_dev *sdev) 381 { 382 struct auxiliary_driver *adrv; 383 struct sof_client_dev *cdev; 384 385 mutex_lock(&sdev->ipc_client_mutex); 386 387 list_for_each_entry(cdev, &sdev->ipc_client_list, list) { 388 /* Skip devices without loaded driver */ 389 if (!cdev->auxdev.dev.driver) 390 continue; 391 392 adrv = to_auxiliary_drv(cdev->auxdev.dev.driver); 393 if (adrv->resume) 394 adrv->resume(&cdev->auxdev); 395 } 396 397 mutex_unlock(&sdev->ipc_client_mutex); 398 399 return 0; 400 } 401 EXPORT_SYMBOL_NS_GPL(sof_resume_clients, SND_SOC_SOF_CLIENT); 402 403 struct dentry *sof_client_get_debugfs_root(struct sof_client_dev *cdev) 404 { 405 return cdev->sdev->debugfs_root; 406 } 407 EXPORT_SYMBOL_NS_GPL(sof_client_get_debugfs_root, SND_SOC_SOF_CLIENT); 408 409 /* DMA buffer allocation in client drivers must use the core SOF device */ 410 struct device *sof_client_get_dma_dev(struct sof_client_dev *cdev) 411 { 412 return cdev->sdev->dev; 413 } 414 EXPORT_SYMBOL_NS_GPL(sof_client_get_dma_dev, SND_SOC_SOF_CLIENT); 415 416 const struct sof_ipc_fw_version *sof_client_get_fw_version(struct sof_client_dev *cdev) 417 { 418 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 419 420 return &sdev->fw_ready.version; 421 } 422 EXPORT_SYMBOL_NS_GPL(sof_client_get_fw_version, SND_SOC_SOF_CLIENT); 423 424 size_t sof_client_get_ipc_max_payload_size(struct sof_client_dev *cdev) 425 { 426 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 427 428 return sdev->ipc->max_payload_size; 429 } 430 EXPORT_SYMBOL_NS_GPL(sof_client_get_ipc_max_payload_size, SND_SOC_SOF_CLIENT); 431 432 enum sof_ipc_type sof_client_get_ipc_type(struct sof_client_dev *cdev) 433 { 434 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 435 436 return sdev->pdata->ipc_type; 437 } 438 EXPORT_SYMBOL_NS_GPL(sof_client_get_ipc_type, SND_SOC_SOF_CLIENT); 439 440 /* module refcount management of SOF core */ 441 int sof_client_core_module_get(struct sof_client_dev *cdev) 442 { 443 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 444 445 if (!try_module_get(sdev->dev->driver->owner)) 446 return -ENODEV; 447 448 return 0; 449 } 450 EXPORT_SYMBOL_NS_GPL(sof_client_core_module_get, SND_SOC_SOF_CLIENT); 451 452 void sof_client_core_module_put(struct sof_client_dev *cdev) 453 { 454 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 455 456 module_put(sdev->dev->driver->owner); 457 } 458 EXPORT_SYMBOL_NS_GPL(sof_client_core_module_put, SND_SOC_SOF_CLIENT); 459 460 /* IPC event handling */ 461 void sof_client_ipc_rx_dispatcher(struct snd_sof_dev *sdev, void *msg_buf) 462 { 463 struct sof_ipc_event_entry *event; 464 u32 msg_type; 465 466 if (sdev->pdata->ipc_type == SOF_IPC) { 467 struct sof_ipc_cmd_hdr *hdr = msg_buf; 468 469 msg_type = hdr->cmd & SOF_GLB_TYPE_MASK; 470 } else if (sdev->pdata->ipc_type == SOF_INTEL_IPC4) { 471 struct sof_ipc4_msg *msg = msg_buf; 472 473 msg_type = SOF_IPC4_NOTIFICATION_TYPE_GET(msg->primary); 474 } else { 475 dev_dbg_once(sdev->dev, "Not supported IPC version: %d\n", 476 sdev->pdata->ipc_type); 477 return; 478 } 479 480 mutex_lock(&sdev->client_event_handler_mutex); 481 482 list_for_each_entry(event, &sdev->ipc_rx_handler_list, list) { 483 if (event->ipc_msg_type == msg_type) 484 event->callback(event->cdev, msg_buf); 485 } 486 487 mutex_unlock(&sdev->client_event_handler_mutex); 488 } 489 490 int sof_client_register_ipc_rx_handler(struct sof_client_dev *cdev, 491 u32 ipc_msg_type, 492 sof_client_event_callback callback) 493 { 494 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 495 struct sof_ipc_event_entry *event; 496 497 if (!callback) 498 return -EINVAL; 499 500 if (cdev->sdev->pdata->ipc_type == SOF_IPC) { 501 if (!(ipc_msg_type & SOF_GLB_TYPE_MASK)) 502 return -EINVAL; 503 } else if (cdev->sdev->pdata->ipc_type == SOF_INTEL_IPC4) { 504 if (!(ipc_msg_type & SOF_IPC4_NOTIFICATION_TYPE_MASK)) 505 return -EINVAL; 506 } else { 507 dev_warn(sdev->dev, "%s: Not supported IPC version: %d\n", 508 __func__, sdev->pdata->ipc_type); 509 return -EINVAL; 510 } 511 512 event = kmalloc(sizeof(*event), GFP_KERNEL); 513 if (!event) 514 return -ENOMEM; 515 516 event->ipc_msg_type = ipc_msg_type; 517 event->cdev = cdev; 518 event->callback = callback; 519 520 /* add to list of SOF client devices */ 521 mutex_lock(&sdev->client_event_handler_mutex); 522 list_add(&event->list, &sdev->ipc_rx_handler_list); 523 mutex_unlock(&sdev->client_event_handler_mutex); 524 525 return 0; 526 } 527 EXPORT_SYMBOL_NS_GPL(sof_client_register_ipc_rx_handler, SND_SOC_SOF_CLIENT); 528 529 void sof_client_unregister_ipc_rx_handler(struct sof_client_dev *cdev, 530 u32 ipc_msg_type) 531 { 532 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 533 struct sof_ipc_event_entry *event; 534 535 mutex_lock(&sdev->client_event_handler_mutex); 536 537 list_for_each_entry(event, &sdev->ipc_rx_handler_list, list) { 538 if (event->cdev == cdev && event->ipc_msg_type == ipc_msg_type) { 539 list_del(&event->list); 540 kfree(event); 541 break; 542 } 543 } 544 545 mutex_unlock(&sdev->client_event_handler_mutex); 546 } 547 EXPORT_SYMBOL_NS_GPL(sof_client_unregister_ipc_rx_handler, SND_SOC_SOF_CLIENT); 548 549 /*DSP state notification and query */ 550 void sof_client_fw_state_dispatcher(struct snd_sof_dev *sdev) 551 { 552 struct sof_state_event_entry *event; 553 554 mutex_lock(&sdev->client_event_handler_mutex); 555 556 list_for_each_entry(event, &sdev->fw_state_handler_list, list) 557 event->callback(event->cdev, sdev->fw_state); 558 559 mutex_unlock(&sdev->client_event_handler_mutex); 560 } 561 562 int sof_client_register_fw_state_handler(struct sof_client_dev *cdev, 563 sof_client_fw_state_callback callback) 564 { 565 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 566 struct sof_state_event_entry *event; 567 568 if (!callback) 569 return -EINVAL; 570 571 event = kmalloc(sizeof(*event), GFP_KERNEL); 572 if (!event) 573 return -ENOMEM; 574 575 event->cdev = cdev; 576 event->callback = callback; 577 578 /* add to list of SOF client devices */ 579 mutex_lock(&sdev->client_event_handler_mutex); 580 list_add(&event->list, &sdev->fw_state_handler_list); 581 mutex_unlock(&sdev->client_event_handler_mutex); 582 583 return 0; 584 } 585 EXPORT_SYMBOL_NS_GPL(sof_client_register_fw_state_handler, SND_SOC_SOF_CLIENT); 586 587 void sof_client_unregister_fw_state_handler(struct sof_client_dev *cdev) 588 { 589 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 590 struct sof_state_event_entry *event; 591 592 mutex_lock(&sdev->client_event_handler_mutex); 593 594 list_for_each_entry(event, &sdev->fw_state_handler_list, list) { 595 if (event->cdev == cdev) { 596 list_del(&event->list); 597 kfree(event); 598 break; 599 } 600 } 601 602 mutex_unlock(&sdev->client_event_handler_mutex); 603 } 604 EXPORT_SYMBOL_NS_GPL(sof_client_unregister_fw_state_handler, SND_SOC_SOF_CLIENT); 605 606 enum sof_fw_state sof_client_get_fw_state(struct sof_client_dev *cdev) 607 { 608 struct snd_sof_dev *sdev = sof_client_dev_to_sof_dev(cdev); 609 610 return sdev->fw_state; 611 } 612 EXPORT_SYMBOL_NS_GPL(sof_client_get_fw_state, SND_SOC_SOF_CLIENT); 613