aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_kms.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_kms.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c187
1 files changed, 113 insertions, 74 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index c75cb2c6ba71..4f2d4f4c1dab 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -50,9 +50,13 @@ int radeon_driver_unload_kms(struct drm_device *dev)
50 50
51 if (rdev == NULL) 51 if (rdev == NULL)
52 return 0; 52 return 0;
53 if (rdev->rmmio == NULL)
54 goto done_free;
53 radeon_acpi_fini(rdev); 55 radeon_acpi_fini(rdev);
54 radeon_modeset_fini(rdev); 56 radeon_modeset_fini(rdev);
55 radeon_device_fini(rdev); 57 radeon_device_fini(rdev);
58
59done_free:
56 kfree(rdev); 60 kfree(rdev);
57 dev->dev_private = NULL; 61 dev->dev_private = NULL;
58 return 0; 62 return 0;
@@ -176,80 +180,65 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
176 struct radeon_device *rdev = dev->dev_private; 180 struct radeon_device *rdev = dev->dev_private;
177 struct drm_radeon_info *info = data; 181 struct drm_radeon_info *info = data;
178 struct radeon_mode_info *minfo = &rdev->mode_info; 182 struct radeon_mode_info *minfo = &rdev->mode_info;
179 uint32_t value, *value_ptr; 183 uint32_t *value, value_tmp, *value_ptr, value_size;
180 uint64_t value64, *value_ptr64; 184 uint64_t value64;
181 struct drm_crtc *crtc; 185 struct drm_crtc *crtc;
182 int i, found; 186 int i, found;
183 187
184 /* TIMESTAMP is a 64-bit value, needs special handling. */
185 if (info->request == RADEON_INFO_TIMESTAMP) {
186 if (rdev->family >= CHIP_R600) {
187 value_ptr64 = (uint64_t*)((unsigned long)info->value);
188 value64 = radeon_get_gpu_clock_counter(rdev);
189
190 if (DRM_COPY_TO_USER(value_ptr64, &value64, sizeof(value64))) {
191 DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__);
192 return -EFAULT;
193 }
194 return 0;
195 } else {
196 DRM_DEBUG_KMS("timestamp is r6xx+ only!\n");
197 return -EINVAL;
198 }
199 }
200
201 value_ptr = (uint32_t *)((unsigned long)info->value); 188 value_ptr = (uint32_t *)((unsigned long)info->value);
202 if (DRM_COPY_FROM_USER(&value, value_ptr, sizeof(value))) { 189 value = &value_tmp;
203 DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__); 190 value_size = sizeof(uint32_t);
204 return -EFAULT;
205 }
206 191
207 switch (info->request) { 192 switch (info->request) {
208 case RADEON_INFO_DEVICE_ID: 193 case RADEON_INFO_DEVICE_ID:
209 value = dev->pci_device; 194 *value = dev->pci_device;
210 break; 195 break;
211 case RADEON_INFO_NUM_GB_PIPES: 196 case RADEON_INFO_NUM_GB_PIPES:
212 value = rdev->num_gb_pipes; 197 *value = rdev->num_gb_pipes;
213 break; 198 break;
214 case RADEON_INFO_NUM_Z_PIPES: 199 case RADEON_INFO_NUM_Z_PIPES:
215 value = rdev->num_z_pipes; 200 *value = rdev->num_z_pipes;
216 break; 201 break;
217 case RADEON_INFO_ACCEL_WORKING: 202 case RADEON_INFO_ACCEL_WORKING:
218 /* xf86-video-ati 6.13.0 relies on this being false for evergreen */ 203 /* xf86-video-ati 6.13.0 relies on this being false for evergreen */
219 if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK)) 204 if ((rdev->family >= CHIP_CEDAR) && (rdev->family <= CHIP_HEMLOCK))
220 value = false; 205 *value = false;
221 else 206 else
222 value = rdev->accel_working; 207 *value = rdev->accel_working;
223 break; 208 break;
224 case RADEON_INFO_CRTC_FROM_ID: 209 case RADEON_INFO_CRTC_FROM_ID:
210 if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
211 DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
212 return -EFAULT;
213 }
225 for (i = 0, found = 0; i < rdev->num_crtc; i++) { 214 for (i = 0, found = 0; i < rdev->num_crtc; i++) {
226 crtc = (struct drm_crtc *)minfo->crtcs[i]; 215 crtc = (struct drm_crtc *)minfo->crtcs[i];
227 if (crtc && crtc->base.id == value) { 216 if (crtc && crtc->base.id == *value) {
228 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); 217 struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
229 value = radeon_crtc->crtc_id; 218 *value = radeon_crtc->crtc_id;
230 found = 1; 219 found = 1;
231 break; 220 break;
232 } 221 }
233 } 222 }
234 if (!found) { 223 if (!found) {
235 DRM_DEBUG_KMS("unknown crtc id %d\n", value); 224 DRM_DEBUG_KMS("unknown crtc id %d\n", *value);
236 return -EINVAL; 225 return -EINVAL;
237 } 226 }
238 break; 227 break;
239 case RADEON_INFO_ACCEL_WORKING2: 228 case RADEON_INFO_ACCEL_WORKING2:
240 value = rdev->accel_working; 229 *value = rdev->accel_working;
241 break; 230 break;
242 case RADEON_INFO_TILING_CONFIG: 231 case RADEON_INFO_TILING_CONFIG:
243 if (rdev->family >= CHIP_TAHITI) 232 if (rdev->family >= CHIP_TAHITI)
244 value = rdev->config.si.tile_config; 233 *value = rdev->config.si.tile_config;
245 else if (rdev->family >= CHIP_CAYMAN) 234 else if (rdev->family >= CHIP_CAYMAN)
246 value = rdev->config.cayman.tile_config; 235 *value = rdev->config.cayman.tile_config;
247 else if (rdev->family >= CHIP_CEDAR) 236 else if (rdev->family >= CHIP_CEDAR)
248 value = rdev->config.evergreen.tile_config; 237 *value = rdev->config.evergreen.tile_config;
249 else if (rdev->family >= CHIP_RV770) 238 else if (rdev->family >= CHIP_RV770)
250 value = rdev->config.rv770.tile_config; 239 *value = rdev->config.rv770.tile_config;
251 else if (rdev->family >= CHIP_R600) 240 else if (rdev->family >= CHIP_R600)
252 value = rdev->config.r600.tile_config; 241 *value = rdev->config.r600.tile_config;
253 else { 242 else {
254 DRM_DEBUG_KMS("tiling config is r6xx+ only!\n"); 243 DRM_DEBUG_KMS("tiling config is r6xx+ only!\n");
255 return -EINVAL; 244 return -EINVAL;
@@ -262,73 +251,81 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
262 * 251 *
263 * When returning, the value is 1 if filp owns hyper-z access, 252 * When returning, the value is 1 if filp owns hyper-z access,
264 * 0 otherwise. */ 253 * 0 otherwise. */
265 if (value >= 2) { 254 if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
266 DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", value); 255 DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
256 return -EFAULT;
257 }
258 if (*value >= 2) {
259 DRM_DEBUG_KMS("WANT_HYPERZ: invalid value %d\n", *value);
267 return -EINVAL; 260 return -EINVAL;
268 } 261 }
269 radeon_set_filp_rights(dev, &rdev->hyperz_filp, filp, &value); 262 radeon_set_filp_rights(dev, &rdev->hyperz_filp, filp, value);
270 break; 263 break;
271 case RADEON_INFO_WANT_CMASK: 264 case RADEON_INFO_WANT_CMASK:
272 /* The same logic as Hyper-Z. */ 265 /* The same logic as Hyper-Z. */
273 if (value >= 2) { 266 if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
274 DRM_DEBUG_KMS("WANT_CMASK: invalid value %d\n", value); 267 DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
268 return -EFAULT;
269 }
270 if (*value >= 2) {
271 DRM_DEBUG_KMS("WANT_CMASK: invalid value %d\n", *value);
275 return -EINVAL; 272 return -EINVAL;
276 } 273 }
277 radeon_set_filp_rights(dev, &rdev->cmask_filp, filp, &value); 274 radeon_set_filp_rights(dev, &rdev->cmask_filp, filp, value);
278 break; 275 break;
279 case RADEON_INFO_CLOCK_CRYSTAL_FREQ: 276 case RADEON_INFO_CLOCK_CRYSTAL_FREQ:
280 /* return clock value in KHz */ 277 /* return clock value in KHz */
281 if (rdev->asic->get_xclk) 278 if (rdev->asic->get_xclk)
282 value = radeon_get_xclk(rdev) * 10; 279 *value = radeon_get_xclk(rdev) * 10;
283 else 280 else
284 value = rdev->clock.spll.reference_freq * 10; 281 *value = rdev->clock.spll.reference_freq * 10;
285 break; 282 break;
286 case RADEON_INFO_NUM_BACKENDS: 283 case RADEON_INFO_NUM_BACKENDS:
287 if (rdev->family >= CHIP_TAHITI) 284 if (rdev->family >= CHIP_TAHITI)
288 value = rdev->config.si.max_backends_per_se * 285 *value = rdev->config.si.max_backends_per_se *
289 rdev->config.si.max_shader_engines; 286 rdev->config.si.max_shader_engines;
290 else if (rdev->family >= CHIP_CAYMAN) 287 else if (rdev->family >= CHIP_CAYMAN)
291 value = rdev->config.cayman.max_backends_per_se * 288 *value = rdev->config.cayman.max_backends_per_se *
292 rdev->config.cayman.max_shader_engines; 289 rdev->config.cayman.max_shader_engines;
293 else if (rdev->family >= CHIP_CEDAR) 290 else if (rdev->family >= CHIP_CEDAR)
294 value = rdev->config.evergreen.max_backends; 291 *value = rdev->config.evergreen.max_backends;
295 else if (rdev->family >= CHIP_RV770) 292 else if (rdev->family >= CHIP_RV770)
296 value = rdev->config.rv770.max_backends; 293 *value = rdev->config.rv770.max_backends;
297 else if (rdev->family >= CHIP_R600) 294 else if (rdev->family >= CHIP_R600)
298 value = rdev->config.r600.max_backends; 295 *value = rdev->config.r600.max_backends;
299 else { 296 else {
300 return -EINVAL; 297 return -EINVAL;
301 } 298 }
302 break; 299 break;
303 case RADEON_INFO_NUM_TILE_PIPES: 300 case RADEON_INFO_NUM_TILE_PIPES:
304 if (rdev->family >= CHIP_TAHITI) 301 if (rdev->family >= CHIP_TAHITI)
305 value = rdev->config.si.max_tile_pipes; 302 *value = rdev->config.si.max_tile_pipes;
306 else if (rdev->family >= CHIP_CAYMAN) 303 else if (rdev->family >= CHIP_CAYMAN)
307 value = rdev->config.cayman.max_tile_pipes; 304 *value = rdev->config.cayman.max_tile_pipes;
308 else if (rdev->family >= CHIP_CEDAR) 305 else if (rdev->family >= CHIP_CEDAR)
309 value = rdev->config.evergreen.max_tile_pipes; 306 *value = rdev->config.evergreen.max_tile_pipes;
310 else if (rdev->family >= CHIP_RV770) 307 else if (rdev->family >= CHIP_RV770)
311 value = rdev->config.rv770.max_tile_pipes; 308 *value = rdev->config.rv770.max_tile_pipes;
312 else if (rdev->family >= CHIP_R600) 309 else if (rdev->family >= CHIP_R600)
313 value = rdev->config.r600.max_tile_pipes; 310 *value = rdev->config.r600.max_tile_pipes;
314 else { 311 else {
315 return -EINVAL; 312 return -EINVAL;
316 } 313 }
317 break; 314 break;
318 case RADEON_INFO_FUSION_GART_WORKING: 315 case RADEON_INFO_FUSION_GART_WORKING:
319 value = 1; 316 *value = 1;
320 break; 317 break;
321 case RADEON_INFO_BACKEND_MAP: 318 case RADEON_INFO_BACKEND_MAP:
322 if (rdev->family >= CHIP_TAHITI) 319 if (rdev->family >= CHIP_TAHITI)
323 value = rdev->config.si.backend_map; 320 *value = rdev->config.si.backend_map;
324 else if (rdev->family >= CHIP_CAYMAN) 321 else if (rdev->family >= CHIP_CAYMAN)
325 value = rdev->config.cayman.backend_map; 322 *value = rdev->config.cayman.backend_map;
326 else if (rdev->family >= CHIP_CEDAR) 323 else if (rdev->family >= CHIP_CEDAR)
327 value = rdev->config.evergreen.backend_map; 324 *value = rdev->config.evergreen.backend_map;
328 else if (rdev->family >= CHIP_RV770) 325 else if (rdev->family >= CHIP_RV770)
329 value = rdev->config.rv770.backend_map; 326 *value = rdev->config.rv770.backend_map;
330 else if (rdev->family >= CHIP_R600) 327 else if (rdev->family >= CHIP_R600)
331 value = rdev->config.r600.backend_map; 328 *value = rdev->config.r600.backend_map;
332 else { 329 else {
333 return -EINVAL; 330 return -EINVAL;
334 } 331 }
@@ -337,50 +334,91 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
337 /* this is where we report if vm is supported or not */ 334 /* this is where we report if vm is supported or not */
338 if (rdev->family < CHIP_CAYMAN) 335 if (rdev->family < CHIP_CAYMAN)
339 return -EINVAL; 336 return -EINVAL;
340 value = RADEON_VA_RESERVED_SIZE; 337 *value = RADEON_VA_RESERVED_SIZE;
341 break; 338 break;
342 case RADEON_INFO_IB_VM_MAX_SIZE: 339 case RADEON_INFO_IB_VM_MAX_SIZE:
343 /* this is where we report if vm is supported or not */ 340 /* this is where we report if vm is supported or not */
344 if (rdev->family < CHIP_CAYMAN) 341 if (rdev->family < CHIP_CAYMAN)
345 return -EINVAL; 342 return -EINVAL;
346 value = RADEON_IB_VM_MAX_SIZE; 343 *value = RADEON_IB_VM_MAX_SIZE;
347 break; 344 break;
348 case RADEON_INFO_MAX_PIPES: 345 case RADEON_INFO_MAX_PIPES:
349 if (rdev->family >= CHIP_TAHITI) 346 if (rdev->family >= CHIP_TAHITI)
350 value = rdev->config.si.max_cu_per_sh; 347 *value = rdev->config.si.max_cu_per_sh;
351 else if (rdev->family >= CHIP_CAYMAN) 348 else if (rdev->family >= CHIP_CAYMAN)
352 value = rdev->config.cayman.max_pipes_per_simd; 349 *value = rdev->config.cayman.max_pipes_per_simd;
353 else if (rdev->family >= CHIP_CEDAR) 350 else if (rdev->family >= CHIP_CEDAR)
354 value = rdev->config.evergreen.max_pipes; 351 *value = rdev->config.evergreen.max_pipes;
355 else if (rdev->family >= CHIP_RV770) 352 else if (rdev->family >= CHIP_RV770)
356 value = rdev->config.rv770.max_pipes; 353 *value = rdev->config.rv770.max_pipes;
357 else if (rdev->family >= CHIP_R600) 354 else if (rdev->family >= CHIP_R600)
358 value = rdev->config.r600.max_pipes; 355 *value = rdev->config.r600.max_pipes;
359 else { 356 else {
360 return -EINVAL; 357 return -EINVAL;
361 } 358 }
362 break; 359 break;
360 case RADEON_INFO_TIMESTAMP:
361 if (rdev->family < CHIP_R600) {
362 DRM_DEBUG_KMS("timestamp is r6xx+ only!\n");
363 return -EINVAL;
364 }
365 value = (uint32_t*)&value64;
366 value_size = sizeof(uint64_t);
367 value64 = radeon_get_gpu_clock_counter(rdev);
368 break;
363 case RADEON_INFO_MAX_SE: 369 case RADEON_INFO_MAX_SE:
364 if (rdev->family >= CHIP_TAHITI) 370 if (rdev->family >= CHIP_TAHITI)
365 value = rdev->config.si.max_shader_engines; 371 *value = rdev->config.si.max_shader_engines;
366 else if (rdev->family >= CHIP_CAYMAN) 372 else if (rdev->family >= CHIP_CAYMAN)
367 value = rdev->config.cayman.max_shader_engines; 373 *value = rdev->config.cayman.max_shader_engines;
368 else if (rdev->family >= CHIP_CEDAR) 374 else if (rdev->family >= CHIP_CEDAR)
369 value = rdev->config.evergreen.num_ses; 375 *value = rdev->config.evergreen.num_ses;
370 else 376 else
371 value = 1; 377 *value = 1;
372 break; 378 break;
373 case RADEON_INFO_MAX_SH_PER_SE: 379 case RADEON_INFO_MAX_SH_PER_SE:
374 if (rdev->family >= CHIP_TAHITI) 380 if (rdev->family >= CHIP_TAHITI)
375 value = rdev->config.si.max_sh_per_se; 381 *value = rdev->config.si.max_sh_per_se;
376 else 382 else
377 return -EINVAL; 383 return -EINVAL;
378 break; 384 break;
385 case RADEON_INFO_FASTFB_WORKING:
386 *value = rdev->fastfb_working;
387 break;
388 case RADEON_INFO_RING_WORKING:
389 if (DRM_COPY_FROM_USER(value, value_ptr, sizeof(uint32_t))) {
390 DRM_ERROR("copy_from_user %s:%u\n", __func__, __LINE__);
391 return -EFAULT;
392 }
393 switch (*value) {
394 case RADEON_CS_RING_GFX:
395 case RADEON_CS_RING_COMPUTE:
396 *value = rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready;
397 break;
398 case RADEON_CS_RING_DMA:
399 *value = rdev->ring[R600_RING_TYPE_DMA_INDEX].ready;
400 *value |= rdev->ring[CAYMAN_RING_TYPE_DMA1_INDEX].ready;
401 break;
402 case RADEON_CS_RING_UVD:
403 *value = rdev->ring[R600_RING_TYPE_UVD_INDEX].ready;
404 break;
405 default:
406 return -EINVAL;
407 }
408 break;
409 case RADEON_INFO_SI_TILE_MODE_ARRAY:
410 if (rdev->family < CHIP_TAHITI) {
411 DRM_DEBUG_KMS("tile mode array is si only!\n");
412 return -EINVAL;
413 }
414 value = rdev->config.si.tile_mode_array;
415 value_size = sizeof(uint32_t)*32;
416 break;
379 default: 417 default:
380 DRM_DEBUG_KMS("Invalid request %d\n", info->request); 418 DRM_DEBUG_KMS("Invalid request %d\n", info->request);
381 return -EINVAL; 419 return -EINVAL;
382 } 420 }
383 if (DRM_COPY_TO_USER(value_ptr, &value, sizeof(uint32_t))) { 421 if (DRM_COPY_TO_USER(value_ptr, (char*)value, value_size)) {
384 DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__); 422 DRM_ERROR("copy_to_user %s:%u\n", __func__, __LINE__);
385 return -EFAULT; 423 return -EFAULT;
386 } 424 }
@@ -513,6 +551,7 @@ void radeon_driver_preclose_kms(struct drm_device *dev,
513 rdev->hyperz_filp = NULL; 551 rdev->hyperz_filp = NULL;
514 if (rdev->cmask_filp == file_priv) 552 if (rdev->cmask_filp == file_priv)
515 rdev->cmask_filp = NULL; 553 rdev->cmask_filp = NULL;
554 radeon_uvd_free_handles(rdev, file_priv);
516} 555}
517 556
518/* 557/*