Merge branch '6.5/scsi-staging' into 6.5/scsi-fixes
[linux-2.6-microblaze.git] / drivers / block / virtio_blk.c
index d6df295..1fe0116 100644 (file)
@@ -348,63 +348,33 @@ static inline void virtblk_request_done(struct request *req)
        blk_mq_end_request(req, status);
 }
 
-static void virtblk_complete_batch(struct io_comp_batch *iob)
-{
-       struct request *req;
-
-       rq_list_for_each(&iob->req_list, req) {
-               virtblk_unmap_data(req, blk_mq_rq_to_pdu(req));
-               virtblk_cleanup_cmd(req);
-       }
-       blk_mq_end_request_batch(iob);
-}
-
-static int virtblk_handle_req(struct virtio_blk_vq *vq,
-                             struct io_comp_batch *iob)
-{
-       struct virtblk_req *vbr;
-       int req_done = 0;
-       unsigned int len;
-
-       while ((vbr = virtqueue_get_buf(vq->vq, &len)) != NULL) {
-               struct request *req = blk_mq_rq_from_pdu(vbr);
-
-               if (likely(!blk_should_fake_timeout(req->q)) &&
-                   !blk_mq_complete_request_remote(req) &&
-                   !blk_mq_add_to_batch(req, iob, virtblk_vbr_status(vbr),
-                                        virtblk_complete_batch))
-                       virtblk_request_done(req);
-               req_done++;
-       }
-
-       return req_done;
-}
-
 static void virtblk_done(struct virtqueue *vq)
 {
        struct virtio_blk *vblk = vq->vdev->priv;
-       struct virtio_blk_vq *vblk_vq = &vblk->vqs[vq->index];
-       int req_done = 0;
+       bool req_done = false;
+       int qid = vq->index;
+       struct virtblk_req *vbr;
        unsigned long flags;
-       DEFINE_IO_COMP_BATCH(iob);
+       unsigned int len;
 
-       spin_lock_irqsave(&vblk_vq->lock, flags);
+       spin_lock_irqsave(&vblk->vqs[qid].lock, flags);
        do {
                virtqueue_disable_cb(vq);
-               req_done += virtblk_handle_req(vblk_vq, &iob);
+               while ((vbr = virtqueue_get_buf(vblk->vqs[qid].vq, &len)) != NULL) {
+                       struct request *req = blk_mq_rq_from_pdu(vbr);
 
+                       if (likely(!blk_should_fake_timeout(req->q)))
+                               blk_mq_complete_request(req);
+                       req_done = true;
+               }
                if (unlikely(virtqueue_is_broken(vq)))
                        break;
        } while (!virtqueue_enable_cb(vq));
 
-       if (req_done) {
-               if (!rq_list_empty(iob.req_list))
-                       iob.complete(&iob);
-
-               /* In case queue is stopped waiting for more buffers. */
+       /* In case queue is stopped waiting for more buffers. */
+       if (req_done)
                blk_mq_start_stopped_hw_queues(vblk->disk->queue, true);
-       }
-       spin_unlock_irqrestore(&vblk_vq->lock, flags);
+       spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags);
 }
 
 static void virtio_commit_rqs(struct blk_mq_hw_ctx *hctx)
@@ -1279,15 +1249,37 @@ static void virtblk_map_queues(struct blk_mq_tag_set *set)
        }
 }
 
+static void virtblk_complete_batch(struct io_comp_batch *iob)
+{
+       struct request *req;
+
+       rq_list_for_each(&iob->req_list, req) {
+               virtblk_unmap_data(req, blk_mq_rq_to_pdu(req));
+               virtblk_cleanup_cmd(req);
+       }
+       blk_mq_end_request_batch(iob);
+}
+
 static int virtblk_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob)
 {
        struct virtio_blk *vblk = hctx->queue->queuedata;
        struct virtio_blk_vq *vq = get_virtio_blk_vq(hctx);
+       struct virtblk_req *vbr;
        unsigned long flags;
+       unsigned int len;
        int found = 0;
 
        spin_lock_irqsave(&vq->lock, flags);
-       found = virtblk_handle_req(vq, iob);
+
+       while ((vbr = virtqueue_get_buf(vq->vq, &len)) != NULL) {
+               struct request *req = blk_mq_rq_from_pdu(vbr);
+
+               found++;
+               if (!blk_mq_complete_request_remote(req) &&
+                   !blk_mq_add_to_batch(req, iob, virtblk_vbr_status(vbr),
+                                               virtblk_complete_batch))
+                       virtblk_request_done(req);
+       }
 
        if (found)
                blk_mq_start_stopped_hw_queues(vblk->disk->queue, true);