[alsa-devel] [PATCH v2 0/8] ASoC: Intel: refactor common SST IPC handling
This series refactors the common SST IPC code to remove some hardcoded assumption which are no longer valid for future platforms like Skylake, These are made configurable and right configuration applied for respective drivers. The changes are mailbox sizes and dsp busy checks.
changes in v2: - fix the mem allocation for IPC mailbox
Subhransu S. Prusty (8): ASoC: Intel: Create an ops to check for DSP busy ASoC: Intel: Move the busy check to ops for Baytrail ASoC: Intel: Move the busy check to ops for HSW ASoC: Intel: Remove the direct register reference from common ipc ASoC: Intel: Allow to configure max size for mailbox data ASoC: Intel: Initialize max mailbox size for baytrail ASoC: Intel: Initialize max mailbox size for haswell ASoC: Intel: Allocate for the mailbox with max size
sound/soc/intel/baytrail/sst-baytrail-ipc.c | 11 ++++++++++ sound/soc/intel/common/sst-ipc.c | 34 +++++++++++++++++++++++++---- sound/soc/intel/common/sst-ipc.h | 7 ++++-- sound/soc/intel/haswell/sst-haswell-ipc.c | 12 ++++++++++ 4 files changed, 58 insertions(+), 6 deletions(-)
From: "Subhransu S. Prusty" subhransu.s.prusty@intel.com
Created an ops to check if DSP busy, to avoid using platform specific registers in common IPC.
Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/common/sst-ipc.h | 1 + 1 file changed, 1 insertion(+)
diff --git a/sound/soc/intel/common/sst-ipc.h b/sound/soc/intel/common/sst-ipc.h index 125ea451a373..77a3befd16b0 100644 --- a/sound/soc/intel/common/sst-ipc.h +++ b/sound/soc/intel/common/sst-ipc.h @@ -51,6 +51,7 @@ struct sst_plat_ipc_ops { void (*shim_dbg)(struct sst_generic_ipc *, const char *); void (*tx_data_copy)(struct ipc_message *, char *, size_t); u64 (*reply_msg_match)(u64 header, u64 *mask); + bool (*is_dsp_busy)(struct sst_dsp *dsp); };
/* SST generic IPC data */
From: "Subhransu S. Prusty" subhransu.s.prusty@intel.com
Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/baytrail/sst-baytrail-ipc.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/sound/soc/intel/baytrail/sst-baytrail-ipc.c b/sound/soc/intel/baytrail/sst-baytrail-ipc.c index 1efb33b36303..799b804f3e34 100644 --- a/sound/soc/intel/baytrail/sst-baytrail-ipc.c +++ b/sound/soc/intel/baytrail/sst-baytrail-ipc.c @@ -679,6 +679,14 @@ static u64 byt_reply_msg_match(u64 header, u64 *mask) return header; }
+static bool byt_is_dsp_busy(struct sst_dsp *dsp) +{ + u64 ipcx; + + ipcx = sst_dsp_shim_read_unlocked(dsp, SST_IPCX); + return (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)); +} + int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) { struct sst_byt *byt; @@ -699,6 +707,7 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) ipc->ops.shim_dbg = byt_shim_dbg; ipc->ops.tx_data_copy = byt_tx_data_copy; ipc->ops.reply_msg_match = byt_reply_msg_match; + ipc->ops.is_dsp_busy = byt_is_dsp_busy;
err = sst_ipc_init(ipc); if (err != 0)
From: "Subhransu S. Prusty" subhransu.s.prusty@intel.com
Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/haswell/sst-haswell-ipc.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/sound/soc/intel/haswell/sst-haswell-ipc.c b/sound/soc/intel/haswell/sst-haswell-ipc.c index 324eceb07b25..6304e4bfccd6 100644 --- a/sound/soc/intel/haswell/sst-haswell-ipc.c +++ b/sound/soc/intel/haswell/sst-haswell-ipc.c @@ -2098,6 +2098,14 @@ static u64 hsw_reply_msg_match(u64 header, u64 *mask) return header; }
+static bool hsw_is_dsp_busy(struct sst_dsp *dsp) +{ + u64 ipcx; + + ipcx = sst_dsp_shim_read_unlocked(dsp, SST_IPCX); + return (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)); +} + int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) { struct sst_hsw_ipc_fw_version version; @@ -2117,6 +2125,7 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) ipc->ops.shim_dbg = hsw_shim_dbg; ipc->ops.tx_data_copy = hsw_tx_data_copy; ipc->ops.reply_msg_match = hsw_reply_msg_match; + ipc->ops.is_dsp_busy = hsw_is_dsp_busy;
ret = sst_ipc_init(ipc); if (ret != 0)
From: "Subhransu S. Prusty" subhransu.s.prusty@intel.com
Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/common/sst-ipc.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c index 4b62a553823c..a7699f35a8d2 100644 --- a/sound/soc/intel/common/sst-ipc.c +++ b/sound/soc/intel/common/sst-ipc.c @@ -142,7 +142,6 @@ static void ipc_tx_msgs(struct kthread_work *work) container_of(work, struct sst_generic_ipc, kwork); struct ipc_message *msg; unsigned long flags; - u64 ipcx;
spin_lock_irqsave(&ipc->dsp->spinlock, flags);
@@ -153,8 +152,8 @@ static void ipc_tx_msgs(struct kthread_work *work)
/* if the DSP is busy, we will TX messages after IRQ. * also postpone if we are in the middle of procesing completion irq*/ - ipcx = sst_dsp_shim_read_unlocked(ipc->dsp, SST_IPCX); - if (ipcx & (SST_IPCX_BUSY | SST_IPCX_DONE)) { + if (ipc->ops.is_dsp_busy && ipc->ops.is_dsp_busy(ipc->dsp)) { + dev_dbg(ipc->dev, "ipc_tx_msgs dsp busy\n"); spin_unlock_irqrestore(&ipc->dsp->spinlock, flags); return; }
From: "Subhransu S. Prusty" subhransu.s.prusty@intel.com
Mailbox size can be different for different platforms. So allow the drivers to configure the size.
Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/common/sst-ipc.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/sound/soc/intel/common/sst-ipc.h b/sound/soc/intel/common/sst-ipc.h index 77a3befd16b0..7139afd2547f 100644 --- a/sound/soc/intel/common/sst-ipc.h +++ b/sound/soc/intel/common/sst-ipc.h @@ -69,6 +69,8 @@ struct sst_generic_ipc { struct kthread_work kwork; bool pending; struct ipc_message *msg; + int tx_data_max_size; + int rx_data_max_size;
struct sst_plat_ipc_ops ops; };
From: "Subhransu S. Prusty" subhransu.s.prusty@intel.com
Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/baytrail/sst-baytrail-ipc.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/sound/soc/intel/baytrail/sst-baytrail-ipc.c b/sound/soc/intel/baytrail/sst-baytrail-ipc.c index 799b804f3e34..773a47552bdf 100644 --- a/sound/soc/intel/baytrail/sst-baytrail-ipc.c +++ b/sound/soc/intel/baytrail/sst-baytrail-ipc.c @@ -708,6 +708,8 @@ int sst_byt_dsp_init(struct device *dev, struct sst_pdata *pdata) ipc->ops.tx_data_copy = byt_tx_data_copy; ipc->ops.reply_msg_match = byt_reply_msg_match; ipc->ops.is_dsp_busy = byt_is_dsp_busy; + ipc->tx_data_max_size = IPC_MAX_MAILBOX_BYTES; + ipc->rx_data_max_size = IPC_MAX_MAILBOX_BYTES;
err = sst_ipc_init(ipc); if (err != 0)
From: "Subhransu S. Prusty" subhransu.s.prusty@intel.com
Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/haswell/sst-haswell-ipc.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/sound/soc/intel/haswell/sst-haswell-ipc.c b/sound/soc/intel/haswell/sst-haswell-ipc.c index 6304e4bfccd6..f95f271aab0c 100644 --- a/sound/soc/intel/haswell/sst-haswell-ipc.c +++ b/sound/soc/intel/haswell/sst-haswell-ipc.c @@ -2127,6 +2127,9 @@ int sst_hsw_dsp_init(struct device *dev, struct sst_pdata *pdata) ipc->ops.reply_msg_match = hsw_reply_msg_match; ipc->ops.is_dsp_busy = hsw_is_dsp_busy;
+ ipc->tx_data_max_size = IPC_MAX_MAILBOX_BYTES; + ipc->rx_data_max_size = IPC_MAX_MAILBOX_BYTES; + ret = sst_ipc_init(ipc); if (ret != 0) goto ipc_init_err;
On Tue, May 19, 2015 at 03:00:39PM +0530, Vinod Koul wrote:
From: "Subhransu S. Prusty" subhransu.s.prusty@intel.com
Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com
Applied up to here, thanks.
From: "Subhransu S. Prusty" subhransu.s.prusty@intel.com
Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com --- sound/soc/intel/common/sst-ipc.c | 29 ++++++++++++++++++++++++++++- sound/soc/intel/common/sst-ipc.h | 4 ++-- 2 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c index a7699f35a8d2..a12c7bb08d3b 100644 --- a/sound/soc/intel/common/sst-ipc.c +++ b/sound/soc/intel/common/sst-ipc.c @@ -129,11 +129,31 @@ static int msg_empty_list_init(struct sst_generic_ipc *ipc) return -ENOMEM;
for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { + ipc->msg[i].tx_data = kzalloc(ipc->tx_data_max_size, GFP_KERNEL); + if (ipc->msg[i].tx_data == NULL) + goto free_mem; + + ipc->msg[i].rx_data = kzalloc(ipc->rx_data_max_size, GFP_KERNEL); + if (ipc->msg[i].rx_data == NULL) { + kfree(ipc->msg[i].tx_data); + goto free_mem; + } + init_waitqueue_head(&ipc->msg[i].waitq); list_add(&ipc->msg[i].list, &ipc->empty_list); }
return 0; + +free_mem: + while (i > 0) { + kfree(ipc->msg[i-1].tx_data); + kfree(ipc->msg[i-1].rx_data); + --i; + } + kfree(ipc->msg); + + return -ENOMEM; }
static void ipc_tx_msgs(struct kthread_work *work) @@ -279,11 +299,18 @@ EXPORT_SYMBOL_GPL(sst_ipc_init);
void sst_ipc_fini(struct sst_generic_ipc *ipc) { + int i; + if (ipc->tx_thread) kthread_stop(ipc->tx_thread);
- if (ipc->msg) + if (ipc->msg) { + for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) { + kfree(ipc->msg[i].tx_data); + kfree(ipc->msg[i].rx_data); + } kfree(ipc->msg); + } } EXPORT_SYMBOL_GPL(sst_ipc_fini);
diff --git a/sound/soc/intel/common/sst-ipc.h b/sound/soc/intel/common/sst-ipc.h index 7139afd2547f..ceb7e468a3fa 100644 --- a/sound/soc/intel/common/sst-ipc.h +++ b/sound/soc/intel/common/sst-ipc.h @@ -32,9 +32,9 @@ struct ipc_message { u64 header;
/* direction wrt host CPU */ - char tx_data[IPC_MAX_MAILBOX_BYTES]; + char *tx_data; size_t tx_size; - char rx_data[IPC_MAX_MAILBOX_BYTES]; + char *rx_data; size_t rx_size;
wait_queue_head_t waitq;
At Tue, 19 May 2015 15:00:40 +0530, Vinod Koul wrote:
From: "Subhransu S. Prusty" subhransu.s.prusty@intel.com
Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com
sound/soc/intel/common/sst-ipc.c | 29 ++++++++++++++++++++++++++++- sound/soc/intel/common/sst-ipc.h | 4 ++-- 2 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c index a7699f35a8d2..a12c7bb08d3b 100644 --- a/sound/soc/intel/common/sst-ipc.c +++ b/sound/soc/intel/common/sst-ipc.c @@ -129,11 +129,31 @@ static int msg_empty_list_init(struct sst_generic_ipc *ipc) return -ENOMEM;
for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) {
ipc->msg[i].tx_data = kzalloc(ipc->tx_data_max_size, GFP_KERNEL);
if (ipc->msg[i].tx_data == NULL)
goto free_mem;
ipc->msg[i].rx_data = kzalloc(ipc->rx_data_max_size, GFP_KERNEL);
if (ipc->msg[i].rx_data == NULL) {
kfree(ipc->msg[i].tx_data);
goto free_mem;
}
- init_waitqueue_head(&ipc->msg[i].waitq); list_add(&ipc->msg[i].list, &ipc->empty_list);
Wouldn't this leave stale linked list entries at error?
Takashi
}
return 0;
+free_mem:
- while (i > 0) {
kfree(ipc->msg[i-1].tx_data);
kfree(ipc->msg[i-1].rx_data);
--i;
- }
- kfree(ipc->msg);
- return -ENOMEM;
}
static void ipc_tx_msgs(struct kthread_work *work) @@ -279,11 +299,18 @@ EXPORT_SYMBOL_GPL(sst_ipc_init);
void sst_ipc_fini(struct sst_generic_ipc *ipc) {
- int i;
- if (ipc->tx_thread) kthread_stop(ipc->tx_thread);
- if (ipc->msg)
- if (ipc->msg) {
for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) {
kfree(ipc->msg[i].tx_data);
kfree(ipc->msg[i].rx_data);
kfree(ipc->msg);}
- }
} EXPORT_SYMBOL_GPL(sst_ipc_fini);
diff --git a/sound/soc/intel/common/sst-ipc.h b/sound/soc/intel/common/sst-ipc.h index 7139afd2547f..ceb7e468a3fa 100644 --- a/sound/soc/intel/common/sst-ipc.h +++ b/sound/soc/intel/common/sst-ipc.h @@ -32,9 +32,9 @@ struct ipc_message { u64 header;
/* direction wrt host CPU */
- char tx_data[IPC_MAX_MAILBOX_BYTES];
- char *tx_data; size_t tx_size;
- char rx_data[IPC_MAX_MAILBOX_BYTES];
char *rx_data; size_t rx_size;
wait_queue_head_t waitq;
-- 1.9.1
On Tue, May 19, 2015 at 12:42:03PM +0200, Takashi Iwai wrote:
At Tue, 19 May 2015 15:00:40 +0530, Vinod Koul wrote:
From: "Subhransu S. Prusty" subhransu.s.prusty@intel.com
Signed-off-by: Subhransu S. Prusty subhransu.s.prusty@intel.com Signed-off-by: Vinod Koul vinod.koul@intel.com
sound/soc/intel/common/sst-ipc.c | 29 ++++++++++++++++++++++++++++- sound/soc/intel/common/sst-ipc.h | 4 ++-- 2 files changed, 30 insertions(+), 3 deletions(-)
diff --git a/sound/soc/intel/common/sst-ipc.c b/sound/soc/intel/common/sst-ipc.c index a7699f35a8d2..a12c7bb08d3b 100644 --- a/sound/soc/intel/common/sst-ipc.c +++ b/sound/soc/intel/common/sst-ipc.c @@ -129,11 +129,31 @@ static int msg_empty_list_init(struct sst_generic_ipc *ipc) return -ENOMEM;
for (i = 0; i < IPC_EMPTY_LIST_SIZE; i++) {
ipc->msg[i].tx_data = kzalloc(ipc->tx_data_max_size, GFP_KERNEL);
if (ipc->msg[i].tx_data == NULL)
goto free_mem;
ipc->msg[i].rx_data = kzalloc(ipc->rx_data_max_size, GFP_KERNEL);
if (ipc->msg[i].rx_data == NULL) {
kfree(ipc->msg[i].tx_data);
goto free_mem;
}
- init_waitqueue_head(&ipc->msg[i].waitq); list_add(&ipc->msg[i].list, &ipc->empty_list);
Wouldn't this leave stale linked list entries at error?
Yes it will, but this is happening at device probe, so the probe will fail and device will no longer be usable. We do free the memory so shouldn't leak.
On Tue, 2015-05-19 at 15:00 +0530, Vinod Koul wrote:
This series refactors the common SST IPC code to remove some hardcoded assumption which are no longer valid for future platforms like Skylake, These are made configurable and right configuration applied for respective drivers. The changes are mailbox sizes and dsp busy checks.
changes in v2:
- fix the mem allocation for IPC mailbox
Subhransu S. Prusty (8): ASoC: Intel: Create an ops to check for DSP busy ASoC: Intel: Move the busy check to ops for Baytrail ASoC: Intel: Move the busy check to ops for HSW ASoC: Intel: Remove the direct register reference from common ipc ASoC: Intel: Allow to configure max size for mailbox data ASoC: Intel: Initialize max mailbox size for baytrail ASoC: Intel: Initialize max mailbox size for haswell ASoC: Intel: Allocate for the mailbox with max size
sound/soc/intel/baytrail/sst-baytrail-ipc.c | 11 ++++++++++ sound/soc/intel/common/sst-ipc.c | 34 +++++++++++++++++++++++++---- sound/soc/intel/common/sst-ipc.h | 7 ++++-- sound/soc/intel/haswell/sst-haswell-ipc.c | 12 ++++++++++ 4 files changed, 58 insertions(+), 6 deletions(-)
Acked-by: Liam Girdwood liam.r.girdwood@linux.intel.com
participants (4)
-
Liam Girdwood
-
Mark Brown
-
Takashi Iwai
-
Vinod Koul