Subversion Repositories Kolibri OS

Rev

Rev 4111 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright © 2009-2011 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. #define mb()    asm volatile("mfence" : : : "memory")
  28. #define rmb()   asm volatile("lfence" : : : "memory")
  29. #define wmb()   asm volatile("sfence" : : : "memory")
  30.  
  31. #include "vmwgfx_drv.h"
  32. #include <drm/drmP.h>
  33. #include <drm/ttm/ttm_bo_driver.h>
  34.  
  35. #define VMW_PPN_SIZE (sizeof(unsigned long))
  36. /* A future safe maximum remap size. */
  37. #define VMW_PPN_PER_REMAP ((31 * 1024) / VMW_PPN_SIZE)
  38. #define DMA_ADDR_INVALID ((dma_addr_t) 0)
  39. #define DMA_PAGE_INVALID 0UL
  40.  
  41. static int vmw_gmr2_bind(struct vmw_private *dev_priv,
  42.                          struct vmw_piter *iter,
  43.                          unsigned long num_pages,
  44.                          int gmr_id)
  45. {
  46.         SVGAFifoCmdDefineGMR2 define_cmd;
  47.         SVGAFifoCmdRemapGMR2 remap_cmd;
  48.         uint32_t *cmd;
  49.         uint32_t *cmd_orig;
  50.         uint32_t define_size = sizeof(define_cmd) + sizeof(*cmd);
  51.         uint32_t remap_num = num_pages / VMW_PPN_PER_REMAP + ((num_pages % VMW_PPN_PER_REMAP) > 0);
  52.         uint32_t remap_size = VMW_PPN_SIZE * num_pages + (sizeof(remap_cmd) + sizeof(*cmd)) * remap_num;
  53.         uint32_t remap_pos = 0;
  54.         uint32_t cmd_size = define_size + remap_size;
  55.         uint32_t i;
  56.  
  57.         cmd_orig = cmd = vmw_fifo_reserve(dev_priv, cmd_size);
  58.         if (unlikely(cmd == NULL))
  59.                 return -ENOMEM;
  60.  
  61.         define_cmd.gmrId = gmr_id;
  62.         define_cmd.numPages = num_pages;
  63.  
  64.         *cmd++ = SVGA_CMD_DEFINE_GMR2;
  65.         memcpy(cmd, &define_cmd, sizeof(define_cmd));
  66.         cmd += sizeof(define_cmd) / sizeof(*cmd);
  67.  
  68.         /*
  69.          * Need to split the command if there are too many
  70.          * pages that goes into the gmr.
  71.          */
  72.  
  73.         remap_cmd.gmrId = gmr_id;
  74.         remap_cmd.flags = (VMW_PPN_SIZE > sizeof(*cmd)) ?
  75.                 SVGA_REMAP_GMR2_PPN64 : SVGA_REMAP_GMR2_PPN32;
  76.  
  77.         while (num_pages > 0) {
  78.                 unsigned long nr = min(num_pages, (unsigned long)VMW_PPN_PER_REMAP);
  79.  
  80.                 remap_cmd.offsetPages = remap_pos;
  81.                 remap_cmd.numPages = nr;
  82.  
  83.         *cmd++ = SVGA_CMD_REMAP_GMR2;
  84.         memcpy(cmd, &remap_cmd, sizeof(remap_cmd));
  85.                 cmd += sizeof(remap_cmd) / sizeof(*cmd);
  86.  
  87.                 for (i = 0; i < nr; ++i) {
  88.                         if (VMW_PPN_SIZE <= 4)
  89.                                 *cmd = vmw_piter_dma_addr(iter) >> PAGE_SHIFT;
  90.                         else
  91.                                 *((uint64_t *)cmd) = vmw_piter_dma_addr(iter) >>
  92.                                         PAGE_SHIFT;
  93.  
  94.                         cmd += VMW_PPN_SIZE / sizeof(*cmd);
  95.                         vmw_piter_next(iter);
  96.                 }
  97.  
  98.                 num_pages -= nr;
  99.                 remap_pos += nr;
  100.         }
  101.  
  102.         BUG_ON(cmd != cmd_orig + cmd_size / sizeof(*cmd));
  103.  
  104.         vmw_fifo_commit(dev_priv, cmd_size);
  105.  
  106.         return 0;
  107. }
  108.  
  109. static void vmw_gmr2_unbind(struct vmw_private *dev_priv,
  110.                             int gmr_id)
  111. {
  112.         SVGAFifoCmdDefineGMR2 define_cmd;
  113.         uint32_t define_size = sizeof(define_cmd) + 4;
  114.         uint32_t *cmd;
  115.  
  116.         cmd = vmw_fifo_reserve(dev_priv, define_size);
  117.         if (unlikely(cmd == NULL)) {
  118.                 DRM_ERROR("GMR2 unbind failed.\n");
  119.                 return;
  120.         }
  121.         define_cmd.gmrId = gmr_id;
  122.         define_cmd.numPages = 0;
  123.  
  124.         *cmd++ = SVGA_CMD_DEFINE_GMR2;
  125.         memcpy(cmd, &define_cmd, sizeof(define_cmd));
  126.  
  127.         vmw_fifo_commit(dev_priv, define_size);
  128. }
  129.  
  130.  
  131. int vmw_gmr_bind(struct vmw_private *dev_priv,
  132.                  const struct vmw_sg_table *vsgt,
  133.                  unsigned long num_pages,
  134.                  int gmr_id)
  135. {
  136.         struct vmw_piter data_iter;
  137.  
  138.         vmw_piter_start(&data_iter, vsgt, 0);
  139.  
  140.         if (unlikely(!vmw_piter_next(&data_iter)))
  141.                 return 0;
  142.  
  143.         if (unlikely(!(dev_priv->capabilities & SVGA_CAP_GMR2)))
  144.     return -EINVAL;
  145.  
  146.         return vmw_gmr2_bind(dev_priv, &data_iter, num_pages, gmr_id);
  147. }
  148.  
  149.  
  150. void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id)
  151. {
  152.         if (likely(dev_priv->capabilities & SVGA_CAP_GMR2))
  153.                 vmw_gmr2_unbind(dev_priv, gmr_id);
  154. }
  155.