@@ -333,6 +333,10 @@ struct its_cmd_desc {
333
333
u16 seq_num ;
334
334
u16 its_list ;
335
335
} its_vmovp_cmd ;
336
+
337
+ struct {
338
+ struct its_vpe * vpe ;
339
+ } its_invdb_cmd ;
336
340
};
337
341
};
338
342
@@ -831,6 +835,21 @@ static struct its_vpe *its_build_vclear_cmd(struct its_node *its,
831
835
return valid_vpe (its , map -> vpe );
832
836
}
833
837
838
+ static struct its_vpe * its_build_invdb_cmd (struct its_node * its ,
839
+ struct its_cmd_block * cmd ,
840
+ struct its_cmd_desc * desc )
841
+ {
842
+ if (WARN_ON (!is_v4_1 (its )))
843
+ return NULL ;
844
+
845
+ its_encode_cmd (cmd , GITS_CMD_INVDB );
846
+ its_encode_vpeid (cmd , desc -> its_invdb_cmd .vpe -> vpe_id );
847
+
848
+ its_fixup_cmd (cmd );
849
+
850
+ return valid_vpe (its , desc -> its_invdb_cmd .vpe );
851
+ }
852
+
834
853
static u64 its_cmd_ptr_to_offset (struct its_node * its ,
835
854
struct its_cmd_block * ptr )
836
855
{
@@ -1239,6 +1258,14 @@ static void its_send_vclear(struct its_device *dev, u32 event_id)
1239
1258
its_send_single_vcommand (dev -> its , its_build_vclear_cmd , & desc );
1240
1259
}
1241
1260
1261
+ static void its_send_invdb (struct its_node * its , struct its_vpe * vpe )
1262
+ {
1263
+ struct its_cmd_desc desc ;
1264
+
1265
+ desc .its_invdb_cmd .vpe = vpe ;
1266
+ its_send_single_vcommand (its , its_build_invdb_cmd , & desc );
1267
+ }
1268
+
1242
1269
/*
1243
1270
* irqchip functions - assumes MSI, mostly.
1244
1271
*/
@@ -3553,6 +3580,50 @@ static struct irq_chip its_vpe_irq_chip = {
3553
3580
.irq_set_vcpu_affinity = its_vpe_set_vcpu_affinity ,
3554
3581
};
3555
3582
3583
+ static struct its_node * find_4_1_its (void )
3584
+ {
3585
+ static struct its_node * its = NULL ;
3586
+
3587
+ if (!its ) {
3588
+ list_for_each_entry (its , & its_nodes , entry ) {
3589
+ if (is_v4_1 (its ))
3590
+ return its ;
3591
+ }
3592
+
3593
+ /* Oops? */
3594
+ its = NULL ;
3595
+ }
3596
+
3597
+ return its ;
3598
+ }
3599
+
3600
+ static void its_vpe_4_1_send_inv (struct irq_data * d )
3601
+ {
3602
+ struct its_vpe * vpe = irq_data_get_irq_chip_data (d );
3603
+ struct its_node * its ;
3604
+
3605
+ /*
3606
+ * GICv4.1 wants doorbells to be invalidated using the
3607
+ * INVDB command in order to be broadcast to all RDs. Send
3608
+ * it to the first valid ITS, and let the HW do its magic.
3609
+ */
3610
+ its = find_4_1_its ();
3611
+ if (its )
3612
+ its_send_invdb (its , vpe );
3613
+ }
3614
+
3615
+ static void its_vpe_4_1_mask_irq (struct irq_data * d )
3616
+ {
3617
+ lpi_write_config (d -> parent_data , LPI_PROP_ENABLED , 0 );
3618
+ its_vpe_4_1_send_inv (d );
3619
+ }
3620
+
3621
+ static void its_vpe_4_1_unmask_irq (struct irq_data * d )
3622
+ {
3623
+ lpi_write_config (d -> parent_data , 0 , LPI_PROP_ENABLED );
3624
+ its_vpe_4_1_send_inv (d );
3625
+ }
3626
+
3556
3627
static int its_vpe_4_1_set_vcpu_affinity (struct irq_data * d , void * vcpu_info )
3557
3628
{
3558
3629
struct its_cmd_info * info = vcpu_info ;
@@ -3574,6 +3645,8 @@ static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
3574
3645
3575
3646
static struct irq_chip its_vpe_4_1_irq_chip = {
3576
3647
.name = "GICv4.1-vpe" ,
3648
+ .irq_mask = its_vpe_4_1_mask_irq ,
3649
+ .irq_unmask = its_vpe_4_1_unmask_irq ,
3577
3650
.irq_eoi = irq_chip_eoi_parent ,
3578
3651
.irq_set_affinity = its_vpe_set_affinity ,
3579
3652
.irq_set_vcpu_affinity = its_vpe_4_1_set_vcpu_affinity ,
0 commit comments