diff --git a/drivers/virtio/virtio-blk.c b/drivers/virtio/virtio-blk.c index 3873234a0e7..e25564fe8dd 100644 --- a/drivers/virtio/virtio-blk.c +++ b/drivers/virtio/virtio-blk.c @@ -175,6 +175,38 @@ static int g_virtio_blk_idx = 0; * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: virtio_blk_wait_complete + * + * Description: + * Wait the virtio block request complete + * + ****************************************************************************/ + +static void virtio_blk_wait_complete(FAR struct virtqueue *vq, + FAR sem_t *respsem) +{ + if (up_interrupt_context()) + { + for (; ; ) + { + FAR sem_t * tmpsem = virtqueue_get_buffer(vq, NULL, NULL); + if (tmpsem == respsem) + { + break; + } + else if (tmpsem != NULL) + { + nxsem_post(tmpsem); + } + } + } + else + { + nxsem_wait_uninterruptible(respsem); + } +} + /**************************************************************************** * Name: virtio_blk_rdwr * @@ -194,10 +226,17 @@ static ssize_t virtio_blk_rdwr(FAR struct virtio_blk_priv_s *priv, ssize_t ret; int readnum; - ret = nxmutex_lock(&priv->lock); - if (ret < 0) + if (up_interrupt_context()) { - return ret; + virtqueue_disable_cb(vq); + } + else + { + ret = nxmutex_lock(&priv->lock); + if (ret < 0) + { + return ret; + } } nxsem_init(&respsem, 0, 0); @@ -233,7 +272,8 @@ static ssize_t virtio_blk_rdwr(FAR struct virtio_blk_priv_s *priv, /* Wait for the request completion */ - nxsem_wait_uninterruptible(&respsem); + virtio_blk_wait_complete(vq, &respsem); + if (priv->resp->status != VIRTIO_BLK_S_OK) { vrterr("%s Error\n", write ? "Write" : "Read"); @@ -241,7 +281,15 @@ static ssize_t virtio_blk_rdwr(FAR struct virtio_blk_priv_s *priv, } err: - nxmutex_unlock(&priv->lock); + if (up_interrupt_context()) + { + virtqueue_enable_cb(vq); + } + else + { + nxmutex_unlock(&priv->lock); + } + return ret >= 0 ? nsectors : ret; }