---help---
This enabled extra debug checks and messages in the Mali driver.
+config MALI400_OS_MEMORY_SIZE
+ depends on MALI400
+ int "OS Memory Size(MB)"
+ range 64 2048
+ default 480
+ ---help---
+ The size of mali OS memory with unit of mega byte.
+
if !PROFILING || !FTRACE
comment "ARM mali streamline with gator is depends on CONFIG_FTRACE and PROFILING.I will"
comment "select them and other options for you.please refer to ARM DS-5 Documentation."
bool "Enable UMP support"
depends on MALI400
---help---
- This enables support for the UMP memory sharing API in the Mali driver.
-endmenu
+ This enables support for the UMP memory sharing API in the Mali driver.
+
+config MALI_DMA_BUF_MAP_ON_ATTACH
+ bool "Map dma-buf attachments on attach"
+ depends on MALI400 && DMA_SHARED_BUFFER
+ default y
+ ---help---
+ This makes the Mali driver map dma-buf attachments after doing
+ attach. If this is not set the dma-buf attachments will be mapped for
+ every time the GPU need to access the buffer.
+
+ Mapping for each access can cause lower performance.
+config MALI_SHARED_INTERRUPTS
+ bool "Support for shared interrupts"
+ depends on MALI400
+ default y
+ ---help---
+ Adds functionality required to properly support shared interrupts. Without this support,
+ the device driver will fail during insmod if it detects shared interrupts. Works even if
+ the GPU is not using shared interrupts, but can cause lower performance.
+endmenu
#
-# Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+# Copyright (C) 2010-2013 ARM Limited. All rights reserved.
#
# This program is free software and is provided to you under the terms of the GNU General Public License version 2
# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
USE_UMPV2=0
USING_PROFILING ?= 1
USING_INTERNAL_PROFILING ?= 0
+MALI_DMA_BUF_MAP_ON_ATTACH ?= 1
# The Makefile sets up "arch" based on the CONFIG, creates the version info
# string and the __malidrv_build_info.c file, and then call the Linux build
endif
endif
+ifeq ($(MALI_DMA_BUF_MAP_ON_ATTACH),1)
+export CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH=y
+export EXTRA_DEFINES += -DCONFIG_MALI_DMA_BUF_MAP_ON_ATTACH
+endif
+
+ifeq ($(MALI_SHARED_INTERRUPTS),1)
+export CONFIG_MALI_SHARED_INTERRUPTS=y
+export EXTRA_DEFINES += -DCONFIG_MALI_SHARED_INTERRUPTS
+endif
+
ifneq ($(BUILD),release)
export CONFIG_MALI400_DEBUG=y
endif
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
alloc->next = NULL; /* Could potentially link many blocks together instead */
+ _mali_osk_memset(block->mapping, 0, size);
+
result = MALI_MEM_ALLOC_FINISHED;
}
}
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
bcast_unit = _mali_osk_malloc(sizeof(struct mali_bcast_unit));
if (NULL == bcast_unit)
{
+ MALI_PRINT_ERROR(("Mali Broadcast unit: Failed to allocate memory for Broadcast unit\n"));
return NULL;
}
}
else
{
- MALI_PRINT_ERROR(("Mali Broadcast unit: Failed to allocate memory for Broadcast unit\n"));
+ MALI_PRINT_ERROR(("Mali Broadcast unit: Failed map broadcast unit\n"));
}
+ _mali_osk_free(bcast_unit);
+
return NULL;
}
void mali_bcast_add_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group)
{
- u32 core_id;
+ u32 bcast_id;
u32 broadcast_mask;
MALI_DEBUG_ASSERT_POINTER(bcast_unit);
MALI_DEBUG_ASSERT_POINTER(group);
- core_id = mali_pp_core_get_id(mali_group_get_pp_core(group));
+ bcast_id = mali_pp_core_get_bcast_id(mali_group_get_pp_core(group));
+
broadcast_mask = bcast_unit->current_mask;
- /* set the bit corresponding to the group's core's id to 1 */
- core_id = 1 << core_id;
- broadcast_mask |= (core_id); /* add PP core to broadcast */
- broadcast_mask |= (core_id << 16); /* add MMU to broadcast */
+ broadcast_mask |= (bcast_id); /* add PP core to broadcast */
+ broadcast_mask |= (bcast_id << 16); /* add MMU to broadcast */
/* store mask so we can restore on reset */
bcast_unit->current_mask = broadcast_mask;
void mali_bcast_remove_group(struct mali_bcast_unit *bcast_unit, struct mali_group *group)
{
- u32 core_id;
+ u32 bcast_id;
u32 broadcast_mask;
MALI_DEBUG_ASSERT_POINTER(bcast_unit);
MALI_DEBUG_ASSERT_POINTER(group);
- core_id = mali_pp_core_get_id(mali_group_get_pp_core(group));
+ bcast_id = mali_pp_core_get_bcast_id(mali_group_get_pp_core(group));
+
broadcast_mask = bcast_unit->current_mask;
- /* set the bit corresponding to the group's core's id to 0 */
- core_id = 1 << core_id;
- broadcast_mask &= ~((core_id << 16) | core_id);
+ broadcast_mask &= ~((bcast_id << 16) | bcast_id);
/* store mask so we can restore on reset */
bcast_unit->current_mask = broadcast_mask;
bcast_unit_addr_irq_override_mask,
bcast_unit->current_mask & 0xFF);
}
+
+void mali_bcast_disable(struct mali_bcast_unit *bcast_unit)
+{
+ MALI_DEBUG_ASSERT_POINTER(bcast_unit);
+
+ /* set broadcast mask */
+ mali_hw_core_register_write(&bcast_unit->hw_core,
+ bcast_unit_addr_broadcast_mask,
+ 0x0);
+
+ /* set IRQ override mask */
+ mali_hw_core_register_write(&bcast_unit->hw_core,
+ bcast_unit_addr_irq_override_mask,
+ 0x0);
+}
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/* Re-set cached mask. This needs to be called after having been suspended. */
void mali_bcast_reset(struct mali_bcast_unit *bcast_unit);
+
+/**
+ * Disable broadcast unit
+ *
+ * mali_bcast_enable must be called to re-enable the unit. Cores may not be
+ * added or removed when the unit is disabled.
+ */
+void mali_bcast_disable(struct mali_bcast_unit *bcast_unit);
+
+/**
+ * Re-enable broadcast unit
+ *
+ * This resets the masks to include the cores present when mali_bcast_disable was called.
+ */
+MALI_STATIC_INLINE void mali_bcast_enable(struct mali_bcast_unit *bcast_unit)
+{
+ mali_bcast_reset(bcast_unit);
+}
/**
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
void mali_dlbu_add_group(struct mali_dlbu_core *dlbu, struct mali_group *group)
{
struct mali_pp_core *pp_core;
- u32 core_id;
+ u32 bcast_id;
MALI_DEBUG_ASSERT_POINTER( dlbu );
MALI_DEBUG_ASSERT_POINTER( group );
pp_core = mali_group_get_pp_core(group);
- core_id = mali_pp_core_get_id(pp_core);
+ bcast_id = mali_pp_core_get_bcast_id(pp_core);
- dlbu->pp_cores_mask |= (0x1 << core_id);
- MALI_DEBUG_PRINT(3, ("Mali DLBU: Adding core[%d] New mask= 0x%02x\n",core_id , dlbu->pp_cores_mask));
+ dlbu->pp_cores_mask |= bcast_id;
+ MALI_DEBUG_PRINT(3, ("Mali DLBU: Adding core[%d] New mask= 0x%02x\n", bcast_id , dlbu->pp_cores_mask));
mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask);
}
void mali_dlbu_remove_group(struct mali_dlbu_core *dlbu, struct mali_group *group)
{
struct mali_pp_core *pp_core;
- u32 core_id;
+ u32 bcast_id;
MALI_DEBUG_ASSERT_POINTER( dlbu );
MALI_DEBUG_ASSERT_POINTER( group );
pp_core = mali_group_get_pp_core(group);
- core_id = mali_pp_core_get_id(pp_core);
+ bcast_id = mali_pp_core_get_bcast_id(pp_core);
- dlbu->pp_cores_mask &= ~(0x1 << core_id);
- MALI_DEBUG_PRINT(3, ("Mali DLBU: Removing core[%d] New mask= 0x%02x\n", core_id, dlbu->pp_cores_mask));
+ dlbu->pp_cores_mask &= ~bcast_id;
+ MALI_DEBUG_PRINT(3, ("Mali DLBU: Removing core[%d] New mask= 0x%02x\n", bcast_id, dlbu->pp_cores_mask));
mali_hw_core_register_write(&dlbu->hw_core, MALI_DLBU_REGISTER_PP_ENABLE_MASK, dlbu->pp_cores_mask);
}
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
if (_MALI_OSK_ERR_OK != mali_group_start_gp_job(slot.group, job))
{
MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Failed to start GP job\n"));
- MALI_DEBUG_ASSERT(0); /* @@@@ todo: this cant fail on Mali-300+, no need to implement put back of job */
+ MALI_DEBUG_ASSERT(0); /* this cant fail on Mali-300+, no need to implement put back of job */
}
mali_group_unlock(slot.group);
}
-/* @@@@ todo: pass the job in as a param to this function, so that we don't have to take the scheduler lock again */
static void mali_gp_scheduler_schedule_on_group(struct mali_group *group)
{
struct mali_gp_job *job;
if (_MALI_OSK_ERR_OK != mali_group_start_gp_job(slot.group, job))
{
MALI_DEBUG_PRINT(3, ("Mali GP scheduler: Failed to start GP job\n"));
- MALI_DEBUG_ASSERT(0); /* @@@@ todo: this cant fail on Mali-300+, no need to implement put back of job */
+ MALI_DEBUG_ASSERT(0); /* this cant fail on Mali-300+, no need to implement put back of job */
}
}
resumed_job = mali_group_resume_gp_with_new_heap(slot.group, args->cookie, args->arguments[0], args->arguments[1]);
if (NULL != resumed_job)
{
- /* @@@@ todo: move this and other notification handling into the job object itself */
resumed_job->oom_notification = new_notification;
mali_group_unlock(slot.group);
return _MALI_OSK_ERR_OK;
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
group->session = NULL;
+ if (NULL != group->dlbu_core)
+ {
+ mali_dlbu_reset(group->dlbu_core);
+ }
+
+ if (NULL != group->bcast_core)
+ {
+ mali_bcast_reset(group->bcast_core);
+ }
+
if (NULL != group->mmu)
{
mali_mmu_reset(group->mmu);
struct mali_group *child;
struct mali_group *temp;
- /* TODO: If we *know* that the group is idle, this could be faster. */
-
mali_pp_reset_async(group->pp_core);
if (!mali_group_is_virtual(group) || NULL == group->pp_running_job)
mali_group_post_process_job_pp(group);
- mali_pp_reset_async(group->pp_core);
+ if (success)
+ {
+ /* Only do soft reset for successful jobs, a full recovery
+ * reset will be done for failed jobs. */
+ mali_pp_reset_async(group->pp_core);
+ }
pp_job_to_return = group->pp_running_job;
pp_sub_job_to_return = group->pp_running_sub_job;
mali_group_deactivate_page_directory(group, group->session);
- if (_MALI_OSK_ERR_OK != mali_pp_reset_wait(group->pp_core))
+ /* Do hard reset if the job failed, or if soft reset fails */
+ if (!success || _MALI_OSK_ERR_OK != mali_pp_reset_wait(group->pp_core))
{
MALI_DEBUG_PRINT(3, ("Mali group: Failed to reset PP, need to reset entire group\n"));
{
MALI_ASSERT_GROUP_LOCKED(group);
- if (group->state == MALI_GROUP_STATE_IDLE ||
+ if (MALI_GROUP_STATE_IDLE == group->state ||
mali_gp_job_get_id(group->gp_running_job) != job_id)
{
return; /* No need to cancel or job has already been aborted or completed */
{
MALI_ASSERT_GROUP_LOCKED(group);
- if (group->state == MALI_GROUP_STATE_IDLE ||
+ if (MALI_GROUP_STATE_IDLE == group->state ||
mali_pp_job_get_id(group->pp_running_job) != job_id)
{
return; /* No need to cancel or job has already been aborted or completed */
{
struct mali_group *group = mali_global_groups[i];
mali_group_lock(group);
- MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state);
+ MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state
+ || MALI_GROUP_STATE_IN_VIRTUAL == group->state);
group->power_is_on = MALI_TRUE;
if (NULL != group->l2_cache_core[0])
{
struct mali_group *group = mali_global_groups[i];
mali_group_lock(group);
- MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state);
+ MALI_DEBUG_ASSERT(MALI_GROUP_STATE_IDLE == group->state
+ || MALI_GROUP_STATE_IN_VIRTUAL == group->state);
group->session = NULL;
group->power_is_on = MALI_FALSE;
{
struct mali_group *child, *temp;
+ /* Disable the broadcast unit while we do reset directly on the member cores. */
+ mali_bcast_disable(group->bcast_core);
+
_MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list)
{
mali_pp_stop_bus_wait(child->pp_core);
mali_pp_hard_reset(child->pp_core);
}
+
+ mali_bcast_enable(group->bcast_core);
}
else
{
struct mali_group *group = (struct mali_group *)data;
struct mali_mmu_core *mmu = group->mmu;
u32 rawstat;
- u32 status;
+ MALI_DEBUG_CODE(u32 status);
MALI_DEBUG_ASSERT_POINTER(mmu);
mali_group_lock(group);
- /* TODO: Remove some of these asserts? Will we ever end up in
- * "physical" bottom half for a member of the virtual group? */
MALI_DEBUG_ASSERT(NULL == group->parent_group);
- MALI_DEBUG_ASSERT(!mali_group_is_in_virtual(group));
if ( MALI_FALSE == mali_group_power_is_on(group) )
{
}
rawstat = mali_mmu_get_rawstat(mmu);
- status = mali_mmu_get_status(mmu);
+ MALI_DEBUG_CODE(status = mali_mmu_get_status(mmu));
MALI_DEBUG_PRINT(4, ("Mali MMU: Bottom half, interrupt 0x%08X, status 0x%08X\n", rawstat, status));
#if defined(CONFIG_MALI400_PROFILING)
if (suspend)
{
- /* @@@@ todo: test this case and see if it is still working*/
_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_SUSPEND|MALI_PROFILING_MAKE_EVENT_CHANNEL_GP(0),
mali_gp_job_get_perf_counter_value0(group->gp_running_job),
mali_gp_job_get_perf_counter_value1(group->gp_running_job),
#endif
#if defined(MALI_UPPER_HALF_SCHEDULING)
- if (irq_readout & MALI200_REG_VAL_IRQ_END_OF_FRAME)
+ /* Check if job is complete without errors */
+ if (MALI200_REG_VAL_IRQ_END_OF_FRAME == irq_readout)
{
_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_START |
MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
mali_group_lock(group);
- /* Read int stat again */
+ /* Check if job is complete without errors, again, after taking the group lock */
irq_readout = mali_pp_read_rawstat(core);
- if (!(irq_readout & MALI200_REG_VAL_IRQ_END_OF_FRAME))
+ if (MALI200_REG_VAL_IRQ_END_OF_FRAME != irq_readout)
{
- /* There was nothing to do */
mali_pp_enable_interrupts(core);
mali_group_unlock(group);
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+ MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+ MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF,
+ 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
return _MALI_OSK_ERR_OK;
}
+ if (mali_group_is_virtual(group))
+ {
+ u32 status_readout = mali_pp_read_status(group->pp_core);
+ if (status_readout & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE)
+ {
+ MALI_DEBUG_PRINT(6, ("Mali PP: Not all cores in broadcast completed\n"));
+ mali_pp_enable_interrupts(core);
+ mali_group_unlock(group);
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+ MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+ MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF,
+ 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
+ return _MALI_OSK_ERR_OK;
+ }
+ }
+
if (mali_group_is_in_virtual(group))
{
/* We're member of a virtual group, so interrupt should be handled by the virtual group */
return _MALI_OSK_ERR_FAULT;
}
- _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
- MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
- MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF,
- 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
-
+ group->core_timed_out = MALI_FALSE;
mali_group_complete_pp(group, MALI_TRUE);
/* No need to enable interrupts again, since the core will be reset while completing the job */
mali_group_unlock(group);
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+ MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+ MALI_PROFILING_EVENT_REASON_START_STOP_SW_UPPER_HALF,
+ 0, 0, MALI_PROFILING_MAKE_EVENT_DATA_CORE_PP(core->core_id), 0, 0);
+
return _MALI_OSK_ERR_OK;
}
#endif
MALI_DEBUG_PRINT(4, ("Mali PP: Bottom half IRQ 0x%08X from core %s\n", irq_readout, mali_pp_get_hw_core_desc(group->pp_core)));
- if (irq_readout & MALI200_REG_VAL_IRQ_END_OF_FRAME)
+ /* Check if job is complete without errors */
+ if (MALI200_REG_VAL_IRQ_END_OF_FRAME == irq_readout)
{
+ if (mali_group_is_virtual(group))
+ {
+ u32 status_readout = mali_pp_read_status(group->pp_core);
+
+ if (status_readout & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE)
+ {
+ MALI_DEBUG_PRINT(6, ("Mali PP: Not all cores in broadcast completed\n"));
+ mali_pp_enable_interrupts(core);
+ mali_group_unlock(group);
+
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+ MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+ MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+ 0, _mali_osk_get_tid(), 0, 0, 0);
+ return;
+ }
+ }
+
MALI_DEBUG_PRINT(3, ("Mali PP: Job completed, calling group handler\n"));
group->core_timed_out = MALI_FALSE;
- _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
- MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
- MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
- 0, _mali_osk_get_tid(), 0, 0, 0);
mali_group_complete_pp(group, MALI_TRUE);
mali_group_unlock(group);
+
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+ MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+ MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+ 0, _mali_osk_get_tid(), 0, 0, 0);
return;
}
irq_errors = irq_readout & ~(MALI200_REG_VAL_IRQ_END_OF_FRAME|MALI200_REG_VAL_IRQ_HANG);
if (0 != irq_errors)
{
- MALI_PRINT_ERROR(("Mali PP: Unknown interrupt 0x%08X from core %s, aborting job\n",
+ MALI_PRINT_ERROR(("Mali PP: Unexpected interrupt 0x%08X from core %s, aborting job\n",
irq_readout, mali_pp_get_hw_core_desc(group->pp_core)));
group->core_timed_out = MALI_FALSE;
+ mali_group_complete_pp(group, MALI_FALSE);
+ mali_group_unlock(group);
+
_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
0, _mali_osk_get_tid(), 0, 0, 0);
- mali_group_complete_pp(group, MALI_FALSE);
- mali_group_unlock(group);
return;
}
else if (group->core_timed_out) /* SW timeout */
{
group->core_timed_out = MALI_FALSE;
- _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
- MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
- MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
- 0, _mali_osk_get_tid(), 0, 0, 0);
if (!_mali_osk_timer_pending(group->timeout_timer) && NULL != group->pp_running_job)
{
MALI_PRINT(("Mali PP: Job %d timed out on core %s\n",
{
mali_group_unlock(group);
}
+
+ _mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP |
+ MALI_PROFILING_EVENT_CHANNEL_SOFTWARE |
+ MALI_PROFILING_EVENT_REASON_START_STOP_SW_BOTTOM_HALF,
+ 0, _mali_osk_get_tid(), 0, 0, 0);
return;
}
/* Stop the timeout timer. */
_mali_osk_timer_del_async(group->timeout_timer);
- /*todo add stop SW counters profiling*/
-
if (NULL != group->pp_running_job)
{
if (MALI_TRUE == mali_group_is_virtual(group))
/* update performance counters from each physical pp core within this virtual group */
_MALI_OSK_LIST_FOREACHENTRY(child, temp, &group->group_list, struct mali_group, group_list)
{
- mali_pp_update_performance_counters(child->pp_core, group->pp_running_job, group->pp_running_sub_job);
+ mali_pp_update_performance_counters(group->pp_core, child->pp_core, group->pp_running_job, mali_pp_core_get_id(child->pp_core));
}
#if defined(CONFIG_MALI400_PROFILING)
else
{
/* update performance counters for a physical group's pp core */
- mali_pp_update_performance_counters(group->pp_core, group->pp_running_job, group->pp_running_sub_job);
+ mali_pp_update_performance_counters(group->pp_core, group->pp_core, group->pp_running_job, group->pp_running_sub_job);
#if defined(CONFIG_MALI400_PROFILING)
_mali_osk_profiling_add_event(MALI_PROFILING_EVENT_TYPE_STOP|
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
int page_dir_ref_count;
mali_bool power_is_on;
- enum mali_group_core_state state; /* @@@@ TODO: include power_is_on in this state? */
+ enum mali_group_core_state state;
struct mali_gp_core *gp_core;
struct mali_gp_job *gp_running_job;
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/* Mali GPU memory. Real values come from module parameter or from device specific data */
-int mali_dedicated_mem_start = 0;
-int mali_dedicated_mem_size = 0;
-int mali_shared_mem_size = 0;
+unsigned int mali_dedicated_mem_start = 0;
+unsigned int mali_dedicated_mem_size = 0;
+unsigned int mali_shared_mem_size = 0;
/* Frame buffer memory to be accessible by Mali GPU */
int mali_fb_start = 0;
/* timer related */
int mali_max_job_runtime = WATCHDOG_MSECS_DEFAULT;
+static _mali_osk_errcode_t mali_set_global_gpu_base_address(void)
+{
+ global_gpu_base_address = _mali_osk_resource_base_address();
+ if (0 == global_gpu_base_address)
+ {
+ return _MALI_OSK_ERR_ITEM_NOT_FOUND;
+ }
+
+ return _MALI_OSK_ERR_OK;
+}
+
+static u32 mali_get_bcast_id(_mali_osk_resource_t *resource_pp)
+{
+ switch (resource_pp->base - global_gpu_base_address)
+ {
+ case 0x08000:
+ case 0x20000: /* fall-through for aliased mapping */
+ return 0x01;
+ case 0x0A000:
+ case 0x22000: /* fall-through for aliased mapping */
+ return 0x02;
+ case 0x0C000:
+ case 0x24000: /* fall-through for aliased mapping */
+ return 0x04;
+ case 0x0E000:
+ case 0x26000: /* fall-through for aliased mapping */
+ return 0x08;
+ case 0x28000:
+ return 0x10;
+ case 0x2A000:
+ return 0x20;
+ case 0x2C000:
+ return 0x40;
+ case 0x2E000:
+ return 0x80;
+ default:
+ return 0;
+ }
+}
+
static _mali_osk_errcode_t mali_parse_product_info(void)
{
/*
u32 first_pp_offset;
_mali_osk_resource_t first_pp_resource;
- global_gpu_base_address = _mali_osk_resource_base_address();
- if (0 == global_gpu_base_address)
- {
- return _MALI_OSK_ERR_ITEM_NOT_FOUND;
- }
-
/* Find out where the first PP core is located */
if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x8000, NULL))
{
struct mali_group *group = mali_group_create(NULL, NULL, NULL);
if (NULL != group)
{
- struct mali_pp_core *pp_core = mali_pp_create(&first_pp_resource, group, MALI_FALSE);
+ struct mali_pp_core *pp_core = mali_pp_create(&first_pp_resource, group, MALI_FALSE, mali_get_bcast_id(&first_pp_resource));
if (NULL != pp_core)
{
u32 pp_version = mali_pp_core_get_version(pp_core);
struct mali_pp_core *pp_core;
/* Create the PP core object inside this group */
- pp_core = mali_pp_create(resource_pp, group, MALI_FALSE);
+ pp_core = mali_pp_create(resource_pp, group, MALI_FALSE, mali_get_bcast_id(resource_pp));
if (NULL == pp_core)
{
/* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
}
/* Create the PP core object inside this group */
- pp_bcast_core = mali_pp_create(resource_pp_bcast, group, MALI_TRUE);
+ pp_bcast_core = mali_pp_create(resource_pp_bcast, group, MALI_TRUE, 0);
if (NULL == pp_bcast_core)
{
/* No need to clean up now, as we will clean up everything linked in from the cluster when we fail this function */
return _MALI_OSK_ERR_FAULT;
}
+static _mali_osk_errcode_t mali_check_shared_interrupts(void)
+{
+#if !defined(CONFIG_MALI_SHARED_INTERRUPTS)
+ if (MALI_TRUE == _mali_osk_shared_interrupts())
+ {
+ MALI_PRINT_ERROR(("Shared interrupts detected, but driver support is not enabled\n"));
+ return _MALI_OSK_ERR_FAULT;
+ }
+#endif /* !defined(CONFIG_MALI_SHARED_INTERRUPTS) */
+
+ /* It is OK to compile support for shared interrupts even if Mali is not using it. */
+ return _MALI_OSK_ERR_OK;
+}
+
static _mali_osk_errcode_t mali_parse_config_pmu(void)
{
_mali_osk_resource_t resource_pmu;
+ MALI_DEBUG_ASSERT(0 != global_gpu_base_address);
+
if (_MALI_OSK_ERR_OK == _mali_osk_resource_find(global_gpu_base_address + 0x02000, &resource_pmu))
{
u32 number_of_pp_cores = 0;
if (NULL == mali_pmu_create(&resource_pmu, number_of_pp_cores, number_of_l2_caches))
{
+ MALI_PRINT_ERROR(("Failed to create PMU\n"));
return _MALI_OSK_ERR_FAULT;
}
}
err = _mali_osk_profiling_init(mali_boot_profiling ? MALI_TRUE : MALI_FALSE);
if (_MALI_OSK_ERR_OK != err)
{
- /* No biggie if we wheren't able to initialize the profiling */
+ /* No biggie if we weren't able to initialize the profiling */
MALI_PRINT_ERROR(("Failed to initialize profiling, feature will be unavailable\n"));
}
#endif
err = mali_parse_config_memory();
if (_MALI_OSK_ERR_OK != err) goto parse_memory_config_failed;
+ err = mali_set_global_gpu_base_address();
+ if (_MALI_OSK_ERR_OK != err) goto set_global_gpu_base_address_failed;
+
+ err = mali_check_shared_interrupts();
+ if (_MALI_OSK_ERR_OK != err) goto check_shared_interrupts_failed;
+
/* Initialize the MALI PMU */
err = mali_parse_config_pmu();
if (_MALI_OSK_ERR_OK != err) goto parse_pmu_config_failed;
}
}
parse_pmu_config_failed:
- /* undoing mali_parse_config_memory() is done by mali_memory_terminate() */
+ /* undoing mali_parse_config_pmu() is done by mali_memory_terminate() */
+check_shared_interrupts_failed:
+ global_gpu_base_address = 0;
+set_global_gpu_base_address_failed:
+ global_gpu_base_address = 0;
parse_memory_config_failed:
mali_memory_terminate();
memory_init_failed:
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
return;
}
+_mali_osk_errcode_t _mali_ukk_mem_write_safe(_mali_uk_mem_write_safe_s *args)
+{
+ MALI_DEBUG_ASSERT_POINTER(args);
+
+ if (NULL == args->ctx)
+ {
+ return _MALI_OSK_ERR_INVALID_ARGS;
+ }
+
+ /* Return number of bytes actually copied */
+ args->size = _mali_osk_mem_write_safe(args->dest, args->src, args->size);
+ return _MALI_OSK_ERR_OK;
+}
+
_mali_osk_errcode_t _mali_ukk_map_external_mem( _mali_uk_map_external_mem_s *args )
{
mali_physical_memory_allocator external_memory_allocator;
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/* The stall can not fail in current hw-state */
MALI_DEBUG_ASSERT(stall_success);
+ MALI_IGNORE(stall_success);
MALI_DEBUG_PRINT(3, ("Mali MMU: mali_kernel_mmu_reset: %s\n", mmu->hw_core.description));
MALI_DEBUG_PRINT(3, ("Activating the empty page directory on MMU %s\n", mmu->hw_core.description));
stall_success = mali_mmu_enable_stall(mmu);
+
/* This function can only be called when the core is idle, so it could not fail. */
- MALI_DEBUG_ASSERT( stall_success );
+ MALI_DEBUG_ASSERT(stall_success);
+ MALI_IGNORE(stall_success);
+
mali_mmu_activate_address_space(mmu, mali_empty_page_directory);
mali_mmu_disable_stall(mmu);
}
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*/
void _mali_osk_wq_delete_work( _mali_osk_wq_work_t *work );
+/** @brief Delete a work object
+ *
+ * This will NOT flush the work queue, so only call this if you are sure that the work handler will
+ * not be called after deletion.
+ */
+void _mali_osk_wq_delete_work_nonflush( _mali_osk_wq_work_t *work );
+
/** @brief Cause a queued, deferred call of the work handler
*
* _mali_osk_wq_schedule_work provides a mechanism for enqueuing deferred calls
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*/
_mali_osk_errcode_t _mali_osk_device_data_get(struct _mali_osk_device_data *data);
+/** @brief Determines if Mali GPU has been configured with shared interrupts.
+ *
+ * @return MALI_TRUE if shared interrupts, MALI_FALSE if not.
+ */
+mali_bool _mali_osk_shared_interrupts(void);
+
/** @} */ /* end group _mali_osk_miscellaneous */
* \ref _MALI_OSK_MEM_MAPREGION_FLAG_OS_ALLOCATED_PHYSADDR set.
*/
void _mali_osk_mem_mapregion_unmap( mali_memory_allocation * descriptor, u32 offset, u32 size, _mali_osk_mem_mapregion_flags_t flags );
+
+/** @brief Copy as much data as possible from src to dest, do not crash if src or dest isn't available.
+ *
+ * @param dest Destination buffer (limited to user space mapped Mali memory)
+ * @param src Source buffer
+ * @param size Number of bytes to copy
+ * @return Number of bytes actually copied
+ */
+u32 _mali_osk_mem_write_safe(void *dest, const void *src, u32 size);
+
/** @} */ /* end group _mali_osk_low_level_memory */
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
void mali_pmu_delete(struct mali_pmu_core *pmu)
{
MALI_DEBUG_ASSERT_POINTER(pmu);
+ MALI_DEBUG_ASSERT(pmu == mali_global_pmu_core);
+ MALI_DEBUG_PRINT(2, ("Mali PMU: Deleting Mali PMU core\n"));
mali_hw_core_delete(&pmu->hw_core);
_mali_osk_free(pmu);
- pmu = NULL;
+ mali_global_pmu_core = NULL;
}
_mali_osk_errcode_t mali_pmu_reset(struct mali_pmu_core *pmu)
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
static void mali_pp_irq_probe_trigger(void *data);
static _mali_osk_errcode_t mali_pp_irq_probe_ack(void *data);
-struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual)
+struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t *resource, struct mali_group *group, mali_bool is_virtual, u32 bcast_id)
{
struct mali_pp_core* core = NULL;
if (NULL != core)
{
core->core_id = mali_global_num_pp_cores;
+ core->bcast_id = bcast_id;
core->counter_src0_used = MALI_HW_CORE_NO_COUNTER;
core->counter_src1_used = MALI_HW_CORE_NO_COUNTER;
int i;
u32 rawstat = 0;
- /* TODO: For virtual Mali-450 core, check that PP active in STATUS is 0 (this must be initiated from group) */
-
for (i = 0; i < MALI_REG_POLL_COUNT_FAST; i++)
{
- rawstat = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT);
- if (rawstat & MALI400PP_REG_VAL_IRQ_RESET_COMPLETED)
+ if (!(mali_pp_read_status(core) & MALI200_REG_VAL_STATUS_RENDERING_ACTIVE))
{
- break;
+ rawstat = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT);
+ if (rawstat == MALI400PP_REG_VAL_IRQ_RESET_COMPLETED)
+ {
+ break;
+ }
}
}
}
#endif
-void mali_pp_update_performance_counters(struct mali_pp_core *core, struct mali_pp_job *job, u32 subjob)
+void mali_pp_update_performance_counters(struct mali_pp_core *parent, struct mali_pp_core *child, struct mali_pp_job *job, u32 subjob)
{
u32 val0 = 0;
u32 val1 = 0;
#if defined(CONFIG_MALI400_PROFILING)
- int counter_index = COUNTER_FP0_C0 + (2 * core->core_id);
+ int counter_index = COUNTER_FP0_C0 + (2 * child->core_id);
#endif
- if (MALI_HW_CORE_NO_COUNTER != core->counter_src0_used)
+ if (MALI_HW_CORE_NO_COUNTER != parent->counter_src0_used)
{
- val0 = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE);
-
+ val0 = mali_hw_core_register_read(&child->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_0_VALUE);
mali_pp_job_set_perf_counter_value0(job, subjob, val0);
#if defined(CONFIG_MALI400_PROFILING)
- /*todo: check if the group is virtual - in such case, does it make sense to send a HW counter ?*/
_mali_osk_profiling_report_hw_counter(counter_index, val0);
#endif
}
- if (MALI_HW_CORE_NO_COUNTER != core->counter_src1_used)
+ if (MALI_HW_CORE_NO_COUNTER != parent->counter_src1_used)
{
- val1 = mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
+ val1 = mali_hw_core_register_read(&child->hw_core, MALI200_REG_ADDR_MGMT_PERF_CNT_1_VALUE);
mali_pp_job_set_perf_counter_value1(job, subjob, val1);
#if defined(CONFIG_MALI400_PROFILING)
- /*todo: check if the group is virtual - in such case, does it make sense to send a HW counter ?*/
_mali_osk_profiling_report_hw_counter(counter_index + 1, val1);
#endif
}
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
struct mali_hw_core hw_core; /**< Common for all HW cores */
_mali_osk_irq_t *irq; /**< IRQ handler */
u32 core_id; /**< Unique core ID */
+ u32 bcast_id; /**< The "flag" value used by the Mali-450 broadcast and DLBU unit */
u32 counter_src0_used; /**< The selected performance counter 0 when a job is running */
u32 counter_src1_used; /**< The selected performance counter 1 when a job is running */
};
_mali_osk_errcode_t mali_pp_initialize(void);
void mali_pp_terminate(void);
-struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t * resource, struct mali_group *group, mali_bool is_virtual);
+struct mali_pp_core *mali_pp_create(const _mali_osk_resource_t * resource, struct mali_group *group, mali_bool is_virtual, u32 bcast_id);
void mali_pp_delete(struct mali_pp_core *core);
void mali_pp_stop_bus(struct mali_pp_core *core);
return core->core_id;
}
+MALI_STATIC_INLINE u32 mali_pp_core_get_bcast_id(struct mali_pp_core *core)
+{
+ MALI_DEBUG_ASSERT_POINTER(core);
+ return core->bcast_id;
+}
+
struct mali_pp_core* mali_pp_get_global_pp_core(u32 index);
u32 mali_pp_get_glob_num_pp_cores(void);
/* Debug */
u32 mali_pp_dump_state(struct mali_pp_core *core, char *buf, u32 size);
-void mali_pp_update_performance_counters(struct mali_pp_core *core, struct mali_pp_job *job, u32 subjob);
+/**
+ * Put instrumented HW counters from the core(s) to the job object (if enabled)
+ *
+ * parent and child is always the same, except for virtual jobs on Mali-450.
+ * In this case, the counters will be enabled on the virtual core (parent),
+ * but values need to be read from the child cores.
+ *
+ * @param parent The core used to see if the counters was enabled
+ * @param child The core to actually read the values from
+ * @job Job object to update with counter values (if enabled)
+ * @subjob Which subjob the counters are applicable for (core ID for virtual jobs)
+ */
+void mali_pp_update_performance_counters(struct mali_pp_core *parent, struct mali_pp_core *child, struct mali_pp_job *job, u32 subjob);
MALI_STATIC_INLINE const char *mali_pp_get_hw_core_desc(struct mali_pp_core *core)
{
return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_RAWSTAT) & MALI200_REG_VAL_IRQ_MASK_USED;
}
+MALI_STATIC_INLINE u32 mali_pp_read_status(struct mali_pp_core *core)
+{
+ return mali_hw_core_register_read(&core->hw_core, MALI200_REG_ADDR_MGMT_STATUS);
+}
+
MALI_STATIC_INLINE void mali_pp_mask_all_interrupts(struct mali_pp_core *core)
{
mali_hw_core_register_write(&core->hw_core, MALI200_REG_ADDR_MGMT_INT_MASK, MALI200_REG_VAL_IRQ_MASK_NONE);
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
struct mali_pp_job *job;
u32 perf_counter_flag;
- job = _mali_osk_malloc(sizeof(struct mali_pp_job));
+ job = _mali_osk_calloc(1, sizeof(struct mali_pp_job));
if (NULL != job)
{
- u32 i;
-
if (0 != _mali_osk_copy_from_user(&job->uargs, uargs, sizeof(_mali_uk_pp_start_job_s)))
{
- _mali_osk_free(job);
- return NULL;
+ goto fail;
}
if (job->uargs.num_cores > _MALI_PP_MAX_SUB_JOBS)
{
MALI_PRINT_ERROR(("Mali PP job: Too many sub jobs specified in job object\n"));
- _mali_osk_free(job);
- return NULL;
+ goto fail;
}
if (!mali_pp_job_use_no_notification(job))
{
job->finished_notification = _mali_osk_notification_create(_MALI_NOTIFICATION_PP_FINISHED, sizeof(_mali_uk_pp_job_finished_s));
- if (NULL == job->finished_notification)
- {
- _mali_osk_free(job);
- return NULL;
- }
- }
- else
- {
- job->finished_notification = NULL;
+ if (NULL == job->finished_notification) goto fail;
}
perf_counter_flag = mali_pp_job_get_perf_counter_flag(job);
_mali_osk_list_init(&job->session_list);
job->id = id;
- for (i = 0; i < job->uargs.num_cores; i++)
- {
- job->perf_counter_value0[i] = 0;
- job->perf_counter_value1[i] = 0;
- }
job->sub_jobs_num = job->uargs.num_cores ? job->uargs.num_cores : 1;
- job->sub_jobs_started = 0;
- job->sub_jobs_completed = 0;
- job->sub_job_errors = 0;
job->pid = _mali_osk_get_pid();
job->tid = _mali_osk_get_tid();
-#if defined(CONFIG_SYNC)
- job->sync_point = NULL;
- job->pre_fence = NULL;
- job->sync_work = NULL;
+
+ job->num_memory_cookies = job->uargs.num_memory_cookies;
+ if (job->num_memory_cookies > 0)
+ {
+ u32 size;
+
+ if (job->uargs.num_memory_cookies > session->descriptor_mapping->current_nr_mappings)
+ {
+ MALI_PRINT_ERROR(("Mali PP job: Too many memory cookies specified in job object\n"));
+ goto fail;
+ }
+
+ size = sizeof(*job->uargs.memory_cookies) * job->num_memory_cookies;
+
+ job->memory_cookies = _mali_osk_malloc(size);
+ if (NULL == job->memory_cookies)
+ {
+ MALI_PRINT_ERROR(("Mali PP job: Failed to allocate %d bytes of memory cookies!\n", size));
+ goto fail;
+ }
+
+ if (0 != _mali_osk_copy_from_user(job->memory_cookies, job->uargs.memory_cookies, size))
+ {
+ MALI_PRINT_ERROR(("Mali PP job: Failed to copy %d bytes of memory cookies from user!\n", size));
+ goto fail;
+ }
+
+#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+ job->num_dma_bufs = job->num_memory_cookies;
+ job->dma_bufs = _mali_osk_calloc(job->num_dma_bufs, sizeof(struct mali_dma_buf_attachment *));
+ if (NULL == job->dma_bufs)
+ {
+ MALI_PRINT_ERROR(("Mali PP job: Failed to allocate dma_bufs array!\n"));
+ goto fail;
+ }
#endif
+ }
+ else
+ {
+ job->memory_cookies = NULL;
+ }
return job;
}
+fail:
+ if (NULL != job)
+ {
+ mali_pp_job_delete(job);
+ }
+
return NULL;
}
void mali_pp_job_delete(struct mali_pp_job *job)
{
#ifdef CONFIG_SYNC
+ /* It is safe to delete the work without flushing. */
+ if (NULL != job->sync_work) _mali_osk_wq_delete_work_nonflush(job->sync_work);
if (NULL != job->pre_fence) sync_fence_put(job->pre_fence);
if (NULL != job->sync_point) sync_fence_put(job->sync_point->fence);
#endif
{
_mali_osk_notification_delete(job->finished_notification);
}
+
+ _mali_osk_free(job->memory_cookies);
+
+#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+ _mali_osk_free(job->dma_bufs);
+#endif
+
_mali_osk_free(job);
}
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
#include <linux/sync.h>
#endif
#include "mali_dlbu.h"
+#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+#include "linux/mali_dma_buf.h"
+#endif
/**
* The structure represents a PP job, including all sub-jobs
u32 pid; /**< Process ID of submitting process */
u32 tid; /**< Thread ID of submitting thread */
_mali_osk_notification_t *finished_notification; /**< Notification sent back to userspace on job complete */
+ u32 num_memory_cookies; /**< Number of memory cookies attached to job */
+ u32 *memory_cookies; /**< Memory cookies attached to job */
+#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+ struct mali_dma_buf_attachment **dma_bufs; /**< Array of DMA-bufs used by job */
+ u32 num_dma_bufs; /**< Number of DMA-bufs used by job */
+#endif
#ifdef CONFIG_SYNC
mali_sync_pt *sync_point; /**< Sync point to signal on completion */
struct sync_fence_waiter sync_waiter; /**< Sync waiter for async wait */
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
#include "mali_group.h"
#include "mali_pm.h"
+#if defined(CONFIG_DMA_SHARED_BUFFER)
+#include "mali_dma_buf.h"
+#endif
+
+/* With certain configurations, job deletion involves functions which cannot be called from atomic context.
+ * This #if checks for those cases and enables job deletion to be deferred and run in a different context. */
#if defined(CONFIG_SYNC)
#define MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE 1
#endif
{
struct mali_group *group, *temp;
+ MALI_DEBUG_ASSERT(_mali_osk_list_empty(&group_list_working));
+ MALI_DEBUG_ASSERT(!virtual_group_working);
+
/* Delete all groups owned by scheduler */
if (NULL != virtual_group)
{
mali_group_delete(virtual_group);
}
- MALI_DEBUG_ASSERT(_mali_osk_list_empty(&group_list_working));
_MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_idle, struct mali_group, pp_scheduler_list)
{
mali_group_delete(group);
mali_group_unlock(group);
- /* @@@@ todo: remove the return value from mali_group_start_xx_job, since we can't fail on Mali-300++ */
+ /* remove the return value from mali_group_start_xx_job, since we can't fail on Mali-300++ */
}
}
if (MALI_FALSE == mali_pp_job_use_no_notification(job))
{
u32 i;
- u32 sub_jobs = mali_pp_job_get_sub_job_count(job);
+ u32 num_counters_to_copy;
mali_bool success = mali_pp_job_was_success(job);
_mali_uk_pp_job_finished_s *jobres = job->finished_notification->result_buffer;
jobres->status = _MALI_UK_JOB_STATUS_END_UNKNOWN_ERR;
}
- for (i = 0; i < sub_jobs; i++)
+ if (mali_pp_job_is_virtual(job))
+ {
+ num_counters_to_copy = num_cores; /* Number of physical cores available */
+ }
+ else
+ {
+ num_counters_to_copy = mali_pp_job_get_sub_job_count(job);
+ }
+
+ for (i = 0; i < num_counters_to_copy; i++)
{
jobres->perf_counter0[i] = mali_pp_job_get_perf_counter_value0(job, i);
jobres->perf_counter1[i] = mali_pp_job_get_perf_counter_value1(job, i);
/* Remove job from session list */
_mali_osk_list_del(&job->session_list);
- /* Send notification back to user space */
MALI_DEBUG_PRINT(4, ("Mali PP scheduler: All parts completed for %s job %u (0x%08X)\n",
mali_pp_job_is_virtual(job) ? "virtual" : "physical",
mali_pp_job_get_id(job), job));
}
#endif
+#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+ /* Unmap buffers attached to job */
+ if (0 < job->num_dma_bufs)
+ {
+ mali_dma_buf_unmap_job(job);
+ }
+#endif /* CONFIG_DMA_SHARED_BUFFER */
+
+
+ /* Send notification back to user space */
#if defined(MALI_PP_SCHEDULER_USE_DEFERRED_JOB_DELETE)
mali_pp_scheduler_return_job_to_user(job, MALI_TRUE);
#else
* num_slots == num_slots_idle, so unless we are done working, no
* threads will actually be woken up.
*/
+ if (mali_group_is_virtual(group))
+ {
+ virtual_group_working = MALI_FALSE;
+ }
+ else
+ {
+ _mali_osk_list_move(&(group->pp_scheduler_list), &group_list_idle);
+ }
_mali_osk_wait_queue_wake_up(pp_scheduler_working_wait_queue);
mali_pp_scheduler_unlock();
return;
{
/* A barrier was resolved, so schedule previously blocked jobs */
_mali_osk_wq_schedule_work(pp_scheduler_wq_schedule);
-
- /* TODO: Subjob optimisation */
}
/* Recycle variables */
}
else
{
- /* @@@@ todo: this cant fail on Mali-300+, no need to implement put back of job */
+ /* this cant fail on Mali-300+, no need to implement put back of job */
MALI_DEBUG_ASSERT(0);
}
else if (NULL != virtual_group)
{
/* Rejoin virtual group */
- /* TODO: In the future, a policy check might be useful here */
+ /* In the future, a policy check might be useful here */
/* We're no longer needed on the scheduler list */
_mali_osk_list_delinit(&(group->pp_scheduler_list));
mali_group_unlock(group);
mali_group_lock(virtual_group);
- /* TODO: Take group lock also? */
mali_group_add_group(virtual_group, group);
mali_group_unlock(virtual_group);
/* We need to return from this function with the group lock held */
- /* TODO: optimise! */
mali_group_lock(group);
}
else
{
MALI_DEBUG_ASSERT_POINTER(job);
+#if defined(CONFIG_DMA_SHARED_BUFFER) && !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+ /* Map buffers attached to job */
+ if (0 != job->num_memory_cookies)
+ {
+ mali_dma_buf_map_job(job);
+ }
+#endif /* CONFIG_DMA_SHARED_BUFFER */
+
mali_pm_core_event(MALI_CORE_EVENT_PP_START);
mali_pp_scheduler_lock();
{
struct mali_session_data *session;
struct mali_pp_job *job;
-#if defined(CONFIG_SYNC)
- int post_fence = -1;
-#endif
MALI_DEBUG_ASSERT_POINTER(uargs);
MALI_DEBUG_ASSERT_POINTER(ctx);
#if defined(CONFIG_SYNC)
if (_MALI_PP_JOB_FLAG_FENCE & job->uargs.flags)
{
+ int post_fence = -1;
+
job->sync_point = mali_stream_create_point(job->uargs.stream);
if (unlikely(NULL == job->sync_point))
MALI_DEBUG_PRINT(3, ("Sync: Created fence %d for job %d\n", post_fence, mali_pp_job_get_id(job)));
}
+ else if (_MALI_PP_JOB_FLAG_EMPTY_FENCE & job->uargs.flags)
+ {
+ int empty_fence_fd = job->uargs.stream;
+ struct sync_fence *empty_fence;
+ struct sync_pt *pt;
+ int ret;
+
+ /* Grab and keep a reference to the fence. It must be around
+ * when the job is completed, so the point can be signalled. */
+ empty_fence = sync_fence_fdget(empty_fence_fd);
+
+ if (unlikely(NULL == empty_fence))
+ {
+ MALI_DEBUG_PRINT_ERROR(("Failed to accept empty fence: %d\n", empty_fence_fd));
+ mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */
+ mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */
+ return _MALI_OSK_ERR_OK;
+ }
+
+ if (unlikely(list_empty(&empty_fence->pt_list_head)))
+ {
+ MALI_DEBUG_PRINT_ERROR(("Failed to accept empty fence: %d\n", empty_fence_fd));
+ sync_fence_put(empty_fence);
+ mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */
+ mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */
+ return _MALI_OSK_ERR_OK;
+ }
+
+ pt = list_first_entry(&empty_fence->pt_list_head, struct sync_pt, pt_list);
+
+ ret = mali_sync_timed_commit(pt);
+
+ if (unlikely(0 != ret))
+ {
+ MALI_DEBUG_PRINT_ERROR(("Empty fence not valid: %d\n", empty_fence_fd));
+ sync_fence_put(empty_fence);
+ mali_pp_job_mark_sub_job_completed(job, MALI_FALSE); /* Flagging the job as failed. */
+ mali_pp_scheduler_return_job_to_user(job, MALI_FALSE); /* This will also delete the job object */
+ return _MALI_OSK_ERR_OK;
+ }
+
+ job->sync_point = pt;
+
+ *fence = empty_fence_fd;
+
+ MALI_DEBUG_PRINT(3, ("Sync: Job %d now backs fence %d\n", mali_pp_job_get_id(job), empty_fence_fd));
+ }
if (0 < job->uargs.fence)
{
int pre_fence_fd = job->uargs.fence;
int err;
- MALI_DEBUG_PRINT(2, ("Sync: Job %d waiting for fence %d\n", mali_pp_job_get_id(job), pre_fence_fd));
+ MALI_DEBUG_PRINT(3, ("Sync: Job %d waiting for fence %d\n", mali_pp_job_get_id(job), pre_fence_fd));
job->pre_fence = sync_fence_fdget(pre_fence_fd); /* Reference will be released when job is deleted. */
if (NULL == job->pre_fence)
{
/* Fence has already signalled */
mali_pp_scheduler_queue_job(job, session);
- if (0 == _mali_osk_list_empty(&group_list_idle)) mali_pp_scheduler_schedule();
+ if (!_mali_osk_list_empty(&group_list_idle) || !virtual_group_working)
+ {
+ mali_pp_scheduler_schedule();
+ }
return _MALI_OSK_ERR_OK;
}
else if (0 > err)
}
MALI_DEBUG_ASSERT(_mali_osk_list_empty(&group_list_working));
+ MALI_DEBUG_ASSERT(!virtual_group_working);
_MALI_OSK_LIST_FOREACHENTRY(group, temp, &group_list_idle, struct mali_group, pp_scheduler_list)
{
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
*/
_mali_osk_errcode_t _mali_ukk_dump_mmu_page_table( _mali_uk_dump_mmu_page_table_s * args );
+/** @brief Write user data to specified Mali memory without causing segfaults.
+ * @param args see _mali_uk_mem_write_safe_s in mali_utgard_uk_types.h
+ * @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
+ */
+_mali_osk_errcode_t _mali_ukk_mem_write_safe( _mali_uk_mem_write_safe_s *args );
+
/** @brief Map a physically contiguous range of memory into Mali
* @param args see _mali_uk_map_external_mem_s in mali_utgard_uk_types.h
* @return _MALI_OSK_ERR_OK on success, otherwise a suitable _mali_osk_errcode_t on failure.
/**
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
{
mali_bool notify = MALI_FALSE;
- MALI_DEBUG_ASSERT(setting < _MALI_UK_USER_SETTING_MAX && setting >= 0);
+ if (setting >= _MALI_UK_USER_SETTING_MAX || setting < 0)
+ {
+ MALI_DEBUG_PRINT_ERROR(("Invalid user setting %ud\n"));
+ return;
+ }
if (mali_user_settings[setting] != value)
{
u32 mali_get_user_setting(_mali_uk_user_setting_t setting)
{
- MALI_DEBUG_ASSERT(setting < _MALI_UK_USER_SETTING_MAX && setting >= 0);
+ if (setting >= _MALI_UK_USER_SETTING_MAX || setting < 0)
+ {
+ return 0;
+ }
return mali_user_settings[setting];
}
/**
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
#define MALI_IOC_GET_USER_SETTING _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTING, _mali_uk_get_user_setting_s *)
#define MALI_IOC_GET_USER_SETTINGS _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_GET_USER_SETTINGS, _mali_uk_get_user_settings_s *)
#define MALI_IOC_STREAM_CREATE _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_STREAM_CREATE, _mali_uk_stream_create_s *)
+#define MALI_IOC_FENCE_CREATE_EMPTY _IOWR(MALI_IOC_CORE_BASE, _MALI_UK_FENCE_CREATE_EMPTY, _mali_uk_fence_create_empty_s *)
#define MALI_IOC_FENCE_VALIDATE _IOR(MALI_IOC_CORE_BASE, _MALI_UK_FENCE_VALIDATE, _mali_uk_fence_validate_s *)
#define MALI_IOC_MEM_GET_BIG_BLOCK _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_GET_BIG_BLOCK, void *)
#define MALI_IOC_MEM_RELEASE_UMP _IOW(MALI_IOC_MEMORY_BASE, _MALI_UK_RELEASE_UMP_MEM, _mali_uk_release_ump_mem_s *)
#define MALI_IOC_MEM_QUERY_MMU_PAGE_TABLE_DUMP_SIZE _IOR (MALI_IOC_MEMORY_BASE, _MALI_UK_QUERY_MMU_PAGE_TABLE_DUMP_SIZE, _mali_uk_query_mmu_page_table_dump_size_s *)
#define MALI_IOC_MEM_DUMP_MMU_PAGE_TABLE _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_DUMP_MMU_PAGE_TABLE, _mali_uk_dump_mmu_page_table_s *)
+#define MALI_IOC_MEM_WRITE_SAFE _IOWR(MALI_IOC_MEMORY_BASE, _MALI_UK_MEM_WRITE_SAFE, _mali_uk_mem_write_safe_s *)
#define MALI_IOC_PP_START_JOB _IOWR(MALI_IOC_PP_BASE, _MALI_UK_PP_START_JOB, _mali_uk_pp_start_job_s *)
#define MALI_IOC_PP_NUMBER_OF_CORES_GET _IOR (MALI_IOC_PP_BASE, _MALI_UK_GET_PP_NUMBER_OF_CORES, _mali_uk_get_pp_number_of_cores_s *)
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
MALI_PROFILING_EVENT_REASON_SINGLE_SW_FB_EVENT = 4,
MALI_PROFILING_EVENT_REASON_SINGLE_SW_GP_ENQUEUE = 5,
MALI_PROFILING_EVENT_REASON_SINGLE_SW_PP_ENQUEUE = 6,
+ MALI_PROFILING_EVENT_REASON_SINGLE_SW_READBACK = 7,
+ MALI_PROFILING_EVENT_REASON_SINGLE_SW_WRITEBACK = 8,
MALI_PROFILING_EVENT_REASON_SINGLE_SW_ENTER_API_FUNC = 10,
MALI_PROFILING_EVENT_REASON_SINGLE_SW_LEAVE_API_FUNC = 11,
+ MALI_PROFILING_EVENT_REASON_SINGLE_SW_DISCARD_ATTACHMENTS = 13,
MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_TRY_LOCK = 53,
MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_LOCK = 54,
MALI_PROFILING_EVENT_REASON_SINGLE_SW_UMP_UNLOCK = 55,
MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_X11_GLOBAL_LOCK = 37, /* Not currently used */
MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_X11_SWAP = 38, /* Not currently used */
MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_MALI_EGL_IMAGE_SYNC_WAIT = 39, /* USED */
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_GP_JOB_HANDLING =40, /* USED */
+ MALI_PROFILING_EVENT_REASON_SUSPEND_RESUME_SW_PP_JOB_HANDLING =41, /* USED */
} cinstr_profiling_event_reason_suspend_resume_sw_t;
/**
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
_MALI_UK_GET_USER_SETTING, /**< _mali_ukk_get_user_setting() *//**< [out] */
_MALI_UK_GET_USER_SETTINGS, /**< _mali_ukk_get_user_settings() *//**< [out] */
_MALI_UK_STREAM_CREATE, /**< _mali_ukk_stream_create() */
+ _MALI_UK_FENCE_CREATE_EMPTY, /**< _mali_ukk_fence_create_empty() */
_MALI_UK_FENCE_VALIDATE, /**< _mali_ukk_fence_validate() */
/** Memory functions */
_MALI_UK_MAP_EXT_MEM, /**< _mali_uku_map_external_mem() */
_MALI_UK_UNMAP_EXT_MEM, /**< _mali_uku_unmap_external_mem() */
_MALI_UK_VA_TO_MALI_PA, /**< _mali_uku_va_to_mali_pa() */
+ _MALI_UK_MEM_WRITE_SAFE, /**< _mali_uku_mem_write_safe() */
/** Common functions for each core */
#define _MALI_PP_JOB_FLAG_NO_NOTIFICATION (1<<0)
#define _MALI_PP_JOB_FLAG_BARRIER (1<<1)
#define _MALI_PP_JOB_FLAG_FENCE (1<<2)
+#define _MALI_PP_JOB_FLAG_EMPTY_FENCE (1<<3)
/** @defgroup _mali_uk_ppstartjob_s Fragment Processor Start Job
* @{ */
u32 flush_id; /**< [in] flush id within the originating frame builder */
u32 flags; /**< [in] See _MALI_PP_JOB_FLAG_* for a list of avaiable flags */
s32 fence; /**< [in,out] Fence to wait on / fence that will be signalled on job completion, if _MALI_PP_JOB_FLAG_FENCE is set */
- s32 stream; /**< [in] Steam identifier */
+ s32 stream; /**< [in] Steam identifier if _MALI_PP_JOB_FLAG_FENCE, an empty fence to use for this job if _MALI_PP_JOB_FLAG_EMPTY_FENCE is set */
+ u32 num_memory_cookies; /**< [in] number of memory cookies attached to job */
+ u32 *memory_cookies; /**< [in] memory cookies attached to job */
} _mali_uk_pp_start_job_s;
/** @} */ /* end group _mali_uk_ppstartjob_s */
* The 16bit integer is stored twice in a 32bit integer
* For example, for version 1 the value would be 0x00010001
*/
-#define _MALI_API_VERSION 19
+#define _MALI_API_VERSION 20
#define _MALI_UK_API_VERSION _MAKE_VERSION_ID(_MALI_API_VERSION)
/**
u32 size; /**< [in,out] Size of the range, in bytes. */
} _mali_uk_va_to_mali_pa_s;
+/**
+ * @brief Arguments for _mali_uk[uk]_mem_write_safe()
+ */
+typedef struct
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ const void *src; /**< [in] Pointer to source data */
+ void *dest; /**< [in] Destination Mali buffer */
+ u32 size; /**< [in,out] Number of bytes to write/copy on input, number of bytes actually written/copied on output */
+} _mali_uk_mem_write_safe_s;
typedef struct
{
int fd; /**< [in] file descriptor describing stream */
} _mali_uk_stream_destroy_s;
+/** @brief Create empty fence
+ */
+typedef struct
+{
+ void *ctx; /**< [in,out] user-kernel context (trashed on output) */
+ s32 stream; /**< [in] stream to create fence on */
+ s32 fence; /**< [out] file descriptor describing fence */
+} _mali_uk_fence_create_empty_s;
+
/** @brief Check fence validity
*/
typedef struct
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
#include <linux/scatterlist.h>
#include <linux/rbtree.h>
#include <linux/platform_device.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <asm/spinlock.h>
#include "mali_ukk.h"
#include "mali_osk.h"
#include "mali_kernel_memory_engine.h"
#include "mali_memory.h"
+#include "mali_dma_buf.h"
struct mali_dma_buf_attachment {
struct dma_buf *buf;
struct dma_buf_attachment *attachment;
struct sg_table *sgt;
- _mali_osk_atomic_t ref;
- struct rb_node rb_node;
+ struct mali_session_data *session;
+ int map_ref;
+ spinlock_t map_lock;
+ mali_bool is_mapped;
+ wait_queue_head_t wait_queue;
};
-static struct rb_root mali_dma_bufs = RB_ROOT;
-static DEFINE_SPINLOCK(mali_dma_bufs_lock);
+void mali_dma_buf_release(void *ctx, void *handle)
+{
+ struct mali_dma_buf_attachment *mem;
+
+ mem = (struct mali_dma_buf_attachment *)handle;
+
+ MALI_DEBUG_PRINT(3, ("Mali DMA-buf: release attachment %p\n", mem));
+
+ MALI_DEBUG_ASSERT_POINTER(mem);
+ MALI_DEBUG_ASSERT_POINTER(mem->attachment);
+ MALI_DEBUG_ASSERT_POINTER(mem->buf);
+
+#if defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+ /* We mapped implicitly on attach, so we need to unmap on release */
+ mali_dma_buf_unmap(mem);
+#endif
+
+ /* Wait for buffer to become unmapped */
+ wait_event(mem->wait_queue, 0 == mem->map_ref);
+ MALI_DEBUG_ASSERT(!mem->is_mapped);
-static inline struct mali_dma_buf_attachment *mali_dma_buf_lookup(struct rb_root *root, struct dma_buf *target)
+ dma_buf_detach(mem->buf, mem->attachment);
+ dma_buf_put(mem->buf);
+
+ _mali_osk_free(mem);
+}
+
+/*
+ * Map DMA buf attachment \a mem into \a session at virtual address \a virt.
+ */
+int mali_dma_buf_map(struct mali_dma_buf_attachment *mem, struct mali_session_data *session, u32 virt, u32 *offset, u32 flags)
{
- struct rb_node *node = root->rb_node;
- struct mali_dma_buf_attachment *res;
+ struct mali_page_directory *pagedir;
+ struct scatterlist *sg;
+ unsigned long irq_flags;
+ int i;
+
+ MALI_DEBUG_ASSERT_POINTER(mem);
+ MALI_DEBUG_ASSERT_POINTER(session);
+ MALI_DEBUG_ASSERT(mem->session == session);
+
+ spin_lock_irqsave(&mem->map_lock, irq_flags);
- spin_lock(&mali_dma_bufs_lock);
- while (node)
+ mem->map_ref++;
+
+ MALI_DEBUG_PRINT(5, ("Mali DMA-buf: map attachment %p, new map_ref = %d\n", mem, mem->map_ref));
+
+ if (1 == mem->map_ref)
{
- res = rb_entry(node, struct mali_dma_buf_attachment, rb_node);
+ spin_unlock_irqrestore(&mem->map_lock, irq_flags);
+
+ /* First reference taken, so we need to map the dma buf */
+ MALI_DEBUG_ASSERT(!mem->is_mapped);
+
+ pagedir = mali_session_get_page_directory(session);
+ MALI_DEBUG_ASSERT_POINTER(pagedir);
+
+ mem->sgt = dma_buf_map_attachment(mem->attachment, DMA_BIDIRECTIONAL);
+ if (IS_ERR_OR_NULL(mem->sgt))
+ {
+ MALI_DEBUG_PRINT_ERROR(("Failed to map dma-buf attachment\n"));
+ return -EFAULT;
+ }
- if (target < res->buf) node = node->rb_left;
- else if (target > res->buf) node = node->rb_right;
- else
+ for_each_sg(mem->sgt->sgl, sg, mem->sgt->nents, i)
{
- _mali_osk_atomic_inc(&res->ref);
- spin_unlock(&mali_dma_bufs_lock);
- return res;
+ u32 size = sg_dma_len(sg);
+ dma_addr_t phys = sg_dma_address(sg);
+
+ /* sg must be page aligned. */
+ MALI_DEBUG_ASSERT(0 == size % MALI_MMU_PAGE_SIZE);
+
+ mali_mmu_pagedir_update(pagedir, virt, phys, size, MALI_CACHE_STANDARD);
+
+ virt += size;
+ *offset += size;
+ }
+
+ if (flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE)
+ {
+ u32 guard_phys;
+ MALI_DEBUG_PRINT(7, ("Mapping in extra guard page\n"));
+
+ guard_phys = sg_dma_address(mem->sgt->sgl);
+ mali_mmu_pagedir_update(pagedir, virt, guard_phys, MALI_MMU_PAGE_SIZE, MALI_CACHE_STANDARD);
+ }
+
+ spin_lock_irqsave(&mem->map_lock, irq_flags);
+ mem->is_mapped = MALI_TRUE;
+ spin_unlock_irqrestore(&mem->map_lock, irq_flags);
+
+ /* Wake up any thread waiting for buffer to become mapped */
+ wake_up_all(&mem->wait_queue);
+ }
+ else
+ {
+ /* Wait for buffer to become mapped */
+ if (!mem->is_mapped)
+ {
+ MALI_DEBUG_PRINT(4, ("Mali DMA-buf: Waiting for buffer to become mapped...\n"));
}
+ spin_unlock_irqrestore(&mem->map_lock, irq_flags);
+ wait_event(mem->wait_queue, MALI_TRUE == mem->is_mapped);
}
- spin_unlock(&mali_dma_bufs_lock);
- return NULL;
+ return 0;
}
-static void mali_dma_buf_add(struct rb_root *root, struct mali_dma_buf_attachment *new)
+void mali_dma_buf_unmap(struct mali_dma_buf_attachment *mem)
{
- struct rb_node **node = &root->rb_node;
- struct rb_node *parent = NULL;
- struct mali_dma_buf_attachment *res;
+ unsigned long irq_flags;
+
+ MALI_DEBUG_ASSERT_POINTER(mem);
+ MALI_DEBUG_ASSERT_POINTER(mem->attachment);
+ MALI_DEBUG_ASSERT_POINTER(mem->buf);
+
+ spin_lock_irqsave(&mem->map_lock, irq_flags);
- spin_lock(&mali_dma_bufs_lock);
- while (*node)
+ mem->map_ref--;
+
+ MALI_DEBUG_PRINT(5, ("Mali DMA-buf: unmap attachment %p, new map_ref = %d\n", mem, mem->map_ref));
+
+ if (0 == mem->map_ref)
{
- parent = *node;
- res = rb_entry(*node, struct mali_dma_buf_attachment, rb_node);
+ dma_buf_unmap_attachment(mem->attachment, mem->sgt, DMA_BIDIRECTIONAL);
- if (new->buf < res->buf) node = &(*node)->rb_left;
- else node = &(*node)->rb_right;
+ mem->is_mapped = MALI_FALSE;
}
- rb_link_node(&new->rb_node, parent, node);
- rb_insert_color(&new->rb_node, &mali_dma_bufs);
-
- spin_unlock(&mali_dma_bufs_lock);
+ spin_unlock_irqrestore(&mem->map_lock, irq_flags);
- return;
+ /* Wake up any thread waiting for buffer to become unmapped */
+ wake_up_all(&mem->wait_queue);
}
-
-static void mali_dma_buf_release(void *ctx, void *handle)
+#if !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+int mali_dma_buf_map_job(struct mali_pp_job *job)
{
+ mali_memory_allocation *descriptor;
struct mali_dma_buf_attachment *mem;
- u32 ref;
+ _mali_osk_errcode_t err;
+ int i;
+ u32 offset = 0;
+ int ret = 0;
- mem = (struct mali_dma_buf_attachment *)handle;
+ _mali_osk_lock_wait( job->session->memory_lock, _MALI_OSK_LOCKMODE_RW );
- MALI_DEBUG_ASSERT_POINTER(mem);
- MALI_DEBUG_ASSERT_POINTER(mem->attachment);
- MALI_DEBUG_ASSERT_POINTER(mem->buf);
+ for (i = 0; i < job->num_memory_cookies; i++)
+ {
+ int cookie = job->memory_cookies[i];
- spin_lock(&mali_dma_bufs_lock);
- ref = _mali_osk_atomic_dec_return(&mem->ref);
+ if (0 == cookie)
+ {
+ /* 0 is not a valid cookie */
+ MALI_DEBUG_ASSERT(NULL == job->dma_bufs[i]);
+ continue;
+ }
- if (0 == ref)
- {
- rb_erase(&mem->rb_node, &mali_dma_bufs);
- spin_unlock(&mali_dma_bufs_lock);
+ MALI_DEBUG_ASSERT(0 < cookie);
- MALI_DEBUG_ASSERT(0 == _mali_osk_atomic_read(&mem->ref));
+ err = mali_descriptor_mapping_get(job->session->descriptor_mapping,
+ cookie, (void**)&descriptor);
- dma_buf_unmap_attachment(mem->attachment, mem->sgt, DMA_BIDIRECTIONAL);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ MALI_DEBUG_PRINT_ERROR(("Mali DMA-buf: Failed to get descriptor for cookie %d\n", cookie));
+ ret = -EFAULT;
+ MALI_DEBUG_ASSERT(NULL == job->dma_bufs[i]);
+ continue;
+ }
- dma_buf_detach(mem->buf, mem->attachment);
- dma_buf_put(mem->buf);
+ if (mali_dma_buf_release != descriptor->physical_allocation.release)
+ {
+ /* Not a DMA-buf */
+ MALI_DEBUG_ASSERT(NULL == job->dma_bufs[i]);
+ continue;
+ }
- _mali_osk_free(mem);
+ mem = (struct mali_dma_buf_attachment *)descriptor->physical_allocation.handle;
+
+ MALI_DEBUG_ASSERT_POINTER(mem);
+ MALI_DEBUG_ASSERT(mem->session == job->session);
+
+ err = mali_dma_buf_map(mem, mem->session, descriptor->mali_address, &offset, descriptor->flags);
+ if (0 != err)
+ {
+ MALI_DEBUG_PRINT_ERROR(("Mali DMA-buf: Failed to map dma-buf for cookie %d at mali address %x\b",
+ cookie, descriptor->mali_address));
+ ret = -EFAULT;
+ MALI_DEBUG_ASSERT(NULL == job->dma_bufs[i]);
+ continue;
+ }
+
+ /* Add mem to list of DMA-bufs mapped for this job */
+ job->dma_bufs[i] = mem;
}
- else
+
+ _mali_osk_lock_signal( job->session->memory_lock, _MALI_OSK_LOCKMODE_RW );
+
+ return ret;
+}
+
+void mali_dma_buf_unmap_job(struct mali_pp_job *job)
+{
+ int i;
+ for (i = 0; i < job->num_dma_bufs; i++)
{
- spin_unlock(&mali_dma_bufs_lock);
+ if (NULL == job->dma_bufs[i]) continue;
+
+ mali_dma_buf_unmap(job->dma_bufs[i]);
+ job->dma_bufs[i] = NULL;
}
}
+#endif /* !CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH */
/* Callback from memory engine which will map into Mali virtual address space */
static mali_physical_memory_allocation_result mali_dma_buf_commit(void* ctx, mali_allocation_engine * engine, mali_memory_allocation * descriptor, u32* offset, mali_physical_memory_allocation * alloc_info)
{
struct mali_session_data *session;
- struct mali_page_directory *pagedir;
struct mali_dma_buf_attachment *mem;
- struct scatterlist *sg;
- int i;
- u32 virt;
MALI_DEBUG_ASSERT_POINTER(ctx);
MALI_DEBUG_ASSERT_POINTER(engine);
/* Mapping dma-buf with an offset is not supported. */
MALI_DEBUG_ASSERT(0 == *offset);
- virt = descriptor->mali_address;
session = (struct mali_session_data *)descriptor->mali_addr_mapping_info;
- pagedir = mali_session_get_page_directory(session);
-
MALI_DEBUG_ASSERT_POINTER(session);
mem = (struct mali_dma_buf_attachment *)ctx;
- MALI_DEBUG_ASSERT_POINTER(mem);
-
- mem->sgt = dma_buf_map_attachment(mem->attachment, DMA_BIDIRECTIONAL);
- if (IS_ERR_OR_NULL(mem->sgt))
- {
- MALI_PRINT_ERROR(("Failed to map dma-buf attachment\n"));
- return MALI_MEM_ALLOC_INTERNAL_FAILURE;
- }
+ MALI_DEBUG_ASSERT(mem->session == session);
- for_each_sg(mem->sgt->sgl, sg, mem->sgt->nents, i)
+#if defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+ if (0 == mali_dma_buf_map(mem, session, descriptor->mali_address, offset, descriptor->flags))
{
- u32 size = sg_dma_len(sg);
- dma_addr_t phys = sg_dma_address(sg);
-
- /* sg must be page aligned. */
- MALI_DEBUG_ASSERT(0 == size % MALI_MMU_PAGE_SIZE);
-
- mali_mmu_pagedir_update(pagedir, virt, phys, size, MALI_CACHE_STANDARD);
-
- virt += size;
- *offset += size;
- }
-
- if (descriptor->flags & MALI_MEMORY_ALLOCATION_FLAG_MAP_GUARD_PAGE)
+ MALI_DEBUG_ASSERT(*offset == descriptor->size);
+#else
{
- u32 guard_phys;
- MALI_DEBUG_PRINT(7, ("Mapping in extra guard page\n"));
+#endif
+ alloc_info->ctx = NULL;
+ alloc_info->handle = mem;
+ alloc_info->next = NULL;
+ alloc_info->release = mali_dma_buf_release;
- guard_phys = sg_dma_address(mem->sgt->sgl);
- mali_mmu_pagedir_update(mali_session_get_page_directory(session), virt, guard_phys, MALI_MMU_PAGE_SIZE, MALI_CACHE_STANDARD);
+ return MALI_MEM_ALLOC_FINISHED;
}
- MALI_DEBUG_ASSERT(*offset == descriptor->size);
-
- alloc_info->ctx = NULL;
- alloc_info->handle = mem;
- alloc_info->next = NULL;
- alloc_info->release = mali_dma_buf_release;
-
- return MALI_MEM_ALLOC_FINISHED;
+ return MALI_MEM_ALLOC_INTERNAL_FAILURE;
}
int mali_attach_dma_buf(struct mali_session_data *session, _mali_uk_attach_dma_buf_s __user *user_arg)
buf = dma_buf_get(fd);
if (IS_ERR_OR_NULL(buf))
{
- MALI_DEBUG_PRINT(2, ("Failed to get dma-buf from fd: %d\n", fd));
+ MALI_DEBUG_PRINT_ERROR(("Failed to get dma-buf from fd: %d\n", fd));
return PTR_RET(buf);
}
/* Currently, mapping of the full buffer are supported. */
if (args.size != buf->size)
{
- MALI_DEBUG_PRINT(2, ("dma-buf size doesn't match mapping size.\n"));
+ MALI_DEBUG_PRINT_ERROR(("dma-buf size doesn't match mapping size.\n"));
dma_buf_put(buf);
return -EINVAL;
}
-
- mem = mali_dma_buf_lookup(&mali_dma_bufs, buf);
+ mem = _mali_osk_calloc(1, sizeof(struct mali_dma_buf_attachment));
if (NULL == mem)
{
- /* dma-buf is not already attached to Mali */
- mem = _mali_osk_calloc(1, sizeof(struct mali_dma_buf_attachment));
- if (NULL == mem)
- {
- MALI_PRINT_ERROR(("Failed to allocate dma-buf tracing struct\n"));
- dma_buf_put(buf);
- return -ENOMEM;
- }
- _mali_osk_atomic_init(&mem->ref, 1);
- mem->buf = buf;
+ MALI_DEBUG_PRINT_ERROR(("Failed to allocate dma-buf tracing struct\n"));
+ dma_buf_put(buf);
+ return -ENOMEM;
+ }
- mem->attachment = dma_buf_attach(mem->buf, &mali_platform_device->dev);
- if (NULL == mem->attachment)
- {
- MALI_DEBUG_PRINT(2, ("Failed to attach to dma-buf %d\n", fd));
- dma_buf_put(mem->buf);
- _mali_osk_free(mem);
- return -EFAULT;
- }
+ mem->buf = buf;
+ mem->session = session;
+ mem->map_ref = 0;
+ spin_lock_init(&mem->map_lock);
+ init_waitqueue_head(&mem->wait_queue);
- mali_dma_buf_add(&mali_dma_bufs, mem);
- }
- else
+ mem->attachment = dma_buf_attach(mem->buf, &mali_platform_device->dev);
+ if (NULL == mem->attachment)
{
- /* dma-buf is already attached to Mali */
- /* Give back the reference we just took, mali_dma_buf_lookup grabbed a new reference for us. */
- dma_buf_put(buf);
+ MALI_DEBUG_PRINT_ERROR(("Failed to attach to dma-buf %d\n", fd));
+ dma_buf_put(mem->buf);
+ _mali_osk_free(mem);
+ return -EFAULT;
}
/* Map dma-buf into this session's page tables */
descriptor = _mali_osk_calloc(1, sizeof(mali_memory_allocation));
if (NULL == descriptor)
{
- MALI_PRINT_ERROR(("Failed to allocate descriptor dma-buf %d\n", fd));
+ MALI_DEBUG_PRINT_ERROR(("Failed to allocate descriptor dma-buf %d\n", fd));
mali_dma_buf_release(NULL, mem);
return -ENOMEM;
}
/* Get descriptor mapping for memory. */
if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_allocate_mapping(session->descriptor_mapping, descriptor, &md))
{
- MALI_PRINT_ERROR(("Failed to create descriptor mapping for dma-buf %d\n", fd));
+ MALI_DEBUG_PRINT_ERROR(("Failed to create descriptor mapping for dma-buf %d\n", fd));
_mali_osk_free(descriptor);
mali_dma_buf_release(NULL, mem);
return -EFAULT;
}
+ MALI_DEBUG_ASSERT(0 < md);
+
external_memory_allocator.allocate = mali_dma_buf_commit;
external_memory_allocator.allocate_page_table_block = NULL;
external_memory_allocator.ctx = mem;
{
_mali_osk_lock_signal(session->memory_lock, _MALI_OSK_LOCKMODE_RW);
- MALI_PRINT_ERROR(("Failed to map dma-buf %d into Mali address space\n", fd));
+ MALI_DEBUG_PRINT_ERROR(("Failed to map dma-buf %d into Mali address space\n", fd));
mali_descriptor_mapping_free(session->descriptor_mapping, md);
mali_dma_buf_release(NULL, mem);
return -ENOMEM;
if (0 != put_user(md, &user_arg->cookie))
{
/* Roll back */
- MALI_PRINT_ERROR(("Failed to return descriptor to user space for dma-buf %d\n", fd));
+ MALI_DEBUG_PRINT_ERROR(("Failed to return descriptor to user space for dma-buf %d\n", fd));
mali_descriptor_mapping_free(session->descriptor_mapping, md);
mali_dma_buf_release(NULL, mem);
return -EFAULT;
int mali_release_dma_buf(struct mali_session_data *session, _mali_uk_release_dma_buf_s __user *user_arg)
{
+ int ret = 0;
_mali_uk_release_dma_buf_s args;
mali_memory_allocation *descriptor;
return -EFAULT;
}
- if (_MALI_OSK_ERR_OK != mali_descriptor_mapping_get(session->descriptor_mapping, args.cookie, (void**)&descriptor))
- {
- MALI_DEBUG_PRINT(1, ("Invalid memory descriptor %d used to release dma-buf\n", args.cookie));
- return -EINVAL;
- }
+ MALI_DEBUG_PRINT(3, ("Mali DMA-buf: release descriptor cookie %d\n", args.cookie));
+
+ _mali_osk_lock_wait( session->memory_lock, _MALI_OSK_LOCKMODE_RW );
descriptor = mali_descriptor_mapping_free(session->descriptor_mapping, args.cookie);
if (NULL != descriptor)
{
- _mali_osk_lock_wait( session->memory_lock, _MALI_OSK_LOCKMODE_RW );
+ MALI_DEBUG_PRINT(3, ("Mali DMA-buf: Releasing dma-buf at mali address %x\n", descriptor->mali_address));
/* Will call back to mali_dma_buf_release() which will release the dma-buf attachment. */
mali_allocation_engine_release_memory(mali_mem_get_memory_engine(), descriptor);
- _mali_osk_lock_signal( session->memory_lock, _MALI_OSK_LOCKMODE_RW );
-
_mali_osk_free(descriptor);
}
+ else
+ {
+ MALI_DEBUG_PRINT_ERROR(("Invalid memory descriptor %d used to release dma-buf\n", args.cookie));
+ ret = -EINVAL;
+ }
+
+ _mali_osk_lock_signal( session->memory_lock, _MALI_OSK_LOCKMODE_RW );
/* Return the error that _mali_ukk_map_external_ump_mem produced */
- return 0;
+ return ret;
}
int mali_dma_buf_get_size(struct mali_session_data *session, _mali_uk_dma_buf_get_size_s __user *user_arg)
buf = dma_buf_get(fd);
if (IS_ERR_OR_NULL(buf))
{
- MALI_DEBUG_PRINT(2, ("Failed to get dma-buf from fd: %d\n", fd));
+ MALI_DEBUG_PRINT_ERROR(("Failed to get dma-buf from fd: %d\n", fd));
return PTR_RET(buf);
}
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
#endif
#include "mali_osk.h"
+#include "common/mali_pp_job.h"
+
+struct mali_dma_buf_attachment;
int mali_attach_dma_buf(struct mali_session_data *session, _mali_uk_attach_dma_buf_s __user *arg);
int mali_release_dma_buf(struct mali_session_data *session, _mali_uk_release_dma_buf_s __user *arg);
int mali_dma_buf_get_size(struct mali_session_data *session, _mali_uk_dma_buf_get_size_s __user *arg);
+int mali_dma_buf_map(struct mali_dma_buf_attachment *mem, struct mali_session_data *session, u32 virt, u32 *offset, u32 flags);
+void mali_dma_buf_unmap(struct mali_dma_buf_attachment *mem);
+void mali_dma_buf_release(void *ctx, void *handle);
+
+#if !defined(CONFIG_MALI_DMA_BUF_MAP_ON_ATTACH)
+int mali_dma_buf_map_job(struct mali_pp_job *job);
+void mali_dma_buf_unmap_job(struct mali_pp_job *job);
+#endif
#ifdef __cplusplus
}
/**
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
#include <linux/device.h>
#include "mali_kernel_license.h"
#include <linux/platform_device.h>
-#if MALI_LICENSE_IS_GPL
#include <linux/miscdevice.h>
-#endif
#include <linux/mali/mali_utgard.h>
#include "mali_kernel_common.h"
#include "mali_session.h"
module_param(mali_l2_max_reads, int, S_IRUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(mali_l2_max_reads, "Maximum reads for Mali L2 cache");
-extern int mali_dedicated_mem_start;
-module_param(mali_dedicated_mem_start, int, S_IRUSR | S_IRGRP | S_IROTH);
+extern unsigned int mali_dedicated_mem_start;
+module_param(mali_dedicated_mem_start, uint, S_IRUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(mali_dedicated_mem_start, "Physical start address of dedicated Mali GPU memory.");
-extern int mali_dedicated_mem_size;
-module_param(mali_dedicated_mem_size, int, S_IRUSR | S_IRGRP | S_IROTH);
+extern unsigned int mali_dedicated_mem_size;
+module_param(mali_dedicated_mem_size, uint, S_IRUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(mali_dedicated_mem_size, "Size of dedicated Mali GPU memory.");
-extern int mali_shared_mem_size;
-module_param(mali_shared_mem_size, int, S_IRUSR | S_IRGRP | S_IROTH);
+extern unsigned int mali_shared_mem_size;
+module_param(mali_shared_mem_size, uint, S_IRUSR | S_IRGRP | S_IROTH);
MODULE_PARM_DESC(mali_shared_mem_size, "Size of shared Mali GPU memory.");
#if defined(CONFIG_MALI400_PROFILING)
err = mem_term_wrapper(session_data, (_mali_uk_term_mem_s __user *)arg);
break;
+ case MALI_IOC_MEM_WRITE_SAFE:
+ err = mem_write_safe_wrapper(session_data, (_mali_uk_mem_write_safe_s __user *)arg);
+ break;
+
case MALI_IOC_MEM_MAP_EXT:
err = mem_map_ext_wrapper(session_data, (_mali_uk_map_external_mem_s __user *)arg);
break;
#if defined(CONFIG_SYNC)
err = stream_create_wrapper(session_data, (_mali_uk_stream_create_s __user *)arg);
break;
+#endif
+ case MALI_IOC_FENCE_CREATE_EMPTY:
+#if defined(CONFIG_SYNC)
+ err = sync_fence_create_empty_wrapper(session_data, (_mali_uk_fence_create_empty_s __user *)arg);
+ break;
#endif
case MALI_IOC_FENCE_VALIDATE:
#if defined(CONFIG_SYNC)
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/**
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+++ /dev/null
-/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
- *
- * This program is free software and is provided to you under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
- *
- * A copy of the licence is included with the program, and can also be obtained from Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-#ifndef __MALI_LINUX_PM_TESTSUITE_H__
-#define __MALI_LINUX_PM_TESTSUITE_H__
-
-#if MALI_POWER_MGMT_TEST_SUITE && defined(CONFIG_PM)
-
-typedef enum
-{
- _MALI_DEVICE_PMM_TIMEOUT_EVENT,
- _MALI_DEVICE_PMM_JOB_SCHEDULING_EVENTS,
- _MALI_DEVICE_PMM_REGISTERED_CORES,
- _MALI_DEVICE_MAX_PMM_EVENTS
-
-} _mali_device_pmm_recording_events;
-
-extern unsigned int mali_timeout_event_recording_on;
-extern unsigned int mali_job_scheduling_events_recording_on;
-extern unsigned int pwr_mgmt_status_reg;
-extern unsigned int is_mali_pmm_testsuite_enabled;
-extern unsigned int is_mali_pmu_present;
-
-#endif /* MALI_POWER_MGMT_TEST_SUITE && defined(CONFIG_PM) */
-
-#endif /* __MALI_LINUX_PM_TESTSUITE_H__ */
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
_mali_osk_irq_t *_mali_osk_irq_init( u32 irqnum, _mali_osk_irq_uhandler_t uhandler, void *int_data, _mali_osk_irq_trigger_t trigger_func, _mali_osk_irq_ack_t ack_func, void *probe_data, const char *description )
{
mali_osk_irq_object_t *irq_object;
+ unsigned long irq_flags = 0;
+
+#if defined(CONFIG_MALI_SHARED_INTERRUPTS)
+ irq_flags |= IRQF_SHARED;
+#endif /* defined(CONFIG_MALI_SHARED_INTERRUPTS) */
irq_object = kmalloc(sizeof(mali_osk_irq_object_t), GFP_KERNEL);
if (NULL == irq_object)
return NULL;
}
- if (0 != request_irq(irqnum, irq_handler_upper_half, IRQF_SHARED, description, irq_object))
+ if (0 != request_irq(irqnum, irq_handler_upper_half, irq_flags, description, irq_object))
{
MALI_DEBUG_PRINT(2, ("Unable to install IRQ handler for core '%s'\n", description));
kfree(irq_object);
*/
static irqreturn_t irq_handler_upper_half (int port_name, void* dev_id ) /* , struct pt_regs *regs*/
{
+ irqreturn_t ret = IRQ_NONE;
mali_osk_irq_object_t *irq_object = (mali_osk_irq_object_t *)dev_id;
- if (irq_object->uhandler(irq_object->data) == _MALI_OSK_ERR_OK)
+#if defined(CONFIG_MALI_SHARED_INTERRUPTS)
+ if (MALI_TRUE == _mali_osk_pm_dev_ref_add_no_power_on())
+#endif /* defined(CONFIG_MALI_SHARED_INTERRUPTS) */
{
- return IRQ_HANDLED;
+
+ if (_MALI_OSK_ERR_OK == irq_object->uhandler(irq_object->data))
+ {
+ ret = IRQ_HANDLED;
+ }
+
}
- return IRQ_NONE;
-}
+#if defined(CONFIG_MALI_SHARED_INTERRUPTS)
+ _mali_osk_pm_dev_ref_dec_no_power_on();
+#endif /* defined(CONFIG_MALI_SHARED_INTERRUPTS) */
+ return ret;
+}
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/* id of the thread currently holding this lock, 0 if no
* threads hold it. */
u32 owner;
- /* number of owners this lock currently has (can be > 1 if
- * taken in R/O mode. */
- u32 nOwners;
/* what mode the lock was taken in */
_mali_osk_lock_mode_t mode;
); /* MALI_DEBUG_CODE */
/* Debug tracking of lock owner */
lock->owner = 0;
- lock->nOwners = 0;
#endif /* DEBUG */
return lock;
return lock->owner;
}
-u32 _mali_osk_lock_get_number_owners( _mali_osk_lock_t *lock )
-{
- return lock->nOwners;
-}
-
u32 _mali_osk_lock_get_mode( _mali_osk_lock_t *lock )
{
return lock->mode;
{
if (mode == _MALI_OSK_LOCKMODE_RW)
{
- /*MALI_DEBUG_ASSERT(0 == lock->owner);*/
if (0 != lock->owner)
{
printk(KERN_ERR "%d: ERROR: Lock %p already has owner %d\n", _mali_osk_get_tid(), lock, lock->owner);
}
lock->owner = _mali_osk_get_tid();
lock->mode = mode;
- ++lock->nOwners;
}
else /* mode == _MALI_OSK_LOCKMODE_RO */
{
- lock->owner |= _mali_osk_get_tid();
lock->mode = mode;
- ++lock->nOwners;
}
}
#endif
/* make sure the thread releasing the lock actually was the owner */
if (mode == _MALI_OSK_LOCKMODE_RW)
{
- /*MALI_DEBUG_ASSERT(_mali_osk_get_tid() == lock->owner);*/
if (_mali_osk_get_tid() != lock->owner)
{
printk(KERN_ERR "%d: ERROR: Lock %p owner was %d\n", _mali_osk_get_tid(), lock, lock->owner);
}
/* This lock now has no owner */
lock->owner = 0;
- --lock->nOwners;
- }
- else /* mode == _MALI_OSK_LOCKMODE_RO */
- {
- if ((_mali_osk_get_tid() & lock->owner) != _mali_osk_get_tid())
- {
- printk(KERN_ERR "%d: ERROR: Not an owner of %p lock.\n", _mali_osk_get_tid(), lock);
- dump_stack();
- }
-
- /* if this is the last thread holding this lock in R/O mode, set owner
- * back to 0 */
- if (0 == --lock->nOwners)
- {
- lock->owner = 0;
- }
- }
+ } /* else if (mode == _MALI_OSK_LOCKMODE_RO) Nothing to check */
#endif /* DEBUG */
switch ( lock->type )
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0)
#include <linux/shrinker.h>
#endif
+#include <linux/sched.h>
+#include <linux/mm_types.h>
+#include <linux/rwsem.h>
#include "mali_osk.h"
#include "mali_ukk.h" /* required to hook in _mali_ukk_mem_mmap handling */
MALI_DEBUG_PRINT(1, ("Page-fault in Mali memory region caused by the CPU.\n"));
MALI_DEBUG_PRINT(1, ("Tried to access %p (process local virtual address) which is not currently mapped to any Mali memory.\n", (void*)address));
+ MALI_IGNORE(address);
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
return VM_FAULT_SIGBUS;
#else
/* dma_alloc_* uses a limited region of address space. On most arch/marchs
* 2 to 14 MiB is available. This should be enough for the page tables, which
* currently is the only user of this function. */
- virt = dma_alloc_coherent(NULL, size, phys, GFP_KERNEL | GFP_DMA );
+ virt = dma_alloc_writecombine(NULL, size, phys, GFP_KERNEL | GFP_DMA | __GFP_ZERO);
MALI_DEBUG_PRINT(3, ("Page table virt: 0x%x = dma_alloc_coherent(size:%d, phys:0x%x, )\n", virt, size, phys));
MALI_DEBUG_ASSERT( 0 != size );
MALI_DEBUG_ASSERT( 0 == (phys & ( (1 << PAGE_SHIFT) - 1 )) );
- dma_free_coherent(NULL, size, virt, phys);
+ dma_free_writecombine(NULL, size, virt, phys);
}
_mali_osk_errcode_t inline _mali_osk_mem_reqregion( u32 phys, u32 size, const char *description )
The memory is reserved, meaning that it's present and can never be paged out (see also previous entry)
*/
vma->vm_flags |= VM_IO;
- vma->vm_flags |= VM_RESERVED;
vma->vm_flags |= VM_DONTCOPY;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
+ vma->vm_flags |= VM_RESERVED;
+#else
+ vma->vm_flags |= VM_DONTDUMP;
+ vma->vm_flags |= VM_DONTEXPAND;
+ vma->vm_flags |= VM_PFNMAP;
+#endif
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
vma->vm_ops = &mali_kernel_vm_ops; /* Operations used on any memory system */
return;
}
+
+u32 _mali_osk_mem_write_safe(void *dest, const void *src, u32 size)
+{
+#define MALI_MEM_SAFE_COPY_BLOCK_SIZE 4096
+ u32 retval = 0;
+ void *temp_buf;
+
+ temp_buf = kmalloc(MALI_MEM_SAFE_COPY_BLOCK_SIZE, GFP_KERNEL);
+ if (NULL != temp_buf)
+ {
+ u32 bytes_left_to_copy = size;
+ u32 i;
+ for (i = 0; i < size; i += MALI_MEM_SAFE_COPY_BLOCK_SIZE)
+ {
+ u32 size_to_copy;
+ u32 size_copied;
+ u32 bytes_left;
+
+ if (bytes_left_to_copy > MALI_MEM_SAFE_COPY_BLOCK_SIZE)
+ {
+ size_to_copy = MALI_MEM_SAFE_COPY_BLOCK_SIZE;
+ }
+ else
+ {
+ size_to_copy = bytes_left_to_copy;
+ }
+
+ bytes_left = copy_from_user(temp_buf, ((char*)src) + i, size_to_copy);
+ size_copied = size_to_copy - bytes_left;
+
+ bytes_left = copy_to_user(((char*)dest) + i, temp_buf, size_copied);
+ size_copied -= bytes_left;
+
+ bytes_left_to_copy -= size_copied;
+ retval += size_copied;
+
+ if (size_copied != size_to_copy)
+ {
+ break; /* Early out, we was not able to copy this entire block */
+ }
+ }
+
+ kfree(temp_buf);
+ }
+
+ return retval;
+}
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
return _MALI_OSK_ERR_ITEM_NOT_FOUND;
}
+
+mali_bool _mali_osk_shared_interrupts(void)
+{
+ u32 irqs[128];
+ u32 i, j, irq, num_irqs_found = 0;
+
+ MALI_DEBUG_ASSERT_POINTER(mali_platform_device);
+ MALI_DEBUG_ASSERT(128 >= mali_platform_device->num_resources);
+
+ for (i = 0; i < mali_platform_device->num_resources; i++)
+ {
+ if (IORESOURCE_IRQ & mali_platform_device->resource[i].flags)
+ {
+ irq = mali_platform_device->resource[i].start;
+
+ for (j = 0; j < num_irqs_found; ++j)
+ {
+ if (irq == irqs[j])
+ {
+ return MALI_TRUE;
+ }
+ }
+
+ irqs[num_irqs_found++] = irq;
+ }
+ }
+
+ return MALI_FALSE;
+}
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2011, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/**
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
static _mali_osk_atomic_t mali_pm_ref_count;
-void _mali_osk_pm_dev_enable(void) /* @@@@ todo: change to init of some kind.. or change the way or where atomics are initialized? */
+void _mali_osk_pm_dev_enable(void)
{
_mali_osk_atomic_init(&mali_pm_ref_count, 0);
}
-void _mali_osk_pm_dev_disable(void) /* @@@@ todo: change to term of some kind */
+void _mali_osk_pm_dev_disable(void)
{
_mali_osk_atomic_term(&mali_pm_ref_count);
}
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
kfree(work_object);
}
+void _mali_osk_wq_delete_work_nonflush( _mali_osk_wq_work_t *work )
+{
+ mali_osk_wq_work_object_t *work_object = (mali_osk_wq_work_object_t *)work;
+ kfree(work_object);
+}
+
void _mali_osk_wq_schedule_work( _mali_osk_wq_work_t *work )
{
mali_osk_wq_work_object_t *work_object = (mali_osk_wq_work_object_t *)work;
/**
- * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
MALI_DEBUG_PRINT(5, ("Mali PMU: Power up\n"));
+ MALI_DEBUG_ASSERT_POINTER(pmu);
if (NULL == pmu)
{
return -ENXIO;
MALI_DEBUG_PRINT(5, ("Mali PMU: Power down\n"));
+ MALI_DEBUG_ASSERT_POINTER(pmu);
if (NULL == pmu)
{
return -ENXIO;
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
#include <linux/seq_file.h>
#include <linux/sync.h>
+#include <linux/timer.h>
#include "mali_osk.h"
#include "mali_kernel_common.h"
struct sync_pt pt;
u32 order;
s32 error;
+ struct timer_list timer;
};
+static void mali_sync_timed_pt_timeout(unsigned long data);
+
static inline struct mali_sync_timeline *to_mali_sync_timeline(struct sync_timeline *timeline)
{
return container_of(timeline, struct mali_sync_timeline, timeline);
}
}
+static void timeline_free_pt(struct sync_pt *pt)
+{
+ struct mali_sync_pt *mpt = to_mali_sync_pt(pt);
+
+ if (mpt->timer.function == mali_sync_timed_pt_timeout)
+ {
+ del_timer_sync(&mpt->timer);
+ }
+}
+
static void timeline_print_tl(struct seq_file *s, struct sync_timeline *sync_timeline)
{
struct mali_sync_timeline *mtl = to_mali_sync_timeline(sync_timeline);
.dup = timeline_dup,
.has_signaled = timeline_has_signaled,
.compare = timeline_compare,
+ .free_pt = timeline_free_pt,
.print_obj = timeline_print_tl,
.print_pt = timeline_print_pt
};
return pt;
}
+static void mali_sync_timed_pt_timeout(unsigned long data)
+{
+ struct sync_pt *pt = (struct sync_pt *)data;
+
+ MALI_DEBUG_ASSERT_POINTER(pt);
+
+ mali_sync_signal_pt(pt, -ETIME);
+}
+
+struct sync_pt *mali_sync_timed_pt_alloc(struct sync_timeline *parent)
+{
+ struct sync_pt *pt;
+ struct mali_sync_pt *mpt;
+ const u32 timeout = msecs_to_jiffies(MALI_SYNC_TIMED_FENCE_TIMEOUT);
+
+ pt = mali_sync_pt_alloc(parent);
+ if (NULL == pt) return NULL;
+ mpt = to_mali_sync_pt(pt);
+
+ init_timer(&mpt->timer);
+
+ mpt->timer.function = mali_sync_timed_pt_timeout;
+ mpt->timer.data = (unsigned long)pt;
+ mpt->timer.expires = jiffies + timeout;
+
+ add_timer(&mpt->timer);
+
+ return pt;
+}
+
+/*
+ * Returns 0 if sync_pt has been committed and are ready for use, -ETIME if
+ * timeout already happened and the fence has been signalled.
+ *
+ * If an error occurs the sync point can not be used.
+ */
+int mali_sync_timed_commit(struct sync_pt *pt)
+{
+ struct mali_sync_pt *mpt = to_mali_sync_pt(pt);
+ int ret;
+
+ if (!mali_sync_timeline_is_ours(pt->parent))
+ {
+ return -EINVAL;
+ }
+
+ /* Stop timer */
+ ret = del_timer_sync(&mpt->timer);
+
+ if (0 == ret)
+ {
+ return -ETIME;
+ }
+
+ MALI_DEBUG_ASSERT(0 == timeline_has_signaled(pt));
+
+ return 0;
+}
+
void mali_sync_signal_pt(struct sync_pt *pt, int error)
{
struct mali_sync_pt *mpt = to_mali_sync_pt(pt);
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
#include <linux/seq_file.h>
#include <linux/sync.h>
+#define MALI_SYNC_TIMED_FENCE_TIMEOUT 4000 /* 4s */
+
/*
* Create a stream object.
* Built on top of timeline object.
*/
struct sync_pt *mali_stream_create_point(int tl_fd);
int mali_stream_create_fence(struct sync_pt *pt);
+int mali_stream_create_empty_fence(int tl_fd);
+
+/**
+ * Commit an empty timed fence
+ *
+ * This stops the timer of the empty fence and returns wether or not the fence
+ * is still suitable for use.
+ *
+ * Returns -ETIME if fence is already signalled, in which case it can not be
+ * used, or 0 when the timer was stopped and the fence is OK to use.
+ */
+int mali_sync_timed_commit(struct sync_pt *pt);
/*
* Validate a fd to be a valid fence
*/
struct sync_pt *mali_sync_pt_alloc(struct sync_timeline *parent);
+/* Allocates a timed sync point within the timeline.
+ *
+ * The timeline must be the one allocated by mali_sync_timeline_alloc
+ *
+ * Sync points must be triggered in *exactly* the same order as they are allocated.
+ *
+ * Timed sync points should be backed by a proper event before reaching the
+ * timeout. If timeout is reached the fence will be signalled with an error (-ETIME).
+ */
+struct sync_pt *mali_sync_timed_pt_alloc(struct sync_timeline *parent);
+
/* Signals a particular sync point
*
* Sync points must be triggered in *exactly* the same order as they are allocated.
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
}
}
-mali_sync_pt *mali_stream_create_point(int tl_fd)
+static mali_sync_pt *mali_stream_create_point_internal(int tl_fd, mali_bool timed)
{
struct sync_timeline *tl;
struct sync_pt * pt;
tl = tl_file->private_data;
- pt = mali_sync_pt_alloc(tl);
+ if (unlikely(timed))
+ {
+ pt = mali_sync_timed_pt_alloc(tl);
+ }
+ else
+ {
+ pt = mali_sync_pt_alloc(tl);
+ }
+
if (!pt)
{
pt = NULL;
return pt;
}
+mali_sync_pt *mali_stream_create_point(int tl_fd)
+{
+ return mali_stream_create_point_internal(tl_fd, MALI_FALSE);
+}
+
int mali_stream_create_fence(mali_sync_pt *pt)
{
struct sync_fence *fence;
return fd;
}
+int mali_stream_create_empty_fence(int tl_fd)
+{
+ int fd;
+ mali_sync_pt *pt;
+
+ pt = mali_stream_create_point_internal(tl_fd, MALI_TRUE);
+
+ if (NULL == pt) return -ENOMEM;
+
+ fd = mali_stream_create_fence(pt);
+
+ return fd;
+}
+
_mali_osk_errcode_t mali_fence_validate(int fd)
{
struct sync_fence * fence;
/*
- * Copyright (C) 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
err = _mali_ukk_get_user_settings(&kargs);
if (_MALI_OSK_ERR_OK != err)
{
- printk("fuckkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk..\n");
return map_errcode(err);
}
return 0;
}
+int sync_fence_create_empty_wrapper(struct mali_session_data *session_data, _mali_uk_fence_create_empty_s __user *uargs)
+{
+ _mali_uk_fence_create_empty_s kargs;
+
+ MALI_CHECK_NON_NULL(uargs, -EINVAL);
+
+ if (0 != get_user(kargs.stream, &uargs->stream)) return -EFAULT;
+
+ kargs.fence = mali_stream_create_empty_fence(kargs.stream);
+ if (0 > kargs.fence)
+ {
+ return kargs.fence;
+ }
+
+ kargs.ctx = NULL; /* prevent kernel address to be returned to user space */
+ if (0 != copy_to_user(uargs, &kargs, sizeof(_mali_uk_fence_create_empty_s))) return -EFAULT;
+
+ return 0;
+}
+
int sync_fence_validate_wrapper(struct mali_session_data *session, _mali_uk_fence_validate_s __user *uargs)
{
int fd;
/*
- * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
return 0;
}
+int mem_write_safe_wrapper(struct mali_session_data *session_data, _mali_uk_mem_write_safe_s __user * uargs)
+{
+ _mali_uk_mem_write_safe_s kargs;
+ _mali_osk_errcode_t err;
+
+ MALI_CHECK_NON_NULL(uargs, -EINVAL);
+ MALI_CHECK_NON_NULL(session_data, -EINVAL);
+
+ if (0 != copy_from_user(&kargs, uargs, sizeof(_mali_uk_mem_write_safe_s)))
+ {
+ return -EFAULT;
+ }
+
+ kargs.ctx = session_data;
+
+ /* Check if we can access the buffers */
+ if (!access_ok(VERIFY_WRITE, kargs.dest, kargs.size)
+ || !access_ok(VERIFY_READ, kargs.src, kargs.size))
+ {
+ return -EINVAL;
+ }
+
+ /* Check if size wraps */
+ if ((kargs.size + kargs.dest) <= kargs.dest
+ || (kargs.size + kargs.src) <= kargs.src)
+ {
+ return -EINVAL;
+ }
+
+ err = _mali_ukk_mem_write_safe(&kargs);
+ if (_MALI_OSK_ERR_OK != err)
+ {
+ return map_errcode(err);
+ }
+
+ if (0 != put_user(kargs.size, &uargs->size))
+ {
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument)
{
_mali_uk_map_external_mem_s uk_args;
if (!access_ok(VERIFY_WRITE, buffer, kargs.size)) goto err_exit;
/* allocate temporary buffer (kernel side) to store mmu page table info */
+ MALI_CHECK(kargs.size > 0, -ENOMEM);
kargs.buffer = _mali_osk_valloc(kargs.size);
if (NULL == kargs.buffer)
{
/*
- * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
err = _mali_ukk_pp_start_job(session_data, uargs, &fence);
if (_MALI_OSK_ERR_OK != err) return map_errcode(err);
- if (-1 != fence)
+#if defined(CONFIG_SYNC)
+ if (0 != put_user(fence, &uargs->fence))
{
- if (0 != put_user(fence, &uargs->fence)) return -EFAULT;
+ /* Since the job has started we can't return an error. */
}
+#endif /* CONFIG_SYNC */
return 0;
}
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2011-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2011-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
int get_user_settings_wrapper(struct mali_session_data *session_data, _mali_uk_get_user_settings_s __user *uargs);
#if defined(CONFIG_SYNC)
int stream_create_wrapper(struct mali_session_data *session_data, _mali_uk_stream_create_s __user *uargs);
+int sync_fence_create_empty_wrapper(struct mali_session_data *session_data, _mali_uk_fence_create_empty_s __user *uargs);
int sync_fence_validate_wrapper(struct mali_session_data *session, _mali_uk_fence_validate_s __user *uargs);
#endif
int post_notification_wrapper(struct mali_session_data *session_data, _mali_uk_post_notification_s __user *uargs);
int mem_init_wrapper(struct mali_session_data *session_data, _mali_uk_init_mem_s __user *uargs);
int mem_term_wrapper(struct mali_session_data *session_data, _mali_uk_term_mem_s __user *uargs);
+int mem_write_safe_wrapper(struct mali_session_data *session_data, _mali_uk_mem_write_safe_s __user * uargs);
int mem_map_ext_wrapper(struct mali_session_data *session_data, _mali_uk_map_external_mem_s __user * argument);
int mem_unmap_ext_wrapper(struct mali_session_data *session_data, _mali_uk_unmap_external_mem_s __user * argument);
int mem_query_mmu_page_table_dump_size_wrapper(struct mali_session_data *session_data, _mali_uk_query_mmu_page_table_dump_size_s __user * uargs);
static struct mali_gpu_device_data mali_gpu_data =
{
- .shared_mem_size =384 * 1024 * 1024, /* 256MB */
+ .shared_mem_size =CONFIG_MALI400_OS_MEMORY_SIZE * 1024 * 1024,
.fb_start = 0x84000000,
.fb_size = 0x06000000,
};
static_pp_mmu_cnt = 1;
# endif
+ if (mali_gpu_data.shared_mem_size < 10) {
+ MALI_DEBUG_PRINT(2, ("mali os memory didn't configered, set to default(512M)\n"));
+ mali_gpu_data.shared_mem_size = 512 * 1024 *1024;
+ }
+
MALI_DEBUG_PRINT(4, ("mali_platform_device_register() called\n"));
/* Detect present Mali GPU and connect the correct resources to the device */
/*
- * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2011, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2011, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2011, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2011, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
#
-# Copyright (C) 2010-2011 ARM Limited. All rights reserved.
+# Copyright (C) 2010-2011, 2013 ARM Limited. All rights reserved.
#
# This program is free software and is provided to you under the terms of the GNU General Public License version 2
# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
mem->lock_usage = (ump_lock_usage) args->lock_usage;
- /** TODO: TAKE LOCK HERE */
-
ump_dd_reference_release(mem);
}
mem->lock_usage = (ump_lock_usage) UMP_NOT_LOCKED;
- /** TODO: RELEASE LOCK HERE */
-
ump_dd_reference_release(mem);
}
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2011, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2011, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2011, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2011, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2011, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
vma->vm_private_data = vma_usage_tracker;
vma->vm_flags |= VM_IO;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
vma->vm_flags |= VM_RESERVED;
+#else
+ vma->vm_flags |= VM_DONTDUMP;
+ vma->vm_flags |= VM_DONTEXPAND;
+ vma->vm_flags |= VM_PFNMAP;
+#endif
+
if (0==descriptor->is_cached)
{
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010-2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
/*
- * Copyright (C) 2010, 2012 ARM Limited. All rights reserved.
+ * Copyright (C) 2010, 2012-2013 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
--- /dev/null
+#
+# Copyright (C) 2012-2013 ARM Limited. All rights reserved.
+#
+# This program is free software and is provided to you under the terms of the GNU General Public License version 2
+# as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+#
+# A copy of the licence is included with the program, and can also be obtained from Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+
+# default to building for the host
+ARCH ?= $(shell uname -m)
+
+# linux build system integration
+
+ifneq ($(KERNELRELEASE),)
+# Inside the kernel build system
+
+EXTRA_CFLAGS += -I$(KBUILD_EXTMOD)
+
+SRC = umplock_driver.c
+
+MODULE:=umplock.ko
+
+obj-m := $(MODULE:.ko=.o)
+$(MODULE:.ko=-y) := $(SRC:.c=.o)
+
+$(MODULE:.ko=-objs) := $(SRC:.c=.o)
+
+else
+# Outside the kernel build system
+#
+#
+
+# Get any user defined KDIR-<names> or maybe even a hardcoded KDIR
+-include KDIR_CONFIGURATION
+
+# Define host system directory
+KDIR-$(shell uname -m):=/lib/modules/$(shell uname -r)/build
+
+ifeq ($(ARCH), arm)
+ # when compiling for ARM we're cross compiling
+ export CROSS_COMPILE ?= arm-none-linux-gnueabi-
+ CONFIG ?= arm
+else
+ # Compiling for the host
+ CONFIG ?= $(shell uname -m)
+endif
+
+# default cpu to select
+CPU ?= $(shell uname -m)
+
+# look up KDIR based om CPU selection
+KDIR ?= $(KDIR-$(CPU))
+
+ifeq ($(KDIR),)
+$(error No KDIR found for platform $(CPU))
+endif
+
+all:
+ $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR)
+
+kernelrelease:
+ $(MAKE) -C $(KDIR) kernelrelease
+
+clean:
+ $(MAKE) ARCH=$(ARCH) -C $(KDIR) M=$(CURDIR) clean
+
+endif
--- /dev/null
+/*
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <asm/uaccess.h>
+#include "umplock_ioctl.h"
+#include <linux/sched.h>
+
+#define MAX_ITEMS 1024
+#define MAX_PIDS 128
+
+typedef struct lock_cmd_priv
+{
+ uint32_t msg[128]; /*ioctl args*/
+ u32 pid; /*process id*/
+}_lock_cmd_priv;
+
+typedef struct lock_ref
+{
+ int ref_count;
+ u32 pid;
+}_lock_ref;
+
+typedef struct umplock_item
+{
+ u32 secure_id;
+ /*u32 references;*/
+ _lock_access_usage usage;
+ _lock_ref references[MAX_PIDS];
+ struct semaphore item_lock;
+} umplock_item;
+
+typedef struct umplock_device_private
+{
+ struct mutex item_list_lock;
+ atomic_t sessions;
+ umplock_item items[MAX_ITEMS];
+ u32 pids[MAX_PIDS];
+} umplock_device_private;
+
+struct umplock_device
+{
+ struct cdev cdev;
+ struct class *umplock_class;
+};
+
+static char umplock_dev_name[] = "umplock";
+
+int umplock_major = 0;
+module_param(umplock_major, int, S_IRUGO); /* r--r--r-- */
+MODULE_PARM_DESC(umplock_major, "Device major number");
+
+static int umplock_driver_open( struct inode *inode, struct file *filp );
+static int umplock_driver_release( struct inode *inode, struct file *filp );
+static long umplock_driver_ioctl( struct file *f, unsigned int cmd, unsigned long arg );
+
+static struct file_operations umplock_fops =
+{
+ .owner = THIS_MODULE,
+ .open = umplock_driver_open,
+ .release = umplock_driver_release,
+ .unlocked_ioctl = umplock_driver_ioctl,
+};
+
+static struct umplock_device umplock_device;
+static umplock_device_private device;
+
+void umplock_init_locklist( void )
+{
+ memset(&device.items, 0, sizeof(umplock_item)*MAX_ITEMS);
+ atomic_set(&device.sessions, 0);
+}
+
+void umplock_deinit_locklist( void )
+{
+ memset(&device.items, 0, sizeof(umplock_item)*MAX_ITEMS);
+}
+
+int umplock_device_initialize( void )
+{
+ int err;
+ dev_t dev = 0;
+
+ if ( 0 == umplock_major )
+ {
+ err = alloc_chrdev_region(&dev, 0, 1, umplock_dev_name);
+ umplock_major = MAJOR(dev);
+ }
+ else
+ {
+ dev = MKDEV(umplock_major, 0);
+ err = register_chrdev_region(dev, 1, umplock_dev_name);
+ }
+
+ if ( 0 == err )
+ {
+ memset(&umplock_device, 0, sizeof(umplock_device));
+ cdev_init(&umplock_device.cdev, &umplock_fops);
+ umplock_device.cdev.owner = THIS_MODULE;
+ umplock_device.cdev.ops = &umplock_fops;
+
+ err = cdev_add(&umplock_device.cdev, dev, 1);
+ if ( 0 == err )
+ {
+ umplock_device.umplock_class = class_create(THIS_MODULE, umplock_dev_name);
+ if ( IS_ERR(umplock_device.umplock_class ) )
+ {
+ err = PTR_ERR(umplock_device.umplock_class);
+ }
+ else
+ {
+ struct device *mdev;
+ mdev = device_create(umplock_device.umplock_class, NULL, dev, NULL, umplock_dev_name);
+ if ( !IS_ERR(mdev) )
+ {
+ return 0; /* all ok */
+ }
+
+ err = PTR_ERR(mdev);
+ class_destroy(umplock_device.umplock_class);
+ }
+ cdev_del(&umplock_device.cdev);
+ }
+
+ unregister_chrdev_region(dev, 1);
+ }
+
+ return 1;
+}
+
+void umplock_device_terminate(void)
+{
+ dev_t dev = MKDEV(umplock_major, 0);
+
+ device_destroy(umplock_device.umplock_class, dev);
+ class_destroy(umplock_device.umplock_class);
+
+ cdev_del(&umplock_device.cdev);
+ unregister_chrdev_region(dev, 1);
+}
+
+int umplock_constructor(void)
+{
+ mutex_init(&device.item_list_lock);
+ if ( !umplock_device_initialize() ) return 1;
+ umplock_init_locklist();
+
+ return 0;
+}
+
+void umplock_destructor(void)
+{
+ umplock_deinit_locklist();
+ umplock_device_terminate();
+ mutex_destroy(&device.item_list_lock);
+}
+
+int umplock_find_item( u32 secure_id )
+{
+ int i;
+ for ( i=0; i<MAX_ITEMS; i++ )
+ {
+ if ( device.items[i].secure_id == secure_id ) return i;
+ }
+
+ return -1;
+}
+
+int umplock_find_slot( void )
+{
+ int i;
+ for ( i=0; i<MAX_ITEMS; i++ )
+ {
+ if ( device.items[i].secure_id == 0 ) return i;
+ }
+
+ return -1;
+}
+
+static int umplock_find_item_by_pid( _lock_cmd_priv *lock_cmd, int *item_slot, int *ref_slot)
+{
+ _lock_item_s *lock_item;
+ int i,j;
+
+ lock_item = (_lock_item_s *)&lock_cmd->msg;
+
+ i = umplock_find_item(lock_item->secure_id);
+
+ if ( i < 0)
+ return -1;
+
+ for(j=0; j<MAX_PIDS; j++)
+ {
+ if(device.items[i].references[j].pid == lock_cmd->pid)
+ {
+ *item_slot = i;
+ *ref_slot = j;
+ return 0;
+ }
+ }
+ return -1 ;
+}
+
+static int umplock_find_client_valid(u32 pid)
+{
+ int i;
+
+ if(pid == 0)
+ return -1;
+
+ for(i=0; i<MAX_PIDS; i++)
+ {
+ if(device.pids[i] == pid) return i;
+ }
+
+ return -1;
+}
+/** IOCTLs **/
+static int do_umplock_create( _lock_cmd_priv *lock_cmd)
+{
+ int i_index,ref_index;
+ int ret;
+ _lock_item_s *lock_item = (_lock_item_s *)&lock_cmd->msg;
+
+ i_index = ref_index = -1;
+
+ #if 0
+ if ( lock_item->usage == 1 ) printk( KERN_DEBUG "UMPLOCK: C 0x%x GPU SURFACE\n", lock_item->secure_id );
+ else if ( lock_item->usage == 2 ) printk( KERN_DEBUG "UMPLOCK: C 0x%x GPU TEXTURE\n", lock_item->secure_id );
+ else printk( KERN_DEBUG "UMPLOCK: C 0x%x CPU\n", lock_item->secure_id );
+ #endif
+
+ mutex_lock(&device.item_list_lock);
+ ret = umplock_find_client_valid( lock_cmd->pid );
+ mutex_unlock(&device.item_list_lock);
+ if( ret < 0 )
+ {
+ /*lock request from an invalid client pid, do nothing*/
+ return 0;
+ }
+
+ mutex_lock(&device.item_list_lock);
+
+ ret = umplock_find_item_by_pid( lock_cmd, &i_index, &ref_index );
+ if ( ret >= 0 )
+ {
+ if (device.items[i_index].references[ref_index].ref_count == 0)
+ device.items[i_index].references[ref_index].ref_count = 1;
+ }
+ else if ( (i_index = umplock_find_item( lock_item->secure_id)) >= 0 )
+ {
+ for ( ref_index = 0; ref_index < MAX_PIDS; ref_index++)
+ {
+ if (device.items[i_index].references[ref_index].pid == 0) break;
+ }
+ if ( ref_index < MAX_PIDS )
+ {
+ device.items[i_index].references[ref_index].pid = lock_cmd->pid;
+ device.items[i_index].references[ref_index].ref_count = 1;
+ }
+ else
+ {
+ printk( KERN_ERR "UMPLOCK: whoops, item ran out of available reference slot\n" );
+ }
+ }
+ else
+ {
+ i_index = umplock_find_slot();
+
+ if ( i_index >= 0 )
+ {
+ device.items[i_index].secure_id = lock_item->secure_id;
+ device.items[i_index].usage = lock_item->usage;
+ device.items[i_index].references[0].pid = lock_cmd->pid;
+ device.items[i_index].references[0].ref_count = 1;
+ sema_init(&device.items[i_index].item_lock, 1);
+ }
+ else
+ {
+ printk( KERN_ERR "UMPLOCK: whoops, ran out of available slots\n" );
+ }
+ }
+
+ mutex_unlock(&device.item_list_lock);
+ return 0;
+}
+
+static int do_umplock_process( _lock_cmd_priv *lock_cmd )
+{
+ int ret, i_index, ref_index, ref_count;
+ _lock_item_s *lock_item = (_lock_item_s *)&lock_cmd->msg;
+
+ mutex_lock(&device.item_list_lock);
+ ret = umplock_find_client_valid( lock_cmd->pid );
+ mutex_unlock(&device.item_list_lock);
+ if( ret < 0 )
+ {
+ /*lock request from an invalid client pid, do nothing*/
+ return 0;
+ }
+
+ mutex_lock(&device.item_list_lock);
+ ret = umplock_find_item_by_pid( lock_cmd, &i_index, &ref_index );
+ ref_count = device.items[i_index].references[ref_index].ref_count;
+ mutex_unlock(&device.item_list_lock);
+ if ( ret >= 0 )
+ {
+ if (ref_count == 1)
+ {
+ if ( down_interruptible(&device.items[i_index].item_lock) )
+ {
+ return -ERESTARTSYS;
+ }
+ }
+
+ mutex_lock(&device.item_list_lock);
+ device.items[i_index].references[ref_index].ref_count++;
+ mutex_unlock(&device.item_list_lock);
+
+ #if 0
+ if ( lock_item->usage == 1 ) printk( KERN_DEBUG "UMPLOCK: P 0x%x GPU SURFACE\n", lock_item->secure_id );
+ else if ( lock_item->usage == 2 ) printk( KERN_DEBUG "UMPLOCK: P 0x%x GPU TEXTURE\n", lock_item->secure_id );
+ else printk( KERN_DEBUG "UMPLOCK: P 0x%x CPU\n", lock_item->secure_id );
+ #endif
+ }
+
+ return 0;
+}
+
+static int do_umplock_release( _lock_cmd_priv *lock_cmd )
+{
+ int i_index,ref_index, ref_count;
+ int ret;
+ _lock_item_s *lock_item = (_lock_item_s *)&lock_cmd->msg;
+
+ mutex_lock(&device.item_list_lock);
+ ret = umplock_find_client_valid( lock_cmd->pid );
+ mutex_unlock(&device.item_list_lock);
+ if( ret < 0 )
+ {
+ /*lock request from an invalid client pid, do nothing*/
+ return 0;
+ }
+
+ i_index = ref_index = -1;
+
+ mutex_lock(&device.item_list_lock);
+ ret = umplock_find_item_by_pid( lock_cmd, &i_index, &ref_index );
+ mutex_unlock(&device.item_list_lock);
+
+ if ( ret >= 0 )
+ {
+ mutex_lock(&device.item_list_lock);
+ device.items[i_index].references[ref_index].ref_count--;
+ ref_count = device.items[i_index].references[ref_index].ref_count;
+ mutex_unlock(&device.item_list_lock);
+
+ #if 0
+ if ( lock_item->usage == 1 ) printk( KERN_DEBUG "UMPLOCK: R 0x%x GPU SURFACE\n", lock_item->secure_id );
+ else if ( lock_item->usage == 2 ) printk( KERN_DEBUG "UMPLOCK: R 0x%x GPU TEXTURE\n", lock_item->secure_id );
+ else printk( KERN_DEBUG "UMPLOCK: R 0x%x CPU\n", lock_item->secure_id );
+ #endif
+ if ( ref_count == 1 )
+ {
+ if ( 0 == down_trylock(&device.items[i_index].item_lock) )
+ {
+ //printk( KERN_ERR "UMPLOCK: semaphore for secure id 0x%x was not taken\n", lock_item->secure_id );
+ }
+ up( &device.items[i_index].item_lock );
+
+ mutex_lock(&device.item_list_lock);
+ device.items[i_index].references[ref_index].ref_count = 0;
+ device.items[i_index].references[ref_index].pid = 0;
+ mutex_unlock(&device.item_list_lock);
+ }
+ }
+ return 0;
+}
+
+static int do_umplock_zap( void )
+{
+ int i;
+
+ printk( KERN_DEBUG "UMPLOCK: ZAP ALL ENTRIES!\n" );
+
+ mutex_lock(&device.item_list_lock);
+
+ for ( i=0; i<MAX_ITEMS; i++ )
+ {
+ device.items[i].secure_id = 0;
+ memset(&device.items[i].references, 0, sizeof(_lock_ref)*MAX_PIDS);
+ sema_init(&device.items[i].item_lock, 1);
+ }
+ mutex_unlock(&device.item_list_lock);
+
+ for ( i=0; i<MAX_PIDS; i++)
+ {
+ device.pids[i] = 0;
+ }
+ return 0;
+}
+
+static int do_umplock_dump( void )
+{
+ int i, j;
+
+ printk("dump all the items\n");
+
+ mutex_lock(&device.item_list_lock);
+ for (i = 0; i < MAX_ITEMS; i++)
+ {
+ for (j = 0; j < MAX_PIDS; j++)
+ {
+ if (device.items[i].secure_id != 0 && device.items[i].references[j].pid != 0)
+ {
+ printk("item[%d]->secure_id=%d\t reference[%d].ref_count=%d.pid=%d\n",
+ i,
+ device.items[i].secure_id,
+ j,
+ device.items[i].references[j].ref_count,
+ device.items[i].references[j].pid);
+ }
+ }
+ }
+ mutex_unlock(&device.item_list_lock);
+
+ return 0;
+}
+
+int do_umplock_client_add (_lock_cmd_priv *lock_cmd )
+{
+ int i;
+
+ for ( i= 0; i<MAX_PIDS; i++)
+ {
+ if(device.pids[i] == lock_cmd->pid)
+ {
+ return 0;
+ }
+ }
+ for ( i=0; i<MAX_PIDS; i++)
+ {
+ if(device.pids[i]==0)
+ {
+ mutex_lock(&device.item_list_lock);
+ device.pids[i] = lock_cmd->pid;
+ mutex_unlock(&device.item_list_lock);
+ break;
+ }
+ }
+ if( i==MAX_PIDS)
+ {
+ printk(KERN_ERR "Oops, Run out of cient slots\n ");
+ }
+ return 0;
+}
+
+int do_umplock_client_delete (_lock_cmd_priv *lock_cmd )
+{
+ int p_index=-1, i_index=-1,ref_index=-1;
+ int ret;
+ _lock_item_s *lock_item;
+ lock_item = (_lock_item_s *)&lock_cmd->msg;
+
+ mutex_lock(&device.item_list_lock);
+ p_index = umplock_find_client_valid( lock_cmd->pid );
+ mutex_unlock(&device.item_list_lock);
+ /*lock item pid is not valid.*/
+ if ( p_index<0 )
+ return 0;
+
+
+ /*walk through umplock item list and release reference attached to this client*/
+ for(i_index = 0; i_index< MAX_ITEMS; i_index++ )
+ {
+ lock_item->secure_id = device.items[i_index].secure_id;
+ mutex_lock(&device.item_list_lock);
+ /*find the item index and reference slot for the lock_item*/
+ ret = umplock_find_item_by_pid(lock_cmd, &i_index, &ref_index);
+ mutex_unlock(&device.item_list_lock);
+
+ if(ret < 0)
+ {
+ /*client has no reference on this umplock item, skip*/
+ continue;
+ }
+ while(device.items[i_index].references[ref_index].ref_count)
+ {
+ /*release references on this client*/
+ do_umplock_release(lock_cmd);
+ }
+ }
+
+ mutex_lock(&device.item_list_lock);
+ /*remove the pid from umplock valid pid list*/
+ device.pids[p_index] = 0;
+ mutex_unlock(&device.item_list_lock);
+
+ return 0;
+}
+
+static long umplock_driver_ioctl( struct file *f, unsigned int cmd, unsigned long arg )
+{
+ int ret;
+ uint32_t size = _IOC_SIZE(cmd);
+ _lock_cmd_priv lock_cmd ;
+
+ if (_IOC_TYPE(cmd) != LOCK_IOCTL_GROUP )
+ {
+ return -ENOTTY;
+ }
+
+ if (_IOC_NR(cmd) >= LOCK_IOCTL_MAX_CMDS )
+ {
+ return -ENOTTY;
+ }
+
+ switch ( cmd )
+ {
+ case LOCK_IOCTL_CREATE:
+ if (size != sizeof(_lock_item_s))
+ {
+ return -ENOTTY;
+ }
+
+ if (copy_from_user(&lock_cmd.msg, (void __user *)arg, size))
+ {
+ return -EFAULT;
+ }
+ lock_cmd.pid = (u32)current->tgid;
+ ret = do_umplock_create(&lock_cmd);
+ if (ret)
+ {
+ return ret;
+ }
+ return 0;
+
+ case LOCK_IOCTL_PROCESS:
+ if (size != sizeof(_lock_item_s))
+ {
+ return -ENOTTY;
+ }
+
+ if (copy_from_user(&lock_cmd.msg, (void __user *)arg, size))
+ {
+ return -EFAULT;
+ }
+ lock_cmd.pid = (u32)current->tgid;
+ return do_umplock_process(&lock_cmd);
+
+ case LOCK_IOCTL_RELEASE:
+ if (size != sizeof(_lock_item_s))
+ {
+ return -ENOTTY;
+ }
+
+ if (copy_from_user(&lock_cmd.msg, (void __user *)arg, size))
+ {
+ return -EFAULT;
+ }
+ lock_cmd.pid = (u32)current->tgid;
+ ret = do_umplock_release( &lock_cmd );
+ if (ret)
+ {
+ return ret;
+ }
+ return 0;
+
+ case LOCK_IOCTL_ZAP:
+ do_umplock_zap();
+ return 0;
+
+ case LOCK_IOCTL_DUMP:
+ do_umplock_dump();
+ return 0;
+ }
+
+ return -ENOIOCTLCMD;
+}
+
+static int umplock_driver_open( struct inode *inode, struct file *filp )
+{
+ _lock_cmd_priv lock_cmd;
+
+ atomic_inc(&device.sessions);
+ printk( KERN_DEBUG "UMPLOCK: OPEN SESSION (%i references)\n", atomic_read(&device.sessions) );
+
+ lock_cmd.pid = (u32)current->tgid;
+ do_umplock_client_add(&lock_cmd);
+
+ return 0;
+}
+
+static int umplock_driver_release( struct inode *inode, struct file *filp )
+{
+ _lock_cmd_priv lock_cmd;
+
+ lock_cmd.pid = (u32)current->tgid;
+ do_umplock_client_delete(&lock_cmd);
+
+ atomic_dec(&device.sessions);
+ printk( KERN_DEBUG "UMPLOCK: CLOSE SESSION (%i references)\n", atomic_read(&device.sessions) );
+ if ( atomic_read(&device.sessions) == 0 )
+ {
+ do_umplock_zap();
+ }
+
+ return 0;
+}
+
+static int __init umplock_initialize_module( void )
+{
+ printk( KERN_DEBUG "Inserting UMP lock device driver. Compiled: %s, time: %s\n", __DATE__, __TIME__ );
+
+ if ( !umplock_constructor() )
+ {
+ printk( KERN_ERR "UMP lock device driver init failed\n");
+ return -ENOTTY;
+ }
+
+ printk( KERN_DEBUG "UMP lock device driver loaded\n" );
+
+ return 0;
+}
+
+static void __exit umplock_cleanup_module( void )
+{
+ printk( KERN_DEBUG "unloading UMP lock module\n" );
+ umplock_destructor();
+ printk( KERN_DEBUG "UMP lock module unloaded\n" );
+}
+
+module_init(umplock_initialize_module);
+module_exit(umplock_cleanup_module);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("ARM Ltd.");
+MODULE_DESCRIPTION("ARM UMP locker");
--- /dev/null
+/*
+ * Copyright (C) 2012-2013 ARM Limited. All rights reserved.
+ *
+ * This program is free software and is provided to you under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
+ *
+ * A copy of the licence is included with the program, and can also be obtained from Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef __UMPLOCK_IOCTL_H__
+#define __UMPLOCK_IOCTL_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#ifndef __user
+#define __user
+#endif
+
+
+/**
+ * @file umplock_ioctl.h
+ * This file describes the interface needed to use the Linux device driver.
+ * The interface is used by the userpace Mali DDK.
+ */
+
+typedef enum
+{
+ _LOCK_ACCESS_RENDERABLE = 1,
+ _LOCK_ACCESS_TEXTURE,
+ _LOCK_ACCESS_CPU_WRITE,
+ _LOCK_ACCESS_CPU_READ,
+} _lock_access_usage;
+
+typedef struct _lock_item_s
+{
+ unsigned int secure_id;
+ _lock_access_usage usage;
+} _lock_item_s;
+
+
+#define LOCK_IOCTL_GROUP 0x91
+
+#define _LOCK_IOCTL_CREATE_CMD 0 /* create kernel lock item */
+#define _LOCK_IOCTL_PROCESS_CMD 1 /* process kernel lock item */
+#define _LOCK_IOCTL_RELEASE_CMD 2 /* release kernel lock item */
+#define _LOCK_IOCTL_ZAP_CMD 3 /* clean up all kernel lock items */
+#define _LOCK_IOCTL_DUMP_CMD 4 /* dump all the items */
+
+#define LOCK_IOCTL_MAX_CMDS 5
+
+#define LOCK_IOCTL_CREATE _IOW( LOCK_IOCTL_GROUP, _LOCK_IOCTL_CREATE_CMD, _lock_item_s )
+#define LOCK_IOCTL_PROCESS _IOW( LOCK_IOCTL_GROUP, _LOCK_IOCTL_PROCESS_CMD, _lock_item_s )
+#define LOCK_IOCTL_RELEASE _IOW( LOCK_IOCTL_GROUP, _LOCK_IOCTL_RELEASE_CMD, _lock_item_s )
+#define LOCK_IOCTL_ZAP _IO ( LOCK_IOCTL_GROUP, _LOCK_IOCTL_ZAP_CMD )
+#define LOCK_IOCTL_DUMP _IO ( LOCK_IOCTL_GROUP, _LOCK_IOCTL_DUMP_CMD )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UMPLOCK_IOCTL_H__ */
+