summaryrefslogtreecommitdiff
path: root/drivers/video/b2r2/b2r2_blt_main.c
diff options
context:
space:
mode:
authorJorgen Nilsson <jorgen.nilsson@stericsson.com>2012-02-06 17:04:49 +0100
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:04:28 +0200
commit57716d2b65bf5fa56f50a5f3d4ebb3a35b2483ab (patch)
tree8b47440bad8bf338431b9baf62ba737ec34b5d95 /drivers/video/b2r2/b2r2_blt_main.c
parent809e8bdcb464d4be59d04825873f41ecebf9dc28 (diff)
video: [ANDROID]: b2r2: Add kernel API to b2r2 and more
Brief: As a preparation for the ICS hardware composer solution a kernel API has been added to the b2r2 driver. Some minor stability fixes are also part of this release. The full support for dual b2r2 configuration should be in place, but has yet to be verified with the apropriate hardware. The change should have minor impact on the single core solution. Details: A new logical device for handling the blitter requests has been added. This is roughly the same device as the old blitter the interfaces are therefore the same. From now there is at least two devices - one blitter device and then for each core one additional device (dual configuration is the current target). As a consequence the maximum number of allowed cores has been raised from 1 to 2. When a dual configuration is active the b2r2 driver seamlessly splits requests over available b2r2 cores. Each request is assigned a core_mask defining which cores are doing part of the job. This helps keep track when waiting for the reports. Also, rectangles are now recalculated (based on intersection of destination rectangle and destination image etc.) before splitting the job in order to maximize throughput. Clock and power source can now be configured from devices-dbxxxx.c or equivalent. Minor bug fixes: - Check the return value from clk_enable - Check if the core is valid before serving a IRQ. - Check if the core is enabled (domain_enabled) before adding a new job. - Return actual job_id used for a request (previously always 0) ST-Ericsson ID: 404691 Original Change-Id: Ic3357c4c1e792a84077c1be4ba4c5acdb19da266 Signed-off-by: Jorgen Nilsson <jorgen.nilsson@stericsson.com>
Diffstat (limited to 'drivers/video/b2r2/b2r2_blt_main.c')
-rw-r--r--drivers/video/b2r2/b2r2_blt_main.c827
1 files changed, 152 insertions, 675 deletions
diff --git a/drivers/video/b2r2/b2r2_blt_main.c b/drivers/video/b2r2/b2r2_blt_main.c
index 919de1ef0ee..3727f742bf1 100644
--- a/drivers/video/b2r2/b2r2_blt_main.c
+++ b/drivers/video/b2r2/b2r2_blt_main.c
@@ -36,6 +36,7 @@
#include <linux/hwmem.h>
#include "b2r2_internal.h"
+#include "b2r2_control.h"
#include "b2r2_node_split.h"
#include "b2r2_generic.h"
#include "b2r2_mem_alloc.h"
@@ -60,28 +61,11 @@
* Support read of many report records at once.
*/
-/**
- * b2r2_blt_dev - Our device(s), /dev/b2r2_blt
- */
-static struct b2r2_control *b2r2_ctl[B2R2_MAX_NBR_DEVICES];
-
-/* Debug file system support */
-#ifdef CONFIG_DEBUG_FS
-static int sprintf_req(struct b2r2_blt_request *request, char *buf, int size);
-#endif
-
/* Local functions */
static void inc_stat(struct b2r2_control *cont, unsigned long *stat);
static void dec_stat(struct b2r2_control *cont, unsigned long *stat);
-static int b2r2_blt_synch(struct b2r2_blt_instance *instance,
- int request_id);
-static int b2r2_blt_query_cap(struct b2r2_blt_instance *instance,
- struct b2r2_blt_query_cap *query_cap);
#ifndef CONFIG_B2R2_GENERIC_ONLY
-static int b2r2_blt(struct b2r2_blt_instance *instance,
- struct b2r2_blt_request *request);
-
static void job_callback(struct b2r2_core_job *job);
static void job_release(struct b2r2_core_job *job);
static int job_acquire_resources(struct b2r2_core_job *job, bool atomic);
@@ -89,9 +73,6 @@ static void job_release_resources(struct b2r2_core_job *job, bool atomic);
#endif
#ifdef CONFIG_B2R2_GENERIC
-static int b2r2_generic_blt(struct b2r2_blt_instance *instance,
- struct b2r2_blt_request *request);
-
static void job_callback_gen(struct b2r2_core_job *job);
static void job_release_gen(struct b2r2_core_job *job);
static int job_acquire_resources_gen(struct b2r2_core_job *job, bool atomic);
@@ -109,8 +90,8 @@ static void unresolve_buf(struct b2r2_control *cont,
static void sync_buf(struct b2r2_control *cont, struct b2r2_blt_img *img,
struct b2r2_resolved_buf *resolved, bool is_dst,
struct b2r2_blt_rect *rect);
-static bool is_report_list_empty(struct b2r2_blt_instance *instance);
-static bool is_synching(struct b2r2_blt_instance *instance);
+static bool is_report_list_empty(struct b2r2_control_instance *instance);
+static bool is_synching(struct b2r2_control_instance *instance);
static void get_actual_dst_rect(struct b2r2_blt_req *req,
struct b2r2_blt_rect *actual_dst_rect);
static void set_up_hwmem_region(struct b2r2_control *cont,
@@ -196,39 +177,18 @@ static void clean_l1_cache_range_all_cpus(struct sync_args *sa)
*
* A B2R2 BLT instance is created and stored in the file structure.
*/
-static int b2r2_blt_open(struct inode *inode, struct file *filp)
+int b2r2_control_open(struct b2r2_control_instance *instance)
{
int ret = 0;
- struct b2r2_blt_instance *instance;
- struct b2r2_control *cont = filp->private_data;
+ struct b2r2_control *cont = instance->control;
b2r2_log_info(cont->dev, "%s\n", __func__);
-
inc_stat(cont, &cont->stat_n_in_open);
- /* Allocate and initialize the instance */
- instance = (struct b2r2_blt_instance *)
- kmalloc(sizeof(*instance), GFP_KERNEL);
- if (!instance) {
- b2r2_log_err(cont->dev, "%s: Failed to alloc\n", __func__);
- goto instance_alloc_failed;
- }
- memset(instance, 0, sizeof(*instance));
INIT_LIST_HEAD(&instance->report_list);
mutex_init(&instance->lock);
init_waitqueue_head(&instance->report_list_waitq);
init_waitqueue_head(&instance->synch_done_waitq);
- instance->control = cont;
-
- /*
- * Remember the instance so that we can retrieve it in
- * other functions
- */
- filp->private_data = instance;
- goto out;
-
-instance_alloc_failed:
-out:
dec_stat(cont, &cont->stat_n_in_open);
return ret;
@@ -244,11 +204,9 @@ out:
* All active jobs are finished or cancelled and allocated data
* is released.
*/
-static int b2r2_blt_release(struct inode *inode, struct file *filp)
+int b2r2_control_release(struct b2r2_control_instance *instance)
{
int ret;
- struct b2r2_blt_instance *instance =
- (struct b2r2_blt_instance *) filp->private_data;
struct b2r2_control *cont = instance->control;
b2r2_log_info(cont->dev, "%s\n", __func__);
@@ -256,7 +214,7 @@ static int b2r2_blt_release(struct inode *inode, struct file *filp)
inc_stat(cont, &cont->stat_n_in_release);
/* Finish all outstanding requests */
- ret = b2r2_blt_synch(instance, 0);
+ ret = b2r2_control_synch(instance, 0);
if (ret < 0)
b2r2_log_warn(cont->dev, "%s: b2r2_blt_sync failed with %d\n",
__func__, ret);
@@ -301,296 +259,68 @@ static int b2r2_blt_release(struct inode *inode, struct file *filp)
}
mutex_unlock(&instance->lock);
- /* Release our instance */
- kfree(instance);
-
dec_stat(cont, &cont->stat_n_in_release);
return 0;
}
-/**
- * b2r2_blt_ioctl - This routine implements b2r2_blt ioctl interface
- *
- * @file: file pointer.
- * @cmd :ioctl command.
- * @arg: input argument for ioctl.
- *
- * Returns 0 if OK else negative error code
- */
-static long b2r2_blt_ioctl(struct file *file,
- unsigned int cmd, unsigned long arg)
+size_t b2r2_control_read(struct b2r2_control_instance *instance,
+ struct b2r2_blt_request **request_out, bool block)
{
- int ret = 0;
- struct b2r2_blt_instance *instance =
- (struct b2r2_blt_instance *) file->private_data;
+ struct b2r2_blt_request *request = NULL;
+#ifdef CONFIG_B2R2_DEBUG
struct b2r2_control *cont = instance->control;
-
- /** Process actual ioctl */
- b2r2_log_info(cont->dev, "%s\n", __func__);
-
- /* Get the instance from the file structure */
- switch (cmd) {
- case B2R2_BLT_IOC: {
- /* This is the "blit" command */
-
- /* arg is user pointer to struct b2r2_blt_request */
- struct b2r2_blt_request *request =
- kmalloc(sizeof(*request), GFP_KERNEL);
- if (!request) {
- b2r2_log_err(cont->dev, "%s: Failed to alloc mem\n",
- __func__);
- return -ENOMEM;
- }
-
- /* Initialize the structure */
- memset(request, 0, sizeof(*request));
- INIT_LIST_HEAD(&request->list);
- request->instance = instance;
-
- /*
- * The user request is a sub structure of the
- * kernel request structure.
- */
-
- /* Get the user data */
- if (copy_from_user(&request->user_req, (void *)arg,
- sizeof(request->user_req))) {
- b2r2_log_err(cont->dev, "%s: copy_from_user failed\n",
- __func__);
- kfree(request);
- return -EFAULT;
- }
-
- if (!b2r2_validate_user_req(cont, &request->user_req)) {
- kfree(request);
- return -EINVAL;
- }
-
- request->profile = is_profiler_registered_approx();
-
- /*
- * If the user specified a color look-up table,
- * make a copy that the HW can use.
- */
- if ((request->user_req.flags &
- B2R2_BLT_FLAG_CLUT_COLOR_CORRECTION) != 0) {
- request->clut = dma_alloc_coherent(cont->dev,
- CLUT_SIZE, &(request->clut_phys_addr),
- GFP_DMA | GFP_KERNEL);
- if (request->clut == NULL) {
- b2r2_log_err(cont->dev, "%s CLUT allocation "
- "failed.\n", __func__);
- kfree(request);
- return -ENOMEM;
- }
-
- if (copy_from_user(request->clut,
- request->user_req.clut, CLUT_SIZE)) {
- b2r2_log_err(cont->dev, "%s: CLUT "
- "copy_from_user failed\n",
- __func__);
- dma_free_coherent(cont->dev, CLUT_SIZE,
- request->clut,
- request->clut_phys_addr);
- request->clut = NULL;
- request->clut_phys_addr = 0;
- kfree(request);
- return -EFAULT;
- }
- }
-
- /* Perform the blit */
-
-#ifdef CONFIG_B2R2_GENERIC_ONLY
- /* Use the generic path for all operations */
- ret = b2r2_generic_blt(instance, request);
-#else
- /* Use the optimized path */
- ret = b2r2_blt(instance, request);
#endif
-#ifdef CONFIG_B2R2_GENERIC_FALLBACK
- /* Fall back to generic path if operation was not supported */
- if (ret == -ENOSYS) {
- struct b2r2_blt_request *request_gen;
-
- if (request->user_req.flags & B2R2_BLT_FLAG_BG_BLEND) {
- /* No support for BG BLEND in generic
- * implementation yet */
- b2r2_log_warn(cont->dev, "%s: Unsupported: "
- "Background blend in b2r2_generic_blt\n",
- __func__);
- return ret;
- }
-
- b2r2_log_info(cont->dev,
- "b2r2_blt=%d Going generic.\n", ret);
- request_gen = kmalloc(sizeof(*request_gen), GFP_KERNEL);
- if (!request_gen) {
- b2r2_log_err(cont->dev,
- "%s: Failed to alloc mem for "
- "request_gen\n", __func__);
- return -ENOMEM;
- }
-
- /* Initialize the structure */
- memset(request_gen, 0, sizeof(*request_gen));
- INIT_LIST_HEAD(&request_gen->list);
- request_gen->instance = instance;
-
- /*
- * The user request is a sub structure of the
- * kernel request structure.
- */
-
- /* Get the user data */
- if (copy_from_user(&request_gen->user_req, (void *)arg,
- sizeof(request_gen->user_req))) {
- b2r2_log_err(cont->dev, "%s: copy_from_user "
- "failed\n", __func__);
- kfree(request_gen);
- return -EFAULT;
- }
+ b2r2_log_info(cont->dev, "%s\n", __func__);
- /*
- * If the user specified a color look-up table,
- * make a copy that the HW can use.
- */
- if ((request_gen->user_req.flags &
- B2R2_BLT_FLAG_CLUT_COLOR_CORRECTION)
- != 0) {
- request_gen->clut = dma_alloc_coherent(
- cont->dev, CLUT_SIZE,
- &(request_gen->clut_phys_addr),
- GFP_DMA | GFP_KERNEL);
- if (request_gen->clut == NULL) {
- b2r2_log_err(cont->dev, "%s CLUT "
- "allocation failed.\n",
- __func__);
- kfree(request_gen);
- return -ENOMEM;
- }
-
- if (copy_from_user(request_gen->clut,
- request_gen->user_req.clut,
- CLUT_SIZE)) {
- b2r2_log_err(cont->dev, "%s: CLUT"
- " copy_from_user failed\n",
- __func__);
- dma_free_coherent(cont->dev, CLUT_SIZE,
- request_gen->clut,
- request_gen->clut_phys_addr);
- request_gen->clut = NULL;
- request_gen->clut_phys_addr = 0;
- kfree(request_gen);
- return -EFAULT;
- }
- }
+ /*
+ * Loop and wait here until we have anything to return or
+ * until interrupted
+ */
+ mutex_lock(&instance->lock);
+ while (list_empty(&instance->report_list)) {
+ mutex_unlock(&instance->lock);
- request_gen->profile = is_profiler_registered_approx();
+ /* Return if non blocking read */
+ if (!block)
+ return -EAGAIN;
- ret = b2r2_generic_blt(instance, request_gen);
- b2r2_log_info(cont->dev, "\nb2r2_generic_blt=%d "
- "Generic done.\n", ret);
- }
-#endif /* CONFIG_B2R2_GENERIC_FALLBACK */
+ b2r2_log_info(cont->dev, "%s - Going to sleep\n", __func__);
+ if (wait_event_interruptible(
+ instance->report_list_waitq,
+ !is_report_list_empty(instance)))
+ /* signal: tell the fs layer to handle it */
+ return -ERESTARTSYS;
- break;
+ /* Otherwise loop, but first reaquire the lock */
+ mutex_lock(&instance->lock);
}
- case B2R2_BLT_SYNCH_IOC:
- /* arg is request_id */
- ret = b2r2_blt_synch(instance, (int) arg);
- break;
-
- case B2R2_BLT_QUERY_CAP_IOC:
- {
- /* Arg is struct b2r2_blt_query_cap */
- struct b2r2_blt_query_cap query_cap;
-
- /* Get the user data */
- if (copy_from_user(&query_cap, (void *)arg,
- sizeof(query_cap))) {
- b2r2_log_err(cont->dev, "%s: copy_from_user failed\n",
- __func__);
- return -EFAULT;
- }
-
- /* Fill in our capabilities */
- ret = b2r2_blt_query_cap(instance, &query_cap);
-
- /* Return data to user */
- if (copy_to_user((void *)arg, &query_cap,
- sizeof(query_cap))) {
- b2r2_log_err(cont->dev, "%s: copy_to_user failed\n",
- __func__);
- return -EFAULT;
- }
- break;
- }
+ if (!list_empty(&instance->report_list))
+ request = list_first_entry(
+ &instance->report_list, struct b2r2_blt_request, list);
- default:
- /* Unknown command */
- b2r2_log_err(cont->dev, "%s: Unknown cmd %d\n", __func__, cmd);
- ret = -EINVAL;
- break;
+ if (request) {
+ /* Remove from list to avoid reading twice */
+ list_del_init(&request->list);
+ *request_out = request;
}
-
- if (ret < 0)
- b2r2_log_err(cont->dev, "EC %d OK!\n", -ret);
-
- return ret;
-}
-
-/**
- * b2r2_blt_poll - Support for user-space poll, select & epoll.
- * Used for user-space callback
- *
- * @filp: File to poll on
- * @wait: Poll table to wait on
- *
- * This function checks if there are anything to read
- */
-static unsigned b2r2_blt_poll(struct file *filp, poll_table *wait)
-{
- struct b2r2_blt_instance *instance =
- (struct b2r2_blt_instance *) filp->private_data;
- unsigned int mask = 0;
-#ifdef CONFIG_B2R2_DEBUG
- struct b2r2_control *cont = instance->control;
-#endif
-
- b2r2_log_info(cont->dev, "%s\n", __func__);
-
- poll_wait(filp, &instance->report_list_waitq, wait);
- mutex_lock(&instance->lock);
- if (!list_empty(&instance->report_list))
- mask |= POLLIN | POLLRDNORM;
mutex_unlock(&instance->lock);
- return mask;
+ if (request)
+ return 1;
+
+ /* No report returned */
+ return 0;
}
-/**
- * b2r2_blt_read - Read report data, user for user-space callback
- *
- * @filp: File pointer
- * @buf: User space buffer
- * @count: Number of bytes to read
- * @f_pos: File position
- *
- * Returns number of bytes read or negative error code
- */
-static ssize_t b2r2_blt_read(struct file *filp, char __user *buf, size_t count,
- loff_t *f_pos)
+size_t b2r2_control_read_id(struct b2r2_control_instance *instance,
+ struct b2r2_blt_request **request_out, bool block,
+ int request_id)
{
- int ret = 0;
struct b2r2_blt_request *request = NULL;
- struct b2r2_blt_report report;
- struct b2r2_blt_instance *instance =
- (struct b2r2_blt_instance *) filp->private_data;
#ifdef CONFIG_B2R2_DEBUG
struct b2r2_control *cont = instance->control;
#endif
@@ -598,17 +328,6 @@ static ssize_t b2r2_blt_read(struct file *filp, char __user *buf, size_t count,
b2r2_log_info(cont->dev, "%s\n", __func__);
/*
- * We return only complete report records, one at a time.
- * Might be more efficient to support read of many.
- */
- count = (count / sizeof(struct b2r2_blt_report)) *
- sizeof(struct b2r2_blt_report);
- if (count > sizeof(struct b2r2_blt_report))
- count = sizeof(struct b2r2_blt_report);
- if (count == 0)
- return count;
-
- /*
* Loop and wait here until we have anything to return or
* until interrupted
*/
@@ -617,7 +336,7 @@ static ssize_t b2r2_blt_read(struct file *filp, char __user *buf, size_t count,
mutex_unlock(&instance->lock);
/* Return if non blocking read */
- if (filp->f_flags & O_NONBLOCK)
+ if (!block)
return -EAGAIN;
b2r2_log_info(cont->dev, "%s - Going to sleep\n", __func__);
@@ -631,55 +350,28 @@ static ssize_t b2r2_blt_read(struct file *filp, char __user *buf, size_t count,
mutex_lock(&instance->lock);
}
- if (!list_empty(&instance->report_list))
- request = list_first_entry(
- &instance->report_list, struct b2r2_blt_request, list);
+ if (!list_empty(&instance->report_list)) {
+ struct b2r2_blt_request *pos;
+ list_for_each_entry(pos, &instance->report_list, list) {
+ if (pos->request_id)
+ request = pos;
+ }
+ }
if (request) {
/* Remove from list to avoid reading twice */
list_del_init(&request->list);
-
- report.request_id = request->request_id;
- report.report1 = request->user_req.report1;
- report.report2 = request->user_req.report2;
- report.usec_elapsed = 0; /* TBD */
-
- mutex_unlock(&instance->lock);
- if (copy_to_user(buf, &report, sizeof(report)))
- ret = -EFAULT;
- mutex_lock(&instance->lock);
-
- if (ret < 0) {
- /* copy to user failed, re-insert into list */
- list_add(&request->list,
- &request->instance->report_list);
- request = NULL;
- }
+ *request_out = request;
}
mutex_unlock(&instance->lock);
if (request)
- /*
- * Release matching the addref when the job was put into
- * the report list
- */
- b2r2_core_job_release(&request->job, __func__);
+ return 1;
- return count;
+ /* No report returned */
+ return 0;
}
-/**
- * b2r2_blt_fops - File operations for b2r2_blt
- */
-static const struct file_operations b2r2_blt_fops = {
- .owner = THIS_MODULE,
- .open = b2r2_blt_open,
- .release = b2r2_blt_release,
- .unlocked_ioctl = b2r2_blt_ioctl,
- .poll = b2r2_blt_poll,
- .read = b2r2_blt_read,
-};
-
#ifndef CONFIG_B2R2_GENERIC_ONLY
/**
* b2r2_blt - Implementation of the B2R2 blit request
@@ -687,14 +379,14 @@ static const struct file_operations b2r2_blt_fops = {
* @instance: The B2R2 BLT instance
* @request; The request to perform
*/
-static int b2r2_blt(struct b2r2_blt_instance *instance,
- struct b2r2_blt_request *request)
+int b2r2_control_blt(struct b2r2_blt_request *request)
{
int ret = 0;
struct b2r2_blt_rect actual_dst_rect;
int request_id = 0;
struct b2r2_node *last_node = request->first_node;
int node_count;
+ struct b2r2_control_instance *instance = request->instance;
struct b2r2_control *cont = instance->control;
u32 thread_runtime_at_start = 0;
@@ -918,6 +610,7 @@ static int b2r2_blt(struct b2r2_blt_instance *instance,
last_node = last_node->next;
request->job.tag = (int) instance;
+ request->job.data = (int) cont->data;
request->job.prio = request->user_req.prio;
request->job.first_node_address =
request->first_node->physical_address;
@@ -1010,33 +703,6 @@ static int b2r2_blt(struct b2r2_blt_instance *instance,
instance->no_of_active_requests++;
mutex_unlock(&instance->lock);
- /* Wait for the job to be done if synchronous */
- if ((request->user_req.flags & B2R2_BLT_FLAG_ASYNCH) == 0) {
- b2r2_log_info(cont->dev, "%s: Synchronous, waiting\n",
- __func__);
-
- inc_stat(cont, &cont->stat_n_in_blt_wait);
-
- ret = b2r2_core_job_wait(&request->job);
-
- dec_stat(cont, &cont->stat_n_in_blt_wait);
-
- if (ret < 0 && ret != -ENOENT)
- b2r2_log_warn(cont->dev, "%s: Failed to wait job,"
- " ret = %d\n", __func__, ret);
- else
- b2r2_log_info(cont->dev, "%s: Synchronous wait done\n",
- __func__);
- ret = 0;
- }
-
- /*
- * Release matching the addref in b2r2_core_job_add,
- * the request must not be accessed after this call
- */
- b2r2_core_job_release(&request->job, __func__);
- dec_stat(cont, &cont->stat_n_in_blt);
-
return ret >= 0 ? request_id : ret;
job_add_failed:
@@ -1057,17 +723,52 @@ resolve_bg_buf_failed:
&request->src_resolved);
resolve_src_buf_failed:
synch_interrupted:
- job_release(&request->job);
- dec_stat(cont, &cont->stat_n_jobs_released);
if ((request->user_req.flags & B2R2_BLT_FLAG_DRY_RUN) == 0 || ret)
b2r2_log_warn(cont->dev, "%s returns with error %d\n",
__func__, ret);
+ job_release(&request->job);
+ dec_stat(cont, &cont->stat_n_jobs_released);
dec_stat(cont, &cont->stat_n_in_blt);
return ret;
}
+int b2r2_control_waitjob(struct b2r2_blt_request *request)
+{
+ int ret = 0;
+ struct b2r2_control_instance *instance = request->instance;
+ struct b2r2_control *cont = instance->control;
+
+ /* Wait for the job to be done if synchronous */
+ if ((request->user_req.flags & B2R2_BLT_FLAG_ASYNCH) == 0) {
+ b2r2_log_info(cont->dev, "%s: Synchronous, waiting\n",
+ __func__);
+
+ inc_stat(cont, &cont->stat_n_in_blt_wait);
+
+ ret = b2r2_core_job_wait(&request->job);
+
+ dec_stat(cont, &cont->stat_n_in_blt_wait);
+
+ if (ret < 0 && ret != -ENOENT)
+ b2r2_log_warn(cont->dev, "%s: Failed to wait job,"
+ " ret = %d\n", __func__, ret);
+ else
+ b2r2_log_info(cont->dev, "%s: Synchronous wait done\n",
+ __func__);
+ }
+
+ /*
+ * Release matching the addref in b2r2_core_job_add,
+ * the request must not be accessed after this call
+ */
+ b2r2_core_job_release(&request->job, __func__);
+ dec_stat(cont, &cont->stat_n_in_blt);
+
+ return ret;
+}
+
/**
* Called when job is done or cancelled
*
@@ -1075,9 +776,13 @@ synch_interrupted:
*/
static void job_callback(struct b2r2_core_job *job)
{
- struct b2r2_blt_request *request =
- container_of(job, struct b2r2_blt_request, job);
- struct b2r2_control *cont = request->instance->control;
+ struct b2r2_blt_request *request = NULL;
+ struct b2r2_core *core = NULL;
+ struct b2r2_control *cont = NULL;
+
+ request = container_of(job, struct b2r2_blt_request, job);
+ core = (struct b2r2_core *) job->data;
+ cont = core->control;
if (cont->dev)
b2r2_log_info(cont->dev, "%s\n", __func__);
@@ -1098,6 +803,8 @@ static void job_callback(struct b2r2_core_job *job)
/* Move to report list if the job shall be reported */
/* FIXME: Use a smaller struct? */
+ /* TODO: In the case of kernel API call, feed an asynch task to the
+ * instance worker (kthread) instead of polling for a report */
mutex_lock(&request->instance->lock);
if (request->user_req.flags & B2R2_BLT_FLAG_REPORT_WHEN_DONE) {
/* Move job to report list */
@@ -1163,9 +870,13 @@ static void job_callback(struct b2r2_core_job *job)
*/
static void job_release(struct b2r2_core_job *job)
{
- struct b2r2_blt_request *request =
- container_of(job, struct b2r2_blt_request, job);
- struct b2r2_control *cont = request->instance->control;
+ struct b2r2_blt_request *request = NULL;
+ struct b2r2_core *core = NULL;
+ struct b2r2_control *cont = NULL;
+
+ request = container_of(job, struct b2r2_blt_request, job);
+ core = (struct b2r2_core *) job->data;
+ cont = core->control;
inc_stat(cont, &cont->stat_n_jobs_released);
@@ -1206,7 +917,8 @@ static int job_acquire_resources(struct b2r2_core_job *job, bool atomic)
{
struct b2r2_blt_request *request =
container_of(job, struct b2r2_blt_request, job);
- struct b2r2_control *cont = request->instance->control;
+ struct b2r2_core *core = (struct b2r2_core *) job->data;
+ struct b2r2_control *cont = core->control;
int ret;
int i;
@@ -1280,7 +992,8 @@ static void job_release_resources(struct b2r2_core_job *job, bool atomic)
{
struct b2r2_blt_request *request =
container_of(job, struct b2r2_blt_request, job);
- struct b2r2_control *cont = request->instance->control;
+ struct b2r2_core *core = (struct b2r2_core *) job->data;
+ struct b2r2_control *cont = core->control;
int i;
b2r2_log_info(cont->dev, "%s\n", __func__);
@@ -1323,9 +1036,9 @@ static void job_release_resources(struct b2r2_core_job *job, bool atomic)
static void tile_job_callback_gen(struct b2r2_core_job *job)
{
#ifdef CONFIG_B2R2_DEBUG
- struct b2r2_blt_instance *instance =
- (struct b2r2_blt_instance *) job->tag;
- struct b2r2_control *cont = instance->control;
+ struct b2r2_core *core =
+ (struct b2r2_core *) job->data;
+ struct b2r2_control *cont = core->control;
#endif
b2r2_log_info(cont->dev, "%s\n", __func__);
@@ -1355,7 +1068,8 @@ static void job_callback_gen(struct b2r2_core_job *job)
{
struct b2r2_blt_request *request =
container_of(job, struct b2r2_blt_request, job);
- struct b2r2_control *cont = request->instance->control;
+ struct b2r2_core *core = (struct b2r2_core *) job->data;
+ struct b2r2_control *cont = core->control;
b2r2_log_info(cont->dev, "%s\n", __func__);
@@ -1372,8 +1086,9 @@ static void job_callback_gen(struct b2r2_core_job *job)
/* Move to report list if the job shall be reported */
/* FIXME: Use a smaller struct? */
+ /* TODO: In the case of kernel API call, feed an asynch task to the
+ * instance worker (kthread) instead of polling for a report */
mutex_lock(&request->instance->lock);
-
if (request->user_req.flags & B2R2_BLT_FLAG_REPORT_WHEN_DONE) {
/* Move job to report list */
list_add_tail(&request->list,
@@ -1398,7 +1113,7 @@ static void job_callback_gen(struct b2r2_core_job *job)
BUG_ON(request->instance->no_of_active_requests == 0);
request->instance->no_of_active_requests--;
if (request->instance->synching &&
- request->instance->no_of_active_requests == 0) {
+ request->instance->no_of_active_requests == 0) {
request->instance->synching = false;
/* Wake up all syncing */
@@ -1438,9 +1153,9 @@ static void job_callback_gen(struct b2r2_core_job *job)
static void tile_job_release_gen(struct b2r2_core_job *job)
{
- struct b2r2_blt_instance *instance =
- (struct b2r2_blt_instance *) job->tag;
- struct b2r2_control *cont = instance->control;
+ struct b2r2_core *core =
+ (struct b2r2_core *) job->data;
+ struct b2r2_control *cont = core->control;
inc_stat(cont, &cont->stat_n_jobs_released);
@@ -1462,7 +1177,8 @@ static void job_release_gen(struct b2r2_core_job *job)
{
struct b2r2_blt_request *request =
container_of(job, struct b2r2_blt_request, job);
- struct b2r2_control *cont = request->instance->control;
+ struct b2r2_core *core = (struct b2r2_core *) job->data;
+ struct b2r2_control *cont = core->control;
inc_stat(cont, &cont->stat_n_jobs_released);
@@ -1503,11 +1219,9 @@ static void job_release_resources_gen(struct b2r2_core_job *job, bool atomic)
/**
* b2r2_generic_blt - Generic implementation of the B2R2 blit request
*
- * @instance: The B2R2 BLT instance
* @request; The request to perform
*/
-static int b2r2_generic_blt(struct b2r2_blt_instance *instance,
- struct b2r2_blt_request *request)
+int b2r2_generic_blt(struct b2r2_blt_request *request)
{
int ret = 0;
struct b2r2_blt_rect actual_dst_rect;
@@ -1527,6 +1241,7 @@ static int b2r2_generic_blt(struct b2r2_blt_instance *instance,
struct b2r2_work_buf work_bufs[4];
struct b2r2_blt_rect dst_rect_tile;
int i;
+ struct b2r2_control_instance *instance = request->instance;
struct b2r2_control *cont = instance->control;
u32 thread_runtime_at_start = 0;
@@ -1754,6 +1469,7 @@ static int b2r2_generic_blt(struct b2r2_blt_instance *instance,
last_node = last_node->next;
request->job.tag = (int) instance;
+ request->job.data = (int) cont->data;
request->job.prio = request->user_req.prio;
request->job.first_node_address =
request->first_node->physical_address;
@@ -1860,7 +1576,9 @@ static int b2r2_generic_blt(struct b2r2_blt_instance *instance,
"(%d, %d)\n", __func__, x, y);
continue;
}
+ tile_job->job_id = request->job.job_id;
tile_job->tag = request->job.tag;
+ tile_job->data = request->job.data;
tile_job->prio = request->job.prio;
tile_job->first_node_address =
request->job.first_node_address;
@@ -1976,7 +1694,9 @@ static int b2r2_generic_blt(struct b2r2_blt_instance *instance,
"(%d, %d)\n", __func__, x, y);
continue;
}
+ tile_job->job_id = request->job.job_id;
tile_job->tag = request->job.tag;
+ tile_job->data = request->job.data;
tile_job->prio = request->job.prio;
tile_job->first_node_address =
request->job.first_node_address;
@@ -2177,7 +1897,7 @@ zero_blt:
* @request_id: If 0, wait for all requests on this instance to finish.
* Else wait for request with given request id to finish.
*/
-static int b2r2_blt_synch(struct b2r2_blt_instance *instance,
+int b2r2_control_synch(struct b2r2_control_instance *instance,
int request_id)
{
int ret = 0;
@@ -2223,19 +1943,6 @@ static int b2r2_blt_synch(struct b2r2_blt_instance *instance,
return ret;
}
-/**
- * Query B2R2 capabilities
- *
- * @instance: The B2R2 BLT instance
- * @query_cap: The structure receiving the capabilities
- */
-static int b2r2_blt_query_cap(struct b2r2_blt_instance *instance,
- struct b2r2_blt_query_cap *query_cap)
-{
- /* FIXME: Not implemented yet */
- return -ENOSYS;
-}
-
static void get_actual_dst_rect(struct b2r2_blt_req *req,
struct b2r2_blt_rect *actual_dst_rect)
{
@@ -2261,12 +1968,12 @@ static void set_up_hwmem_region(struct b2r2_control *cont,
if (b2r2_is_zero_area_rect(rect))
return;
- img_size = b2r2_get_img_size(cont, img);
+ img_size = b2r2_get_img_size(cont->dev, img);
if (b2r2_is_single_plane_fmt(img->fmt) &&
b2r2_is_independent_pixel_fmt(img->fmt)) {
- int img_fmt_bpp = b2r2_get_fmt_bpp(cont, img->fmt);
- u32 img_pitch = b2r2_get_img_pitch(cont, img);
+ int img_fmt_bpp = b2r2_get_fmt_bpp(cont->dev, img->fmt);
+ u32 img_pitch = b2r2_get_img_pitch(cont->dev, img);
region->offset = (u32)(img->buf.offset + (rect->y *
img_pitch));
@@ -2319,8 +2026,9 @@ static int resolve_hwmem(struct b2r2_control *cont,
required_access = (is_dst ? HWMEM_ACCESS_WRITE : HWMEM_ACCESS_READ) |
HWMEM_ACCESS_IMPORT;
if ((required_access & access) != required_access) {
- b2r2_log_info(cont->dev, "%s: Insufficient access to hwmem "
- "buffer.\n", __func__);
+ b2r2_log_info(cont->dev,
+ "%s: Insufficient access to hwmem (%d, requires %d)"
+ "buffer.\n", __func__, access, required_access);
return_value = -EACCES;
goto access_check_failed;
}
@@ -2333,11 +2041,12 @@ static int resolve_hwmem(struct b2r2_control *cont,
}
if (resolved_buf->file_len <
- img->buf.offset + (__u32)b2r2_get_img_size(cont, img)) {
+ img->buf.offset +
+ (__u32)b2r2_get_img_size(cont->dev, img)) {
b2r2_log_info(cont->dev, "%s: Hwmem buffer too small. (%d < "
"%d)\n", __func__, resolved_buf->file_len,
img->buf.offset +
- (__u32)b2r2_get_img_size(cont, img));
+ (__u32)b2r2_get_img_size(cont->dev, img));
return_value = -EINVAL;
goto size_check_failed;
}
@@ -2714,7 +2423,7 @@ static void sync_buf(struct b2r2_control *cont,
*
* @instance: The B2R2 BLT instance
*/
-static bool is_report_list_empty(struct b2r2_blt_instance *instance)
+static bool is_report_list_empty(struct b2r2_control_instance *instance)
{
bool is_empty;
@@ -2730,7 +2439,7 @@ static bool is_report_list_empty(struct b2r2_blt_instance *instance)
*
* @instance: The B2R2 BLT instance
*/
-static bool is_synching(struct b2r2_blt_instance *instance)
+static bool is_synching(struct b2r2_control_instance *instance)
{
bool is_synching;
@@ -2768,213 +2477,6 @@ static void dec_stat(struct b2r2_control *cont, unsigned long *stat)
#ifdef CONFIG_DEBUG_FS
/**
- * sprintf_req() - Builds a string representing the request, for debug
- *
- * @request:Request that should be encoded into a string
- * @buf: Receiving buffer
- * @size: Size of receiving buffer
- *
- * Returns number of characters in string, excluding null terminator
- */
-static int sprintf_req(struct b2r2_blt_request *request, char *buf, int size)
-{
- size_t dev_size = 0;
-
- /* generic request info */
- dev_size += sprintf(buf + dev_size,
- "instance : 0x%08lX\n",
- (unsigned long) request->instance);
- dev_size += sprintf(buf + dev_size,
- "size : %d bytes\n", request->user_req.size);
- dev_size += sprintf(buf + dev_size,
- "flags : 0x%08lX\n",
- (unsigned long) request->user_req.flags);
- dev_size += sprintf(buf + dev_size,
- "transform : %d\n",
- (int) request->user_req.transform);
- dev_size += sprintf(buf + dev_size,
- "prio : %d\n", request->user_req.transform);
- dev_size += sprintf(buf + dev_size,
- "global_alpha : %d\n",
- (int) request->user_req.global_alpha);
- dev_size += sprintf(buf + dev_size,
- "report1 : 0x%08lX\n",
- (unsigned long) request->user_req.report1);
- dev_size += sprintf(buf + dev_size,
- "report2 : 0x%08lX\n",
- (unsigned long) request->user_req.report2);
- dev_size += sprintf(buf + dev_size,
- "request_id : 0x%08lX\n\n",
- (unsigned long) request->request_id);
-
- /* src info */
- dev_size += sprintf(buf + dev_size,
- "src_img.fmt : %#010x\n",
- request->user_req.src_img.fmt);
- dev_size += sprintf(buf + dev_size,
- "src_img.buf : {type=%d, hwmem_buf_name=%d, fd=%d, "
- "offset=%d, len=%d}\n",
- request->user_req.src_img.buf.type,
- request->user_req.src_img.buf.hwmem_buf_name,
- request->user_req.src_img.buf.fd,
- request->user_req.src_img.buf.offset,
- request->user_req.src_img.buf.len);
- dev_size += sprintf(buf + dev_size,
- "src_img : {width=%d, height=%d, pitch=%d}\n",
- request->user_req.src_img.width,
- request->user_req.src_img.height,
- request->user_req.src_img.pitch);
- dev_size += sprintf(buf + dev_size,
- "src_mask.fmt : %#010x\n",
- request->user_req.src_mask.fmt);
- dev_size += sprintf(buf + dev_size,
- "src_mask.buf : {type=%d, hwmem_buf_name=%d, fd=%d,"
- " offset=%d, len=%d}\n",
- request->user_req.src_mask.buf.type,
- request->user_req.src_mask.buf.hwmem_buf_name,
- request->user_req.src_mask.buf.fd,
- request->user_req.src_mask.buf.offset,
- request->user_req.src_mask.buf.len);
- dev_size += sprintf(buf + dev_size,
- "src_mask : {width=%d, height=%d, pitch=%d}\n",
- request->user_req.src_mask.width,
- request->user_req.src_mask.height,
- request->user_req.src_mask.pitch);
- dev_size += sprintf(buf + dev_size,
- "src_rect : {x=%d, y=%d, width=%d, height=%d}\n",
- request->user_req.src_rect.x,
- request->user_req.src_rect.y,
- request->user_req.src_rect.width,
- request->user_req.src_rect.height);
- dev_size += sprintf(buf + dev_size,
- "src_color : 0x%08lX\n\n",
- (unsigned long) request->user_req.src_color);
-
- /* bg info */
- dev_size += sprintf(buf + dev_size,
- "bg_img.fmt : %#010x\n",
- request->user_req.bg_img.fmt);
- dev_size += sprintf(buf + dev_size,
- "bg_img.buf : {type=%d, hwmem_buf_name=%d, fd=%d,"
- " offset=%d, len=%d}\n",
- request->user_req.bg_img.buf.type,
- request->user_req.bg_img.buf.hwmem_buf_name,
- request->user_req.bg_img.buf.fd,
- request->user_req.bg_img.buf.offset,
- request->user_req.bg_img.buf.len);
- dev_size += sprintf(buf + dev_size,
- "bg_img : {width=%d, height=%d, pitch=%d}\n",
- request->user_req.bg_img.width,
- request->user_req.bg_img.height,
- request->user_req.bg_img.pitch);
- dev_size += sprintf(buf + dev_size,
- "bg_rect : {x=%d, y=%d, width=%d, height=%d}\n\n",
- request->user_req.bg_rect.x,
- request->user_req.bg_rect.y,
- request->user_req.bg_rect.width,
- request->user_req.bg_rect.height);
-
- /* dst info */
- dev_size += sprintf(buf + dev_size,
- "dst_img.fmt : %#010x\n",
- request->user_req.dst_img.fmt);
- dev_size += sprintf(buf + dev_size,
- "dst_img.buf : {type=%d, hwmem_buf_name=%d, fd=%d,"
- " offset=%d, len=%d}\n",
- request->user_req.dst_img.buf.type,
- request->user_req.dst_img.buf.hwmem_buf_name,
- request->user_req.dst_img.buf.fd,
- request->user_req.dst_img.buf.offset,
- request->user_req.dst_img.buf.len);
- dev_size += sprintf(buf + dev_size,
- "dst_img : {width=%d, height=%d, pitch=%d}\n",
- request->user_req.dst_img.width,
- request->user_req.dst_img.height,
- request->user_req.dst_img.pitch);
- dev_size += sprintf(buf + dev_size,
- "dst_rect : {x=%d, y=%d, width=%d, height=%d}\n",
- request->user_req.dst_rect.x,
- request->user_req.dst_rect.y,
- request->user_req.dst_rect.width,
- request->user_req.dst_rect.height);
- dev_size += sprintf(buf + dev_size,
- "dst_clip_rect : {x=%d, y=%d, width=%d, height=%d}\n",
- request->user_req.dst_clip_rect.x,
- request->user_req.dst_clip_rect.y,
- request->user_req.dst_clip_rect.width,
- request->user_req.dst_clip_rect.height);
- dev_size += sprintf(buf + dev_size,
- "dst_color : 0x%08lX\n\n",
- (unsigned long) request->user_req.dst_color);
-
- dev_size += sprintf(buf + dev_size,
- "src_resolved.physical : 0x%08lX\n",
- (unsigned long) request->src_resolved.
- physical_address);
- dev_size += sprintf(buf + dev_size,
- "src_resolved.virtual : 0x%08lX\n",
- (unsigned long) request->src_resolved.virtual_address);
- dev_size += sprintf(buf + dev_size,
- "src_resolved.filep : 0x%08lX\n",
- (unsigned long) request->src_resolved.filep);
- dev_size += sprintf(buf + dev_size,
- "src_resolved.filep_physical_start : 0x%08lX\n",
- (unsigned long) request->src_resolved.
- file_physical_start);
- dev_size += sprintf(buf + dev_size,
- "src_resolved.filep_virtual_start : 0x%08lX\n",
- (unsigned long) request->src_resolved.file_virtual_start);
- dev_size += sprintf(buf + dev_size,
- "src_resolved.file_len : %d\n\n",
- request->src_resolved.file_len);
-
- dev_size += sprintf(buf + dev_size,
- "src_mask_resolved.physical : 0x%08lX\n",
- (unsigned long) request->src_mask_resolved.
- physical_address);
- dev_size += sprintf(buf + dev_size,
- "src_mask_resolved.virtual : 0x%08lX\n",
- (unsigned long) request->src_mask_resolved.virtual_address);
- dev_size += sprintf(buf + dev_size,
- "src_mask_resolved.filep : 0x%08lX\n",
- (unsigned long) request->src_mask_resolved.filep);
- dev_size += sprintf(buf + dev_size,
- "src_mask_resolved.filep_physical_start : 0x%08lX\n",
- (unsigned long) request->src_mask_resolved.
- file_physical_start);
- dev_size += sprintf(buf + dev_size,
- "src_mask_resolved.filep_virtual_start : 0x%08lX\n",
- (unsigned long) request->src_mask_resolved.
- file_virtual_start);
- dev_size += sprintf(buf + dev_size,
- "src_mask_resolved.file_len : %d\n\n",
- request->src_mask_resolved.file_len);
-
- dev_size += sprintf(buf + dev_size,
- "dst_resolved.physical : 0x%08lX\n",
- (unsigned long) request->dst_resolved.
- physical_address);
- dev_size += sprintf(buf + dev_size,
- "dst_resolved.virtual : 0x%08lX\n",
- (unsigned long) request->dst_resolved.virtual_address);
- dev_size += sprintf(buf + dev_size,
- "dst_resolved.filep : 0x%08lX\n",
- (unsigned long) request->dst_resolved.filep);
- dev_size += sprintf(buf + dev_size,
- "dst_resolved.filep_physical_start : 0x%08lX\n",
- (unsigned long) request->dst_resolved.
- file_physical_start);
- dev_size += sprintf(buf + dev_size,
- "dst_resolved.filep_virtual_start : 0x%08lX\n",
- (unsigned long) request->dst_resolved.file_virtual_start);
- dev_size += sprintf(buf + dev_size,
- "dst_resolved.file_len : %d\n\n",
- request->dst_resolved.file_len);
-
- return dev_size;
-}
-
-/**
* debugfs_b2r2_blt_request_read() - Implements debugfs read for B2R2 register
*
* @filp: File pointer
@@ -3246,27 +2748,12 @@ static void destroy_tmp_bufs(struct b2r2_control *cont)
*
* Returns 0 if OK else negative error code
*/
-int b2r2_blt_module_init(struct b2r2_control *cont)
+int b2r2_control_init(struct b2r2_control *cont)
{
int ret;
mutex_init(&cont->stat_lock);
- /* Register b2r2 driver */
- cont->miscdev.minor = MISC_DYNAMIC_MINOR;
- cont->miscdev.name = cont->name;
- cont->miscdev.fops = &b2r2_blt_fops;
-
- ret = misc_register(&cont->miscdev);
- if (ret) {
- printk(KERN_WARNING "%s: registering misc device fails\n",
- __func__);
- goto b2r2_misc_register_fail;
- }
-
- cont->dev = cont->miscdev.this_device;
- dev_set_drvdata(cont->dev, cont);
-
#ifdef CONFIG_B2R2_GENERIC
/* Initialize generic path */
b2r2_generic_init(cont);
@@ -3280,11 +2767,6 @@ int b2r2_blt_module_init(struct b2r2_control *cont)
b2r2_log_info(cont->dev, "%s: device registered\n", __func__);
- /*
- * FIXME: This stuff should be done before the first requests i.e.
- * before misc_register, but they need the device which is not
- * available until after misc_register.
- */
cont->dev->coherent_dma_mask = 0xFFFFFFFF;
init_tmp_bufs(cont);
ret = b2r2_filters_init(cont);
@@ -3315,7 +2797,6 @@ int b2r2_blt_module_init(struct b2r2_control *cont)
}
#endif
- b2r2_ctl[cont->id] = cont;
b2r2_log_info(cont->dev, "%s: done\n", __func__);
return ret;
@@ -3328,15 +2809,13 @@ b2r2_node_split_init_fail:
#ifdef CONFIG_B2R2_GENERIC
b2r2_generic_exit(cont);
#endif
- misc_deregister(&cont->miscdev);
-b2r2_misc_register_fail:
return ret;
}
/**
- * b2r2_module_exit() - Module exit function
+ * b2r2_control_exit() - Module exit function
*/
-void b2r2_blt_module_exit(struct b2r2_control *cont)
+void b2r2_control_exit(struct b2r2_control *cont)
{
if (cont) {
b2r2_log_info(cont->dev, "%s\n", __func__);
@@ -3348,8 +2827,6 @@ void b2r2_blt_module_exit(struct b2r2_control *cont)
#endif
b2r2_mem_exit(cont);
destroy_tmp_bufs(cont);
- b2r2_ctl[cont->id] = NULL;
- misc_deregister(&cont->miscdev);
b2r2_node_split_exit(cont);
#if defined(CONFIG_B2R2_GENERIC)
b2r2_generic_exit(cont);