^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Intel SST generic IPC Support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2015, Intel Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/list.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <sound/asound.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "sst-dsp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include "sst-dsp-priv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "sst-ipc.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /* IPC message timeout (msecs) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define IPC_TIMEOUT_MSECS 300
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define IPC_EMPTY_LIST_SIZE 8
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* locks held by caller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static struct ipc_message *msg_get_empty(struct sst_generic_ipc *ipc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) struct ipc_message *msg = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (!list_empty(&ipc->empty_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) msg = list_first_entry(&ipc->empty_list, struct ipc_message,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) list_del(&msg->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static int tx_wait_done(struct sst_generic_ipc *ipc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) struct ipc_message *msg, struct sst_ipc_message *reply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) /* wait for DSP completion (in all cases atm inc pending) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) ret = wait_event_timeout(msg->waitq, msg->complete,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) msecs_to_jiffies(IPC_TIMEOUT_MSECS));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) spin_lock_irqsave(&ipc->dsp->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (ret == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (ipc->ops.shim_dbg != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) ipc->ops.shim_dbg(ipc, "message timeout");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) list_del(&msg->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) ret = -ETIMEDOUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* copy the data returned from DSP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (reply) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) reply->header = msg->rx.header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) if (reply->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) memcpy(reply->data, msg->rx.data, msg->rx.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) ret = msg->errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) list_add_tail(&msg->list, &ipc->empty_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static int ipc_tx_message(struct sst_generic_ipc *ipc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) struct sst_ipc_message request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct sst_ipc_message *reply, int wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) struct ipc_message *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) spin_lock_irqsave(&ipc->dsp->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) msg = msg_get_empty(ipc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (msg == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) msg->tx.header = request.header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) msg->tx.size = request.size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) msg->rx.header = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) msg->rx.size = reply ? reply->size : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) msg->wait = wait;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) msg->errno = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) msg->pending = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) msg->complete = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if ((request.size) && (ipc->ops.tx_data_copy != NULL))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ipc->ops.tx_data_copy(msg, request.data, request.size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) list_add_tail(&msg->list, &ipc->tx_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) schedule_work(&ipc->kwork);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) spin_unlock_irqrestore(&ipc->dsp->spinlock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return tx_wait_done(ipc, msg, reply);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) static int msg_empty_list_init(struct sst_generic_ipc *ipc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ipc->msg = kcalloc(IPC_EMPTY_LIST_SIZE, sizeof(struct ipc_message),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (ipc->msg == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) ipc->msg[i].tx.data = kzalloc(ipc->tx_data_max_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (ipc->msg[i].tx.data == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) goto free_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) ipc->msg[i].rx.data = kzalloc(ipc->rx_data_max_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (ipc->msg[i].rx.data == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) kfree(ipc->msg[i].tx.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) goto free_mem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) init_waitqueue_head(&ipc->msg[i].waitq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) list_add(&ipc->msg[i].list, &ipc->empty_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) free_mem:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) while (i > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) kfree(ipc->msg[i-1].tx.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) kfree(ipc->msg[i-1].rx.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) --i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) kfree(ipc->msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) static void ipc_tx_msgs(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct sst_generic_ipc *ipc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) container_of(work, struct sst_generic_ipc, kwork);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) struct ipc_message *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) spin_lock_irq(&ipc->dsp->spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) while (!list_empty(&ipc->tx_list) && !ipc->pending) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) /* if the DSP is busy, we will TX messages after IRQ.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * also postpone if we are in the middle of processing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * completion irq
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) if (ipc->ops.is_dsp_busy && ipc->ops.is_dsp_busy(ipc->dsp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) dev_dbg(ipc->dev, "ipc_tx_msgs dsp busy\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) msg = list_first_entry(&ipc->tx_list, struct ipc_message, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) list_move(&msg->list, &ipc->rx_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) if (ipc->ops.tx_msg != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) ipc->ops.tx_msg(ipc, msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) spin_unlock_irq(&ipc->dsp->spinlock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) int sst_ipc_tx_message_wait(struct sst_generic_ipc *ipc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct sst_ipc_message request, struct sst_ipc_message *reply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) * DSP maybe in lower power active state, so
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) * check if the DSP supports DSP lp On method
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) * if so invoke that before sending IPC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) if (ipc->ops.check_dsp_lp_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (ipc->ops.check_dsp_lp_on(ipc->dsp, true))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) ret = ipc_tx_message(ipc, request, reply, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) if (ipc->ops.check_dsp_lp_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) if (ipc->ops.check_dsp_lp_on(ipc->dsp, false))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) EXPORT_SYMBOL_GPL(sst_ipc_tx_message_wait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) int sst_ipc_tx_message_nowait(struct sst_generic_ipc *ipc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct sst_ipc_message request)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return ipc_tx_message(ipc, request, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) EXPORT_SYMBOL_GPL(sst_ipc_tx_message_nowait);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) int sst_ipc_tx_message_nopm(struct sst_generic_ipc *ipc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) struct sst_ipc_message request, struct sst_ipc_message *reply)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return ipc_tx_message(ipc, request, reply, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) EXPORT_SYMBOL_GPL(sst_ipc_tx_message_nopm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) struct ipc_message *sst_ipc_reply_find_msg(struct sst_generic_ipc *ipc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) u64 header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct ipc_message *msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) u64 mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (ipc->ops.reply_msg_match != NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) header = ipc->ops.reply_msg_match(header, &mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) mask = (u64)-1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (list_empty(&ipc->rx_list)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) dev_err(ipc->dev, "error: rx list empty but received 0x%llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) list_for_each_entry(msg, &ipc->rx_list, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if ((msg->tx.header & mask) == header)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) return msg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) EXPORT_SYMBOL_GPL(sst_ipc_reply_find_msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /* locks held by caller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) void sst_ipc_tx_msg_reply_complete(struct sst_generic_ipc *ipc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct ipc_message *msg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) msg->complete = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (!msg->wait)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) list_add_tail(&msg->list, &ipc->empty_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) wake_up(&msg->waitq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) EXPORT_SYMBOL_GPL(sst_ipc_tx_msg_reply_complete);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) int sst_ipc_init(struct sst_generic_ipc *ipc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) INIT_LIST_HEAD(&ipc->tx_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) INIT_LIST_HEAD(&ipc->rx_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) INIT_LIST_HEAD(&ipc->empty_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) init_waitqueue_head(&ipc->wait_txq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) ret = msg_empty_list_init(ipc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) INIT_WORK(&ipc->kwork, ipc_tx_msgs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) EXPORT_SYMBOL_GPL(sst_ipc_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) void sst_ipc_fini(struct sst_generic_ipc *ipc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) cancel_work_sync(&ipc->kwork);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (ipc->msg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) kfree(ipc->msg[i].tx.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) kfree(ipc->msg[i].rx.data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) kfree(ipc->msg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) EXPORT_SYMBOL_GPL(sst_ipc_fini);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) /* Module information */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) MODULE_AUTHOR("Jin Yao");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) MODULE_DESCRIPTION("Intel SST IPC generic");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) MODULE_LICENSE("GPL v2");