aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c93
1 files changed, 77 insertions, 16 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
index 116c49736763..f9881f9e62bd 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -29,12 +29,18 @@
29#include <drm/vmwgfx_drm.h> 29#include <drm/vmwgfx_drm.h>
30#include "vmwgfx_kms.h" 30#include "vmwgfx_kms.h"
31 31
32struct svga_3d_compat_cap {
33 SVGA3dCapsRecordHeader header;
34 SVGA3dCapPair pairs[SVGA3D_DEVCAP_MAX];
35};
36
32int vmw_getparam_ioctl(struct drm_device *dev, void *data, 37int vmw_getparam_ioctl(struct drm_device *dev, void *data,
33 struct drm_file *file_priv) 38 struct drm_file *file_priv)
34{ 39{
35 struct vmw_private *dev_priv = vmw_priv(dev); 40 struct vmw_private *dev_priv = vmw_priv(dev);
36 struct drm_vmw_getparam_arg *param = 41 struct drm_vmw_getparam_arg *param =
37 (struct drm_vmw_getparam_arg *)data; 42 (struct drm_vmw_getparam_arg *)data;
43 struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
38 44
39 switch (param->param) { 45 switch (param->param) {
40 case DRM_VMW_PARAM_NUM_STREAMS: 46 case DRM_VMW_PARAM_NUM_STREAMS:
@@ -60,6 +66,11 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
60 __le32 __iomem *fifo_mem = dev_priv->mmio_virt; 66 __le32 __iomem *fifo_mem = dev_priv->mmio_virt;
61 const struct vmw_fifo_state *fifo = &dev_priv->fifo; 67 const struct vmw_fifo_state *fifo = &dev_priv->fifo;
62 68
69 if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS)) {
70 param->value = SVGA3D_HWVERSION_WS8_B1;
71 break;
72 }
73
63 param->value = 74 param->value =
64 ioread32(fifo_mem + 75 ioread32(fifo_mem +
65 ((fifo->capabilities & 76 ((fifo->capabilities &
@@ -69,17 +80,26 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
69 break; 80 break;
70 } 81 }
71 case DRM_VMW_PARAM_MAX_SURF_MEMORY: 82 case DRM_VMW_PARAM_MAX_SURF_MEMORY:
72 param->value = dev_priv->memory_size; 83 if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS) &&
84 !vmw_fp->gb_aware)
85 param->value = dev_priv->max_mob_pages * PAGE_SIZE / 2;
86 else
87 param->value = dev_priv->memory_size;
73 break; 88 break;
74 case DRM_VMW_PARAM_3D_CAPS_SIZE: 89 case DRM_VMW_PARAM_3D_CAPS_SIZE:
75 if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS) 90 if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS) &&
76 param->value = SVGA3D_DEVCAP_MAX; 91 vmw_fp->gb_aware)
92 param->value = SVGA3D_DEVCAP_MAX * sizeof(uint32_t);
93 else if (dev_priv->capabilities & SVGA_CAP_GBOBJECTS)
94 param->value = sizeof(struct svga_3d_compat_cap) +
95 sizeof(uint32_t);
77 else 96 else
78 param->value = (SVGA_FIFO_3D_CAPS_LAST - 97 param->value = (SVGA_FIFO_3D_CAPS_LAST -
79 SVGA_FIFO_3D_CAPS + 1); 98 SVGA_FIFO_3D_CAPS + 1) *
80 param->value *= sizeof(uint32_t); 99 sizeof(uint32_t);
81 break; 100 break;
82 case DRM_VMW_PARAM_MAX_MOB_MEMORY: 101 case DRM_VMW_PARAM_MAX_MOB_MEMORY:
102 vmw_fp->gb_aware = true;
83 param->value = dev_priv->max_mob_pages * PAGE_SIZE; 103 param->value = dev_priv->max_mob_pages * PAGE_SIZE;
84 break; 104 break;
85 default: 105 default:
@@ -91,6 +111,38 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data,
91 return 0; 111 return 0;
92} 112}
93 113
114static int vmw_fill_compat_cap(struct vmw_private *dev_priv, void *bounce,
115 size_t size)
116{
117 struct svga_3d_compat_cap *compat_cap =
118 (struct svga_3d_compat_cap *) bounce;
119 unsigned int i;
120 size_t pair_offset = offsetof(struct svga_3d_compat_cap, pairs);
121 unsigned int max_size;
122
123 if (size < pair_offset)
124 return -EINVAL;
125
126 max_size = (size - pair_offset) / sizeof(SVGA3dCapPair);
127
128 if (max_size > SVGA3D_DEVCAP_MAX)
129 max_size = SVGA3D_DEVCAP_MAX;
130
131 compat_cap->header.length =
132 (pair_offset + max_size * sizeof(SVGA3dCapPair)) / sizeof(u32);
133 compat_cap->header.type = SVGA3DCAPS_RECORD_DEVCAPS;
134
135 mutex_lock(&dev_priv->hw_mutex);
136 for (i = 0; i < max_size; ++i) {
137 vmw_write(dev_priv, SVGA_REG_DEV_CAP, i);
138 compat_cap->pairs[i][0] = i;
139 compat_cap->pairs[i][1] = vmw_read(dev_priv, SVGA_REG_DEV_CAP);
140 }
141 mutex_unlock(&dev_priv->hw_mutex);
142
143 return 0;
144}
145
94 146
95int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data, 147int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
96 struct drm_file *file_priv) 148 struct drm_file *file_priv)
@@ -104,41 +156,49 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
104 void *bounce; 156 void *bounce;
105 int ret; 157 int ret;
106 bool gb_objects = !!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS); 158 bool gb_objects = !!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS);
159 struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
107 160
108 if (unlikely(arg->pad64 != 0)) { 161 if (unlikely(arg->pad64 != 0)) {
109 DRM_ERROR("Illegal GET_3D_CAP argument.\n"); 162 DRM_ERROR("Illegal GET_3D_CAP argument.\n");
110 return -EINVAL; 163 return -EINVAL;
111 } 164 }
112 165
113 if (gb_objects) 166 if (gb_objects && vmw_fp->gb_aware)
114 size = SVGA3D_DEVCAP_MAX; 167 size = SVGA3D_DEVCAP_MAX * sizeof(uint32_t);
168 else if (gb_objects)
169 size = sizeof(struct svga_3d_compat_cap) + sizeof(uint32_t);
115 else 170 else
116 size = (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1); 171 size = (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1) *
117 172 sizeof(uint32_t);
118 size *= sizeof(uint32_t);
119 173
120 if (arg->max_size < size) 174 if (arg->max_size < size)
121 size = arg->max_size; 175 size = arg->max_size;
122 176
123 bounce = vmalloc(size); 177 bounce = vzalloc(size);
124 if (unlikely(bounce == NULL)) { 178 if (unlikely(bounce == NULL)) {
125 DRM_ERROR("Failed to allocate bounce buffer for 3D caps.\n"); 179 DRM_ERROR("Failed to allocate bounce buffer for 3D caps.\n");
126 return -ENOMEM; 180 return -ENOMEM;
127 } 181 }
128 182
129 if (gb_objects) { 183 if (gb_objects && vmw_fp->gb_aware) {
130 int i; 184 int i, num;
131 uint32_t *bounce32 = (uint32_t *) bounce; 185 uint32_t *bounce32 = (uint32_t *) bounce;
132 186
187 num = size / sizeof(uint32_t);
188 if (num > SVGA3D_DEVCAP_MAX)
189 num = SVGA3D_DEVCAP_MAX;
190
133 mutex_lock(&dev_priv->hw_mutex); 191 mutex_lock(&dev_priv->hw_mutex);
134 for (i = 0; i < SVGA3D_DEVCAP_MAX; ++i) { 192 for (i = 0; i < num; ++i) {
135 vmw_write(dev_priv, SVGA_REG_DEV_CAP, i); 193 vmw_write(dev_priv, SVGA_REG_DEV_CAP, i);
136 *bounce32++ = vmw_read(dev_priv, SVGA_REG_DEV_CAP); 194 *bounce32++ = vmw_read(dev_priv, SVGA_REG_DEV_CAP);
137 } 195 }
138 mutex_unlock(&dev_priv->hw_mutex); 196 mutex_unlock(&dev_priv->hw_mutex);
139 197 } else if (gb_objects) {
198 ret = vmw_fill_compat_cap(dev_priv, bounce, size);
199 if (unlikely(ret != 0))
200 goto out_err;
140 } else { 201 } else {
141
142 fifo_mem = dev_priv->mmio_virt; 202 fifo_mem = dev_priv->mmio_virt;
143 memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size); 203 memcpy_fromio(bounce, &fifo_mem[SVGA_FIFO_3D_CAPS], size);
144 } 204 }
@@ -146,6 +206,7 @@ int vmw_get_cap_3d_ioctl(struct drm_device *dev, void *data,
146 ret = copy_to_user(buffer, bounce, size); 206 ret = copy_to_user(buffer, bounce, size);
147 if (ret) 207 if (ret)
148 ret = -EFAULT; 208 ret = -EFAULT;
209out_err:
149 vfree(bounce); 210 vfree(bounce);
150 211
151 if (unlikely(ret != 0)) 212 if (unlikely(ret != 0))