@@ -250,6 +250,7 @@ struct gpio_irq_desc {
250
250
int fd ; /* read event */
251
251
int pin ; /* pin number */
252
252
bool mask ; /* mask and unmask */
253
+ bool deinit ; /* deinit state */
253
254
uint8_t level ; /* level value */
254
255
uint64_t mode ; /* interrupt trigger mode */
255
256
void * data ; /* virtio gpio instance */
@@ -401,17 +402,32 @@ gpio_get_value(struct virtio_gpio *gpio, unsigned int offset)
401
402
{
402
403
struct gpio_line * line ;
403
404
struct gpiohandle_data data ;
404
- int rc ;
405
+ int rc , fd ;
405
406
406
407
line = gpio -> vlines [offset ];
407
- if (line -> busy || line -> fd < 0 ) {
408
- DPRINTF ("failed to get gpio%d value, busy:%d, fd:%d\n" ,
409
- offset , line -> busy , line -> fd );
408
+ if (line -> busy ) {
409
+ DPRINTF ("failed to get gpio %d value, it is busy\n" , offset );
410
410
return -1 ;
411
411
}
412
412
413
+ fd = line -> fd ;
414
+ if (fd < 0 ) {
415
+
416
+ /*
417
+ * if the GPIO line has configured as IRQ mode, then can't use
418
+ * gpio line fd to get its value, instead, use IRQ fd to get
419
+ * the value.
420
+ */
421
+ if (line -> irq -> fd < 0 ) {
422
+ DPRINTF ("failed to get gpio %d value, fd is invalid\n" ,
423
+ offset );
424
+ return -1 ;
425
+ }
426
+ fd = line -> irq -> fd ;
427
+ }
428
+
413
429
memset (& data , 0 , sizeof (data ));
414
- rc = ioctl (line -> fd , GPIOHANDLE_GET_LINE_VALUES_IOCTL , & data );
430
+ rc = ioctl (fd , GPIOHANDLE_GET_LINE_VALUES_IOCTL , & data );
415
431
if (rc < 0 ) {
416
432
DPRINTF ("ioctl GPIOHANDLE_GET_LINE_VALUES_IOCTL error %s\n" ,
417
433
strerror (errno ));
@@ -951,6 +967,7 @@ gpio_irq_disable(struct gpio_irq_chip *chip, unsigned int pin)
951
967
952
968
/* Release the mevent, mevent teardown handles IRQ desc reset */
953
969
if (desc -> mevt ) {
970
+ desc -> deinit = false;
954
971
mevent_delete (desc -> mevt );
955
972
desc -> mevt = NULL ;
956
973
}
@@ -970,6 +987,10 @@ gpio_irq_teardown(void *param)
970
987
close (desc -> fd );
971
988
desc -> fd = -1 ;
972
989
}
990
+
991
+ /* if deinit is not set, switch the pin to GPIO mode */
992
+ if (!desc -> deinit )
993
+ native_gpio_open_line (desc -> gpio , 0 , 0 );
973
994
}
974
995
975
996
static void
@@ -1168,6 +1189,7 @@ gpio_irq_deinit(struct virtio_gpio *gpio)
1168
1189
for (i = 0 ; i < gpio -> nvline ; i ++ ) {
1169
1190
desc = & chip -> descs [i ];
1170
1191
if (desc -> mevt ) {
1192
+ desc -> deinit = true;
1171
1193
mevent_delete (desc -> mevt );
1172
1194
desc -> mevt = NULL ;
1173
1195
0 commit comments