virtio_blk: v1.0 support
authorMichael S. Tsirkin <mst@redhat.com>
Tue, 7 Oct 2014 14:39:49 +0000 (16:39 +0200)
committerMichael S. Tsirkin <mst@redhat.com>
Tue, 9 Dec 2014 10:05:26 +0000 (12:05 +0200)
Based on patch by Cornelia Huck.

Note: for consistency, and to avoid sparse errors,
      convert all fields, even those no longer in use
      for virtio v1.0.

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
drivers/block/virtio_blk.c
include/uapi/linux/virtio_blk.h

index c6a27d54ad620b5ea25ae674d6b9a358b0f312fa..f601f16eabf4f802038ff66ce16f36d08b227cd0 100644 (file)
@@ -80,7 +80,7 @@ static int __virtblk_add_req(struct virtqueue *vq,
 {
        struct scatterlist hdr, status, cmd, sense, inhdr, *sgs[6];
        unsigned int num_out = 0, num_in = 0;
-       int type = vbr->out_hdr.type & ~VIRTIO_BLK_T_OUT;
+       __virtio32 type = vbr->out_hdr.type & ~cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_OUT);
 
        sg_init_one(&hdr, &vbr->out_hdr, sizeof(vbr->out_hdr));
        sgs[num_out++] = &hdr;
@@ -91,19 +91,19 @@ static int __virtblk_add_req(struct virtqueue *vq,
         * block, and before the normal inhdr we put the sense data and the
         * inhdr with additional status information.
         */
-       if (type == VIRTIO_BLK_T_SCSI_CMD) {
+       if (type == cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_SCSI_CMD)) {
                sg_init_one(&cmd, vbr->req->cmd, vbr->req->cmd_len);
                sgs[num_out++] = &cmd;
        }
 
        if (have_data) {
-               if (vbr->out_hdr.type & VIRTIO_BLK_T_OUT)
+               if (vbr->out_hdr.type & cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_OUT))
                        sgs[num_out++] = data_sg;
                else
                        sgs[num_out + num_in++] = data_sg;
        }
 
-       if (type == VIRTIO_BLK_T_SCSI_CMD) {
+       if (type == cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_SCSI_CMD)) {
                sg_init_one(&sense, vbr->req->sense, SCSI_SENSE_BUFFERSIZE);
                sgs[num_out + num_in++] = &sense;
                sg_init_one(&inhdr, &vbr->in_hdr, sizeof(vbr->in_hdr));
@@ -119,12 +119,13 @@ static int __virtblk_add_req(struct virtqueue *vq,
 static inline void virtblk_request_done(struct request *req)
 {
        struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
+       struct virtio_blk *vblk = req->q->queuedata;
        int error = virtblk_result(vbr);
 
        if (req->cmd_type == REQ_TYPE_BLOCK_PC) {
-               req->resid_len = vbr->in_hdr.residual;
-               req->sense_len = vbr->in_hdr.sense_len;
-               req->errors = vbr->in_hdr.errors;
+               req->resid_len = virtio32_to_cpu(vblk->vdev, vbr->in_hdr.residual);
+               req->sense_len = virtio32_to_cpu(vblk->vdev, vbr->in_hdr.sense_len);
+               req->errors = virtio32_to_cpu(vblk->vdev, vbr->in_hdr.errors);
        } else if (req->cmd_type == REQ_TYPE_SPECIAL) {
                req->errors = (error != 0);
        }
@@ -173,25 +174,25 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req,
 
        vbr->req = req;
        if (req->cmd_flags & REQ_FLUSH) {
-               vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH;
+               vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_FLUSH);
                vbr->out_hdr.sector = 0;
-               vbr->out_hdr.ioprio = req_get_ioprio(vbr->req);
+               vbr->out_hdr.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(vbr->req));
        } else {
                switch (req->cmd_type) {
                case REQ_TYPE_FS:
                        vbr->out_hdr.type = 0;
-                       vbr->out_hdr.sector = blk_rq_pos(vbr->req);
-                       vbr->out_hdr.ioprio = req_get_ioprio(vbr->req);
+                       vbr->out_hdr.sector = cpu_to_virtio64(vblk->vdev, blk_rq_pos(vbr->req));
+                       vbr->out_hdr.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(vbr->req));
                        break;
                case REQ_TYPE_BLOCK_PC:
-                       vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD;
+                       vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_SCSI_CMD);
                        vbr->out_hdr.sector = 0;
-                       vbr->out_hdr.ioprio = req_get_ioprio(vbr->req);
+                       vbr->out_hdr.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(vbr->req));
                        break;
                case REQ_TYPE_SPECIAL:
-                       vbr->out_hdr.type = VIRTIO_BLK_T_GET_ID;
+                       vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_GET_ID);
                        vbr->out_hdr.sector = 0;
-                       vbr->out_hdr.ioprio = req_get_ioprio(vbr->req);
+                       vbr->out_hdr.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(vbr->req));
                        break;
                default:
                        /* We don't put anything else in the queue. */
@@ -204,9 +205,9 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req,
        num = blk_rq_map_sg(hctx->queue, vbr->req, vbr->sg);
        if (num) {
                if (rq_data_dir(vbr->req) == WRITE)
-                       vbr->out_hdr.type |= VIRTIO_BLK_T_OUT;
+                       vbr->out_hdr.type |= cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_OUT);
                else
-                       vbr->out_hdr.type |= VIRTIO_BLK_T_IN;
+                       vbr->out_hdr.type |= cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_IN);
        }
 
        spin_lock_irqsave(&vblk->vqs[qid].lock, flags);
@@ -476,7 +477,8 @@ static int virtblk_get_cache_mode(struct virtio_device *vdev)
                                   struct virtio_blk_config, wce,
                                   &writeback);
        if (err)
-               writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE);
+               writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE) ||
+                           virtio_has_feature(vdev, VIRTIO_F_VERSION_1);
 
        return writeback;
 }
@@ -821,25 +823,35 @@ static const struct virtio_device_id id_table[] = {
        { 0 },
 };
 
-static unsigned int features[] = {
+static unsigned int features_legacy[] = {
        VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY,
        VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_SCSI,
        VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE,
        VIRTIO_BLK_F_MQ,
+}
+;
+static unsigned int features[] = {
+       VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY,
+       VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
+       VIRTIO_BLK_F_TOPOLOGY,
+       VIRTIO_BLK_F_MQ,
+       VIRTIO_F_VERSION_1,
 };
 
 static struct virtio_driver virtio_blk = {
-       .feature_table          = features,
-       .feature_table_size     = ARRAY_SIZE(features),
-       .driver.name            = KBUILD_MODNAME,
-       .driver.owner           = THIS_MODULE,
-       .id_table               = id_table,
-       .probe                  = virtblk_probe,
-       .remove                 = virtblk_remove,
-       .config_changed         = virtblk_config_changed,
+       .feature_table                  = features,
+       .feature_table_size             = ARRAY_SIZE(features),
+       .feature_table_legacy           = features_legacy,
+       .feature_table_size_legacy      = ARRAY_SIZE(features_legacy),
+       .driver.name                    = KBUILD_MODNAME,
+       .driver.owner                   = THIS_MODULE,
+       .id_table                       = id_table,
+       .probe                          = virtblk_probe,
+       .remove                         = virtblk_remove,
+       .config_changed                 = virtblk_config_changed,
 #ifdef CONFIG_PM_SLEEP
-       .freeze                 = virtblk_freeze,
-       .restore                = virtblk_restore,
+       .freeze                         = virtblk_freeze,
+       .restore                        = virtblk_restore,
 #endif
 };
 
index 9ad67b2675847b237bab3ab0117a3fa449f68fd4..247c8ba8544a33ea896aa684b928bb9c3db512b5 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/types.h>
 #include <linux/virtio_ids.h>
 #include <linux/virtio_config.h>
+#include <linux/virtio_types.h>
 
 /* Feature bits */
 #define VIRTIO_BLK_F_BARRIER   0       /* Does host support barriers? */
@@ -114,18 +115,18 @@ struct virtio_blk_config {
 /* This is the first element of the read scatter-gather list. */
 struct virtio_blk_outhdr {
        /* VIRTIO_BLK_T* */
-       __u32 type;
+       __virtio32 type;
        /* io priority. */
-       __u32 ioprio;
+       __virtio32 ioprio;
        /* Sector (ie. 512 byte offset) */
-       __u64 sector;
+       __virtio64 sector;
 };
 
 struct virtio_scsi_inhdr {
-       __u32 errors;
-       __u32 data_len;
-       __u32 sense_len;
-       __u32 residual;
+       __virtio32 errors;
+       __virtio32 data_len;
+       __virtio32 sense_len;
+       __virtio32 residual;
 };
 
 /* And this is the final byte of the write scatter-gather list. */