@@ -117,6 +117,8 @@ static FILE *dbg_file;
117
117
} \
118
118
} while (0)
119
119
120
+ #define BIT (x ) (1 << (x))
121
+
120
122
/* Virtio GPIO supports maximum number of virtual gpio */
121
123
#define VIRTIO_GPIO_MAX_VLINES 64
122
124
@@ -130,6 +132,14 @@ static FILE *dbg_file;
130
132
#define VIRTIO_GPIO_F_CHIP 1
131
133
#define VIRTIO_GPIO_S_HOSTCAPS VIRTIO_GPIO_F_CHIP
132
134
135
+ #define IRQ_TYPE_NONE 0
136
+ #define IRQ_TYPE_EDGE_RISING (1 << 0)
137
+ #define IRQ_TYPE_EDGE_FALLING (1 << 1)
138
+ #define IRQ_TYPE_LEVEL_HIGH (1 << 2)
139
+ #define IRQ_TYPE_LEVEL_LOW (1 << 3)
140
+ #define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)
141
+ #define IRQ_TYPE_LEVEL_MASK (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)
142
+
133
143
/* make virtio gpio mediator a singleton mode */
134
144
static bool virtio_gpio_is_active ;
135
145
@@ -171,6 +181,16 @@ enum virtio_gpio_request_command {
171
181
GPIO_REQ_MAX
172
182
};
173
183
184
+ enum gpio_irq_action {
185
+ IRQ_ACTION_ENABLE = 0 ,
186
+ IRQ_ACTION_DISABLE ,
187
+ IRQ_ACTION_ACK ,
188
+ IRQ_ACTION_MASK ,
189
+ IRQ_ACTION_UNMASK ,
190
+
191
+ IRQ_ACTION_MAX
192
+ };
193
+
174
194
struct virtio_gpio_request {
175
195
uint8_t cmd ;
176
196
uint8_t offset ;
@@ -807,10 +827,255 @@ native_gpio_init(struct virtio_gpio *gpio, char *opts)
807
827
free (b );
808
828
return ln == 0 ? -1 : 0 ;
809
829
}
830
+
831
+ static void
832
+ gpio_irq_deliver_intr (struct virtio_gpio * gpio , uint64_t mask )
833
+ {
834
+ struct virtio_vq_info * vq ;
835
+ struct iovec iov [1 ];
836
+ uint16_t idx ;
837
+ uint64_t * data ;
838
+
839
+ vq = & gpio -> queues [2 ];
840
+ if (vq_has_descs (vq ) && mask ) {
841
+ vq_getchain (vq , & idx , iov , 1 , NULL );
842
+ data = iov [0 ].iov_base ;
843
+ assert (sizeof (* data ) == iov [0 ].iov_len );
844
+
845
+ * data = mask ;
846
+
847
+ /*
848
+ * Release this chain and handle more
849
+ */
850
+ vq_relchain (vq , idx , sizeof (* data ));
851
+
852
+ /* Generate interrupt if appropriate. */
853
+ vq_endchains (vq , 1 );
854
+
855
+ } else
856
+ DPRINTF ("virtio gpio failed to send an IRQ, mask %lu" , mask );
857
+ }
858
+
859
+ static void
860
+ gpio_irq_generate_intr (struct virtio_gpio * gpio , int pin )
861
+ {
862
+ struct gpio_irq_chip * chip ;
863
+ struct gpio_irq_desc * desc ;
864
+
865
+ chip = & gpio -> irq_chip ;
866
+ desc = & chip -> descs [pin ];
867
+
868
+ /* Ignore interrupt until it is unmasked */
869
+ if (desc -> mask )
870
+ return ;
871
+
872
+ pthread_mutex_lock (& chip -> intr_mtx );
873
+
874
+ /* set it to pending mask */
875
+ chip -> intr_pending |= BIT (pin );
876
+
877
+ /*
878
+ * if all interrupts in service are acknowledged, then send pending
879
+ * interrupts.
880
+ */
881
+ if (!chip -> intr_service ) {
882
+ chip -> intr_service = chip -> intr_pending ;
883
+ chip -> intr_pending = 0 ;
884
+
885
+ /* deliver interrupt */
886
+ gpio_irq_deliver_intr (gpio , chip -> intr_service );
887
+ }
888
+ pthread_mutex_unlock (& chip -> intr_mtx );
889
+ }
890
+
891
+ static void
892
+ gpio_irq_set_pin_state (int fd __attribute__((unused )),
893
+ enum ev_type t __attribute__((unused )),
894
+ void * arg )
895
+ {
896
+ struct gpioevent_data data ;
897
+ struct virtio_gpio * gpio ;
898
+ struct gpio_irq_desc * desc ;
899
+ int last_level , err ;
900
+
901
+ assert (arg != NULL );
902
+ desc = (struct gpio_irq_desc * ) arg ;
903
+ gpio = (struct virtio_gpio * ) desc -> data ;
904
+ last_level = desc -> level ;
905
+
906
+ /* get pin state */
907
+ memset (& data , 0 , sizeof (data ));
908
+ err = read (desc -> fd , & data , sizeof (data ));
909
+ if (err != sizeof (data )) {
910
+ DPRINTF ("virtio gpio, gpio mevent read error %s, len %d\n" ,
911
+ strerror (errno ), err );
912
+ return ;
913
+ }
914
+
915
+ if (data .id == GPIOEVENT_EVENT_RISING_EDGE ) {
916
+
917
+ /* pin level is high */
918
+ desc -> level = 1 ;
919
+
920
+ /* jitter protection */
921
+ if (((desc -> mode & IRQ_TYPE_EDGE_RISING ) && (last_level == 0 ))
922
+ || (desc -> mode & IRQ_TYPE_LEVEL_HIGH )) {
923
+ gpio_irq_generate_intr (gpio , desc -> pin );
924
+ }
925
+ } else if (data .id == GPIOEVENT_EVENT_FALLING_EDGE ) {
926
+
927
+ /* pin level is low */
928
+ desc -> level = 0 ;
929
+
930
+ /* jitter protection */
931
+ if (((desc -> mode & IRQ_TYPE_EDGE_FALLING ) && (last_level == 1 ))
932
+ || (desc -> mode & IRQ_TYPE_LEVEL_LOW )) {
933
+ gpio_irq_generate_intr (gpio , desc -> pin );
934
+ }
935
+ } else
936
+ DPRINTF ("virtio gpio, undefined GPIO event id %d\n" , data .id );
937
+ }
938
+
939
+ static void
940
+ gpio_irq_disable (struct gpio_irq_chip * chip , unsigned int pin )
941
+ {
942
+ struct gpio_irq_desc * desc ;
943
+
944
+ if (pin >= VIRTIO_GPIO_MAX_VLINES ) {
945
+ DPRINTF (" gpio irq disable pin %d is invalid\n" , pin );
946
+ return ;
947
+ }
948
+ desc = & chip -> descs [pin ];
949
+ DPRINTF ("disable IRQ pin %d <-> native chip %s, GPIO %d\n" ,
950
+ pin , desc -> gpio -> chip -> dev_name , desc -> gpio -> offset );
951
+
952
+ /* Release the mevent, mevent teardown handles IRQ desc reset */
953
+ if (desc -> mevt ) {
954
+ mevent_delete (desc -> mevt );
955
+ desc -> mevt = NULL ;
956
+ }
957
+ }
958
+
959
+ static void
960
+ gpio_irq_teardown (void * param )
961
+ {
962
+ struct gpio_irq_desc * desc ;
963
+
964
+ DPRINTF ("%s" , "virtio gpio tear down\n" );
965
+ assert (param != NULL );
966
+ desc = (struct gpio_irq_desc * ) param ;
967
+ desc -> mask = false;
968
+ desc -> mode = IRQ_TYPE_NONE ;
969
+ if (desc -> fd > -1 ) {
970
+ close (desc -> fd );
971
+ desc -> fd = -1 ;
972
+ }
973
+ }
974
+
975
+ static void
976
+ gpio_irq_enable (struct virtio_gpio * gpio , unsigned int pin ,
977
+ uint64_t mode )
978
+ {
979
+ struct gpioevent_request req ;
980
+ struct gpio_line * line ;
981
+ struct gpio_irq_chip * chip ;
982
+ struct gpio_irq_desc * desc ;
983
+ int err ;
984
+
985
+ chip = & gpio -> irq_chip ;
986
+ desc = & chip -> descs [pin ];
987
+ line = desc -> gpio ;
988
+ DPRINTF ("enable IRQ pin %d, mode %lu <-> chip %s, GPIO %d\n" ,
989
+ pin , mode , desc -> gpio -> chip -> dev_name , desc -> gpio -> offset );
990
+
991
+ /*
992
+ * Front-end should set the gpio direction to input before
993
+ * enable one gpio to irq, so get the gpio value directly
994
+ * no need to set it to input direction.
995
+ */
996
+ desc -> level = gpio_get_value (gpio , pin );
997
+
998
+ /* Release the GPIO line before enable it for IRQ */
999
+ native_gpio_close_line (line );
1000
+
1001
+ memset (& req , 0 , sizeof (req ));
1002
+ if (mode & IRQ_TYPE_EDGE_RISING )
1003
+ req .eventflags |= GPIOEVENT_REQUEST_RISING_EDGE ;
1004
+ if (mode & IRQ_TYPE_EDGE_FALLING )
1005
+ req .eventflags |= GPIOEVENT_REQUEST_FALLING_EDGE ;
1006
+
1007
+ /*
1008
+ * For level tigger, detect rising and fallling edges to
1009
+ * update the IRQ level value, the value is used to check
1010
+ * the level IRQ is active.
1011
+ */
1012
+ if (mode & IRQ_TYPE_LEVEL_MASK )
1013
+ req .eventflags |= GPIOEVENT_REQUEST_BOTH_EDGES ;
1014
+ if (!req .eventflags ) {
1015
+ DPRINTF ("failed to enable pin %d to IRQ with invalid flags\n" ,
1016
+ pin );
1017
+ return ;
1018
+ }
1019
+
1020
+ desc -> mode = mode ;
1021
+ req .lineoffset = line -> offset ;
1022
+ strncpy (req .consumer_label , "acrn_dm_irq" ,
1023
+ sizeof (req .consumer_label ) - 1 );
1024
+ err = ioctl (line -> chip -> fd , GPIO_GET_LINEEVENT_IOCTL , & req );
1025
+ if (err < 0 ) {
1026
+ DPRINTF ("ioctl GPIO_GET_LINEEVENT_IOCTL error %s\n" ,
1027
+ strerror (errno ));
1028
+ goto error ;
1029
+ }
1030
+
1031
+ desc -> fd = req .fd ;
1032
+ desc -> mevt = mevent_add (desc -> fd , EVF_READ ,
1033
+ gpio_irq_set_pin_state , desc ,
1034
+ gpio_irq_teardown , desc );
1035
+ if (!desc -> mevt ) {
1036
+ DPRINTF ("failed to enable IRQ pin %d, mevent add error\n" ,
1037
+ pin );
1038
+ goto error ;
1039
+ }
1040
+
1041
+ return ;
1042
+ error :
1043
+ gpio_irq_disable (chip , pin );
1044
+ }
1045
+
1046
+ static bool
1047
+ gpio_irq_has_pending_intr (struct gpio_irq_desc * desc )
1048
+ {
1049
+ bool level_high , level_low ;
1050
+
1051
+ /*
1052
+ * For level trigger mode, check the pin mode and level value
1053
+ * to resend an interrupt.
1054
+ */
1055
+ if (desc -> mode & IRQ_TYPE_LEVEL_MASK ) {
1056
+ level_high = desc -> mode & IRQ_TYPE_LEVEL_HIGH ;
1057
+ level_low = desc -> mode & IRQ_TYPE_LEVEL_LOW ;
1058
+ if ((level_high && desc -> level == 1 ) ||
1059
+ (level_low && desc -> level == 0 ))
1060
+ return true;
1061
+ }
1062
+ return false;
1063
+ }
1064
+
1065
+ static void
1066
+ gpio_irq_clear_intr (struct gpio_irq_chip * chip , int pin )
1067
+ {
1068
+ pthread_mutex_lock (& chip -> intr_mtx );
1069
+ chip -> intr_service &= ~BIT (pin );
1070
+ pthread_mutex_unlock (& chip -> intr_mtx );
1071
+ }
1072
+
810
1073
static void
811
1074
virtio_gpio_irq_proc (struct virtio_gpio * gpio , struct iovec * iov , uint16_t flag )
812
1075
{
813
1076
struct virtio_gpio_irq_request * req ;
1077
+ struct gpio_irq_chip * chip ;
1078
+ struct gpio_irq_desc * desc ;
814
1079
int len ;
815
1080
816
1081
req = iov [0 ].iov_base ;
@@ -822,7 +1087,42 @@ virtio_gpio_irq_proc(struct virtio_gpio *gpio, struct iovec *iov, uint16_t flag)
822
1087
return ;
823
1088
}
824
1089
825
- /* implement in next patch */
1090
+ chip = & gpio -> irq_chip ;
1091
+ desc = & chip -> descs [req -> pin ];
1092
+ switch (req -> action ) {
1093
+ case IRQ_ACTION_ENABLE :
1094
+ /*
1095
+ * TODO: need to notify the FE driver
1096
+ * if gpio_irq_enable failure.
1097
+ */
1098
+ gpio_irq_enable (gpio , req -> pin , req -> mode );
1099
+ break ;
1100
+ case IRQ_ACTION_DISABLE :
1101
+ gpio_irq_disable (chip , req -> pin );
1102
+
1103
+ /* reopen the GPIO */
1104
+ native_gpio_open_line (desc -> gpio , 0 , 0 );
1105
+ break ;
1106
+ case IRQ_ACTION_ACK :
1107
+ /*
1108
+ * For level trigger, we need to check the level value
1109
+ * for next interrupt.
1110
+ */
1111
+ gpio_irq_clear_intr (chip , req -> pin );
1112
+ if (gpio_irq_has_pending_intr (desc ))
1113
+ gpio_irq_generate_intr (gpio , req -> pin );
1114
+ break ;
1115
+ case IRQ_ACTION_MASK :
1116
+ desc -> mask = true;
1117
+ break ;
1118
+ case IRQ_ACTION_UNMASK :
1119
+ desc -> mask = false;
1120
+ if (gpio_irq_has_pending_intr (desc ))
1121
+ gpio_irq_generate_intr (gpio , req -> pin );
1122
+ break ;
1123
+ default :
1124
+ DPRINTF ("virtio gpio, unknown IRQ action %d\n" , req -> action );
1125
+ }
826
1126
}
827
1127
828
1128
static void
@@ -850,6 +1150,9 @@ virtio_irq_notify(void *vdev, struct virtio_vq_info *vq)
850
1150
* Release this chain and handle more
851
1151
*/
852
1152
vq_relchain (vq , idx , 1 );
1153
+
1154
+ /* Generate interrupt if appropriate. */
1155
+ vq_endchains (vq , 1 );
853
1156
}
854
1157
}
855
1158
0 commit comments