Linux Audio

Check our new training course

Loading...
v4.6
 
  1/**************************************************************************
  2 *
  3 * Copyright © 2009-2015 VMware, Inc., Palo Alto, CA., USA
  4 * All Rights Reserved.
  5 *
  6 * Permission is hereby granted, free of charge, to any person obtaining a
  7 * copy of this software and associated documentation files (the
  8 * "Software"), to deal in the Software without restriction, including
  9 * without limitation the rights to use, copy, modify, merge, publish,
 10 * distribute, sub license, and/or sell copies of the Software, and to
 11 * permit persons to whom the Software is furnished to do so, subject to
 12 * the following conditions:
 13 *
 14 * The above copyright notice and this permission notice (including the
 15 * next paragraph) shall be included in all copies or substantial portions
 16 * of the Software.
 17 *
 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
 22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 25 *
 26 **************************************************************************/
 27
 28#include "vmwgfx_drv.h"
 29#include <drm/drmP.h>
 30#include <drm/ttm/ttm_bo_driver.h>
 31
 
 
 32#define VMW_PPN_SIZE (sizeof(unsigned long))
 33/* A future safe maximum remap size. */
 34#define VMW_PPN_PER_REMAP ((31 * 1024) / VMW_PPN_SIZE)
 35#define DMA_ADDR_INVALID ((dma_addr_t) 0)
 36#define DMA_PAGE_INVALID 0UL
 37
 38static int vmw_gmr2_bind(struct vmw_private *dev_priv,
 39			 struct vmw_piter *iter,
 40			 unsigned long num_pages,
 41			 int gmr_id)
 42{
 43	SVGAFifoCmdDefineGMR2 define_cmd;
 44	SVGAFifoCmdRemapGMR2 remap_cmd;
 45	uint32_t *cmd;
 46	uint32_t *cmd_orig;
 47	uint32_t define_size = sizeof(define_cmd) + sizeof(*cmd);
 48	uint32_t remap_num = num_pages / VMW_PPN_PER_REMAP + ((num_pages % VMW_PPN_PER_REMAP) > 0);
 49	uint32_t remap_size = VMW_PPN_SIZE * num_pages + (sizeof(remap_cmd) + sizeof(*cmd)) * remap_num;
 50	uint32_t remap_pos = 0;
 51	uint32_t cmd_size = define_size + remap_size;
 52	uint32_t i;
 53
 54	cmd_orig = cmd = vmw_fifo_reserve(dev_priv, cmd_size);
 55	if (unlikely(cmd == NULL))
 56		return -ENOMEM;
 57
 58	define_cmd.gmrId = gmr_id;
 59	define_cmd.numPages = num_pages;
 60
 61	*cmd++ = SVGA_CMD_DEFINE_GMR2;
 62	memcpy(cmd, &define_cmd, sizeof(define_cmd));
 63	cmd += sizeof(define_cmd) / sizeof(*cmd);
 64
 65	/*
 66	 * Need to split the command if there are too many
 67	 * pages that goes into the gmr.
 68	 */
 69
 70	remap_cmd.gmrId = gmr_id;
 71	remap_cmd.flags = (VMW_PPN_SIZE > sizeof(*cmd)) ?
 72		SVGA_REMAP_GMR2_PPN64 : SVGA_REMAP_GMR2_PPN32;
 73
 74	while (num_pages > 0) {
 75		unsigned long nr = min(num_pages, (unsigned long)VMW_PPN_PER_REMAP);
 76
 77		remap_cmd.offsetPages = remap_pos;
 78		remap_cmd.numPages = nr;
 79
 80		*cmd++ = SVGA_CMD_REMAP_GMR2;
 81		memcpy(cmd, &remap_cmd, sizeof(remap_cmd));
 82		cmd += sizeof(remap_cmd) / sizeof(*cmd);
 83
 84		for (i = 0; i < nr; ++i) {
 85			if (VMW_PPN_SIZE <= 4)
 86				*cmd = vmw_piter_dma_addr(iter) >> PAGE_SHIFT;
 87			else
 88				*((uint64_t *)cmd) = vmw_piter_dma_addr(iter) >>
 89					PAGE_SHIFT;
 90
 91			cmd += VMW_PPN_SIZE / sizeof(*cmd);
 92			vmw_piter_next(iter);
 93		}
 94
 95		num_pages -= nr;
 96		remap_pos += nr;
 97	}
 98
 99	BUG_ON(cmd != cmd_orig + cmd_size / sizeof(*cmd));
100
101	vmw_fifo_commit(dev_priv, cmd_size);
102
103	return 0;
104}
105
106static void vmw_gmr2_unbind(struct vmw_private *dev_priv,
107			    int gmr_id)
108{
109	SVGAFifoCmdDefineGMR2 define_cmd;
110	uint32_t define_size = sizeof(define_cmd) + 4;
111	uint32_t *cmd;
112
113	cmd = vmw_fifo_reserve(dev_priv, define_size);
114	if (unlikely(cmd == NULL)) {
115		DRM_ERROR("GMR2 unbind failed.\n");
116		return;
117	}
118	define_cmd.gmrId = gmr_id;
119	define_cmd.numPages = 0;
120
121	*cmd++ = SVGA_CMD_DEFINE_GMR2;
122	memcpy(cmd, &define_cmd, sizeof(define_cmd));
123
124	vmw_fifo_commit(dev_priv, define_size);
125}
126
127
128int vmw_gmr_bind(struct vmw_private *dev_priv,
129		 const struct vmw_sg_table *vsgt,
130		 unsigned long num_pages,
131		 int gmr_id)
132{
133	struct vmw_piter data_iter;
134
135	vmw_piter_start(&data_iter, vsgt, 0);
136
137	if (unlikely(!vmw_piter_next(&data_iter)))
138		return 0;
139
140	if (unlikely(!(dev_priv->capabilities & SVGA_CAP_GMR2)))
141		return -EINVAL;
142
143	return vmw_gmr2_bind(dev_priv, &data_iter, num_pages, gmr_id);
144}
145
146
147void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id)
148{
149	if (likely(dev_priv->capabilities & SVGA_CAP_GMR2))
150		vmw_gmr2_unbind(dev_priv, gmr_id);
151}
v5.4
  1// SPDX-License-Identifier: GPL-2.0 OR MIT
  2/**************************************************************************
  3 *
  4 * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA
 
  5 *
  6 * Permission is hereby granted, free of charge, to any person obtaining a
  7 * copy of this software and associated documentation files (the
  8 * "Software"), to deal in the Software without restriction, including
  9 * without limitation the rights to use, copy, modify, merge, publish,
 10 * distribute, sub license, and/or sell copies of the Software, and to
 11 * permit persons to whom the Software is furnished to do so, subject to
 12 * the following conditions:
 13 *
 14 * The above copyright notice and this permission notice (including the
 15 * next paragraph) shall be included in all copies or substantial portions
 16 * of the Software.
 17 *
 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
 21 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
 22 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 23 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 24 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 25 *
 26 **************************************************************************/
 27
 
 
 28#include <drm/ttm/ttm_bo_driver.h>
 29
 30#include "vmwgfx_drv.h"
 31
 32#define VMW_PPN_SIZE (sizeof(unsigned long))
 33/* A future safe maximum remap size. */
 34#define VMW_PPN_PER_REMAP ((31 * 1024) / VMW_PPN_SIZE)
 35#define DMA_ADDR_INVALID ((dma_addr_t) 0)
 36#define DMA_PAGE_INVALID 0UL
 37
 38static int vmw_gmr2_bind(struct vmw_private *dev_priv,
 39			 struct vmw_piter *iter,
 40			 unsigned long num_pages,
 41			 int gmr_id)
 42{
 43	SVGAFifoCmdDefineGMR2 define_cmd;
 44	SVGAFifoCmdRemapGMR2 remap_cmd;
 45	uint32_t *cmd;
 46	uint32_t *cmd_orig;
 47	uint32_t define_size = sizeof(define_cmd) + sizeof(*cmd);
 48	uint32_t remap_num = num_pages / VMW_PPN_PER_REMAP + ((num_pages % VMW_PPN_PER_REMAP) > 0);
 49	uint32_t remap_size = VMW_PPN_SIZE * num_pages + (sizeof(remap_cmd) + sizeof(*cmd)) * remap_num;
 50	uint32_t remap_pos = 0;
 51	uint32_t cmd_size = define_size + remap_size;
 52	uint32_t i;
 53
 54	cmd_orig = cmd = VMW_FIFO_RESERVE(dev_priv, cmd_size);
 55	if (unlikely(cmd == NULL))
 56		return -ENOMEM;
 57
 58	define_cmd.gmrId = gmr_id;
 59	define_cmd.numPages = num_pages;
 60
 61	*cmd++ = SVGA_CMD_DEFINE_GMR2;
 62	memcpy(cmd, &define_cmd, sizeof(define_cmd));
 63	cmd += sizeof(define_cmd) / sizeof(*cmd);
 64
 65	/*
 66	 * Need to split the command if there are too many
 67	 * pages that goes into the gmr.
 68	 */
 69
 70	remap_cmd.gmrId = gmr_id;
 71	remap_cmd.flags = (VMW_PPN_SIZE > sizeof(*cmd)) ?
 72		SVGA_REMAP_GMR2_PPN64 : SVGA_REMAP_GMR2_PPN32;
 73
 74	while (num_pages > 0) {
 75		unsigned long nr = min(num_pages, (unsigned long)VMW_PPN_PER_REMAP);
 76
 77		remap_cmd.offsetPages = remap_pos;
 78		remap_cmd.numPages = nr;
 79
 80		*cmd++ = SVGA_CMD_REMAP_GMR2;
 81		memcpy(cmd, &remap_cmd, sizeof(remap_cmd));
 82		cmd += sizeof(remap_cmd) / sizeof(*cmd);
 83
 84		for (i = 0; i < nr; ++i) {
 85			if (VMW_PPN_SIZE <= 4)
 86				*cmd = vmw_piter_dma_addr(iter) >> PAGE_SHIFT;
 87			else
 88				*((uint64_t *)cmd) = vmw_piter_dma_addr(iter) >>
 89					PAGE_SHIFT;
 90
 91			cmd += VMW_PPN_SIZE / sizeof(*cmd);
 92			vmw_piter_next(iter);
 93		}
 94
 95		num_pages -= nr;
 96		remap_pos += nr;
 97	}
 98
 99	BUG_ON(cmd != cmd_orig + cmd_size / sizeof(*cmd));
100
101	vmw_fifo_commit(dev_priv, cmd_size);
102
103	return 0;
104}
105
106static void vmw_gmr2_unbind(struct vmw_private *dev_priv,
107			    int gmr_id)
108{
109	SVGAFifoCmdDefineGMR2 define_cmd;
110	uint32_t define_size = sizeof(define_cmd) + 4;
111	uint32_t *cmd;
112
113	cmd = VMW_FIFO_RESERVE(dev_priv, define_size);
114	if (unlikely(cmd == NULL))
 
115		return;
116
117	define_cmd.gmrId = gmr_id;
118	define_cmd.numPages = 0;
119
120	*cmd++ = SVGA_CMD_DEFINE_GMR2;
121	memcpy(cmd, &define_cmd, sizeof(define_cmd));
122
123	vmw_fifo_commit(dev_priv, define_size);
124}
125
126
127int vmw_gmr_bind(struct vmw_private *dev_priv,
128		 const struct vmw_sg_table *vsgt,
129		 unsigned long num_pages,
130		 int gmr_id)
131{
132	struct vmw_piter data_iter;
133
134	vmw_piter_start(&data_iter, vsgt, 0);
135
136	if (unlikely(!vmw_piter_next(&data_iter)))
137		return 0;
138
139	if (unlikely(!(dev_priv->capabilities & SVGA_CAP_GMR2)))
140		return -EINVAL;
141
142	return vmw_gmr2_bind(dev_priv, &data_iter, num_pages, gmr_id);
143}
144
145
146void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id)
147{
148	if (likely(dev_priv->capabilities & SVGA_CAP_GMR2))
149		vmw_gmr2_unbind(dev_priv, gmr_id);
150}