1fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/************************************************************************** 2fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * 32de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom * Copyright © 2009-2011 VMware, Inc., Palo Alto, CA., USA 4fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * All Rights Reserved. 5fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * 6fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Permission is hereby granted, free of charge, to any person obtaining a 7fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * copy of this software and associated documentation files (the 8fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * "Software"), to deal in the Software without restriction, including 9fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * without limitation the rights to use, copy, modify, merge, publish, 10fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * distribute, sub license, and/or sell copies of the Software, and to 11fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * permit persons to whom the Software is furnished to do so, subject to 12fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * the following conditions: 13fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * 14fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * The above copyright notice and this permission notice (including the 15fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * next paragraph) shall be included in all copies or substantial portions 16fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * of the Software. 17fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * 18fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 21fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, 22fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 23fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 24fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * USE OR OTHER DEALINGS IN THE SOFTWARE. 25fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * 26fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz **************************************************************************/ 27fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 28fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#include "vmwgfx_drv.h" 29760285e7e7ab282c25b5e90816f7c47000557f4fDavid Howells#include <drm/drmP.h> 30760285e7e7ab282c25b5e90816f7c47000557f4fDavid Howells#include <drm/ttm/ttm_bo_driver.h> 31fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 326e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz#define VMW_PPN_SIZE (sizeof(unsigned long)) 336e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz/* A future safe maximum remap size. */ 346e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz#define VMW_PPN_PER_REMAP ((31 * 1024) / VMW_PPN_SIZE) 35d92d985177c495aab53c7167f310a7efb1853918Thomas Hellstrom#define DMA_ADDR_INVALID ((dma_addr_t) 0) 36d92d985177c495aab53c7167f310a7efb1853918Thomas Hellstrom#define DMA_PAGE_INVALID 0UL 372de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 382de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstromstatic int vmw_gmr2_bind(struct vmw_private *dev_priv, 39d92d985177c495aab53c7167f310a7efb1853918Thomas Hellstrom struct vmw_piter *iter, 402de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom unsigned long num_pages, 412de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom int gmr_id) 422de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom{ 432de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom SVGAFifoCmdDefineGMR2 define_cmd; 442de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom SVGAFifoCmdRemapGMR2 remap_cmd; 452de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom uint32_t *cmd; 462de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom uint32_t *cmd_orig; 476e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz uint32_t define_size = sizeof(define_cmd) + sizeof(*cmd); 486e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz uint32_t remap_num = num_pages / VMW_PPN_PER_REMAP + ((num_pages % VMW_PPN_PER_REMAP) > 0); 496e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz uint32_t remap_size = VMW_PPN_SIZE * num_pages + (sizeof(remap_cmd) + sizeof(*cmd)) * remap_num; 506e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz uint32_t remap_pos = 0; 516e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz uint32_t cmd_size = define_size + remap_size; 522de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom uint32_t i; 532de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 546e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz cmd_orig = cmd = vmw_fifo_reserve(dev_priv, cmd_size); 552de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom if (unlikely(cmd == NULL)) 562de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom return -ENOMEM; 572de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 582de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom define_cmd.gmrId = gmr_id; 592de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom define_cmd.numPages = num_pages; 602de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 616e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz *cmd++ = SVGA_CMD_DEFINE_GMR2; 626e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz memcpy(cmd, &define_cmd, sizeof(define_cmd)); 636e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz cmd += sizeof(define_cmd) / sizeof(*cmd); 646e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz 656e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz /* 666e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz * Need to split the command if there are too many 676e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz * pages that goes into the gmr. 686e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz */ 696e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz 702de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom remap_cmd.gmrId = gmr_id; 712de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom remap_cmd.flags = (VMW_PPN_SIZE > sizeof(*cmd)) ? 722de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom SVGA_REMAP_GMR2_PPN64 : SVGA_REMAP_GMR2_PPN32; 732de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 746e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz while (num_pages > 0) { 756e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz unsigned long nr = min(num_pages, (unsigned long)VMW_PPN_PER_REMAP); 766e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz 776e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz remap_cmd.offsetPages = remap_pos; 786e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz remap_cmd.numPages = nr; 792de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 806e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz *cmd++ = SVGA_CMD_REMAP_GMR2; 816e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz memcpy(cmd, &remap_cmd, sizeof(remap_cmd)); 826e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz cmd += sizeof(remap_cmd) / sizeof(*cmd); 832de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 846e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz for (i = 0; i < nr; ++i) { 856e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz if (VMW_PPN_SIZE <= 4) 86d92d985177c495aab53c7167f310a7efb1853918Thomas Hellstrom *cmd = vmw_piter_dma_addr(iter) >> PAGE_SHIFT; 876e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz else 88d92d985177c495aab53c7167f310a7efb1853918Thomas Hellstrom *((uint64_t *)cmd) = vmw_piter_dma_addr(iter) >> 89d92d985177c495aab53c7167f310a7efb1853918Thomas Hellstrom PAGE_SHIFT; 902de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 916e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz cmd += VMW_PPN_SIZE / sizeof(*cmd); 92d92d985177c495aab53c7167f310a7efb1853918Thomas Hellstrom vmw_piter_next(iter); 936e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz } 946e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz 956e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz num_pages -= nr; 966e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz remap_pos += nr; 972de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom } 982de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 996e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz BUG_ON(cmd != cmd_orig + cmd_size / sizeof(*cmd)); 1006e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz 1016e4dcff3adbf25acb87e74500a58e3c07bdec40fJakob Bornecrantz vmw_fifo_commit(dev_priv, cmd_size); 1022de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 1032de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom return 0; 1042de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom} 1052de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 1062de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstromstatic void vmw_gmr2_unbind(struct vmw_private *dev_priv, 1072de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom int gmr_id) 1082de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom{ 1092de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom SVGAFifoCmdDefineGMR2 define_cmd; 1102de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom uint32_t define_size = sizeof(define_cmd) + 4; 1112de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom uint32_t *cmd; 1122de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 1132de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom cmd = vmw_fifo_reserve(dev_priv, define_size); 1142de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom if (unlikely(cmd == NULL)) { 1152de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom DRM_ERROR("GMR2 unbind failed.\n"); 1162de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom return; 1172de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom } 1182de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom define_cmd.gmrId = gmr_id; 1192de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom define_cmd.numPages = 0; 1202de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 1212de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom *cmd++ = SVGA_CMD_DEFINE_GMR2; 1222de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom memcpy(cmd, &define_cmd, sizeof(define_cmd)); 1232de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 1242de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom vmw_fifo_commit(dev_priv, define_size); 1252de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom} 1262de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 127d92d985177c495aab53c7167f310a7efb1853918Thomas Hellstrom 128fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_gmr_bind(struct vmw_private *dev_priv, 129d92d985177c495aab53c7167f310a7efb1853918Thomas Hellstrom const struct vmw_sg_table *vsgt, 130135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom unsigned long num_pages, 131135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom int gmr_id) 132fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 133d92d985177c495aab53c7167f310a7efb1853918Thomas Hellstrom struct vmw_piter data_iter; 134fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 135d92d985177c495aab53c7167f310a7efb1853918Thomas Hellstrom vmw_piter_start(&data_iter, vsgt, 0); 136d92d985177c495aab53c7167f310a7efb1853918Thomas Hellstrom 137d92d985177c495aab53c7167f310a7efb1853918Thomas Hellstrom if (unlikely(!vmw_piter_next(&data_iter))) 138d92d985177c495aab53c7167f310a7efb1853918Thomas Hellstrom return 0; 139d92d985177c495aab53c7167f310a7efb1853918Thomas Hellstrom 1400d00c488f3de59d19784d5ce774528acaa194525Thomas Hellstrom if (unlikely(!(dev_priv->capabilities & SVGA_CAP_GMR2))) 141fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 142fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1430d00c488f3de59d19784d5ce774528acaa194525Thomas Hellstrom return vmw_gmr2_bind(dev_priv, &data_iter, num_pages, gmr_id); 144fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 145fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 146135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom 147fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id) 148fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 1490d00c488f3de59d19784d5ce774528acaa194525Thomas Hellstrom if (likely(dev_priv->capabilities & SVGA_CAP_GMR2)) 1502de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom vmw_gmr2_unbind(dev_priv, gmr_id); 151fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 152