ASoC: wm_adsp: Split firmware load into smaller chunks
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>
Wed, 5 Mar 2014 14:28:16 +0000 (14:28 +0000)
committerMark Brown <broonie@linaro.org>
Thu, 6 Mar 2014 04:34:31 +0000 (12:34 +0800)
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>
Signed-off-by: Mark Brown <broonie@linaro.org>
sound/soc/codecs/wm_adsp.c

index f9fd56444a14d7043a40f4543ab0b7ca1b6c333b..937af6f31ffa3e8c5de2256b1a463663f3b797c4 100644 (file)
@@ -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;
                        }
                }