@@ -2630,14 +2630,16 @@ static int __init allocate_lpi_tables(void)
2630
2630
return 0 ;
2631
2631
}
2632
2632
2633
- static u64 its_clear_vpend_valid (void __iomem * vlpi_base )
2633
+ static u64 its_clear_vpend_valid (void __iomem * vlpi_base , u64 clr , u64 set )
2634
2634
{
2635
2635
u32 count = 1000000 ; /* 1s! */
2636
2636
bool clean ;
2637
2637
u64 val ;
2638
2638
2639
2639
val = gits_read_vpendbaser (vlpi_base + GICR_VPENDBASER );
2640
2640
val &= ~GICR_VPENDBASER_Valid ;
2641
+ val &= ~clr ;
2642
+ val |= set ;
2641
2643
gits_write_vpendbaser (val , vlpi_base + GICR_VPENDBASER );
2642
2644
2643
2645
do {
@@ -2650,6 +2652,11 @@ static u64 its_clear_vpend_valid(void __iomem *vlpi_base)
2650
2652
}
2651
2653
} while (!clean && count );
2652
2654
2655
+ if (unlikely (val & GICR_VPENDBASER_Dirty )) {
2656
+ pr_err_ratelimited ("ITS virtual pending table not cleaning\n" );
2657
+ val |= GICR_VPENDBASER_PendingLast ;
2658
+ }
2659
+
2653
2660
return val ;
2654
2661
}
2655
2662
@@ -2758,7 +2765,7 @@ static void its_cpu_init_lpis(void)
2758
2765
* ancient programming gets left in and has possibility of
2759
2766
* corrupting memory.
2760
2767
*/
2761
- val = its_clear_vpend_valid (vlpi_base );
2768
+ val = its_clear_vpend_valid (vlpi_base , 0 , 0 );
2762
2769
WARN_ON (val & GICR_VPENDBASER_Dirty );
2763
2770
}
2764
2771
@@ -3438,16 +3445,10 @@ static void its_vpe_deschedule(struct its_vpe *vpe)
3438
3445
void __iomem * vlpi_base = gic_data_rdist_vlpi_base ();
3439
3446
u64 val ;
3440
3447
3441
- val = its_clear_vpend_valid (vlpi_base );
3448
+ val = its_clear_vpend_valid (vlpi_base , 0 , 0 );
3442
3449
3443
- if (unlikely (val & GICR_VPENDBASER_Dirty )) {
3444
- pr_err_ratelimited ("ITS virtual pending table not cleaning\n" );
3445
- vpe -> idai = false;
3446
- vpe -> pending_last = true;
3447
- } else {
3448
- vpe -> idai = !!(val & GICR_VPENDBASER_IDAI );
3449
- vpe -> pending_last = !!(val & GICR_VPENDBASER_PendingLast );
3450
- }
3450
+ vpe -> idai = !!(val & GICR_VPENDBASER_IDAI );
3451
+ vpe -> pending_last = !!(val & GICR_VPENDBASER_PendingLast );
3451
3452
}
3452
3453
3453
3454
static void its_vpe_invall (struct its_vpe * vpe )
@@ -3639,6 +3640,35 @@ static void its_vpe_4_1_schedule(struct its_vpe *vpe,
3639
3640
gits_write_vpendbaser (val , vlpi_base + GICR_VPENDBASER );
3640
3641
}
3641
3642
3643
+ static void its_vpe_4_1_deschedule (struct its_vpe * vpe ,
3644
+ struct its_cmd_info * info )
3645
+ {
3646
+ void __iomem * vlpi_base = gic_data_rdist_vlpi_base ();
3647
+ u64 val ;
3648
+
3649
+ if (info -> req_db ) {
3650
+ /*
3651
+ * vPE is going to block: make the vPE non-resident with
3652
+ * PendingLast clear and DB set. The GIC guarantees that if
3653
+ * we read-back PendingLast clear, then a doorbell will be
3654
+ * delivered when an interrupt comes.
3655
+ */
3656
+ val = its_clear_vpend_valid (vlpi_base ,
3657
+ GICR_VPENDBASER_PendingLast ,
3658
+ GICR_VPENDBASER_4_1_DB );
3659
+ vpe -> pending_last = !!(val & GICR_VPENDBASER_PendingLast );
3660
+ } else {
3661
+ /*
3662
+ * We're not blocking, so just make the vPE non-resident
3663
+ * with PendingLast set, indicating that we'll be back.
3664
+ */
3665
+ val = its_clear_vpend_valid (vlpi_base ,
3666
+ 0 ,
3667
+ GICR_VPENDBASER_PendingLast );
3668
+ vpe -> pending_last = true;
3669
+ }
3670
+ }
3671
+
3642
3672
static int its_vpe_4_1_set_vcpu_affinity (struct irq_data * d , void * vcpu_info )
3643
3673
{
3644
3674
struct its_vpe * vpe = irq_data_get_irq_chip_data (d );
@@ -3650,6 +3680,7 @@ static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
3650
3680
return 0 ;
3651
3681
3652
3682
case DESCHEDULE_VPE :
3683
+ its_vpe_4_1_deschedule (vpe , info );
3653
3684
return 0 ;
3654
3685
3655
3686
case INVALL_VPE :
0 commit comments