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" 29fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#include "drmP.h" 30fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz#include "ttm/ttm_bo_driver.h" 31fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 322de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom#define VMW_PPN_SIZE sizeof(unsigned long) 332de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 342de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstromstatic int vmw_gmr2_bind(struct vmw_private *dev_priv, 352de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom struct page *pages[], 362de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom unsigned long num_pages, 372de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom int gmr_id) 382de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom{ 392de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom SVGAFifoCmdDefineGMR2 define_cmd; 402de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom SVGAFifoCmdRemapGMR2 remap_cmd; 412de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom uint32_t define_size = sizeof(define_cmd) + 4; 422de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom uint32_t remap_size = VMW_PPN_SIZE * num_pages + sizeof(remap_cmd) + 4; 432de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom uint32_t *cmd; 442de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom uint32_t *cmd_orig; 452de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom uint32_t i; 462de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 472de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom cmd_orig = cmd = vmw_fifo_reserve(dev_priv, define_size + remap_size); 482de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom if (unlikely(cmd == NULL)) 492de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom return -ENOMEM; 502de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 512de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom define_cmd.gmrId = gmr_id; 522de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom define_cmd.numPages = num_pages; 532de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 542de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom remap_cmd.gmrId = gmr_id; 552de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom remap_cmd.flags = (VMW_PPN_SIZE > sizeof(*cmd)) ? 562de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom SVGA_REMAP_GMR2_PPN64 : SVGA_REMAP_GMR2_PPN32; 572de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom remap_cmd.offsetPages = 0; 582de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom remap_cmd.numPages = num_pages; 592de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 602de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom *cmd++ = SVGA_CMD_DEFINE_GMR2; 612de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom memcpy(cmd, &define_cmd, sizeof(define_cmd)); 622de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom cmd += sizeof(define_cmd) / sizeof(uint32); 632de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 642de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom *cmd++ = SVGA_CMD_REMAP_GMR2; 652de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom memcpy(cmd, &remap_cmd, sizeof(remap_cmd)); 662de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom cmd += sizeof(remap_cmd) / sizeof(uint32); 672de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 682de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom for (i = 0; i < num_pages; ++i) { 697e9f6a5a90c6c261247fbd9dbd38bf6f78779af6Thomas Hellstrom if (VMW_PPN_SIZE <= 4) 702de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom *cmd = page_to_pfn(*pages++); 712de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom else 722de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom *((uint64_t *)cmd) = page_to_pfn(*pages++); 732de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 742de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom cmd += VMW_PPN_SIZE / sizeof(*cmd); 752de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom } 762de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 772de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom vmw_fifo_commit(dev_priv, define_size + remap_size); 782de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 792de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom return 0; 802de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom} 812de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 822de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstromstatic void vmw_gmr2_unbind(struct vmw_private *dev_priv, 832de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom int gmr_id) 842de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom{ 852de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom SVGAFifoCmdDefineGMR2 define_cmd; 862de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom uint32_t define_size = sizeof(define_cmd) + 4; 872de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom uint32_t *cmd; 882de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 892de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom cmd = vmw_fifo_reserve(dev_priv, define_size); 902de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom if (unlikely(cmd == NULL)) { 912de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom DRM_ERROR("GMR2 unbind failed.\n"); 922de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom return; 932de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom } 942de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom define_cmd.gmrId = gmr_id; 952de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom define_cmd.numPages = 0; 962de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 972de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom *cmd++ = SVGA_CMD_DEFINE_GMR2; 982de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom memcpy(cmd, &define_cmd, sizeof(define_cmd)); 992de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 1002de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom vmw_fifo_commit(dev_priv, define_size); 1012de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom} 1022de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 103fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 104fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * FIXME: Adjust to the ttm lowmem / highmem storage to minimize 105fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * the number of used descriptors. 106fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 107fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 108fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic int vmw_gmr_build_descriptors(struct list_head *desc_pages, 109fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct page *pages[], 110fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz unsigned long num_pages) 111fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 112fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct page *page, *next; 113fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct svga_guest_mem_descriptor *page_virtual = NULL; 114fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct svga_guest_mem_descriptor *desc_virtual = NULL; 115fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz unsigned int desc_per_page; 116fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz unsigned long prev_pfn; 117fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz unsigned long pfn; 118fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int ret; 119fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 120fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz desc_per_page = PAGE_SIZE / 121fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz sizeof(struct svga_guest_mem_descriptor) - 1; 122fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 123fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz while (likely(num_pages != 0)) { 124fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz page = alloc_page(__GFP_HIGHMEM); 125fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(page == NULL)) { 126fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ret = -ENOMEM; 127fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz goto out_err; 128fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 129fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 130fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz list_add_tail(&page->lru, desc_pages); 131fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 132fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz /* 133fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * Point previous page terminating descriptor to this 134fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * page before unmapping it. 135fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 136fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 137fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (likely(page_virtual != NULL)) { 138fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz desc_virtual->ppn = page_to_pfn(page); 1391c9c20f60230bd5a6195d41f9dd2dfa60874b1daCong Wang kunmap_atomic(page_virtual); 140fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 141fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 1421c9c20f60230bd5a6195d41f9dd2dfa60874b1daCong Wang page_virtual = kmap_atomic(page); 143fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz desc_virtual = page_virtual - 1; 144fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz prev_pfn = ~(0UL); 145fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 146fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz while (likely(num_pages != 0)) { 147fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz pfn = page_to_pfn(*pages); 148fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 149fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (pfn != prev_pfn + 1) { 150fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 151fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (desc_virtual - page_virtual == 152fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz desc_per_page - 1) 153fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz break; 154fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 155fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (++desc_virtual)->ppn = cpu_to_le32(pfn); 156fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz desc_virtual->num_pages = cpu_to_le32(1); 157fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } else { 158fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz uint32_t tmp = 159fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz le32_to_cpu(desc_virtual->num_pages); 160fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz desc_virtual->num_pages = cpu_to_le32(tmp + 1); 161fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 162fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz prev_pfn = pfn; 163fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz --num_pages; 164fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ++pages; 165fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 166fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 167fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz (++desc_virtual)->ppn = cpu_to_le32(0); 168fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz desc_virtual->num_pages = cpu_to_le32(0); 169fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 170fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 171fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (likely(page_virtual != NULL)) 1721c9c20f60230bd5a6195d41f9dd2dfa60874b1daCong Wang kunmap_atomic(page_virtual); 173fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 174fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return 0; 175fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzout_err: 176fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz list_for_each_entry_safe(page, next, desc_pages, lru) { 177fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz list_del_init(&page->lru); 178fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz __free_page(page); 179fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 180fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return ret; 181fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 182fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 183fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic inline void vmw_gmr_free_descriptors(struct list_head *desc_pages) 184fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 185fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct page *page, *next; 186fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 187fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz list_for_each_entry_safe(page, next, desc_pages, lru) { 188fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz list_del_init(&page->lru); 189fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz __free_page(page); 190fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 191fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 192fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 193fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic void vmw_gmr_fire_descriptors(struct vmw_private *dev_priv, 194fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz int gmr_id, struct list_head *desc_pages) 195fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 196fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct page *page; 197fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 198fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(list_empty(desc_pages))) 199fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return; 200fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 201fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz page = list_entry(desc_pages->next, struct page, lru); 202fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 203fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz mutex_lock(&dev_priv->hw_mutex); 204fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 205fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_write(dev_priv, SVGA_REG_GMR_ID, gmr_id); 206fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz wmb(); 207fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_write(dev_priv, SVGA_REG_GMR_DESCRIPTOR, page_to_pfn(page)); 208fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz mb(); 209fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 210fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz mutex_unlock(&dev_priv->hw_mutex); 211fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 212fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 213fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 214fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz/** 215fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * FIXME: Adjust to the ttm lowmem / highmem storage to minimize 216fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz * the number of used descriptors. 217fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz */ 218fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 219fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzstatic unsigned long vmw_gmr_count_descriptors(struct page *pages[], 220135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom unsigned long num_pages) 221fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 222fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz unsigned long prev_pfn = ~(0UL); 223fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz unsigned long pfn; 224fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz unsigned long descriptors = 0; 225fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 226fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz while (num_pages--) { 227fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz pfn = page_to_pfn(*pages++); 228fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (prev_pfn + 1 != pfn) 229fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz ++descriptors; 230fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz prev_pfn = pfn; 231fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz } 232fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 233fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return descriptors; 234fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 235fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 236fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzint vmw_gmr_bind(struct vmw_private *dev_priv, 237135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom struct page *pages[], 238135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom unsigned long num_pages, 239135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom int gmr_id) 240fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 241fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz struct list_head desc_pages; 242135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom int ret; 243fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 2442de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom if (likely(dev_priv->capabilities & SVGA_CAP_GMR2)) 2452de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom return vmw_gmr2_bind(dev_priv, pages, num_pages, gmr_id); 2462de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 247135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom if (unlikely(!(dev_priv->capabilities & SVGA_CAP_GMR))) 248fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 249fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 250135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom if (vmw_gmr_count_descriptors(pages, num_pages) > 251135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom dev_priv->max_gmr_descriptors) 252fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz return -EINVAL; 253fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 254fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz INIT_LIST_HEAD(&desc_pages); 255fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 256135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom ret = vmw_gmr_build_descriptors(&desc_pages, pages, num_pages); 257fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz if (unlikely(ret != 0)) 258135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom return ret; 259fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 260135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom vmw_gmr_fire_descriptors(dev_priv, gmr_id, &desc_pages); 261fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_gmr_free_descriptors(&desc_pages); 262fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 263135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom return 0; 264fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 265fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz 266135cba0dc399fdd47bd3ae305c1db75fcd77243fThomas Hellstrom 267fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantzvoid vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id) 268fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz{ 2692de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom if (likely(dev_priv->capabilities & SVGA_CAP_GMR2)) { 2702de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom vmw_gmr2_unbind(dev_priv, gmr_id); 2712de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom return; 2722de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom } 2732de59d0161d1c5e102e2140364cc27a2676e8816Thomas Hellstrom 274fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz mutex_lock(&dev_priv->hw_mutex); 275fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_write(dev_priv, SVGA_REG_GMR_ID, gmr_id); 276fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz wmb(); 277fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz vmw_write(dev_priv, SVGA_REG_GMR_DESCRIPTOR, 0); 278fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz mb(); 279fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz mutex_unlock(&dev_priv->hw_mutex); 280fb1d9738ca053ea8afa5e86af6463155f983b01cJakob Bornecrantz} 281