@@ -516,11 +516,27 @@ static void clean_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num)
516
516
port -> dpcd = NULL ;
517
517
}
518
518
519
+ static enum hrtimer_restart vblank_timer_fn (struct hrtimer * data )
520
+ {
521
+ struct intel_vgpu_vblank_timer * vblank_timer ;
522
+ struct intel_vgpu * vgpu ;
523
+
524
+ vblank_timer = container_of (data , struct intel_vgpu_vblank_timer , timer );
525
+ vgpu = container_of (vblank_timer , struct intel_vgpu , vblank_timer );
526
+
527
+ /* Set vblank emulation request per-vGPU bit */
528
+ intel_gvt_request_service (vgpu -> gvt ,
529
+ INTEL_GVT_REQUEST_EMULATE_VBLANK + vgpu -> id );
530
+ hrtimer_add_expires_ns (& vblank_timer -> timer , vblank_timer -> period );
531
+ return HRTIMER_RESTART ;
532
+ }
533
+
519
534
static int setup_virtual_dp_monitor (struct intel_vgpu * vgpu , int port_num ,
520
535
int type , unsigned int resolution )
521
536
{
522
537
struct drm_i915_private * i915 = vgpu -> gvt -> gt -> i915 ;
523
538
struct intel_vgpu_port * port = intel_vgpu_port (vgpu , port_num );
539
+ struct intel_vgpu_vblank_timer * vblank_timer = & vgpu -> vblank_timer ;
524
540
525
541
if (drm_WARN_ON (& i915 -> drm , resolution >= GVT_EDID_NUM ))
526
542
return - EINVAL ;
@@ -544,48 +560,59 @@ static int setup_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num,
544
560
port -> dpcd -> data [DPCD_SINK_COUNT ] = 0x1 ;
545
561
port -> type = type ;
546
562
port -> id = resolution ;
563
+ port -> vrefresh_k = GVT_DEFAULT_REFRESH_RATE * MSEC_PER_SEC ;
564
+ vgpu -> display .port_num = port_num ;
565
+
566
+ /* Init hrtimer based on default refresh rate */
567
+ hrtimer_init (& vblank_timer -> timer , CLOCK_MONOTONIC , HRTIMER_MODE_ABS );
568
+ vblank_timer -> timer .function = vblank_timer_fn ;
569
+ vblank_timer -> vrefresh_k = port -> vrefresh_k ;
570
+ vblank_timer -> period = DIV64_U64_ROUND_CLOSEST (NSEC_PER_SEC * MSEC_PER_SEC , vblank_timer -> vrefresh_k );
547
571
548
572
emulate_monitor_status_change (vgpu );
549
573
550
574
return 0 ;
551
575
}
552
576
553
577
/**
554
- * intel_gvt_check_vblank_emulation - check if vblank emulation timer should
555
- * be turned on/off when a virtual pipe is enabled/disabled.
556
- * @gvt: a GVT device
578
+ * vgpu_update_vblank_emulation - Update per-vGPU vblank_timer
579
+ * @vgpu: vGPU operated
580
+ * @turnon: Turn ON/OFF vblank_timer
557
581
*
558
- * This function is used to turn on/off vblank timer according to currently
559
- * enabled/disabled virtual pipes.
582
+ * This function is used to turn on/off or update the per-vGPU vblank_timer
583
+ * when PIPECONF is enabled or disabled. vblank_timer period is also updated
584
+ * if guest changed the refresh rate.
560
585
*
561
586
*/
562
- void intel_gvt_check_vblank_emulation (struct intel_gvt * gvt )
587
+ void vgpu_update_vblank_emulation (struct intel_vgpu * vgpu , bool turnon )
563
588
{
564
- struct intel_gvt_irq * irq = & gvt -> irq ;
565
- struct intel_vgpu * vgpu ;
566
- int pipe , id ;
567
- int found = false;
568
-
569
- mutex_lock (& gvt -> lock );
570
- for_each_active_vgpu (gvt , vgpu , id ) {
571
- for (pipe = 0 ; pipe < I915_MAX_PIPES ; pipe ++ ) {
572
- if (pipe_is_enabled (vgpu , pipe )) {
573
- found = true;
574
- break ;
575
- }
589
+ struct intel_vgpu_vblank_timer * vblank_timer = & vgpu -> vblank_timer ;
590
+ struct intel_vgpu_port * port =
591
+ intel_vgpu_port (vgpu , vgpu -> display .port_num );
592
+
593
+ if (turnon ) {
594
+ /*
595
+ * Skip the re-enable if already active and vrefresh unchanged.
596
+ * Otherwise, stop timer if already active and restart with new
597
+ * period.
598
+ */
599
+ if (vblank_timer -> vrefresh_k != port -> vrefresh_k ||
600
+ !hrtimer_active (& vblank_timer -> timer )) {
601
+ /* Stop timer before start with new period if active */
602
+ if (hrtimer_active (& vblank_timer -> timer ))
603
+ hrtimer_cancel (& vblank_timer -> timer );
604
+
605
+ /* Make sure new refresh rate updated to timer period */
606
+ vblank_timer -> vrefresh_k = port -> vrefresh_k ;
607
+ vblank_timer -> period = DIV64_U64_ROUND_CLOSEST (NSEC_PER_SEC * MSEC_PER_SEC , vblank_timer -> vrefresh_k );
608
+ hrtimer_start (& vblank_timer -> timer ,
609
+ ktime_add_ns (ktime_get (), vblank_timer -> period ),
610
+ HRTIMER_MODE_ABS );
576
611
}
577
- if (found )
578
- break ;
612
+ } else {
613
+ /* Caller request to stop vblank */
614
+ hrtimer_cancel (& vblank_timer -> timer );
579
615
}
580
-
581
- /* all the pipes are disabled */
582
- if (!found )
583
- hrtimer_cancel (& irq -> vblank_timer .timer );
584
- else
585
- hrtimer_start (& irq -> vblank_timer .timer ,
586
- ktime_add_ns (ktime_get (), irq -> vblank_timer .period ),
587
- HRTIMER_MODE_ABS );
588
- mutex_unlock (& gvt -> lock );
589
616
}
590
617
591
618
static void emulate_vblank_on_pipe (struct intel_vgpu * vgpu , int pipe )
@@ -617,7 +644,7 @@ static void emulate_vblank_on_pipe(struct intel_vgpu *vgpu, int pipe)
617
644
}
618
645
}
619
646
620
- static void emulate_vblank (struct intel_vgpu * vgpu )
647
+ void intel_vgpu_emulate_vblank (struct intel_vgpu * vgpu )
621
648
{
622
649
int pipe ;
623
650
@@ -627,24 +654,6 @@ static void emulate_vblank(struct intel_vgpu *vgpu)
627
654
mutex_unlock (& vgpu -> vgpu_lock );
628
655
}
629
656
630
- /**
631
- * intel_gvt_emulate_vblank - trigger vblank events for vGPUs on GVT device
632
- * @gvt: a GVT device
633
- *
634
- * This function is used to trigger vblank interrupts for vGPUs on GVT device
635
- *
636
- */
637
- void intel_gvt_emulate_vblank (struct intel_gvt * gvt )
638
- {
639
- struct intel_vgpu * vgpu ;
640
- int id ;
641
-
642
- mutex_lock (& gvt -> lock );
643
- for_each_active_vgpu (gvt , vgpu , id )
644
- emulate_vblank (vgpu );
645
- mutex_unlock (& gvt -> lock );
646
- }
647
-
648
657
/**
649
658
* intel_vgpu_emulate_hotplug - trigger hotplug event for vGPU
650
659
* @vgpu: a vGPU
@@ -753,6 +762,8 @@ void intel_vgpu_clean_display(struct intel_vgpu *vgpu)
753
762
clean_virtual_dp_monitor (vgpu , PORT_D );
754
763
else
755
764
clean_virtual_dp_monitor (vgpu , PORT_B );
765
+
766
+ vgpu_update_vblank_emulation (vgpu , false);
756
767
}
757
768
758
769
/**
0 commit comments