Subversion Repositories Kolibri OS

Rev

Rev 4569 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  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.  
  38. static 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.  
  106. static 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.  
  128. int 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.  
  147. void 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. }
  152.