diff options
author | Christian König <christian.koenig@amd.com> | 2014-05-27 10:49:22 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2014-06-02 10:25:13 -0400 |
commit | 1aab5514ca9604e0263f658a067da0189c86a35b (patch) | |
tree | f96125f31d9cd42d673ee2e6dcffbfcff9f37eed | |
parent | 1a0e79184132c5dc0e03a4047eacecc52c24deae (diff) |
drm/radeon: rework page flip handling v3
Instead of trying to flip inside the vblank period when
the buffer is idle, offload blocking for idle to a kernel
thread and program the flip directly into the hardware.
v2: add error handling, fix EBUSY handling
v3: add proper exclusive_lock handling
Signed-off-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 245 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_mode.h | 4 |
3 files changed, 150 insertions, 115 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 4ae304d7e932..736bfa2c7528 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -676,14 +676,16 @@ void radeon_doorbell_free(struct radeon_device *rdev, u32 doorbell); | |||
676 | * IRQS. | 676 | * IRQS. |
677 | */ | 677 | */ |
678 | 678 | ||
679 | struct radeon_unpin_work { | 679 | struct radeon_flip_work { |
680 | struct work_struct work; | 680 | struct work_struct flip_work; |
681 | struct radeon_device *rdev; | 681 | struct work_struct unpin_work; |
682 | int crtc_id; | 682 | struct radeon_device *rdev; |
683 | struct radeon_fence *fence; | 683 | int crtc_id; |
684 | struct drm_framebuffer *fb; | ||
684 | struct drm_pending_vblank_event *event; | 685 | struct drm_pending_vblank_event *event; |
685 | struct radeon_bo *old_rbo; | 686 | struct radeon_bo *old_rbo; |
686 | u64 new_crtc_base; | 687 | struct radeon_bo *new_rbo; |
688 | struct radeon_fence *fence; | ||
687 | }; | 689 | }; |
688 | 690 | ||
689 | struct r500_irq_stat_regs { | 691 | struct r500_irq_stat_regs { |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 88e3cbe11dad..6b3de5ca5bc7 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -249,16 +249,21 @@ static void radeon_crtc_destroy(struct drm_crtc *crtc) | |||
249 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 249 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
250 | 250 | ||
251 | drm_crtc_cleanup(crtc); | 251 | drm_crtc_cleanup(crtc); |
252 | destroy_workqueue(radeon_crtc->flip_queue); | ||
252 | kfree(radeon_crtc); | 253 | kfree(radeon_crtc); |
253 | } | 254 | } |
254 | 255 | ||
255 | /* | 256 | /** |
256 | * Handle unpin events outside the interrupt handler proper. | 257 | * radeon_unpin_work_func - unpin old buffer object |
258 | * | ||
259 | * @__work - kernel work item | ||
260 | * | ||
261 | * Unpin the old frame buffer object outside of the interrupt handler | ||
257 | */ | 262 | */ |
258 | static void radeon_unpin_work_func(struct work_struct *__work) | 263 | static void radeon_unpin_work_func(struct work_struct *__work) |
259 | { | 264 | { |
260 | struct radeon_unpin_work *work = | 265 | struct radeon_flip_work *work = |
261 | container_of(__work, struct radeon_unpin_work, work); | 266 | container_of(__work, struct radeon_flip_work, unpin_work); |
262 | int r; | 267 | int r; |
263 | 268 | ||
264 | /* unpin of the old buffer */ | 269 | /* unpin of the old buffer */ |
@@ -279,30 +284,19 @@ static void radeon_unpin_work_func(struct work_struct *__work) | |||
279 | void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) | 284 | void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) |
280 | { | 285 | { |
281 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; | 286 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; |
282 | struct radeon_unpin_work *work; | 287 | struct radeon_flip_work *work; |
283 | unsigned long flags; | 288 | unsigned long flags; |
284 | u32 update_pending; | 289 | u32 update_pending; |
285 | int vpos, hpos; | 290 | int vpos, hpos; |
286 | 291 | ||
287 | spin_lock_irqsave(&rdev->ddev->event_lock, flags); | 292 | spin_lock_irqsave(&rdev->ddev->event_lock, flags); |
288 | work = radeon_crtc->unpin_work; | 293 | work = radeon_crtc->flip_work; |
289 | if (work == NULL || | 294 | if (work == NULL) { |
290 | (work->fence && !radeon_fence_signaled(work->fence))) { | ||
291 | spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); | 295 | spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); |
292 | return; | 296 | return; |
293 | } | 297 | } |
294 | /* New pageflip, or just completion of a previous one? */ | 298 | |
295 | if (!radeon_crtc->deferred_flip_completion) { | 299 | update_pending = radeon_page_flip_pending(rdev, crtc_id); |
296 | /* do the flip (mmio) */ | ||
297 | radeon_page_flip(rdev, crtc_id, work->new_crtc_base); | ||
298 | update_pending = radeon_page_flip_pending(rdev, crtc_id); | ||
299 | } else { | ||
300 | /* This is just a completion of a flip queued in crtc | ||
301 | * at last invocation. Make sure we go directly to | ||
302 | * completion routine. | ||
303 | */ | ||
304 | update_pending = 0; | ||
305 | } | ||
306 | 300 | ||
307 | /* Has the pageflip already completed in crtc, or is it certain | 301 | /* Has the pageflip already completed in crtc, or is it certain |
308 | * to complete in this vblank? | 302 | * to complete in this vblank? |
@@ -320,19 +314,9 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) | |||
320 | */ | 314 | */ |
321 | update_pending = 0; | 315 | update_pending = 0; |
322 | } | 316 | } |
323 | if (update_pending) { | 317 | spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); |
324 | /* crtc didn't flip in this target vblank interval, | 318 | if (!update_pending) |
325 | * but flip is pending in crtc. It will complete it | ||
326 | * in next vblank interval, so complete the flip at | ||
327 | * next vblank irq. | ||
328 | */ | ||
329 | radeon_crtc->deferred_flip_completion = 1; | ||
330 | spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); | ||
331 | return; | ||
332 | } else { | ||
333 | spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); | ||
334 | radeon_crtc_handle_flip(rdev, crtc_id); | 319 | radeon_crtc_handle_flip(rdev, crtc_id); |
335 | } | ||
336 | } | 320 | } |
337 | 321 | ||
338 | /** | 322 | /** |
@@ -346,7 +330,7 @@ void radeon_crtc_handle_vblank(struct radeon_device *rdev, int crtc_id) | |||
346 | void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) | 330 | void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) |
347 | { | 331 | { |
348 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; | 332 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; |
349 | struct radeon_unpin_work *work; | 333 | struct radeon_flip_work *work; |
350 | unsigned long flags; | 334 | unsigned long flags; |
351 | 335 | ||
352 | /* this can happen at init */ | 336 | /* this can happen at init */ |
@@ -354,15 +338,14 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) | |||
354 | return; | 338 | return; |
355 | 339 | ||
356 | spin_lock_irqsave(&rdev->ddev->event_lock, flags); | 340 | spin_lock_irqsave(&rdev->ddev->event_lock, flags); |
357 | work = radeon_crtc->unpin_work; | 341 | work = radeon_crtc->flip_work; |
358 | if (work == NULL) { | 342 | if (work == NULL) { |
359 | spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); | 343 | spin_unlock_irqrestore(&rdev->ddev->event_lock, flags); |
360 | return; | 344 | return; |
361 | } | 345 | } |
362 | 346 | ||
363 | /* Pageflip (will be) certainly completed in this vblank. Clean up. */ | 347 | /* Pageflip completed. Clean up. */ |
364 | radeon_crtc->unpin_work = NULL; | 348 | radeon_crtc->flip_work = NULL; |
365 | radeon_crtc->deferred_flip_completion = 0; | ||
366 | 349 | ||
367 | /* wakeup userspace */ | 350 | /* wakeup userspace */ |
368 | if (work->event) | 351 | if (work->event) |
@@ -372,83 +355,69 @@ void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id) | |||
372 | 355 | ||
373 | radeon_fence_unref(&work->fence); | 356 | radeon_fence_unref(&work->fence); |
374 | radeon_irq_kms_pflip_irq_get(rdev, work->crtc_id); | 357 | radeon_irq_kms_pflip_irq_get(rdev, work->crtc_id); |
375 | schedule_work(&work->work); | 358 | queue_work(radeon_crtc->flip_queue, &work->unpin_work); |
376 | } | 359 | } |
377 | 360 | ||
378 | static int radeon_crtc_page_flip(struct drm_crtc *crtc, | 361 | /** |
379 | struct drm_framebuffer *fb, | 362 | * radeon_flip_work_func - page flip framebuffer |
380 | struct drm_pending_vblank_event *event, | 363 | * |
381 | uint32_t page_flip_flags) | 364 | * @work - kernel work item |
365 | * | ||
366 | * Wait for the buffer object to become idle and do the actual page flip | ||
367 | */ | ||
368 | static void radeon_flip_work_func(struct work_struct *__work) | ||
382 | { | 369 | { |
383 | struct drm_device *dev = crtc->dev; | 370 | struct radeon_flip_work *work = |
384 | struct radeon_device *rdev = dev->dev_private; | 371 | container_of(__work, struct radeon_flip_work, flip_work); |
385 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 372 | struct radeon_device *rdev = work->rdev; |
386 | struct radeon_framebuffer *old_radeon_fb; | 373 | struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[work->crtc_id]; |
387 | struct radeon_framebuffer *new_radeon_fb; | ||
388 | struct drm_gem_object *obj; | ||
389 | struct radeon_bo *rbo; | ||
390 | struct radeon_unpin_work *work; | ||
391 | unsigned long flags; | ||
392 | u32 tiling_flags, pitch_pixels; | ||
393 | u64 base; | ||
394 | int r; | ||
395 | 374 | ||
396 | work = kzalloc(sizeof *work, GFP_KERNEL); | 375 | struct drm_crtc *crtc = &radeon_crtc->base; |
397 | if (work == NULL) | 376 | struct drm_framebuffer *fb = work->fb; |
398 | return -ENOMEM; | ||
399 | 377 | ||
400 | work->event = event; | 378 | uint32_t tiling_flags, pitch_pixels; |
401 | work->rdev = rdev; | 379 | uint64_t base; |
402 | work->crtc_id = radeon_crtc->crtc_id; | ||
403 | old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb); | ||
404 | new_radeon_fb = to_radeon_framebuffer(fb); | ||
405 | /* schedule unpin of the old buffer */ | ||
406 | obj = old_radeon_fb->obj; | ||
407 | /* take a reference to the old object */ | ||
408 | drm_gem_object_reference(obj); | ||
409 | rbo = gem_to_radeon_bo(obj); | ||
410 | work->old_rbo = rbo; | ||
411 | obj = new_radeon_fb->obj; | ||
412 | rbo = gem_to_radeon_bo(obj); | ||
413 | 380 | ||
414 | spin_lock(&rbo->tbo.bdev->fence_lock); | 381 | unsigned long flags; |
415 | if (rbo->tbo.sync_obj) | 382 | int r; |
416 | work->fence = radeon_fence_ref(rbo->tbo.sync_obj); | ||
417 | spin_unlock(&rbo->tbo.bdev->fence_lock); | ||
418 | 383 | ||
419 | INIT_WORK(&work->work, radeon_unpin_work_func); | 384 | down_read(&rdev->exclusive_lock); |
385 | while (work->fence) { | ||
386 | r = radeon_fence_wait(work->fence, false); | ||
387 | if (r == -EDEADLK) { | ||
388 | up_read(&rdev->exclusive_lock); | ||
389 | r = radeon_gpu_reset(rdev); | ||
390 | down_read(&rdev->exclusive_lock); | ||
391 | } | ||
420 | 392 | ||
421 | /* We borrow the event spin lock for protecting unpin_work */ | 393 | if (r) { |
422 | spin_lock_irqsave(&dev->event_lock, flags); | 394 | DRM_ERROR("failed to wait on page flip fence (%d)!\n", |
423 | if (radeon_crtc->unpin_work) { | 395 | r); |
424 | DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); | 396 | goto cleanup; |
425 | r = -EBUSY; | 397 | } else |
426 | goto unlock_free; | 398 | radeon_fence_unref(&work->fence); |
427 | } | 399 | } |
428 | radeon_crtc->unpin_work = work; | ||
429 | radeon_crtc->deferred_flip_completion = 0; | ||
430 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
431 | 400 | ||
432 | /* pin the new buffer */ | 401 | /* pin the new buffer */ |
433 | DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n", | 402 | DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n", |
434 | work->old_rbo, rbo); | 403 | work->old_rbo, work->new_rbo); |
435 | 404 | ||
436 | r = radeon_bo_reserve(rbo, false); | 405 | r = radeon_bo_reserve(work->new_rbo, false); |
437 | if (unlikely(r != 0)) { | 406 | if (unlikely(r != 0)) { |
438 | DRM_ERROR("failed to reserve new rbo buffer before flip\n"); | 407 | DRM_ERROR("failed to reserve new rbo buffer before flip\n"); |
439 | goto pflip_cleanup; | 408 | goto cleanup; |
440 | } | 409 | } |
441 | /* Only 27 bit offset for legacy CRTC */ | 410 | /* Only 27 bit offset for legacy CRTC */ |
442 | r = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM, | 411 | r = radeon_bo_pin_restricted(work->new_rbo, RADEON_GEM_DOMAIN_VRAM, |
443 | ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, &base); | 412 | ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, &base); |
444 | if (unlikely(r != 0)) { | 413 | if (unlikely(r != 0)) { |
445 | radeon_bo_unreserve(rbo); | 414 | radeon_bo_unreserve(work->new_rbo); |
446 | r = -EINVAL; | 415 | r = -EINVAL; |
447 | DRM_ERROR("failed to pin new rbo buffer before flip\n"); | 416 | DRM_ERROR("failed to pin new rbo buffer before flip\n"); |
448 | goto pflip_cleanup; | 417 | goto cleanup; |
449 | } | 418 | } |
450 | radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); | 419 | radeon_bo_get_tiling_flags(work->new_rbo, &tiling_flags, NULL); |
451 | radeon_bo_unreserve(rbo); | 420 | radeon_bo_unreserve(work->new_rbo); |
452 | 421 | ||
453 | if (!ASIC_IS_AVIVO(rdev)) { | 422 | if (!ASIC_IS_AVIVO(rdev)) { |
454 | /* crtc offset is from display base addr not FB location */ | 423 | /* crtc offset is from display base addr not FB location */ |
@@ -486,28 +455,91 @@ static int radeon_crtc_page_flip(struct drm_crtc *crtc, | |||
486 | base &= ~7; | 455 | base &= ~7; |
487 | } | 456 | } |
488 | 457 | ||
489 | spin_lock_irqsave(&dev->event_lock, flags); | 458 | /* We borrow the event spin lock for protecting flip_work */ |
490 | work->new_crtc_base = base; | 459 | spin_lock_irqsave(&crtc->dev->event_lock, flags); |
491 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
492 | |||
493 | /* update crtc fb */ | ||
494 | crtc->primary->fb = fb; | ||
495 | 460 | ||
496 | /* set the proper interrupt */ | 461 | /* set the proper interrupt */ |
497 | radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id); | 462 | radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id); |
498 | 463 | ||
499 | return 0; | 464 | /* do the flip (mmio) */ |
465 | radeon_page_flip(rdev, radeon_crtc->crtc_id, base); | ||
500 | 466 | ||
501 | pflip_cleanup: | 467 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); |
502 | spin_lock_irqsave(&dev->event_lock, flags); | 468 | up_read(&rdev->exclusive_lock); |
503 | radeon_crtc->unpin_work = NULL; | 469 | |
504 | unlock_free: | 470 | return; |
505 | spin_unlock_irqrestore(&dev->event_lock, flags); | 471 | |
506 | drm_gem_object_unreference_unlocked(old_radeon_fb->obj); | 472 | cleanup: |
473 | drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); | ||
507 | radeon_fence_unref(&work->fence); | 474 | radeon_fence_unref(&work->fence); |
508 | kfree(work); | 475 | kfree(work); |
476 | up_read(&rdev->exclusive_lock); | ||
477 | } | ||
478 | |||
479 | static int radeon_crtc_page_flip(struct drm_crtc *crtc, | ||
480 | struct drm_framebuffer *fb, | ||
481 | struct drm_pending_vblank_event *event, | ||
482 | uint32_t page_flip_flags) | ||
483 | { | ||
484 | struct drm_device *dev = crtc->dev; | ||
485 | struct radeon_device *rdev = dev->dev_private; | ||
486 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
487 | struct radeon_framebuffer *old_radeon_fb; | ||
488 | struct radeon_framebuffer *new_radeon_fb; | ||
489 | struct drm_gem_object *obj; | ||
490 | struct radeon_flip_work *work; | ||
491 | unsigned long flags; | ||
492 | |||
493 | work = kzalloc(sizeof *work, GFP_KERNEL); | ||
494 | if (work == NULL) | ||
495 | return -ENOMEM; | ||
496 | |||
497 | INIT_WORK(&work->flip_work, radeon_flip_work_func); | ||
498 | INIT_WORK(&work->unpin_work, radeon_unpin_work_func); | ||
509 | 499 | ||
510 | return r; | 500 | work->rdev = rdev; |
501 | work->crtc_id = radeon_crtc->crtc_id; | ||
502 | work->fb = fb; | ||
503 | work->event = event; | ||
504 | |||
505 | /* schedule unpin of the old buffer */ | ||
506 | old_radeon_fb = to_radeon_framebuffer(crtc->primary->fb); | ||
507 | obj = old_radeon_fb->obj; | ||
508 | |||
509 | /* take a reference to the old object */ | ||
510 | drm_gem_object_reference(obj); | ||
511 | work->old_rbo = gem_to_radeon_bo(obj); | ||
512 | |||
513 | new_radeon_fb = to_radeon_framebuffer(fb); | ||
514 | obj = new_radeon_fb->obj; | ||
515 | work->new_rbo = gem_to_radeon_bo(obj); | ||
516 | |||
517 | spin_lock(&work->new_rbo->tbo.bdev->fence_lock); | ||
518 | if (work->new_rbo->tbo.sync_obj) | ||
519 | work->fence = radeon_fence_ref(work->new_rbo->tbo.sync_obj); | ||
520 | spin_unlock(&work->new_rbo->tbo.bdev->fence_lock); | ||
521 | |||
522 | /* update crtc fb */ | ||
523 | crtc->primary->fb = fb; | ||
524 | |||
525 | /* We borrow the event spin lock for protecting flip_work */ | ||
526 | spin_lock_irqsave(&crtc->dev->event_lock, flags); | ||
527 | |||
528 | if (radeon_crtc->flip_work) { | ||
529 | DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); | ||
530 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | ||
531 | drm_gem_object_unreference_unlocked(&work->old_rbo->gem_base); | ||
532 | radeon_fence_unref(&work->fence); | ||
533 | kfree(work); | ||
534 | return -EBUSY; | ||
535 | } | ||
536 | radeon_crtc->flip_work = work; | ||
537 | |||
538 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | ||
539 | |||
540 | queue_work(radeon_crtc->flip_queue, &work->flip_work); | ||
541 | |||
542 | return 0; | ||
511 | } | 543 | } |
512 | 544 | ||
513 | static int | 545 | static int |
@@ -577,6 +609,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index) | |||
577 | 609 | ||
578 | drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); | 610 | drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); |
579 | radeon_crtc->crtc_id = index; | 611 | radeon_crtc->crtc_id = index; |
612 | radeon_crtc->flip_queue = create_singlethread_workqueue("radeon-crtc"); | ||
580 | rdev->mode_info.crtcs[index] = radeon_crtc; | 613 | rdev->mode_info.crtcs[index] = radeon_crtc; |
581 | 614 | ||
582 | if (rdev->family >= CHIP_BONAIRE) { | 615 | if (rdev->family >= CHIP_BONAIRE) { |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 718be1a932ac..ea72ad889a11 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -325,8 +325,8 @@ struct radeon_crtc { | |||
325 | struct drm_display_mode native_mode; | 325 | struct drm_display_mode native_mode; |
326 | int pll_id; | 326 | int pll_id; |
327 | /* page flipping */ | 327 | /* page flipping */ |
328 | struct radeon_unpin_work *unpin_work; | 328 | struct workqueue_struct *flip_queue; |
329 | int deferred_flip_completion; | 329 | struct radeon_flip_work *flip_work; |
330 | /* pll sharing */ | 330 | /* pll sharing */ |
331 | struct radeon_atom_ss ss; | 331 | struct radeon_atom_ss ss; |
332 | bool ss_enabled; | 332 | bool ss_enabled; |