From patchwork Fri Nov 2 15:25:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jordan Crouse X-Patchwork-Id: 10665677 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1CEB7109C for ; Fri, 2 Nov 2018 15:26:03 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 095F828D72 for ; Fri, 2 Nov 2018 15:26:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F16522B5BF; Fri, 2 Nov 2018 15:26:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id F17AA2B5D7 for ; Fri, 2 Nov 2018 15:26:01 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D5A846E568; Fri, 2 Nov 2018 15:26:00 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from smtp.codeaurora.org (smtp.codeaurora.org [198.145.29.96]) by gabe.freedesktop.org (Postfix) with ESMTPS id 527186E567; Fri, 2 Nov 2018 15:25:59 +0000 (UTC) Received: by smtp.codeaurora.org (Postfix, from userid 1000) id DE74860C64; Fri, 2 Nov 2018 15:25:41 +0000 (UTC) Received: from jcrouse-lnx.qualcomm.com (i-global254.qualcomm.com [199.106.103.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: jcrouse@smtp.codeaurora.org) by smtp.codeaurora.org (Postfix) with ESMTPSA id 3C65961322; Fri, 2 Nov 2018 15:25:38 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 smtp.codeaurora.org 3C65961322 From: Jordan Crouse To: freedreno@lists.freedesktop.org Subject: [PATCH 10/10] drm/msm/a6xx: Track and manage a6xx state memory Date: Fri, 2 Nov 2018 09:25:26 -0600 Message-Id: <20181102152526.23854-11-jcrouse@codeaurora.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20181102152526.23854-1-jcrouse@codeaurora.org> References: <20181102152526.23854-1-jcrouse@codeaurora.org> X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-arm-msm@vger.kernel.org, hoegsberg@chromium.org, smasetty@codeaurora.org, dri-devel@lists.freedesktop.org MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP The a6xx GPU state allocates a LOT of memory. Add a bit of infrastructure to track the memory allocations in the GPU structure and delete them when the state is destroyed much the same way that devm works with the device model as a whole. This protects against the developer accidentally forgetting to add a kfree() to an ever growing list. Signed-off-by: Jordan Crouse --- drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c | 192 +++++++++++--------- 1 file changed, 102 insertions(+), 90 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c index 20f5b914c6fb..ec57ddeb8c77 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c @@ -41,6 +41,8 @@ struct a6xx_gpu_state { struct a6xx_gpu_state_obj *cx_debugbus; int nr_cx_debugbus; + + struct list_head objs; }; static inline int CRASHDUMP_WRITE(u64 *in, u32 reg, u32 val) @@ -73,6 +75,33 @@ struct a6xx_crashdumper { u64 iova; }; +struct a6xx_state_memobj { + struct list_head node; + unsigned long long data[]; +}; + +void *state_kcalloc(struct a6xx_gpu_state *a6xx_state, int nr, size_t objsize) +{ + struct a6xx_state_memobj *obj = + kzalloc((nr * objsize) + sizeof(*obj), GFP_KERNEL); + + if (!obj) + return NULL; + + list_add_tail(&obj->node, &a6xx_state->objs); + return &obj->data; +} + +void *state_kmemdup(struct a6xx_gpu_state *a6xx_state, void *src, + size_t size) +{ + void *dst = state_kcalloc(a6xx_state, 1, size); + + if (dst) + memcpy(dst, src, size); + return dst; +} + /* * Allocate 1MB for the crashdumper scratch region - 8k for the script and * the rest for the data @@ -203,12 +232,17 @@ static int vbif_debugbus_read(struct msm_gpu *gpu, u32 ctrl0, u32 ctrl1, (12 * XIN_CORE_BLOCKS)) static void a6xx_get_vbif_debugbus_block(struct msm_gpu *gpu, + struct a6xx_gpu_state *a6xx_state, struct a6xx_gpu_state_obj *obj) { u32 clk, *ptr; int i; - obj->data = kcalloc(VBIF_DEBUGBUS_BLOCK_SIZE, sizeof(u32), GFP_KERNEL); + obj->data = state_kcalloc(a6xx_state, VBIF_DEBUGBUS_BLOCK_SIZE, + sizeof(u32)); + if (!obj->data) + return; + obj->handle = NULL; /* Get the current clock setting */ @@ -252,13 +286,14 @@ static void a6xx_get_vbif_debugbus_block(struct msm_gpu *gpu, } static void a6xx_get_debugbus_block(struct msm_gpu *gpu, + struct a6xx_gpu_state *a6xx_state, const struct a6xx_debugbus_block *block, struct a6xx_gpu_state_obj *obj) { int i; u32 *ptr; - obj->data = kcalloc(block->count, sizeof(u64), GFP_KERNEL); + obj->data = state_kcalloc(a6xx_state, block->count, sizeof(u64)); if (!obj->data) return; @@ -269,13 +304,14 @@ static void a6xx_get_debugbus_block(struct msm_gpu *gpu, } static void a6xx_get_cx_debugbus_block(void __iomem *cxdbg, + struct a6xx_gpu_state *a6xx_state, const struct a6xx_debugbus_block *block, struct a6xx_gpu_state_obj *obj) { int i; u32 *ptr; - obj->data = kcalloc(block->count, sizeof(u64), GFP_KERNEL); + obj->data = state_kcalloc(a6xx_state, block->count, sizeof(u64)); if (!obj->data) return; @@ -344,36 +380,42 @@ static void a6xx_get_debugbus(struct msm_gpu *gpu, cxdbg_write(cxdbg, REG_A6XX_DBGC_CFG_DBGBUS_MASKL_3, 0); } - a6xx_state->debugbus = kcalloc(ARRAY_SIZE(a6xx_debugbus_blocks), - sizeof(*a6xx_state->debugbus), GFP_KERNEL); + a6xx_state->debugbus = state_kcalloc(a6xx_state, + ARRAY_SIZE(a6xx_debugbus_blocks), + sizeof(*a6xx_state->debugbus)); if (a6xx_state->debugbus) { int i; for (i = 0; i < ARRAY_SIZE(a6xx_debugbus_blocks); i++) a6xx_get_debugbus_block(gpu, + a6xx_state, &a6xx_debugbus_blocks[i], &a6xx_state->debugbus[i]); a6xx_state->nr_debugbus = ARRAY_SIZE(a6xx_debugbus_blocks); } - a6xx_state->vbif_debugbus = kzalloc(sizeof(*a6xx_state->vbif_debugbus), - GFP_KERNEL); + a6xx_state->vbif_debugbus = + state_kcalloc(a6xx_state, 1, + sizeof(*a6xx_state->vbif_debugbus)); if (a6xx_state->vbif_debugbus) - a6xx_get_vbif_debugbus_block(gpu, a6xx_state->vbif_debugbus); + a6xx_get_vbif_debugbus_block(gpu, a6xx_state, + a6xx_state->vbif_debugbus); if (cxdbg) { a6xx_state->cx_debugbus = - kcalloc(ARRAY_SIZE(a6xx_cx_debugbus_blocks), - sizeof(*a6xx_state->cx_debugbus), GFP_KERNEL); + state_kcalloc(a6xx_state, + ARRAY_SIZE(a6xx_cx_debugbus_blocks), + sizeof(*a6xx_state->cx_debugbus)); if (a6xx_state->cx_debugbus) { int i; for (i = 0; i < ARRAY_SIZE(a6xx_cx_debugbus_blocks); i++) a6xx_get_cx_debugbus_block(cxdbg, + a6xx_state, &a6xx_cx_debugbus_blocks[i], &a6xx_state->cx_debugbus[i]); @@ -389,6 +431,7 @@ static void a6xx_get_debugbus(struct msm_gpu *gpu, /* Read a data cluster from behind the AHB aperture */ static void a6xx_get_dbgahb_cluster(struct msm_gpu *gpu, + struct a6xx_gpu_state *a6xx_state, const struct a6xx_dbgahb_cluster *dbgahb, struct a6xx_gpu_state_obj *obj, struct a6xx_crashdumper *dumper) @@ -429,8 +472,8 @@ static void a6xx_get_dbgahb_cluster(struct msm_gpu *gpu, return; obj->handle = dbgahb; - obj->data = kmemdup(dumper->ptr + A6XX_CD_DATA_OFFSET, - datasize, GFP_KERNEL); + obj->data = state_kmemdup(a6xx_state, dumper->ptr + A6XX_CD_DATA_OFFSET, + datasize); } static void a6xx_get_dbgahb_clusters(struct msm_gpu *gpu, @@ -439,8 +482,9 @@ static void a6xx_get_dbgahb_clusters(struct msm_gpu *gpu, { int i; - a6xx_state->dbgahb_clusters = kcalloc(ARRAY_SIZE(a6xx_dbgahb_clusters), - sizeof(*a6xx_state->dbgahb_clusters), GFP_KERNEL); + a6xx_state->dbgahb_clusters = state_kcalloc(a6xx_state, + ARRAY_SIZE(a6xx_dbgahb_clusters), + sizeof(*a6xx_state->dbgahb_clusters)); if (!a6xx_state->dbgahb_clusters) return; @@ -448,12 +492,14 @@ static void a6xx_get_dbgahb_clusters(struct msm_gpu *gpu, a6xx_state->nr_dbgahb_clusters = ARRAY_SIZE(a6xx_dbgahb_clusters); for (i = 0; i < ARRAY_SIZE(a6xx_dbgahb_clusters); i++) - a6xx_get_dbgahb_cluster(gpu, &a6xx_dbgahb_clusters[i], + a6xx_get_dbgahb_cluster(gpu, a6xx_state, + &a6xx_dbgahb_clusters[i], &a6xx_state->dbgahb_clusters[i], dumper); } /* Read a data cluster from the CP aperture with the crashdumper */ static void a6xx_get_cluster(struct msm_gpu *gpu, + struct a6xx_gpu_state *a6xx_state, const struct a6xx_cluster *cluster, struct a6xx_gpu_state_obj *obj, struct a6xx_crashdumper *dumper) @@ -497,8 +543,8 @@ static void a6xx_get_cluster(struct msm_gpu *gpu, return; obj->handle = cluster; - obj->data = kmemdup(dumper->ptr + A6XX_CD_DATA_OFFSET, - datasize, GFP_KERNEL); + obj->data = state_kmemdup(a6xx_state, dumper->ptr + A6XX_CD_DATA_OFFSET, + datasize); } static void a6xx_get_clusters(struct msm_gpu *gpu, @@ -507,8 +553,8 @@ static void a6xx_get_clusters(struct msm_gpu *gpu, { int i; - a6xx_state->clusters = kcalloc(ARRAY_SIZE(a6xx_clusters), - sizeof(*a6xx_state->clusters), GFP_KERNEL); + a6xx_state->clusters = state_kcalloc(a6xx_state, + ARRAY_SIZE(a6xx_clusters), sizeof(*a6xx_state->clusters)); if (!a6xx_state->clusters) return; @@ -516,12 +562,13 @@ static void a6xx_get_clusters(struct msm_gpu *gpu, a6xx_state->nr_clusters = ARRAY_SIZE(a6xx_clusters); for (i = 0; i < ARRAY_SIZE(a6xx_clusters); i++) - a6xx_get_cluster(gpu, &a6xx_clusters[i], + a6xx_get_cluster(gpu, a6xx_state, &a6xx_clusters[i], &a6xx_state->clusters[i], dumper); } /* Read a shader / debug block from the HLSQ aperture with the crashdumper */ static void a6xx_get_shader_block(struct msm_gpu *gpu, + struct a6xx_gpu_state *a6xx_state, const struct a6xx_shader_block *block, struct a6xx_gpu_state_obj *obj, struct a6xx_crashdumper *dumper) @@ -547,8 +594,8 @@ static void a6xx_get_shader_block(struct msm_gpu *gpu, return; obj->handle = block; - obj->data = kmemdup(dumper->ptr + A6XX_CD_DATA_OFFSET, - datasize, GFP_KERNEL); + obj->data = state_kmemdup(a6xx_state, dumper->ptr + A6XX_CD_DATA_OFFSET, + datasize); } static void a6xx_get_shaders(struct msm_gpu *gpu, @@ -557,8 +604,8 @@ static void a6xx_get_shaders(struct msm_gpu *gpu, { int i; - a6xx_state->shaders = kcalloc(ARRAY_SIZE(a6xx_shader_blocks), - sizeof(*a6xx_state->shaders), GFP_KERNEL); + a6xx_state->shaders = state_kcalloc(a6xx_state, + ARRAY_SIZE(a6xx_shader_blocks), sizeof(*a6xx_state->shaders)); if (!a6xx_state->shaders) return; @@ -566,12 +613,13 @@ static void a6xx_get_shaders(struct msm_gpu *gpu, a6xx_state->nr_shaders = ARRAY_SIZE(a6xx_shader_blocks); for (i = 0; i < ARRAY_SIZE(a6xx_shader_blocks); i++) - a6xx_get_shader_block(gpu, &a6xx_shader_blocks[i], + a6xx_get_shader_block(gpu, a6xx_state, &a6xx_shader_blocks[i], &a6xx_state->shaders[i], dumper); } /* Read registers from behind the HLSQ aperture with the crashdumper */ static void a6xx_get_crashdumper_hlsq_registers(struct msm_gpu *gpu, + struct a6xx_gpu_state *a6xx_state, const struct a6xx_registers *regs, struct a6xx_gpu_state_obj *obj, struct a6xx_crashdumper *dumper) @@ -603,12 +651,13 @@ static void a6xx_get_crashdumper_hlsq_registers(struct msm_gpu *gpu, return; obj->handle = regs; - obj->data = kmemdup(dumper->ptr + A6XX_CD_DATA_OFFSET, - regcount * sizeof(u32), GFP_KERNEL); + obj->data = state_kmemdup(a6xx_state, dumper->ptr + A6XX_CD_DATA_OFFSET, + regcount * sizeof(u32)); } /* Read a block of registers using the crashdumper */ static void a6xx_get_crashdumper_registers(struct msm_gpu *gpu, + struct a6xx_gpu_state *a6xx_state, const struct a6xx_registers *regs, struct a6xx_gpu_state_obj *obj, struct a6xx_crashdumper *dumper) @@ -640,12 +689,13 @@ static void a6xx_get_crashdumper_registers(struct msm_gpu *gpu, return; obj->handle = regs; - obj->data = kmemdup(dumper->ptr + A6XX_CD_DATA_OFFSET, - regcount * sizeof(u32), GFP_KERNEL); + obj->data = state_kmemdup(a6xx_state, dumper->ptr + A6XX_CD_DATA_OFFSET, + regcount * sizeof(u32)); } /* Read a block of registers via AHB */ static void a6xx_get_ahb_gpu_registers(struct msm_gpu *gpu, + struct a6xx_gpu_state *a6xx_state, const struct a6xx_registers *regs, struct a6xx_gpu_state_obj *obj) { @@ -655,7 +705,7 @@ static void a6xx_get_ahb_gpu_registers(struct msm_gpu *gpu, regcount += RANGE(regs->registers, i); obj->handle = (const void *) regs; - obj->data = kcalloc(regcount, sizeof(u32), GFP_KERNEL); + obj->data = state_kcalloc(a6xx_state, regcount, sizeof(u32)); if (!obj->data) return; @@ -671,6 +721,7 @@ static void a6xx_get_ahb_gpu_registers(struct msm_gpu *gpu, /* Read a block of GMU registers */ static void _a6xx_get_gmu_registers(struct msm_gpu *gpu, + struct a6xx_gpu_state *a6xx_state, const struct a6xx_registers *regs, struct a6xx_gpu_state_obj *obj) { @@ -683,7 +734,7 @@ static void _a6xx_get_gmu_registers(struct msm_gpu *gpu, regcount += RANGE(regs->registers, i); obj->handle = (const void *) regs; - obj->data = kcalloc(regcount, sizeof(u32), GFP_KERNEL); + obj->data = state_kcalloc(a6xx_state, regcount, sizeof(u32)); if (!obj->data) return; @@ -703,8 +754,8 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu, struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu); - a6xx_state->gmu_registers = kcalloc(2, - sizeof(*a6xx_state->gmu_registers), GFP_KERNEL); + a6xx_state->gmu_registers = state_kcalloc(a6xx_state, + 2, sizeof(*a6xx_state->gmu_registers)); if (!a6xx_state->gmu_registers) return; @@ -712,7 +763,7 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu, a6xx_state->nr_gmu_registers = 2; /* Get the CX GMU registers from AHB */ - _a6xx_get_gmu_registers(gpu, &a6xx_gmu_reglist[0], + _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[0], &a6xx_state->gmu_registers[0]); if (!a6xx_gmu_gx_is_on(&a6xx_gpu->gmu)) @@ -721,7 +772,7 @@ static void a6xx_get_gmu_registers(struct msm_gpu *gpu, /* Set the fence to ALLOW mode so we can access the registers */ gpu_write(gpu, REG_A6XX_GMU_AO_AHB_FENCE_CTRL, 0); - _a6xx_get_gmu_registers(gpu, &a6xx_gmu_reglist[1], + _a6xx_get_gmu_registers(gpu, a6xx_state, &a6xx_gmu_reglist[1], &a6xx_state->gmu_registers[1]); } @@ -734,8 +785,8 @@ static void a6xx_get_registers(struct msm_gpu *gpu, ARRAY_SIZE(a6xx_hlsq_reglist); int index = 0; - a6xx_state->registers = kcalloc(count, sizeof(*a6xx_state->registers), - GFP_KERNEL); + a6xx_state->registers = state_kcalloc(a6xx_state, + count, sizeof(*a6xx_state->registers)); if (!a6xx_state->registers) return; @@ -744,31 +795,32 @@ static void a6xx_get_registers(struct msm_gpu *gpu, for (i = 0; i < ARRAY_SIZE(a6xx_ahb_reglist); i++) a6xx_get_ahb_gpu_registers(gpu, - &a6xx_ahb_reglist[i], + a6xx_state, &a6xx_ahb_reglist[i], &a6xx_state->registers[index++]); for (i = 0; i < ARRAY_SIZE(a6xx_reglist); i++) a6xx_get_crashdumper_registers(gpu, - &a6xx_reglist[i], + a6xx_state, &a6xx_reglist[i], &a6xx_state->registers[index++], dumper); for (i = 0; i < ARRAY_SIZE(a6xx_hlsq_reglist); i++) a6xx_get_crashdumper_hlsq_registers(gpu, - &a6xx_hlsq_reglist[i], + a6xx_state, &a6xx_hlsq_reglist[i], &a6xx_state->registers[index++], dumper); } /* Read a block of data from an indexed register pair */ static void a6xx_get_indexed_regs(struct msm_gpu *gpu, + struct a6xx_gpu_state *a6xx_state, const struct a6xx_indexed_registers *indexed, struct a6xx_gpu_state_obj *obj) { int i; obj->handle = (const void *) indexed; - obj->data = kcalloc(indexed->count, sizeof(u32), GFP_KERNEL); + obj->data = state_kcalloc(a6xx_state, indexed->count, sizeof(u32)); if (!obj->data) return; @@ -787,13 +839,13 @@ static void a6xx_get_indexed_registers(struct msm_gpu *gpu, int count = ARRAY_SIZE(a6xx_indexed_reglist) + 1; int i; - a6xx_state->indexed_regs = kcalloc(count, - sizeof(a6xx_state->indexed_regs), GFP_KERNEL); + a6xx_state->indexed_regs = state_kcalloc(a6xx_state, count, + sizeof(a6xx_state->indexed_regs)); if (!a6xx_state->indexed_regs) return; for (i = 0; i < ARRAY_SIZE(a6xx_indexed_reglist); i++) - a6xx_get_indexed_regs(gpu, &a6xx_indexed_reglist[i], + a6xx_get_indexed_regs(gpu, a6xx_state, &a6xx_indexed_reglist[i], &a6xx_state->indexed_regs[i]); /* Set the CP mempool size to 0 to stabilize it while dumping */ @@ -801,7 +853,7 @@ static void a6xx_get_indexed_registers(struct msm_gpu *gpu, gpu_write(gpu, REG_A6XX_CP_MEM_POOL_SIZE, 0); /* Get the contents of the CP mempool */ - a6xx_get_indexed_regs(gpu, &a6xx_cp_mempool_indexed, + a6xx_get_indexed_regs(gpu, a6xx_state, &a6xx_cp_mempool_indexed, &a6xx_state->indexed_regs[i]); /* @@ -827,6 +879,8 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu) if (!a6xx_state) return ERR_PTR(-ENOMEM); + INIT_LIST_HEAD(&a6xx_state->objs); + /* Get the generic state from the adreno core */ adreno_gpu_state_get(gpu, &a6xx_state->base); @@ -856,56 +910,14 @@ struct msm_gpu_state *a6xx_gpu_state_get(struct msm_gpu *gpu) void a6xx_gpu_state_destroy(struct kref *kref) { + struct a6xx_state_memobj *obj, *tmp; struct msm_gpu_state *state = container_of(kref, struct msm_gpu_state, ref); struct a6xx_gpu_state *a6xx_state = container_of(state, struct a6xx_gpu_state, base); - int i; - - for (i = 0; i < a6xx_state->nr_gmu_registers; i++) - kfree(a6xx_state->gmu_registers[i].data); - - kfree(a6xx_state->gmu_registers); - - for (i = 0; i < a6xx_state->nr_registers; i++) - kfree(a6xx_state->registers[i].data); - - kfree(a6xx_state->registers); - - for (i = 0; i < a6xx_state->nr_shaders; i++) - kfree(a6xx_state->shaders[i].data); - - kfree(a6xx_state->shaders); - - for (i = 0; i < a6xx_state->nr_clusters; i++) - kfree(a6xx_state->clusters[i].data); - - kfree(a6xx_state->clusters); - - for (i = 0; i < a6xx_state->nr_dbgahb_clusters; i++) - kfree(a6xx_state->dbgahb_clusters[i].data); - - kfree(a6xx_state->dbgahb_clusters); - - for (i = 0; i < a6xx_state->nr_indexed_regs; i++) - kfree(a6xx_state->indexed_regs[i].data); - - kfree(a6xx_state->indexed_regs); - - for (i = 0; i < a6xx_state->nr_debugbus; i++) - kfree(a6xx_state->debugbus[i].data); - - kfree(a6xx_state->debugbus); - - if (a6xx_state->vbif_debugbus) - kfree(a6xx_state->vbif_debugbus->data); - - kfree(a6xx_state->vbif_debugbus); - - for (i = 0; i < a6xx_state->nr_cx_debugbus; i++) - kfree(a6xx_state->cx_debugbus[i].data); - kfree(a6xx_state->cx_debugbus); + list_for_each_entry_safe(obj, tmp, &a6xx_state->objs, node) + kfree(obj); adreno_gpu_state_destroy(state); kfree(a6xx_state);