Skip to content

Commit 83a98ac

Browse files
yliu80Eddie Dong
authored andcommitted
DM: virtio-gpio: support reading value from IRQ descriptor
Support reading GPIO value when the GPIO switches to IRQ mode. Tracked-On: #2512 Signed-off-by: Yuan Liu <yuan1.liu@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com>
1 parent d34b3eb commit 83a98ac

File tree

1 file changed

+27
-5
lines changed

1 file changed

+27
-5
lines changed

devicemodel/hw/pci/virtio/virtio_gpio.c

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ struct gpio_irq_desc {
250250
int fd; /* read event */
251251
int pin; /* pin number */
252252
bool mask; /* mask and unmask */
253+
bool deinit; /* deinit state */
253254
uint8_t level; /* level value */
254255
uint64_t mode; /* interrupt trigger mode */
255256
void *data; /* virtio gpio instance */
@@ -401,17 +402,32 @@ gpio_get_value(struct virtio_gpio *gpio, unsigned int offset)
401402
{
402403
struct gpio_line *line;
403404
struct gpiohandle_data data;
404-
int rc;
405+
int rc, fd;
405406

406407
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);
410410
return -1;
411411
}
412412

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+
413429
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);
415431
if (rc < 0) {
416432
DPRINTF("ioctl GPIOHANDLE_GET_LINE_VALUES_IOCTL error %s\n",
417433
strerror(errno));
@@ -951,6 +967,7 @@ gpio_irq_disable(struct gpio_irq_chip *chip, unsigned int pin)
951967

952968
/* Release the mevent, mevent teardown handles IRQ desc reset */
953969
if (desc->mevt) {
970+
desc->deinit = false;
954971
mevent_delete(desc->mevt);
955972
desc->mevt = NULL;
956973
}
@@ -970,6 +987,10 @@ gpio_irq_teardown(void *param)
970987
close(desc->fd);
971988
desc->fd = -1;
972989
}
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);
973994
}
974995

975996
static void
@@ -1168,6 +1189,7 @@ gpio_irq_deinit(struct virtio_gpio *gpio)
11681189
for (i = 0; i < gpio->nvline; i++) {
11691190
desc = &chip->descs[i];
11701191
if (desc->mevt) {
1192+
desc->deinit = true;
11711193
mevent_delete(desc->mevt);
11721194
desc->mevt = NULL;
11731195

0 commit comments

Comments
 (0)