ASoC: wm_adsp: Split firmware load into smaller chunks
diff mbox

Message ID 1394029696-25975-1-git-send-email-ckeepax@opensource.wolfsonmicro.com
State Accepted
Commit c1a7898d655fd265feefcf6fe82ab0096e6d078e
Headers show

Commit Message

Charles Keepax March 5, 2014, 2:28 p.m. UTC
The firmware files can be quite large and allocating the whole firmware
a single DMA safe buffer can be problematic if the system is under a
high memory load. Ease the requirements slightly by writing the firmware
out in page sized chunks.

Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com>
---
 sound/soc/codecs/wm_adsp.c |   50 ++++++++++++++++++++++++++++---------------
 1 files changed, 32 insertions(+), 18 deletions(-)

Comments

Mark Brown March 6, 2014, 4:35 a.m. UTC | #1
On Wed, Mar 05, 2014 at 02:28:16PM +0000, Charles Keepax wrote:
> The firmware files can be quite large and allocating the whole firmware
> a single DMA safe buffer can be problematic if the system is under a
> high memory load. Ease the requirements slightly by writing the firmware
> out in page sized chunks.

Applied, thanks.
Mark Brown March 12, 2014, 12:29 a.m. UTC | #2
On Wed, Mar 05, 2014 at 02:28:16PM +0000, Charles Keepax wrote:
> The firmware files can be quite large and allocating the whole firmware
> a single DMA safe buffer can be problematic if the system is under a
> high memory load. Ease the requirements slightly by writing the firmware
> out in page sized chunks.

While looking at some other related stuff it occurred to me that while
this is probably what you want for your backported code for upstream you
probably want to just convert to vmalloc() - SPI will do DMA mappings in
page sized chunks in order to support this so you get a similar effect
but without needing to split into multiple physical writes so it can all
be pushed down into hardware for best performance.
Charles Keepax March 12, 2014, 3:31 p.m. UTC | #3
On Wed, Mar 12, 2014 at 12:29:06AM +0000, Mark Brown wrote:
> On Wed, Mar 05, 2014 at 02:28:16PM +0000, Charles Keepax wrote:
> > The firmware files can be quite large and allocating the whole firmware
> > a single DMA safe buffer can be problematic if the system is under a
> > high memory load. Ease the requirements slightly by writing the firmware
> > out in page sized chunks.
> 
> While looking at some other related stuff it occurred to me that while
> this is probably what you want for your backported code for upstream you
> probably want to just convert to vmalloc() - SPI will do DMA mappings in
> page sized chunks in order to support this so you get a similar effect
> but without needing to split into multiple physical writes so it can all
> be pushed down into hardware for best performance.

Sounds sensible I will look at testing this and doing a patch for
it.

Thanks,
Charles

Patch
diff mbox

diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index f9fd564..937af6f 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -684,24 +684,38 @@  static int wm_adsp_load(struct wm_adsp *dsp)
 		}
 
 		if (reg) {
-			buf = wm_adsp_buf_alloc(region->data,
-						le32_to_cpu(region->len),
-						&buf_list);
-			if (!buf) {
-				adsp_err(dsp, "Out of memory\n");
-				ret = -ENOMEM;
-				goto out_fw;
-			}
+			size_t to_write = PAGE_SIZE;
+			size_t remain = le32_to_cpu(region->len);
+			const u8 *data = region->data;
+
+			while (remain > 0) {
+				if (remain < PAGE_SIZE)
+					to_write = remain;
+
+				buf = wm_adsp_buf_alloc(data,
+							to_write,
+							&buf_list);
+				if (!buf) {
+					adsp_err(dsp, "Out of memory\n");
+					ret = -ENOMEM;
+					goto out_fw;
+				}
 
-			ret = regmap_raw_write_async(regmap, reg, buf->buf,
-						     le32_to_cpu(region->len));
-			if (ret != 0) {
-				adsp_err(dsp,
-					"%s.%d: Failed to write %d bytes at %d in %s: %d\n",
-					file, regions,
-					le32_to_cpu(region->len), offset,
-					region_name, ret);
-				goto out_fw;
+				ret = regmap_raw_write_async(regmap, reg,
+							     buf->buf,
+							     to_write);
+				if (ret != 0) {
+					adsp_err(dsp,
+						"%s.%d: Failed to write %d bytes at %d in %s: %d\n",
+						file, regions,
+						to_write, offset,
+						region_name, ret);
+					goto out_fw;
+				}
+
+				data += to_write;
+				reg += to_write / 2;
+				remain -= to_write;
 			}
 		}