DM: virtio-gpio: setup two virqueues for gpio irq

There are two virtqueues for irq, one for handling the operations of
front-end irq controller and the other for triggering the interrupt.

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:10:11 +08:00 committed by Eddie Dong
parent e381aef220
commit 9480af8d32

View File

@ -62,6 +62,37 @@
* +------------------+
*/
/*
* GPIO IRQ virtualization architecture
*
* SOS UOS
* +-------------------------------+
* | virtio GPIO mediator |
* | +-------------------------+ |
* | | GPIO IRQ chip | | IRQ chip
* | | +-------------------+ | | virtqueue
* | | |Enable, Disable +<--|---|-----------+
* | | |Mask, Unmask, Ack | | | |
* | | +-------------------+ | | IRQ event |
* | | +--------------+ | | virtqueue |
* | | | Generate IRQ +--------|---|--------+ |
* | | +--------------+ | | | |
* | +-------------------------+ | | |
* | ^ ^ ^ ^ | | |
* +---|----|----|----|------------+ | |
* -----|----|----|----|---------------------+--+-------------------------------
* +-+----+----+----+-+ | | +------------+ +------------+
* | gpiolib framework| | | |IRQ consumer| |IRQ consumer|
* +------------------+ | | +------------+ +------------+
* | | +----------------------------+
* | | | UOS gpiolib framework |
* | | +----------------------------+
* | | +----------------------+
* | +-+ UOS virtio GPIO |
* +--->| IRQ chip |
* +----------------------+
*/
static int gpio_debug;
static FILE *dbg_file;
#define VIRTIO_GPIO_LOG_INIT do { \
@ -93,7 +124,7 @@ static FILE *dbg_file;
#define VIRTIO_GPIO_MAX_CHIPS 8
/* Virtio GPIO virtqueue numbers*/
#define VIRTIO_GPIO_MAXQ 1
#define VIRTIO_GPIO_MAXQ 3
/* Virtio GPIO capabilities */
#define VIRTIO_GPIO_F_CHIP 1
@ -165,6 +196,13 @@ struct virtio_gpio_config {
uint16_t ngpio; /* number of gpios */
} __attribute__((packed));
struct virtio_gpio_irq_request {
uint8_t action;
uint8_t pin;
uint8_t mode;
} __attribute__((packed));
struct gpio_line {
char name[32]; /* native gpio name */
char vname[32]; /* virtual gpio name */
@ -749,6 +787,51 @@ native_gpio_init(struct virtio_gpio *gpio, char *opts)
free(b);
return ln == 0 ? -1 : 0;
}
static void
virtio_gpio_irq_proc(struct virtio_gpio *gpio, struct iovec *iov, uint16_t flag)
{
struct virtio_gpio_irq_request *req;
int len;
req = iov[0].iov_base;
len = iov[0].iov_len;
assert(len == sizeof(*req));
if (req->pin >= gpio->nvline) {
DPRINTF("virtio gpio, invalid IRQ pin %d, ignore action %d\n",
req->pin, req->action);
return;
}
/* implement in next patch */
}
static void
virtio_irq_evt_notify(void *vdev, struct virtio_vq_info *vq)
{
/* The front-end driver does not make a kick, just avoid warning */
DPRINTF("%s", "virtio gpio irq_evt_notify\n");
}
static void
virtio_irq_notify(void *vdev, struct virtio_vq_info *vq)
{
struct iovec iov[1];
struct virtio_gpio *gpio;
uint16_t idx, flag;
int n;
gpio = (struct virtio_gpio *)vdev;
if (vq_has_descs(vq)) {
n = vq_getchain(vq, &idx, iov, 1, &flag);
assert(n == 1);
virtio_gpio_irq_proc(gpio, iov, flag);
/*
* Release this chain and handle more
*/
vq_relchain(vq, idx, 1);
}
}
static int
virtio_gpio_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
@ -813,6 +896,10 @@ virtio_gpio_init(struct vmctx *ctx, struct pci_vdev *dev, char *opts)
gpio->base.mtx = &gpio->mtx;
gpio->queues[0].qsize = 64;
gpio->queues[0].notify = virtio_gpio_notify;
gpio->queues[1].qsize = 64;
gpio->queues[1].notify = virtio_irq_notify;
gpio->queues[2].qsize = 64;
gpio->queues[2].notify = virtio_irq_evt_notify;
/* initialize config space */
pci_set_cfgdata16(dev, PCIR_DEVICE, VIRTIO_DEV_GPIO);