blob: 365b1ba7ebb4799eb4d4d184921612db4aef3fee [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2015 - 2022 Intel Corporation
#include <linux/bitmap.h>
#include <linux/errno.h>
#include <linux/gfp.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <uapi/linux/ipu-psys.h>
#include "ipu-fw-psys.h"
#include "ipu-psys.h"
struct ipu6_psys_hw_res_variant hw_var;
void ipu6_psys_hw_res_variant_init(void)
{
if (ipu_ver == IPU_VER_6SE) {
hw_var.queue_num = IPU6SE_FW_PSYS_N_PSYS_CMD_QUEUE_ID;
hw_var.cell_num = IPU6SE_FW_PSYS_N_CELL_ID;
} else if (ipu_ver == IPU_VER_6) {
hw_var.queue_num = IPU6_FW_PSYS_N_PSYS_CMD_QUEUE_ID;
hw_var.cell_num = IPU6_FW_PSYS_N_CELL_ID;
} else if (ipu_ver == IPU_VER_6EP || ipu_ver == IPU_VER_6EP_MTL) {
hw_var.queue_num = IPU6_FW_PSYS_N_PSYS_CMD_QUEUE_ID;
hw_var.cell_num = IPU6EP_FW_PSYS_N_CELL_ID;
} else {
WARN(1, "ipu6 psys res var is not initialised correctly.");
}
hw_var.set_proc_dev_chn = ipu6_fw_psys_set_proc_dev_chn;
hw_var.set_proc_dfm_bitmap = ipu6_fw_psys_set_proc_dfm_bitmap;
hw_var.set_proc_ext_mem = ipu6_fw_psys_set_process_ext_mem;
hw_var.get_pgm_by_proc =
ipu6_fw_psys_get_program_manifest_by_process;
}
static const struct ipu_fw_resource_definitions *get_res(void)
{
if (ipu_ver == IPU_VER_6SE)
return ipu6se_res_defs;
if (ipu_ver == IPU_VER_6EP || ipu_ver == IPU_VER_6EP_MTL)
return ipu6ep_res_defs;
return ipu6_res_defs;
}
static int ipu_resource_init(struct ipu_resource *res, u32 id, int elements)
{
if (elements <= 0) {
res->bitmap = NULL;
return 0;
}
res->bitmap = bitmap_zalloc(elements, GFP_KERNEL);
if (!res->bitmap)
return -ENOMEM;
res->elements = elements;
res->id = id;
return 0;
}
static unsigned long
ipu_resource_alloc_with_pos(struct ipu_resource *res, int n,
int pos,
struct ipu_resource_alloc *alloc,
enum ipu_resource_type type)
{
unsigned long p;
if (n <= 0) {
alloc->elements = 0;
return 0;
}
if (!res->bitmap || pos >= res->elements)
return (unsigned long)(-ENOSPC);
p = bitmap_find_next_zero_area(res->bitmap, res->elements, pos, n, 0);
alloc->resource = NULL;
if (p != pos)
return (unsigned long)(-ENOSPC);
bitmap_set(res->bitmap, p, n);
alloc->resource = res;
alloc->elements = n;
alloc->pos = p;
alloc->type = type;
return pos;
}
static unsigned long
ipu_resource_alloc(struct ipu_resource *res, int n,
struct ipu_resource_alloc *alloc,
enum ipu_resource_type type)
{
unsigned long p;
if (n <= 0) {
alloc->elements = 0;
return 0;
}
if (!res->bitmap)
return (unsigned long)(-ENOSPC);
p = bitmap_find_next_zero_area(res->bitmap, res->elements, 0, n, 0);
alloc->resource = NULL;
if (p >= res->elements)
return (unsigned long)(-ENOSPC);
bitmap_set(res->bitmap, p, n);
alloc->resource = res;
alloc->elements = n;
alloc->pos = p;
alloc->type = type;
return p;
}
static void ipu_resource_free(struct ipu_resource_alloc *alloc)
{
if (alloc->elements <= 0)
return;
if (alloc->type == IPU_RESOURCE_DFM)
*alloc->resource->bitmap &= ~(unsigned long)(alloc->elements);
else
bitmap_clear(alloc->resource->bitmap, alloc->pos,
alloc->elements);
alloc->resource = NULL;
}
static void ipu_resource_cleanup(struct ipu_resource *res)
{
bitmap_free(res->bitmap);
res->bitmap = NULL;
}
/********** IPU PSYS-specific resource handling **********/
int ipu_psys_resource_pool_init(struct ipu_psys_resource_pool *pool)
{
int i, j, k, ret;
const struct ipu_fw_resource_definitions *res_defs;
res_defs = get_res();
spin_lock_init(&pool->queues_lock);
pool->cells = 0;
for (i = 0; i < res_defs->num_dev_channels; i++) {
ret = ipu_resource_init(&pool->dev_channels[i], i,
res_defs->dev_channels[i]);
if (ret)
goto error;
}
for (j = 0; j < res_defs->num_ext_mem_ids; j++) {
ret = ipu_resource_init(&pool->ext_memory[j], j,
res_defs->ext_mem_ids[j]);
if (ret)
goto memory_error;
}
for (k = 0; k < res_defs->num_dfm_ids; k++) {
ret = ipu_resource_init(&pool->dfms[k], k, res_defs->dfms[k]);
if (ret)
goto dfm_error;
}
spin_lock(&pool->queues_lock);
if (ipu_ver == IPU_VER_6SE)
bitmap_zero(pool->cmd_queues,
IPU6SE_FW_PSYS_N_PSYS_CMD_QUEUE_ID);
else
bitmap_zero(pool->cmd_queues,
IPU6_FW_PSYS_N_PSYS_CMD_QUEUE_ID);
spin_unlock(&pool->queues_lock);
return 0;
dfm_error:
for (k--; k >= 0; k--)
ipu_resource_cleanup(&pool->dfms[k]);
memory_error:
for (j--; j >= 0; j--)
ipu_resource_cleanup(&pool->ext_memory[j]);
error:
for (i--; i >= 0; i--)
ipu_resource_cleanup(&pool->dev_channels[i]);
return ret;
}
void ipu_psys_resource_copy(struct ipu_psys_resource_pool *src,
struct ipu_psys_resource_pool *dest)
{
int i;
const struct ipu_fw_resource_definitions *res_defs;
res_defs = get_res();
dest->cells = src->cells;
for (i = 0; i < res_defs->num_dev_channels; i++)
*dest->dev_channels[i].bitmap = *src->dev_channels[i].bitmap;
for (i = 0; i < res_defs->num_ext_mem_ids; i++)
*dest->ext_memory[i].bitmap = *src->ext_memory[i].bitmap;
for (i = 0; i < res_defs->num_dfm_ids; i++)
*dest->dfms[i].bitmap = *src->dfms[i].bitmap;
}
void ipu_psys_resource_pool_cleanup(struct ipu_psys_resource_pool
*pool)
{
u32 i;
const struct ipu_fw_resource_definitions *res_defs;
res_defs = get_res();
for (i = 0; i < res_defs->num_dev_channels; i++)
ipu_resource_cleanup(&pool->dev_channels[i]);
for (i = 0; i < res_defs->num_ext_mem_ids; i++)
ipu_resource_cleanup(&pool->ext_memory[i]);
for (i = 0; i < res_defs->num_dfm_ids; i++)
ipu_resource_cleanup(&pool->dfms[i]);
}
static int __alloc_one_resrc(const struct device *dev,
struct ipu_fw_psys_process *process,
struct ipu_resource *resource,
struct ipu_fw_generic_program_manifest *pm,
u32 resource_id,
struct ipu_psys_resource_alloc *alloc)
{
const u16 resource_req = pm->dev_chn_size[resource_id];
const u16 resource_offset_req = pm->dev_chn_offset[resource_id];
unsigned long retl;
if (!resource_req)
return -ENXIO;
if (alloc->resources >= IPU_MAX_RESOURCES) {
dev_err(dev, "out of resource handles\n");
return -ENOSPC;
}
if (resource_offset_req != (u16)(-1))
retl = ipu_resource_alloc_with_pos
(resource,
resource_req,
resource_offset_req,
&alloc->resource_alloc[alloc->resources],
IPU_RESOURCE_DEV_CHN);
else
retl = ipu_resource_alloc
(resource, resource_req,
&alloc->resource_alloc[alloc->resources],
IPU_RESOURCE_DEV_CHN);
if (IS_ERR_VALUE(retl)) {
dev_dbg(dev, "out of device channel resources\n");
return (int)retl;
}
alloc->resources++;
return 0;
}
static int ipu_psys_allocate_one_dfm(const struct device *dev,
struct ipu_fw_psys_process *process,
struct ipu_resource *resource,
struct ipu_fw_generic_program_manifest *pm,
u32 resource_id,
struct ipu_psys_resource_alloc *alloc)
{
u32 dfm_bitmap_req = pm->dfm_port_bitmap[resource_id];
u32 active_dfm_bitmap_req = pm->dfm_active_port_bitmap[resource_id];
const u8 is_relocatable = pm->is_dfm_relocatable[resource_id];
struct ipu_resource_alloc *alloc_resource;
unsigned long p = 0;
if (!dfm_bitmap_req)
return -ENXIO;
if (alloc->resources >= IPU_MAX_RESOURCES) {
dev_err(dev, "out of resource handles\n");
return -ENOSPC;
}
if (!resource->bitmap)
return -ENOSPC;
if (!is_relocatable) {
if (*resource->bitmap & dfm_bitmap_req) {
dev_warn(dev,
"out of dfm resources, req 0x%x, get 0x%lx\n",
dfm_bitmap_req, *resource->bitmap);
return -ENOSPC;
}
*resource->bitmap |= dfm_bitmap_req;
} else {
unsigned int n = hweight32(dfm_bitmap_req);
p = bitmap_find_next_zero_area(resource->bitmap,
resource->elements, 0, n, 0);
if (p >= resource->elements)
return -ENOSPC;
bitmap_set(resource->bitmap, p, n);
dfm_bitmap_req = dfm_bitmap_req << p;
active_dfm_bitmap_req = active_dfm_bitmap_req << p;
}
alloc_resource = &alloc->resource_alloc[alloc->resources];
alloc_resource->resource = resource;
/* Using elements to indicate the bitmap */
alloc_resource->elements = dfm_bitmap_req;
alloc_resource->pos = p;
alloc_resource->type = IPU_RESOURCE_DFM;
alloc->resources++;
return 0;
}
/*
* ext_mem_type_id is a generic type id for memory (like DMEM, VMEM)
* ext_mem_bank_id is detailed type id for memory (like DMEM0, DMEM1 etc.)
*/
static int __alloc_mem_resrc(const struct device *dev,
struct ipu_fw_psys_process *process,
struct ipu_resource *resource,
struct ipu_fw_generic_program_manifest *pm,
u32 ext_mem_type_id, u32 ext_mem_bank_id,
struct ipu_psys_resource_alloc *alloc)
{
const u16 memory_resource_req = pm->ext_mem_size[ext_mem_type_id];
const u16 memory_offset_req = pm->ext_mem_offset[ext_mem_type_id];
unsigned long retl;
if (!memory_resource_req)
return -ENXIO;
if (alloc->resources >= IPU_MAX_RESOURCES) {
dev_err(dev, "out of resource handles\n");
return -ENOSPC;
}
if (memory_offset_req != (u16)(-1))
retl = ipu_resource_alloc_with_pos
(resource,
memory_resource_req, memory_offset_req,
&alloc->resource_alloc[alloc->resources],
IPU_RESOURCE_EXT_MEM);
else
retl = ipu_resource_alloc
(resource, memory_resource_req,
&alloc->resource_alloc[alloc->resources],
IPU_RESOURCE_EXT_MEM);
if (IS_ERR_VALUE(retl)) {
dev_dbg(dev, "out of memory resources\n");
return (int)retl;
}
alloc->resources++;
return 0;
}
int ipu_psys_allocate_cmd_queue_resource(struct ipu_psys_resource_pool *pool)
{
unsigned long p;
int size, start;
size = IPU6_FW_PSYS_N_PSYS_CMD_QUEUE_ID;
start = IPU6_FW_PSYS_CMD_QUEUE_PPG0_COMMAND_ID;
if (ipu_ver == IPU_VER_6SE) {
size = IPU6SE_FW_PSYS_N_PSYS_CMD_QUEUE_ID;
start = IPU6SE_FW_PSYS_CMD_QUEUE_PPG0_COMMAND_ID;
}
spin_lock(&pool->queues_lock);
/* find available cmd queue from ppg0_cmd_id */
p = bitmap_find_next_zero_area(pool->cmd_queues, size, start, 1, 0);
if (p >= size) {
spin_unlock(&pool->queues_lock);
return -ENOSPC;
}
bitmap_set(pool->cmd_queues, p, 1);
spin_unlock(&pool->queues_lock);
return p;
}
void ipu_psys_free_cmd_queue_resource(struct ipu_psys_resource_pool *pool,
u8 queue_id)
{
spin_lock(&pool->queues_lock);
bitmap_clear(pool->cmd_queues, queue_id, 1);
spin_unlock(&pool->queues_lock);
}
int ipu_psys_try_allocate_resources(struct device *dev,
struct ipu_fw_psys_process_group *pg,
void *pg_manifest,
struct ipu_psys_resource_pool *pool)
{
u32 id, idx;
u32 mem_type_id;
int ret, i;
u16 *process_offset_table;
u8 processes;
u32 cells = 0;
struct ipu_psys_resource_alloc *alloc;
const struct ipu_fw_resource_definitions *res_defs;
if (!pg)
return -EINVAL;
process_offset_table = (u16 *)((u8 *)pg + pg->processes_offset);
processes = pg->process_count;
alloc = kzalloc(sizeof(*alloc), GFP_KERNEL);
if (!alloc)
return -ENOMEM;
res_defs = get_res();
for (i = 0; i < processes; i++) {
u32 cell;
struct ipu_fw_psys_process *process =
(struct ipu_fw_psys_process *)
((char *)pg + process_offset_table[i]);
struct ipu_fw_generic_program_manifest pm;
memset(&pm, 0, sizeof(pm));
if (!process) {
dev_err(dev, "can not get process\n");
ret = -ENOENT;
goto free_out;
}
ret = ipu_fw_psys_get_program_manifest_by_process
(&pm, pg_manifest, process);
if (ret < 0) {
dev_err(dev, "can not get manifest\n");
goto free_out;
}
if (pm.cell_id == res_defs->num_cells &&
pm.cell_type_id == res_defs->num_cells_type) {
cell = res_defs->num_cells;
} else if ((pm.cell_id != res_defs->num_cells &&
pm.cell_type_id == res_defs->num_cells_type)) {
cell = pm.cell_id;
} else {
/* Find a free cell of desired type */
u32 type = pm.cell_type_id;
for (cell = 0; cell < res_defs->num_cells; cell++)
if (res_defs->cells[cell] == type &&
((pool->cells | cells) & (1 << cell)) == 0)
break;
if (cell >= res_defs->num_cells) {
dev_dbg(dev, "no free cells of right type\n");
ret = -ENOSPC;
goto free_out;
}
}
if (cell < res_defs->num_cells)
cells |= 1 << cell;
if (pool->cells & cells) {
dev_dbg(dev, "out of cell resources\n");
ret = -ENOSPC;
goto free_out;
}
if (pm.dev_chn_size) {
for (id = 0; id < res_defs->num_dev_channels; id++) {
ret = __alloc_one_resrc(dev, process,
&pool->dev_channels[id],
&pm, id, alloc);
if (ret == -ENXIO)
continue;
if (ret)
goto free_out;
}
}
if (pm.dfm_port_bitmap) {
for (id = 0; id < res_defs->num_dfm_ids; id++) {
ret = ipu_psys_allocate_one_dfm
(dev, process,
&pool->dfms[id], &pm, id, alloc);
if (ret == -ENXIO)
continue;
if (ret)
goto free_out;
}
}
if (pm.ext_mem_size) {
for (mem_type_id = 0;
mem_type_id < res_defs->num_ext_mem_types;
mem_type_id++) {
u32 bank = res_defs->num_ext_mem_ids;
if (cell != res_defs->num_cells) {
idx = res_defs->cell_mem_row * cell +
mem_type_id;
bank = res_defs->cell_mem[idx];
}
if (bank == res_defs->num_ext_mem_ids)
continue;
ret = __alloc_mem_resrc(dev, process,
&pool->ext_memory[bank],
&pm, mem_type_id, bank,
alloc);
if (ret == -ENXIO)
continue;
if (ret)
goto free_out;
}
}
}
pool->cells |= cells;
kfree(alloc);
return 0;
free_out:
dev_dbg(dev, "failed to try_allocate resource\n");
kfree(alloc);
return ret;
}
/*
* Allocate resources for pg from `pool'. Mark the allocated
* resources into `alloc'. Returns 0 on success, -ENOSPC
* if there are no enough resources, in which cases resources
* are not allocated at all, or some other error on other conditions.
*/
int ipu_psys_allocate_resources(const struct device *dev,
struct ipu_fw_psys_process_group *pg,
void *pg_manifest,
struct ipu_psys_resource_alloc
*alloc, struct ipu_psys_resource_pool
*pool)
{
u32 id;
u32 mem_type_id;
int ret, i;
u16 *process_offset_table;
u8 processes;
u32 cells = 0;
int p, idx;
u32 bmp, a_bmp;
const struct ipu_fw_resource_definitions *res_defs;
if (!pg)
return -EINVAL;
res_defs = get_res();
process_offset_table = (u16 *)((u8 *)pg + pg->processes_offset);
processes = pg->process_count;
for (i = 0; i < processes; i++) {
u32 cell;
struct ipu_fw_psys_process *process =
(struct ipu_fw_psys_process *)
((char *)pg + process_offset_table[i]);
struct ipu_fw_generic_program_manifest pm;
memset(&pm, 0, sizeof(pm));
if (!process) {
dev_err(dev, "can not get process\n");
ret = -ENOENT;
goto free_out;
}
ret = ipu_fw_psys_get_program_manifest_by_process
(&pm, pg_manifest, process);
if (ret < 0) {
dev_err(dev, "can not get manifest\n");
goto free_out;
}
if (pm.cell_id == res_defs->num_cells &&
pm.cell_type_id == res_defs->num_cells_type) {
cell = res_defs->num_cells;
} else if ((pm.cell_id != res_defs->num_cells &&
pm.cell_type_id == res_defs->num_cells_type)) {
cell = pm.cell_id;
} else {
/* Find a free cell of desired type */
u32 type = pm.cell_type_id;
for (cell = 0; cell < res_defs->num_cells; cell++)
if (res_defs->cells[cell] == type &&
((pool->cells | cells) & (1 << cell)) == 0)
break;
if (cell >= res_defs->num_cells) {
dev_dbg(dev, "no free cells of right type\n");
ret = -ENOSPC;
goto free_out;
}
ret = ipu_fw_psys_set_process_cell_id(process, 0, cell);
if (ret)
goto free_out;
}
if (cell < res_defs->num_cells)
cells |= 1 << cell;
if (pool->cells & cells) {
dev_dbg(dev, "out of cell resources\n");
ret = -ENOSPC;
goto free_out;
}
if (pm.dev_chn_size) {
for (id = 0; id < res_defs->num_dev_channels; id++) {
ret = __alloc_one_resrc(dev, process,
&pool->dev_channels[id],
&pm, id, alloc);
if (ret == -ENXIO)
continue;
if (ret)
goto free_out;
idx = alloc->resources - 1;
p = alloc->resource_alloc[idx].pos;
ret = ipu_fw_psys_set_proc_dev_chn(process, id,
p);
if (ret)
goto free_out;
}
}
if (pm.dfm_port_bitmap) {
for (id = 0; id < res_defs->num_dfm_ids; id++) {
ret = ipu_psys_allocate_one_dfm(dev, process,
&pool->dfms[id],
&pm, id, alloc);
if (ret == -ENXIO)
continue;
if (ret)
goto free_out;
idx = alloc->resources - 1;
p = alloc->resource_alloc[idx].pos;
bmp = pm.dfm_port_bitmap[id];
bmp = bmp << p;
a_bmp = pm.dfm_active_port_bitmap[id];
a_bmp = a_bmp << p;
ret = ipu_fw_psys_set_proc_dfm_bitmap(process,
id, bmp,
a_bmp);
if (ret)
goto free_out;
}
}
if (pm.ext_mem_size) {
for (mem_type_id = 0;
mem_type_id < res_defs->num_ext_mem_types;
mem_type_id++) {
u32 bank = res_defs->num_ext_mem_ids;
if (cell != res_defs->num_cells) {
idx = res_defs->cell_mem_row * cell +
mem_type_id;
bank = res_defs->cell_mem[idx];
}
if (bank == res_defs->num_ext_mem_ids)
continue;
ret = __alloc_mem_resrc(dev, process,
&pool->ext_memory[bank],
&pm, mem_type_id,
bank, alloc);
if (ret == -ENXIO)
continue;
if (ret)
goto free_out;
/* no return value check here because fw api
* will do some checks, and would return
* non-zero except mem_type_id == 0.
* This maybe caused by that above flow of
* allocating mem_bank_id is improper.
*/
idx = alloc->resources - 1;
p = alloc->resource_alloc[idx].pos;
ipu_fw_psys_set_process_ext_mem(process,
mem_type_id,
bank, p);
}
}
}
alloc->cells |= cells;
pool->cells |= cells;
return 0;
free_out:
dev_err(dev, "failed to allocate resources, ret %d\n", ret);
ipu_psys_reset_process_cell(dev, pg, pg_manifest, i + 1);
ipu_psys_free_resources(alloc, pool);
return ret;
}
int ipu_psys_move_resources(const struct device *dev,
struct ipu_psys_resource_alloc *alloc,
struct ipu_psys_resource_pool
*source_pool, struct ipu_psys_resource_pool
*target_pool)
{
int i;
if (target_pool->cells & alloc->cells) {
dev_dbg(dev, "out of cell resources\n");
return -ENOSPC;
}
for (i = 0; i < alloc->resources; i++) {
unsigned long bitmap = 0;
unsigned int id = alloc->resource_alloc[i].resource->id;
unsigned long fbit, end;
switch (alloc->resource_alloc[i].type) {
case IPU_RESOURCE_DEV_CHN:
bitmap_set(&bitmap, alloc->resource_alloc[i].pos,
alloc->resource_alloc[i].elements);
if (*target_pool->dev_channels[id].bitmap & bitmap)
return -ENOSPC;
break;
case IPU_RESOURCE_EXT_MEM:
end = alloc->resource_alloc[i].elements +
alloc->resource_alloc[i].pos;
fbit = find_next_bit(target_pool->ext_memory[id].bitmap,
end, alloc->resource_alloc[i].pos);
/* if find_next_bit returns "end" it didn't find 1bit */
if (end != fbit)
return -ENOSPC;
break;
case IPU_RESOURCE_DFM:
bitmap = alloc->resource_alloc[i].elements;
if (*target_pool->dfms[id].bitmap & bitmap)
return -ENOSPC;
break;
default:
dev_err(dev, "Illegal resource type\n");
return -EINVAL;
}
}
for (i = 0; i < alloc->resources; i++) {
u32 id = alloc->resource_alloc[i].resource->id;
switch (alloc->resource_alloc[i].type) {
case IPU_RESOURCE_DEV_CHN:
bitmap_set(target_pool->dev_channels[id].bitmap,
alloc->resource_alloc[i].pos,
alloc->resource_alloc[i].elements);
ipu_resource_free(&alloc->resource_alloc[i]);
alloc->resource_alloc[i].resource =
&target_pool->dev_channels[id];
break;
case IPU_RESOURCE_EXT_MEM:
bitmap_set(target_pool->ext_memory[id].bitmap,
alloc->resource_alloc[i].pos,
alloc->resource_alloc[i].elements);
ipu_resource_free(&alloc->resource_alloc[i]);
alloc->resource_alloc[i].resource =
&target_pool->ext_memory[id];
break;
case IPU_RESOURCE_DFM:
*target_pool->dfms[id].bitmap |=
alloc->resource_alloc[i].elements;
*alloc->resource_alloc[i].resource->bitmap &=
~(alloc->resource_alloc[i].elements);
alloc->resource_alloc[i].resource =
&target_pool->dfms[id];
break;
default:
/*
* Just keep compiler happy. This case failed already
* in above loop.
*/
break;
}
}
target_pool->cells |= alloc->cells;
source_pool->cells &= ~alloc->cells;
return 0;
}
void ipu_psys_reset_process_cell(const struct device *dev,
struct ipu_fw_psys_process_group *pg,
void *pg_manifest,
int process_count)
{
int i;
u16 *process_offset_table;
const struct ipu_fw_resource_definitions *res_defs;
if (!pg)
return;
res_defs = get_res();
process_offset_table = (u16 *)((u8 *)pg + pg->processes_offset);
for (i = 0; i < process_count; i++) {
struct ipu_fw_psys_process *process =
(struct ipu_fw_psys_process *)
((char *)pg + process_offset_table[i]);
struct ipu_fw_generic_program_manifest pm;
int ret;
if (!process)
break;
ret = ipu_fw_psys_get_program_manifest_by_process(&pm,
pg_manifest,
process);
if (ret < 0) {
dev_err(dev, "can not get manifest\n");
break;
}
if ((pm.cell_id != res_defs->num_cells &&
pm.cell_type_id == res_defs->num_cells_type))
continue;
/* no return value check here because if finding free cell
* failed, process cell would not set then calling clear_cell
* will return non-zero.
*/
ipu_fw_psys_clear_process_cell(process);
}
}
/* Free resources marked in `alloc' from `resources' */
void ipu_psys_free_resources(struct ipu_psys_resource_alloc
*alloc, struct ipu_psys_resource_pool *pool)
{
unsigned int i;
pool->cells &= ~alloc->cells;
alloc->cells = 0;
for (i = 0; i < alloc->resources; i++)
ipu_resource_free(&alloc->resource_alloc[i]);
alloc->resources = 0;
}