summaryrefslogtreecommitdiff
path: root/drivers/base
diff options
context:
space:
mode:
authorDeepak Nibade <dnibade@nvidia.com>2014-06-10 18:51:00 +0530
committerSimone Willett <swillett@nvidia.com>2014-06-20 10:53:52 -0700
commitc47990a2ee14ea889f5a9f69cac0e2712cb5e43c (patch)
treeca1f61d910325c378af9e62fbd2c3914154f65c8 /drivers/base
parent64b4af9f0c0ab51006ccdd573f6794d94977281c (diff)
dma: coherent: error handling on heap resize failure
- Update memory resize callbacks to return error codes - error handling on heap resize update failure Bug 1487804 Bug 1517584 Change-Id: I5ac044677e883fbecf6d04a8c1e83794325703f3 Signed-off-by: Deepak Nibade <dnibade@nvidia.com> Signed-off-by: Vandana Salve <vsalve@nvidia.com> Reviewed-on: http://git-master/r/423748 Reviewed-by: Krishna Reddy <vdumpa@nvidia.com> Reviewed-by: Bharat Nihalani <bnihalani@nvidia.com>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/dma-coherent.c88
1 files changed, 66 insertions, 22 deletions
diff --git a/drivers/base/dma-coherent.c b/drivers/base/dma-coherent.c
index 47e791afea66..e07ad7911e20 100644
--- a/drivers/base/dma-coherent.c
+++ b/drivers/base/dma-coherent.c
@@ -35,7 +35,7 @@ struct heap_info {
size_t cma_len;
size_t rem_chunk_size;
struct dentry *dma_debug_root;
- void (*update_resize_cfg)(phys_addr_t , size_t);
+ int (*update_resize_cfg)(phys_addr_t , size_t);
};
#define DMA_RESERVED_COUNT 8
@@ -329,19 +329,26 @@ static int heap_resize_locked(struct heap_info *h)
phys_addr_t base;
bool at_bottom = false;
size_t cma_chunk_size = h->cma_chunk_size;
+ int err = 0;
base = alloc_from_contiguous_heap(h, 0, h->cma_chunk_size);
- if (dma_mapping_error(h->cma_dev, base))
+ if (dma_mapping_error(h->cma_dev, base)) {
+ dev_err(&h->devs[idx],
+ "Failed to allocate contiguous memory on resize\n");
return 1;
-
+ }
idx = div_u64(base - h->cma_base, h->cma_chunk_size);
- if (!h->len || base == h->base - h->cma_chunk_size)
+ if (!h->len || base == h->base - h->cma_chunk_size) {
/* new chunk can be added at bottom. */
+ h->base = base;
at_bottom = true;
- else if (base != h->base + h->len)
+ } else if (base != h->base + h->len) {
/* new chunk can't be added at top */
+ dev_err(&h->devs[idx],
+ "Failed to get contiguous block(0x%pa) on resize\n",
+ &base);
goto fail_non_contig;
-
+ }
BUG_ON(h->dev_start - 1 != idx && h->dev_end + 1 != idx && h->len);
if (h->len && (h->dev_end + 1 == (h->num_devs - 1))
&& h->rem_chunk_size) {
@@ -349,11 +356,21 @@ static int heap_resize_locked(struct heap_info *h)
dev_dbg(h->cma_dev, "rem_chunk_size (%d)\n", cma_chunk_size);
}
- if (declare_coherent_heap(&h->devs[idx], base, cma_chunk_size))
- goto fail_declare;
+ if (declare_coherent_heap(&h->devs[idx], base, cma_chunk_size)) {
+ dev_err(&h->devs[idx],
+ "Failed to declare coherent memory on resize\n");
+ goto fail_non_contig;
+ }
+ /* Handle VPR configuration updates*/
+ if (h->update_resize_cfg) {
+ err = h->update_resize_cfg(h->base, h->len + cma_chunk_size);
+ if (err) {
+ dev_err(&h->devs[idx], "Failed to update VPR resize\n");
+ goto fail_update;
+ }
+ }
if (at_bottom) {
- h->base = base;
h->dev_start = idx;
if (!h->len)
h->dev_end = h->dev_start;
@@ -369,14 +386,11 @@ static int heap_resize_locked(struct heap_info *h)
}
h->len += cma_chunk_size;
- /* Handle VPR configuration updates*/
- if (h->update_resize_cfg)
- h->update_resize_cfg(h->base, h->len);
return 0;
+fail_update:
+ dma_release_declared_memory(&h->devs[idx]);
fail_non_contig:
- dev_dbg(&h->devs[idx], "Found Non-Contiguous block(0x%pa)\n", &base);
-fail_declare:
release_from_contiguous_heap(h, base, cma_chunk_size);
return 1;
}
@@ -530,7 +544,7 @@ static int dma_release_from_coherent_heap_dev(struct device *dev, size_t len,
int err = 0;
int resize_err = 0;
void *ret = NULL;
- dma_addr_t dev_base;
+ dma_addr_t dev_base, update_base;
struct heap_info *h = NULL;
size_t cma_chunk_size = h->cma_chunk_size;
@@ -585,10 +599,43 @@ check_next_chunk:
&h->devs[idx]);
BUG_ON(h->devs[idx].dma_mem != NULL);
h->len -= cma_chunk_size;
+ update_base = h->base;
+
+ if ((idx == h->dev_start))
+ update_base += cma_chunk_size;
+
+ /* Handle VPR configuration updates */
+ if (h->update_resize_cfg) {
+ resize_err =
+ h->update_resize_cfg(update_base,
+ h->len);
+ if (resize_err) {
+ /* On update failure re-declare heap */
+ err = declare_coherent_heap(
+ &h->devs[idx], dev_base,
+ cma_chunk_size);
+ if (!err)
+ h->len += cma_chunk_size;
+ else {
+ /* on declare coherent failure release
+ * heap chunk
+ */
+ release_from_contiguous_heap(
+ h, dev_base,
+ cma_chunk_size);
+
+ dev_err(&h->devs[idx],
+ "Failed to update VPR "
+ "resize\n");
+ }
+
+ goto out_unlock;
+ }
+ }
- if ((idx == h->dev_start)) {
- h->base += cma_chunk_size;
+ if (idx == h->dev_start) {
h->dev_start++;
+ h->base = update_base;
dev_dbg(&h->devs[idx],
"Release Chunk at bottom\n");
dev_dbg(&h->devs[idx],
@@ -609,11 +656,8 @@ check_next_chunk:
idx--;
}
- /* Handle VPR configuration updates*/
- if (h->update_resize_cfg)
- h->update_resize_cfg(h->base, h->len);
- release_from_contiguous_heap(h,
- dev_base, cma_chunk_size);
+ release_from_contiguous_heap(h, dev_base,
+ cma_chunk_size);
}
goto check_next_chunk;
}