diff options
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c')
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c | 81 |
1 files changed, 80 insertions, 1 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c index de0c5948521d..f4e7763a7694 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /************************************************************************** | 1 | /************************************************************************** |
2 | * | 2 | * |
3 | * Copyright © 2009 VMware, Inc., Palo Alto, CA., USA | 3 | * Copyright © 2009-2011 VMware, Inc., Palo Alto, CA., USA |
4 | * All Rights Reserved. | 4 | * All Rights Reserved. |
5 | * | 5 | * |
6 | * Permission is hereby granted, free of charge, to any person obtaining a | 6 | * Permission is hereby granted, free of charge, to any person obtaining a |
@@ -29,6 +29,77 @@ | |||
29 | #include "drmP.h" | 29 | #include "drmP.h" |
30 | #include "ttm/ttm_bo_driver.h" | 30 | #include "ttm/ttm_bo_driver.h" |
31 | 31 | ||
32 | #define VMW_PPN_SIZE sizeof(unsigned long) | ||
33 | |||
34 | static int vmw_gmr2_bind(struct vmw_private *dev_priv, | ||
35 | struct page *pages[], | ||
36 | unsigned long num_pages, | ||
37 | int gmr_id) | ||
38 | { | ||
39 | SVGAFifoCmdDefineGMR2 define_cmd; | ||
40 | SVGAFifoCmdRemapGMR2 remap_cmd; | ||
41 | uint32_t define_size = sizeof(define_cmd) + 4; | ||
42 | uint32_t remap_size = VMW_PPN_SIZE * num_pages + sizeof(remap_cmd) + 4; | ||
43 | uint32_t *cmd; | ||
44 | uint32_t *cmd_orig; | ||
45 | uint32_t i; | ||
46 | |||
47 | cmd_orig = cmd = vmw_fifo_reserve(dev_priv, define_size + remap_size); | ||
48 | if (unlikely(cmd == NULL)) | ||
49 | return -ENOMEM; | ||
50 | |||
51 | define_cmd.gmrId = gmr_id; | ||
52 | define_cmd.numPages = num_pages; | ||
53 | |||
54 | remap_cmd.gmrId = gmr_id; | ||
55 | remap_cmd.flags = (VMW_PPN_SIZE > sizeof(*cmd)) ? | ||
56 | SVGA_REMAP_GMR2_PPN64 : SVGA_REMAP_GMR2_PPN32; | ||
57 | remap_cmd.offsetPages = 0; | ||
58 | remap_cmd.numPages = num_pages; | ||
59 | |||
60 | *cmd++ = SVGA_CMD_DEFINE_GMR2; | ||
61 | memcpy(cmd, &define_cmd, sizeof(define_cmd)); | ||
62 | cmd += sizeof(define_cmd) / sizeof(uint32); | ||
63 | |||
64 | *cmd++ = SVGA_CMD_REMAP_GMR2; | ||
65 | memcpy(cmd, &remap_cmd, sizeof(remap_cmd)); | ||
66 | cmd += sizeof(remap_cmd) / sizeof(uint32); | ||
67 | |||
68 | for (i = 0; i < num_pages; ++i) { | ||
69 | if (VMW_PPN_SIZE > 4) | ||
70 | *cmd = page_to_pfn(*pages++); | ||
71 | else | ||
72 | *((uint64_t *)cmd) = page_to_pfn(*pages++); | ||
73 | |||
74 | cmd += VMW_PPN_SIZE / sizeof(*cmd); | ||
75 | } | ||
76 | |||
77 | vmw_fifo_commit(dev_priv, define_size + remap_size); | ||
78 | |||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static void vmw_gmr2_unbind(struct vmw_private *dev_priv, | ||
83 | int gmr_id) | ||
84 | { | ||
85 | SVGAFifoCmdDefineGMR2 define_cmd; | ||
86 | uint32_t define_size = sizeof(define_cmd) + 4; | ||
87 | uint32_t *cmd; | ||
88 | |||
89 | cmd = vmw_fifo_reserve(dev_priv, define_size); | ||
90 | if (unlikely(cmd == NULL)) { | ||
91 | DRM_ERROR("GMR2 unbind failed.\n"); | ||
92 | return; | ||
93 | } | ||
94 | define_cmd.gmrId = gmr_id; | ||
95 | define_cmd.numPages = 0; | ||
96 | |||
97 | *cmd++ = SVGA_CMD_DEFINE_GMR2; | ||
98 | memcpy(cmd, &define_cmd, sizeof(define_cmd)); | ||
99 | |||
100 | vmw_fifo_commit(dev_priv, define_size); | ||
101 | } | ||
102 | |||
32 | /** | 103 | /** |
33 | * FIXME: Adjust to the ttm lowmem / highmem storage to minimize | 104 | * FIXME: Adjust to the ttm lowmem / highmem storage to minimize |
34 | * the number of used descriptors. | 105 | * the number of used descriptors. |
@@ -170,6 +241,9 @@ int vmw_gmr_bind(struct vmw_private *dev_priv, | |||
170 | struct list_head desc_pages; | 241 | struct list_head desc_pages; |
171 | int ret; | 242 | int ret; |
172 | 243 | ||
244 | if (likely(dev_priv->capabilities & SVGA_CAP_GMR2)) | ||
245 | return vmw_gmr2_bind(dev_priv, pages, num_pages, gmr_id); | ||
246 | |||
173 | if (unlikely(!(dev_priv->capabilities & SVGA_CAP_GMR))) | 247 | if (unlikely(!(dev_priv->capabilities & SVGA_CAP_GMR))) |
174 | return -EINVAL; | 248 | return -EINVAL; |
175 | 249 | ||
@@ -192,6 +266,11 @@ int vmw_gmr_bind(struct vmw_private *dev_priv, | |||
192 | 266 | ||
193 | void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id) | 267 | void vmw_gmr_unbind(struct vmw_private *dev_priv, int gmr_id) |
194 | { | 268 | { |
269 | if (likely(dev_priv->capabilities & SVGA_CAP_GMR2)) { | ||
270 | vmw_gmr2_unbind(dev_priv, gmr_id); | ||
271 | return; | ||
272 | } | ||
273 | |||
195 | mutex_lock(&dev_priv->hw_mutex); | 274 | mutex_lock(&dev_priv->hw_mutex); |
196 | vmw_write(dev_priv, SVGA_REG_GMR_ID, gmr_id); | 275 | vmw_write(dev_priv, SVGA_REG_GMR_ID, gmr_id); |
197 | wmb(); | 276 | wmb(); |