DM: virtio-gpio: GPIO IRQ initialization.

add the GPIO IRQ definitions, and implement the GPIO IRQ
initialization and deinitialization.

Tracked-On: #2512
Signed-off-by: Yuan Liu <yuan1.liu@intel.com>
Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
Yuan Liu 2019-03-04 21:23:34 +08:00 committed by Eddie Dong
parent 9480af8d32
commit 92a0a399b7
1 changed files with 77 additions and 0 deletions

View File

@ -212,6 +212,7 @@ struct gpio_line {
int dir; /* gpio direction */
bool busy; /* gpio line request by kernel */
struct native_gpio_chip *chip; /* parent gpio chip */
struct gpio_irq_desc *irq; /* connect to irq descriptor */
};
struct native_gpio_chip {
@ -223,6 +224,24 @@ struct native_gpio_chip {
struct gpio_line *lines; /* gpio lines in the chip */
};
struct gpio_irq_desc {
struct gpio_line *gpio; /* connect to gpio line */
struct mevent *mevt; /* mevent for event report */
int fd; /* read event */
int pin; /* pin number */
bool mask; /* mask and unmask */
uint8_t level; /* level value */
uint64_t mode; /* interrupt trigger mode */
void *data; /* virtio gpio instance */
};
struct gpio_irq_chip {
pthread_mutex_t intr_mtx;
struct gpio_irq_desc descs[VIRTIO_GPIO_MAX_VLINES];
uint64_t intr_pending; /* pending interrupts */
uint64_t intr_service; /* service interrupts */
};
struct virtio_gpio {
struct virtio_base base;
pthread_mutex_t mtx;
@ -232,6 +251,7 @@ struct virtio_gpio {
struct gpio_line *vlines[VIRTIO_GPIO_MAX_VLINES];
uint32_t nvline;
struct virtio_gpio_config config;
struct gpio_irq_chip irq_chip;
};
static void print_gpio_info(struct virtio_gpio *gpio);
@ -833,6 +853,53 @@ virtio_irq_notify(void *vdev, struct virtio_vq_info *vq)
}
}
static void
gpio_irq_deinit(struct virtio_gpio *gpio)
{
struct gpio_irq_chip *chip;
struct gpio_irq_desc *desc;
int i;
chip = &gpio->irq_chip;
pthread_mutex_destroy(&chip->intr_mtx);
for (i = 0; i < gpio->nvline; i++) {
desc = &chip->descs[i];
if (desc->mevt) {
mevent_delete(desc->mevt);
desc->mevt = NULL;
/* desc fd will be closed by mevent teardown */
}
}
}
static int
gpio_irq_init(struct virtio_gpio *gpio)
{
struct gpio_irq_chip *chip;
struct gpio_irq_desc *desc;
struct gpio_line *line;
int i, rc;
chip = &gpio->irq_chip;
rc = pthread_mutex_init(&chip->intr_mtx, NULL);
if (rc) {
DPRINTF("IRQ pthread_mutex_init failed with error %d!\n", rc);
return -1;
}
for (i = 0; i < gpio->nvline; i++) {
desc = &chip->descs[i];
line = gpio->vlines[i];
desc->pin = i;
desc->fd = -1;
desc->mevt = NULL;
desc->data = gpio;
desc->gpio = line;
line->irq = desc;
}
return 0;
}
static int
virtio_gpio_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
{
@ -865,6 +932,12 @@ virtio_gpio_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
goto gpio_fail;
}
rc = gpio_irq_init(gpio);
if (rc) {
DPRINTF("%s", "virtio gpio: failed to initialize gpio irq\n");
goto irq_fail;
}
/* init mutex attribute properly to avoid deadlock */
rc = pthread_mutexattr_init(&attr);
if (rc) {
@ -927,6 +1000,9 @@ fail:
pthread_mutex_destroy(&gpio->mtx);
mtx_fail:
gpio_irq_deinit(gpio);
irq_fail:
for (i = 0; i < gpio->nchip; i++)
native_gpio_close_chip(&gpio->chips[i]);
@ -950,6 +1026,7 @@ virtio_gpio_deinit(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
gpio = (struct virtio_gpio *)dev->arg;
if (gpio) {
pthread_mutex_destroy(&gpio->mtx);
gpio_irq_deinit(gpio);
for (i = 0; i < gpio->nchip; i++)
native_gpio_close_chip(&gpio->chips[i]);
free(gpio);