ipc.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. //
  3. // Copyright(c) 2021-2022 Intel Corporation
  4. //
  5. // Authors: Cezary Rojewski <cezary.rojewski@intel.com>
  6. // Amadeusz Slawinski <amadeuszx.slawinski@linux.intel.com>
  7. //
  8. #include <linux/io-64-nonatomic-lo-hi.h>
  9. #include <linux/slab.h>
  10. #include <sound/hdaudio_ext.h>
  11. #include "avs.h"
  12. #include "messages.h"
  13. #include "registers.h"
  14. #include "trace.h"
  15. #define AVS_IPC_TIMEOUT_MS 300
  16. #define AVS_D0IX_DELAY_MS 300
  17. static int
  18. avs_dsp_set_d0ix(struct avs_dev *adev, bool enable)
  19. {
  20. struct avs_ipc *ipc = adev->ipc;
  21. int ret;
  22. /* Is transition required? */
  23. if (ipc->in_d0ix == enable)
  24. return 0;
  25. ret = avs_dsp_op(adev, set_d0ix, enable);
  26. if (ret) {
  27. /* Prevent further d0ix attempts on conscious IPC failure. */
  28. if (ret == -AVS_EIPC)
  29. atomic_inc(&ipc->d0ix_disable_depth);
  30. ipc->in_d0ix = false;
  31. return ret;
  32. }
  33. ipc->in_d0ix = enable;
  34. return 0;
  35. }
  36. static void avs_dsp_schedule_d0ix(struct avs_dev *adev, struct avs_ipc_msg *tx)
  37. {
  38. if (atomic_read(&adev->ipc->d0ix_disable_depth))
  39. return;
  40. mod_delayed_work(system_power_efficient_wq, &adev->ipc->d0ix_work,
  41. msecs_to_jiffies(AVS_D0IX_DELAY_MS));
  42. }
  43. static void avs_dsp_d0ix_work(struct work_struct *work)
  44. {
  45. struct avs_ipc *ipc = container_of(work, struct avs_ipc, d0ix_work.work);
  46. avs_dsp_set_d0ix(to_avs_dev(ipc->dev), true);
  47. }
  48. static int avs_dsp_wake_d0i0(struct avs_dev *adev, struct avs_ipc_msg *tx)
  49. {
  50. struct avs_ipc *ipc = adev->ipc;
  51. if (!atomic_read(&ipc->d0ix_disable_depth)) {
  52. cancel_delayed_work_sync(&ipc->d0ix_work);
  53. return avs_dsp_set_d0ix(adev, false);
  54. }
  55. return 0;
  56. }
  57. int avs_dsp_disable_d0ix(struct avs_dev *adev)
  58. {
  59. struct avs_ipc *ipc = adev->ipc;
  60. /* Prevent PG only on the first disable. */
  61. if (atomic_inc_return(&ipc->d0ix_disable_depth) == 1) {
  62. cancel_delayed_work_sync(&ipc->d0ix_work);
  63. return avs_dsp_set_d0ix(adev, false);
  64. }
  65. return 0;
  66. }
  67. int avs_dsp_enable_d0ix(struct avs_dev *adev)
  68. {
  69. struct avs_ipc *ipc = adev->ipc;
  70. if (atomic_dec_and_test(&ipc->d0ix_disable_depth))
  71. queue_delayed_work(system_power_efficient_wq, &ipc->d0ix_work,
  72. msecs_to_jiffies(AVS_D0IX_DELAY_MS));
  73. return 0;
  74. }
  75. static void avs_dsp_recovery(struct avs_dev *adev)
  76. {
  77. struct avs_soc_component *acomp;
  78. unsigned int core_mask;
  79. int ret;
  80. mutex_lock(&adev->comp_list_mutex);
  81. /* disconnect all running streams */
  82. list_for_each_entry(acomp, &adev->comp_list, node) {
  83. struct snd_soc_pcm_runtime *rtd;
  84. struct snd_soc_card *card;
  85. card = acomp->base.card;
  86. if (!card)
  87. continue;
  88. for_each_card_rtds(card, rtd) {
  89. struct snd_pcm *pcm;
  90. int dir;
  91. pcm = rtd->pcm;
  92. if (!pcm || rtd->dai_link->no_pcm)
  93. continue;
  94. for_each_pcm_streams(dir) {
  95. struct snd_pcm_substream *substream;
  96. substream = pcm->streams[dir].substream;
  97. if (!substream || !substream->runtime)
  98. continue;
  99. /* No need for _irq() as we are in nonatomic context. */
  100. snd_pcm_stream_lock(substream);
  101. snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
  102. snd_pcm_stream_unlock(substream);
  103. }
  104. }
  105. }
  106. mutex_unlock(&adev->comp_list_mutex);
  107. /* forcibly shutdown all cores */
  108. core_mask = GENMASK(adev->hw_cfg.dsp_cores - 1, 0);
  109. avs_dsp_core_disable(adev, core_mask);
  110. /* attempt dsp reboot */
  111. ret = avs_dsp_boot_firmware(adev, true);
  112. if (ret < 0)
  113. dev_err(adev->dev, "dsp reboot failed: %d\n", ret);
  114. pm_runtime_mark_last_busy(adev->dev);
  115. pm_runtime_enable(adev->dev);
  116. pm_request_autosuspend(adev->dev);
  117. atomic_set(&adev->ipc->recovering, 0);
  118. }
  119. static void avs_dsp_recovery_work(struct work_struct *work)
  120. {
  121. struct avs_ipc *ipc = container_of(work, struct avs_ipc, recovery_work);
  122. avs_dsp_recovery(to_avs_dev(ipc->dev));
  123. }
  124. static void avs_dsp_exception_caught(struct avs_dev *adev, union avs_notify_msg *msg)
  125. {
  126. struct avs_ipc *ipc = adev->ipc;
  127. /* Account for the double-exception case. */
  128. ipc->ready = false;
  129. if (!atomic_add_unless(&ipc->recovering, 1, 1)) {
  130. dev_err(adev->dev, "dsp recovery is already in progress\n");
  131. return;
  132. }
  133. dev_crit(adev->dev, "communication severed, rebooting dsp..\n");
  134. /* Avoid deadlock as the exception may be the response to SET_D0IX. */
  135. if (current_work() != &ipc->d0ix_work.work)
  136. cancel_delayed_work_sync(&ipc->d0ix_work);
  137. ipc->in_d0ix = false;
  138. /* Re-enabled on recovery completion. */
  139. pm_runtime_disable(adev->dev);
  140. /* Process received notification. */
  141. avs_dsp_op(adev, coredump, msg);
  142. schedule_work(&ipc->recovery_work);
  143. }
  144. static void avs_dsp_receive_rx(struct avs_dev *adev, u64 header)
  145. {
  146. struct avs_ipc *ipc = adev->ipc;
  147. union avs_reply_msg msg = AVS_MSG(header);
  148. u64 reg;
  149. reg = readq(avs_sram_addr(adev, AVS_FW_REGS_WINDOW));
  150. trace_avs_ipc_reply_msg(header, reg);
  151. ipc->rx.header = header;
  152. /* Abort copying payload if request processing was unsuccessful. */
  153. if (!msg.status) {
  154. /* update size in case of LARGE_CONFIG_GET */
  155. if (msg.msg_target == AVS_MOD_MSG &&
  156. msg.global_msg_type == AVS_MOD_LARGE_CONFIG_GET)
  157. ipc->rx.size = min_t(u32, AVS_MAILBOX_SIZE,
  158. msg.ext.large_config.data_off_size);
  159. memcpy_fromio(ipc->rx.data, avs_uplink_addr(adev), ipc->rx.size);
  160. trace_avs_msg_payload(ipc->rx.data, ipc->rx.size);
  161. }
  162. }
  163. static void avs_dsp_process_notification(struct avs_dev *adev, u64 header)
  164. {
  165. struct avs_notify_mod_data mod_data;
  166. union avs_notify_msg msg = AVS_MSG(header);
  167. size_t data_size = 0;
  168. void *data = NULL;
  169. u64 reg;
  170. reg = readq(avs_sram_addr(adev, AVS_FW_REGS_WINDOW));
  171. trace_avs_ipc_notify_msg(header, reg);
  172. /* Ignore spurious notifications until handshake is established. */
  173. if (!adev->ipc->ready && msg.notify_msg_type != AVS_NOTIFY_FW_READY) {
  174. dev_dbg(adev->dev, "FW not ready, skip notification: 0x%08x\n", msg.primary);
  175. return;
  176. }
  177. /* Calculate notification payload size. */
  178. switch (msg.notify_msg_type) {
  179. case AVS_NOTIFY_FW_READY:
  180. break;
  181. case AVS_NOTIFY_PHRASE_DETECTED:
  182. data_size = sizeof(struct avs_notify_voice_data);
  183. break;
  184. case AVS_NOTIFY_RESOURCE_EVENT:
  185. data_size = sizeof(struct avs_notify_res_data);
  186. break;
  187. case AVS_NOTIFY_LOG_BUFFER_STATUS:
  188. case AVS_NOTIFY_EXCEPTION_CAUGHT:
  189. break;
  190. case AVS_NOTIFY_MODULE_EVENT:
  191. /* To know the total payload size, header needs to be read first. */
  192. memcpy_fromio(&mod_data, avs_uplink_addr(adev), sizeof(mod_data));
  193. data_size = sizeof(mod_data) + mod_data.data_size;
  194. break;
  195. default:
  196. dev_info(adev->dev, "unknown notification: 0x%08x\n", msg.primary);
  197. break;
  198. }
  199. if (data_size) {
  200. data = kmalloc(data_size, GFP_KERNEL);
  201. if (!data)
  202. return;
  203. memcpy_fromio(data, avs_uplink_addr(adev), data_size);
  204. trace_avs_msg_payload(data, data_size);
  205. }
  206. /* Perform notification-specific operations. */
  207. switch (msg.notify_msg_type) {
  208. case AVS_NOTIFY_FW_READY:
  209. dev_dbg(adev->dev, "FW READY 0x%08x\n", msg.primary);
  210. adev->ipc->ready = true;
  211. complete(&adev->fw_ready);
  212. break;
  213. case AVS_NOTIFY_LOG_BUFFER_STATUS:
  214. avs_log_buffer_status_locked(adev, &msg);
  215. break;
  216. case AVS_NOTIFY_EXCEPTION_CAUGHT:
  217. avs_dsp_exception_caught(adev, &msg);
  218. break;
  219. default:
  220. break;
  221. }
  222. kfree(data);
  223. }
  224. void avs_dsp_process_response(struct avs_dev *adev, u64 header)
  225. {
  226. struct avs_ipc *ipc = adev->ipc;
  227. /*
  228. * Response may either be solicited - a reply for a request that has
  229. * been sent beforehand - or unsolicited (notification).
  230. */
  231. if (avs_msg_is_reply(header)) {
  232. /* Response processing is invoked from IRQ thread. */
  233. spin_lock_irq(&ipc->rx_lock);
  234. avs_dsp_receive_rx(adev, header);
  235. ipc->rx_completed = true;
  236. spin_unlock_irq(&ipc->rx_lock);
  237. } else {
  238. avs_dsp_process_notification(adev, header);
  239. }
  240. complete(&ipc->busy_completion);
  241. }
  242. static bool avs_ipc_is_busy(struct avs_ipc *ipc)
  243. {
  244. struct avs_dev *adev = to_avs_dev(ipc->dev);
  245. const struct avs_spec *const spec = adev->spec;
  246. u32 hipc_rsp;
  247. hipc_rsp = snd_hdac_adsp_readl(adev, spec->hipc->rsp_offset);
  248. return hipc_rsp & spec->hipc->rsp_busy_mask;
  249. }
  250. static int avs_ipc_wait_busy_completion(struct avs_ipc *ipc, int timeout)
  251. {
  252. u32 repeats_left = 128; /* to avoid infinite looping */
  253. int ret;
  254. again:
  255. ret = wait_for_completion_timeout(&ipc->busy_completion, msecs_to_jiffies(timeout));
  256. /* DSP could be unresponsive at this point. */
  257. if (!ipc->ready)
  258. return -EPERM;
  259. if (!ret) {
  260. if (!avs_ipc_is_busy(ipc))
  261. return -ETIMEDOUT;
  262. /*
  263. * Firmware did its job, either notification or reply
  264. * has been received - now wait until it's processed.
  265. */
  266. wait_for_completion_killable(&ipc->busy_completion);
  267. }
  268. /* Ongoing notification's bottom-half may cause early wakeup */
  269. spin_lock(&ipc->rx_lock);
  270. if (!ipc->rx_completed) {
  271. if (repeats_left) {
  272. /* Reply delayed due to notification. */
  273. repeats_left--;
  274. reinit_completion(&ipc->busy_completion);
  275. spin_unlock(&ipc->rx_lock);
  276. goto again;
  277. }
  278. spin_unlock(&ipc->rx_lock);
  279. return -ETIMEDOUT;
  280. }
  281. spin_unlock(&ipc->rx_lock);
  282. return 0;
  283. }
  284. static void avs_ipc_msg_init(struct avs_ipc *ipc, struct avs_ipc_msg *reply)
  285. {
  286. lockdep_assert_held(&ipc->rx_lock);
  287. ipc->rx.header = 0;
  288. ipc->rx.size = reply ? reply->size : 0;
  289. ipc->rx_completed = false;
  290. reinit_completion(&ipc->done_completion);
  291. reinit_completion(&ipc->busy_completion);
  292. }
  293. static void avs_dsp_send_tx(struct avs_dev *adev, struct avs_ipc_msg *tx, bool read_fwregs)
  294. {
  295. const struct avs_spec *const spec = adev->spec;
  296. u64 reg = ULONG_MAX;
  297. tx->header |= spec->hipc->req_busy_mask;
  298. if (read_fwregs)
  299. reg = readq(avs_sram_addr(adev, AVS_FW_REGS_WINDOW));
  300. trace_avs_request(tx, reg);
  301. if (tx->size)
  302. memcpy_toio(avs_downlink_addr(adev), tx->data, tx->size);
  303. snd_hdac_adsp_writel(adev, spec->hipc->req_ext_offset, tx->header >> 32);
  304. snd_hdac_adsp_writel(adev, spec->hipc->req_offset, tx->header & UINT_MAX);
  305. }
  306. static int avs_dsp_do_send_msg(struct avs_dev *adev, struct avs_ipc_msg *request,
  307. struct avs_ipc_msg *reply, int timeout, const char *name)
  308. {
  309. struct avs_ipc *ipc = adev->ipc;
  310. int ret;
  311. if (!ipc->ready)
  312. return -EPERM;
  313. mutex_lock(&ipc->msg_mutex);
  314. spin_lock(&ipc->rx_lock);
  315. avs_ipc_msg_init(ipc, reply);
  316. avs_dsp_send_tx(adev, request, true);
  317. spin_unlock(&ipc->rx_lock);
  318. ret = avs_ipc_wait_busy_completion(ipc, timeout);
  319. if (ret) {
  320. if (ret == -ETIMEDOUT) {
  321. union avs_notify_msg msg = AVS_NOTIFICATION(EXCEPTION_CAUGHT);
  322. /* Same treatment as on exception, just stack_dump=0. */
  323. avs_dsp_exception_caught(adev, &msg);
  324. }
  325. goto exit;
  326. }
  327. ret = ipc->rx.rsp.status;
  328. /*
  329. * If IPC channel is blocked e.g.: due to ongoing recovery,
  330. * -EPERM error code is expected and thus it's not an actual error.
  331. *
  332. * Unsupported IPCs are of no harm either.
  333. */
  334. if (ret == -EPERM || ret == AVS_IPC_NOT_SUPPORTED)
  335. dev_dbg(adev->dev, "%s (0x%08x 0x%08x) failed: %d\n",
  336. name, request->glb.primary, request->glb.ext.val, ret);
  337. else if (ret)
  338. dev_err(adev->dev, "%s (0x%08x 0x%08x) failed: %d\n",
  339. name, request->glb.primary, request->glb.ext.val, ret);
  340. if (reply) {
  341. reply->header = ipc->rx.header;
  342. reply->size = ipc->rx.size;
  343. if (reply->data && ipc->rx.size)
  344. memcpy(reply->data, ipc->rx.data, reply->size);
  345. }
  346. exit:
  347. mutex_unlock(&ipc->msg_mutex);
  348. return ret;
  349. }
  350. static int avs_dsp_send_msg_sequence(struct avs_dev *adev, struct avs_ipc_msg *request,
  351. struct avs_ipc_msg *reply, int timeout, bool wake_d0i0,
  352. bool schedule_d0ix, const char *name)
  353. {
  354. int ret;
  355. trace_avs_d0ix("wake", wake_d0i0, request->header);
  356. if (wake_d0i0) {
  357. ret = avs_dsp_wake_d0i0(adev, request);
  358. if (ret)
  359. return ret;
  360. }
  361. ret = avs_dsp_do_send_msg(adev, request, reply, timeout, name);
  362. if (ret)
  363. return ret;
  364. trace_avs_d0ix("schedule", schedule_d0ix, request->header);
  365. if (schedule_d0ix)
  366. avs_dsp_schedule_d0ix(adev, request);
  367. return 0;
  368. }
  369. int avs_dsp_send_msg_timeout(struct avs_dev *adev, struct avs_ipc_msg *request,
  370. struct avs_ipc_msg *reply, int timeout, const char *name)
  371. {
  372. bool wake_d0i0 = avs_dsp_op(adev, d0ix_toggle, request, true);
  373. bool schedule_d0ix = avs_dsp_op(adev, d0ix_toggle, request, false);
  374. return avs_dsp_send_msg_sequence(adev, request, reply, timeout, wake_d0i0, schedule_d0ix,
  375. name);
  376. }
  377. int avs_dsp_send_msg(struct avs_dev *adev, struct avs_ipc_msg *request,
  378. struct avs_ipc_msg *reply, const char *name)
  379. {
  380. return avs_dsp_send_msg_timeout(adev, request, reply, adev->ipc->default_timeout_ms, name);
  381. }
  382. int avs_dsp_send_pm_msg_timeout(struct avs_dev *adev, struct avs_ipc_msg *request,
  383. struct avs_ipc_msg *reply, int timeout, bool wake_d0i0,
  384. const char *name)
  385. {
  386. return avs_dsp_send_msg_sequence(adev, request, reply, timeout, wake_d0i0, false, name);
  387. }
  388. int avs_dsp_send_pm_msg(struct avs_dev *adev, struct avs_ipc_msg *request,
  389. struct avs_ipc_msg *reply, bool wake_d0i0, const char *name)
  390. {
  391. return avs_dsp_send_pm_msg_timeout(adev, request, reply, adev->ipc->default_timeout_ms,
  392. wake_d0i0, name);
  393. }
  394. static int avs_dsp_do_send_rom_msg(struct avs_dev *adev, struct avs_ipc_msg *request, int timeout,
  395. const char *name)
  396. {
  397. struct avs_ipc *ipc = adev->ipc;
  398. int ret;
  399. mutex_lock(&ipc->msg_mutex);
  400. spin_lock(&ipc->rx_lock);
  401. avs_ipc_msg_init(ipc, NULL);
  402. /*
  403. * with hw still stalled, memory windows may not be
  404. * configured properly so avoid accessing SRAM
  405. */
  406. avs_dsp_send_tx(adev, request, false);
  407. spin_unlock(&ipc->rx_lock);
  408. /* ROM messages must be sent before main core is unstalled */
  409. ret = avs_dsp_op(adev, stall, AVS_MAIN_CORE_MASK, false);
  410. if (!ret) {
  411. ret = wait_for_completion_timeout(&ipc->done_completion, msecs_to_jiffies(timeout));
  412. ret = ret ? 0 : -ETIMEDOUT;
  413. }
  414. if (ret)
  415. dev_err(adev->dev, "%s (0x%08x 0x%08x) failed: %d\n",
  416. name, request->glb.primary, request->glb.ext.val, ret);
  417. mutex_unlock(&ipc->msg_mutex);
  418. return ret;
  419. }
  420. int avs_dsp_send_rom_msg_timeout(struct avs_dev *adev, struct avs_ipc_msg *request, int timeout,
  421. const char *name)
  422. {
  423. return avs_dsp_do_send_rom_msg(adev, request, timeout, name);
  424. }
  425. int avs_dsp_send_rom_msg(struct avs_dev *adev, struct avs_ipc_msg *request, const char *name)
  426. {
  427. return avs_dsp_send_rom_msg_timeout(adev, request, adev->ipc->default_timeout_ms, name);
  428. }
  429. void avs_dsp_interrupt_control(struct avs_dev *adev, bool enable)
  430. {
  431. const struct avs_spec *const spec = adev->spec;
  432. u32 value, mask;
  433. /*
  434. * No particular bit setting order. All of these are required
  435. * to have a functional SW <-> FW communication.
  436. */
  437. value = enable ? AVS_ADSP_ADSPIC_IPC : 0;
  438. snd_hdac_adsp_updatel(adev, AVS_ADSP_REG_ADSPIC, AVS_ADSP_ADSPIC_IPC, value);
  439. mask = AVS_ADSP_HIPCCTL_DONE | AVS_ADSP_HIPCCTL_BUSY;
  440. value = enable ? mask : 0;
  441. snd_hdac_adsp_updatel(adev, spec->hipc->ctl_offset, mask, value);
  442. }
  443. int avs_ipc_init(struct avs_ipc *ipc, struct device *dev)
  444. {
  445. ipc->rx.data = devm_kzalloc(dev, AVS_MAILBOX_SIZE, GFP_KERNEL);
  446. if (!ipc->rx.data)
  447. return -ENOMEM;
  448. ipc->dev = dev;
  449. ipc->ready = false;
  450. ipc->default_timeout_ms = AVS_IPC_TIMEOUT_MS;
  451. INIT_WORK(&ipc->recovery_work, avs_dsp_recovery_work);
  452. INIT_DELAYED_WORK(&ipc->d0ix_work, avs_dsp_d0ix_work);
  453. init_completion(&ipc->done_completion);
  454. init_completion(&ipc->busy_completion);
  455. spin_lock_init(&ipc->rx_lock);
  456. mutex_init(&ipc->msg_mutex);
  457. return 0;
  458. }
  459. void avs_ipc_block(struct avs_ipc *ipc)
  460. {
  461. ipc->ready = false;
  462. cancel_work_sync(&ipc->recovery_work);
  463. cancel_delayed_work_sync(&ipc->d0ix_work);
  464. ipc->in_d0ix = false;
  465. }