Received: by 10.223.185.111 with SMTP id b44csp802221wrg; Fri, 9 Mar 2018 14:05:51 -0800 (PST) X-Google-Smtp-Source: AG47ELvqbpvYIxBvtDBnq7yoylSLPC8ku+TBDQR1vKvkCm6ygAWueVmJmNkeDvvEN18Lra3P8ICF X-Received: by 10.98.215.2 with SMTP id b2mr31220085pfh.87.1520633151883; Fri, 09 Mar 2018 14:05:51 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1520633151; cv=none; d=google.com; s=arc-20160816; b=rUipVFHelgIMKPKjEnDJ56xXXpAaYX8VyeK/bbMLXHLXjDiflIzlRGNUSoh8ZHRxoe MjX/dwKdQ9Tw32YF/BNwNUAVxomPc2R1guBZaGHkkbDzjTIdsPuNap8TmTb+yZ2MWg5w gfGuN3Q94XE/xqs2739ZA6OewEyQGaNLJdM0V7Y/SGfVxyeZmj5njcTBVNRTtrr92RVo Nx59RfoTeHg6YPWK2QPMDnxbxp+6ff+XHffpQgl5K/22mdI2hY9Z7kYjI8GpCaRbwlIX gFHNTMp/9LTClyzAtALsPVOfI9iYL3SbbAKdWphXMtb3/Xe6RPbcibubnoUB+Hxl8xKF FRzQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=I5GA8Bi8AluUUl3NbdgYdw3jKZXXBwpIpJ0lrIsCZJM=; b=je0+BTZAG1Omosf/RjhuefU7bYCg3GZANakXf5CL9Zo9dT6CgkWeCyVC+Ivc+RPFmO IcYzX868T6/02w1JR/4DZ/dcXrhCZe3N70xFWJPU3aC3s3nSWpYPhpHW/4uUaD638A1f fMqTFlQ/6VxOGt5rK/4J2rnmV5KeZRN7KwCxtotjQutxDNpTsLU0OHC1URXTLgYEc5ck luujYWchqkOuJADgNkyAL9gi9+eBsHGgZdWtyOryIVn+RD1bYYEOryZoSKv+ztMqZcLn vepSaetZvN4iEa3zJgYsm3lX3zP0QI+HQtk3ukV3eNnNpCN0TON86kBpV+Gys9+L78jz RaNg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b=DqRa169J; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u14si1565428pfa.271.2018.03.09.14.05.36; Fri, 09 Mar 2018 14:05:51 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass (test mode) header.i=@ideasonboard.com header.s=mail header.b=DqRa169J; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932862AbeCIWEY (ORCPT + 99 others); Fri, 9 Mar 2018 17:04:24 -0500 Received: from galahad.ideasonboard.com ([185.26.127.97]:39422 "EHLO galahad.ideasonboard.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932804AbeCIWEW (ORCPT ); Fri, 9 Mar 2018 17:04:22 -0500 Received: from localhost.localdomain (cpc89242-aztw30-2-0-cust488.18-1.cable.virginm.net [86.31.129.233]) by galahad.ideasonboard.com (Postfix) with ESMTPSA id 2444620D35; Fri, 9 Mar 2018 23:02:14 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1520632934; bh=PjHzuBYJrRiLJsaaehl+x46DcgQ57mtpYYgmAiZ6saA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:In-Reply-To: References:From; b=DqRa169JjGVRUAXT1TzSW0lgMFZX0ilbPMgrkjV9OeUnAj7pSsZQGkkPu4tyENGsu MfBp0N2Adea4Xuj3U0CBUohdA2tbHmGWcyo/sJ0xHwBt73qccW/ZT5fQJmy+52crmD nYPuuMFB/pXhTuV9yDmSBbF6jaO2C2Xvgv01lWJ0= From: Kieran Bingham To: Laurent Pinchart , linux-renesas-soc@vger.kernel.org, linux-media@vger.kernel.org Cc: Kieran Bingham , Mauro Carvalho Chehab , linux-kernel@vger.kernel.org (open list) Subject: [PATCH 09/11] media: vsp1: Provide support for extended command pools Date: Fri, 9 Mar 2018 22:04:07 +0000 Message-Id: <02dcefdd58c734623b9caf2513316380feb9f993.1520632434.git-series.kieran.bingham+renesas@ideasonboard.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org VSPD and VSP-DL devices can provide extended display lists supporting extended command display list objects. These extended commands require their own dma memory areas for a header and body specific to the command type. Implement a command pool to allocate all necessary memory in a single DMA allocation to reduce pressure on the TLB, and provide convenvient re-usable command objects for the entities to utilise. Signed-off-by: Kieran Bingham --- drivers/media/platform/vsp1/vsp1_dl.c | 189 +++++++++++++++++++++++++++- drivers/media/platform/vsp1/vsp1_dl.h | 3 +- 2 files changed, 192 insertions(+) diff --git a/drivers/media/platform/vsp1/vsp1_dl.c b/drivers/media/platform/vsp1/vsp1_dl.c index 36440a2a2c8b..6d17b8bfa21c 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.c +++ b/drivers/media/platform/vsp1/vsp1_dl.c @@ -121,6 +121,30 @@ struct vsp1_dl_body_pool { }; /** + * struct vsp1_cmd_pool - display list body pool + * @dma: DMA address of the entries + * @size: size of the full DMA memory pool in bytes + * @mem: CPU memory pointer for the pool + * @bodies: Array of DLB structures for the pool + * @free: List of free DLB entries + * @lock: Protects the pool and free list + * @vsp1: the VSP1 device + */ +struct vsp1_dl_cmd_pool { + /* DMA allocation */ + dma_addr_t dma; + size_t size; + void *mem; + + struct vsp1_dl_ext_cmd *cmds; + struct list_head free; + + spinlock_t lock; + + struct vsp1_device *vsp1; +}; + +/** * struct vsp1_dl_list - Display list * @list: entry in the display list manager lists * @dlm: the display list manager @@ -176,6 +200,7 @@ struct vsp1_dl_manager { struct vsp1_dl_list *pending; struct vsp1_dl_body_pool *pool; + struct vsp1_dl_cmd_pool *autfld_cmds; }; /* ----------------------------------------------------------------------------- @@ -339,6 +364,139 @@ void vsp1_dl_body_write(struct vsp1_dl_body *dlb, u32 reg, u32 data) } /* ----------------------------------------------------------------------------- + * Display List Extended Command Management + */ + +enum vsp1_extcmd_type { + VSP1_EXTCMD_AUTODISP, + VSP1_EXTCMD_AUTOFLD, +}; + +struct vsp1_extended_command_info { + u16 opcode; + size_t body_size; +} vsp1_extended_commands[] = { + [VSP1_EXTCMD_AUTODISP] = { 0x02, 96 }, + [VSP1_EXTCMD_AUTOFLD] = { 0x03, 160 }, +}; + +/** + * vsp1_dl_cmd_pool_create - Create a pool of commands from a single allocation + * @vsp1: The VSP1 device + * @type: The command pool type + * @num_commands: The quantity of commands to allocate + * + * Allocate a pool of commands each with enough memory to contain the private + * data of each command. The allocation sizes are dependent upon the command + * type. + * + * Return a pointer to a pool on success or NULL if memory can't be allocated. + */ +struct vsp1_dl_cmd_pool * +vsp1_dl_cmd_pool_create(struct vsp1_device *vsp1, enum vsp1_extcmd_type type, + unsigned int num_cmds) +{ + struct vsp1_dl_cmd_pool *pool; + unsigned int i; + size_t cmd_size; + + pool = kzalloc(sizeof(*pool), GFP_KERNEL); + if (!pool) + return NULL; + + pool->cmds = kcalloc(num_cmds, sizeof(*pool->cmds), GFP_KERNEL); + if (!pool->cmds) { + kfree(pool); + return NULL; + } + + cmd_size = sizeof(struct vsp1_dl_ext_cmd_header) + + vsp1_extended_commands[type].body_size; + cmd_size = ALIGN(cmd_size, 16); + + pool->size = cmd_size * num_cmds; + pool->mem = dma_alloc_wc(vsp1->bus_master, pool->size, &pool->dma, + GFP_KERNEL); + if (!pool->mem) { + kfree(pool->cmds); + kfree(pool); + return NULL; + } + + spin_lock_init(&pool->lock); + INIT_LIST_HEAD(&pool->free); + + for (i = 0; i < num_cmds; ++i) { + struct vsp1_dl_ext_cmd *cmd = &pool->cmds[i]; + size_t cmd_offset = i * cmd_size; + size_t data_offset = sizeof(struct vsp1_dl_ext_cmd_header) + + cmd_offset; + + cmd->pool = pool; + cmd->cmd_opcode = vsp1_extended_commands[type].opcode; + + /* TODO: Auto-disp can utilise more than one command per cmd */ + cmd->num_cmds = 1; + cmd->cmds = pool->mem + cmd_offset; + cmd->cmd_dma = pool->dma + cmd_offset; + + cmd->data = pool->mem + data_offset; + cmd->data_dma = pool->dma + data_offset; + cmd->data_size = vsp1_extended_commands[type].body_size; + + list_add_tail(&cmd->free, &pool->free); + } + + return pool; +} + +struct vsp1_dl_ext_cmd *vsp1_dl_ext_cmd_get(struct vsp1_dl_cmd_pool *pool) +{ + struct vsp1_dl_ext_cmd *cmd = NULL; + unsigned long flags; + + spin_lock_irqsave(&pool->lock, flags); + + if (!list_empty(&pool->free)) { + cmd = list_first_entry(&pool->free, struct vsp1_dl_ext_cmd, + free); + list_del(&cmd->free); + } + + spin_unlock_irqrestore(&pool->lock, flags); + + return cmd; +} + +void vsp1_dl_ext_cmd_put(struct vsp1_dl_ext_cmd *cmd) +{ + unsigned long flags; + + if (!cmd) + return; + + /* Reset flags, these mark data usage */ + cmd->flags = 0; + + spin_lock_irqsave(&cmd->pool->lock, flags); + list_add_tail(&cmd->free, &cmd->pool->free); + spin_unlock_irqrestore(&cmd->pool->lock, flags); +} + +void vsp1_dl_ext_cmd_pool_destroy(struct vsp1_dl_cmd_pool *pool) +{ + if (!pool) + return; + + if (pool->mem) + dma_free_wc(pool->vsp1->bus_master, pool->size, pool->mem, + pool->dma); + + kfree(pool->cmds); + kfree(pool); +} + +/* ---------------------------------------------------------------------------- * Display List Transaction Management */ @@ -442,6 +600,12 @@ static void __vsp1_dl_list_put(struct vsp1_dl_list *dl) vsp1_dl_list_bodies_put(dl); + vsp1_dl_ext_cmd_put(dl->pre_cmd); + vsp1_dl_ext_cmd_put(dl->post_cmd); + + dl->pre_cmd = NULL; + dl->post_cmd = NULL; + /* * body0 is reused as as an optimisation as presently every display list * has at least one body, thus we reinitialise the entries list @@ -863,6 +1027,15 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, list_add_tail(&dl->list, &dlm->free); } + if (vsp1_feature(vsp1, VSP1_HAS_EXT_DL)) { + dlm->autfld_cmds = vsp1_dl_cmd_pool_create(vsp1, + VSP1_EXTCMD_AUTOFLD, prealloc); + if (!dlm->autfld_cmds) { + vsp1_dlm_destroy(dlm); + return NULL; + } + } + return dlm; } @@ -879,4 +1052,20 @@ void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm) } vsp1_dl_body_pool_destroy(dlm->pool); + vsp1_dl_ext_cmd_pool_destroy(dlm->autfld_cmds); +} + +struct vsp1_dl_ext_cmd *vsp1_dlm_get_autofld_cmd(struct vsp1_dl_list *dl) +{ + struct vsp1_dl_manager *dlm = dl->dlm; + struct vsp1_dl_ext_cmd *cmd; + + if (dl->pre_cmd) + return dl->pre_cmd; + + cmd = vsp1_dl_ext_cmd_get(dlm->autfld_cmds); + if (cmd) + dl->pre_cmd = cmd; + + return cmd; } diff --git a/drivers/media/platform/vsp1/vsp1_dl.h b/drivers/media/platform/vsp1/vsp1_dl.h index 4898b21dc840..3009912ddefb 100644 --- a/drivers/media/platform/vsp1/vsp1_dl.h +++ b/drivers/media/platform/vsp1/vsp1_dl.h @@ -23,6 +23,7 @@ struct vsp1_dl_manager; /** * struct vsp1_dl_ext_cmd - Extended Display command + * @pool: pool to which this command belongs * @free: entry in the pool of free commands list * @cmd_opcode: command type opcode * @flags: flags used by the command @@ -34,6 +35,7 @@ struct vsp1_dl_manager; * @data_size: size of the @data_dma memory in bytes */ struct vsp1_dl_ext_cmd { + struct vsp1_dl_cmd_pool *pool; struct list_head free; u8 cmd_opcode; @@ -56,6 +58,7 @@ struct vsp1_dl_manager *vsp1_dlm_create(struct vsp1_device *vsp1, void vsp1_dlm_destroy(struct vsp1_dl_manager *dlm); void vsp1_dlm_reset(struct vsp1_dl_manager *dlm); bool vsp1_dlm_irq_frame_end(struct vsp1_dl_manager *dlm); +struct vsp1_dl_ext_cmd *vsp1_dlm_get_autofld_cmd(struct vsp1_dl_list *dl); struct vsp1_dl_list *vsp1_dl_list_get(struct vsp1_dl_manager *dlm); void vsp1_dl_list_put(struct vsp1_dl_list *dl); -- git-series 0.9.1