diff options
author | Michael S. Tsirkin <mst@redhat.com> | 2014-10-07 10:39:49 -0400 |
---|---|---|
committer | Michael S. Tsirkin <mst@redhat.com> | 2014-12-09 05:05:26 -0500 |
commit | 19c1c5a64c3b8eeb65b63abba248b880dd584589 (patch) | |
tree | d0c2ae46d54dbde97cb167613e3f732b15c3b6e1 /drivers/block/virtio_blk.c | |
parent | fdd819b21576c361bf0dcdd9522df4ccabf7aaa8 (diff) |
virtio_blk: v1.0 support
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>
Diffstat (limited to 'drivers/block/virtio_blk.c')
-rw-r--r-- | drivers/block/virtio_blk.c | 70 |
1 files changed, 41 insertions, 29 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index c6a27d54ad62..f601f16eabf4 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -80,7 +80,7 @@ static int __virtblk_add_req(struct virtqueue *vq, | |||
80 | { | 80 | { |
81 | struct scatterlist hdr, status, cmd, sense, inhdr, *sgs[6]; | 81 | struct scatterlist hdr, status, cmd, sense, inhdr, *sgs[6]; |
82 | unsigned int num_out = 0, num_in = 0; | 82 | unsigned int num_out = 0, num_in = 0; |
83 | int type = vbr->out_hdr.type & ~VIRTIO_BLK_T_OUT; | 83 | __virtio32 type = vbr->out_hdr.type & ~cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_OUT); |
84 | 84 | ||
85 | sg_init_one(&hdr, &vbr->out_hdr, sizeof(vbr->out_hdr)); | 85 | sg_init_one(&hdr, &vbr->out_hdr, sizeof(vbr->out_hdr)); |
86 | sgs[num_out++] = &hdr; | 86 | sgs[num_out++] = &hdr; |
@@ -91,19 +91,19 @@ static int __virtblk_add_req(struct virtqueue *vq, | |||
91 | * block, and before the normal inhdr we put the sense data and the | 91 | * block, and before the normal inhdr we put the sense data and the |
92 | * inhdr with additional status information. | 92 | * inhdr with additional status information. |
93 | */ | 93 | */ |
94 | if (type == VIRTIO_BLK_T_SCSI_CMD) { | 94 | if (type == cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_SCSI_CMD)) { |
95 | sg_init_one(&cmd, vbr->req->cmd, vbr->req->cmd_len); | 95 | sg_init_one(&cmd, vbr->req->cmd, vbr->req->cmd_len); |
96 | sgs[num_out++] = &cmd; | 96 | sgs[num_out++] = &cmd; |
97 | } | 97 | } |
98 | 98 | ||
99 | if (have_data) { | 99 | if (have_data) { |
100 | if (vbr->out_hdr.type & VIRTIO_BLK_T_OUT) | 100 | if (vbr->out_hdr.type & cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_OUT)) |
101 | sgs[num_out++] = data_sg; | 101 | sgs[num_out++] = data_sg; |
102 | else | 102 | else |
103 | sgs[num_out + num_in++] = data_sg; | 103 | sgs[num_out + num_in++] = data_sg; |
104 | } | 104 | } |
105 | 105 | ||
106 | if (type == VIRTIO_BLK_T_SCSI_CMD) { | 106 | if (type == cpu_to_virtio32(vq->vdev, VIRTIO_BLK_T_SCSI_CMD)) { |
107 | sg_init_one(&sense, vbr->req->sense, SCSI_SENSE_BUFFERSIZE); | 107 | sg_init_one(&sense, vbr->req->sense, SCSI_SENSE_BUFFERSIZE); |
108 | sgs[num_out + num_in++] = &sense; | 108 | sgs[num_out + num_in++] = &sense; |
109 | sg_init_one(&inhdr, &vbr->in_hdr, sizeof(vbr->in_hdr)); | 109 | sg_init_one(&inhdr, &vbr->in_hdr, sizeof(vbr->in_hdr)); |
@@ -119,12 +119,13 @@ static int __virtblk_add_req(struct virtqueue *vq, | |||
119 | static inline void virtblk_request_done(struct request *req) | 119 | static inline void virtblk_request_done(struct request *req) |
120 | { | 120 | { |
121 | struct virtblk_req *vbr = blk_mq_rq_to_pdu(req); | 121 | struct virtblk_req *vbr = blk_mq_rq_to_pdu(req); |
122 | struct virtio_blk *vblk = req->q->queuedata; | ||
122 | int error = virtblk_result(vbr); | 123 | int error = virtblk_result(vbr); |
123 | 124 | ||
124 | if (req->cmd_type == REQ_TYPE_BLOCK_PC) { | 125 | if (req->cmd_type == REQ_TYPE_BLOCK_PC) { |
125 | req->resid_len = vbr->in_hdr.residual; | 126 | req->resid_len = virtio32_to_cpu(vblk->vdev, vbr->in_hdr.residual); |
126 | req->sense_len = vbr->in_hdr.sense_len; | 127 | req->sense_len = virtio32_to_cpu(vblk->vdev, vbr->in_hdr.sense_len); |
127 | req->errors = vbr->in_hdr.errors; | 128 | req->errors = virtio32_to_cpu(vblk->vdev, vbr->in_hdr.errors); |
128 | } else if (req->cmd_type == REQ_TYPE_SPECIAL) { | 129 | } else if (req->cmd_type == REQ_TYPE_SPECIAL) { |
129 | req->errors = (error != 0); | 130 | req->errors = (error != 0); |
130 | } | 131 | } |
@@ -173,25 +174,25 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req, | |||
173 | 174 | ||
174 | vbr->req = req; | 175 | vbr->req = req; |
175 | if (req->cmd_flags & REQ_FLUSH) { | 176 | if (req->cmd_flags & REQ_FLUSH) { |
176 | vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH; | 177 | vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_FLUSH); |
177 | vbr->out_hdr.sector = 0; | 178 | vbr->out_hdr.sector = 0; |
178 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | 179 | vbr->out_hdr.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(vbr->req)); |
179 | } else { | 180 | } else { |
180 | switch (req->cmd_type) { | 181 | switch (req->cmd_type) { |
181 | case REQ_TYPE_FS: | 182 | case REQ_TYPE_FS: |
182 | vbr->out_hdr.type = 0; | 183 | vbr->out_hdr.type = 0; |
183 | vbr->out_hdr.sector = blk_rq_pos(vbr->req); | 184 | vbr->out_hdr.sector = cpu_to_virtio64(vblk->vdev, blk_rq_pos(vbr->req)); |
184 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | 185 | vbr->out_hdr.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(vbr->req)); |
185 | break; | 186 | break; |
186 | case REQ_TYPE_BLOCK_PC: | 187 | case REQ_TYPE_BLOCK_PC: |
187 | vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD; | 188 | vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_SCSI_CMD); |
188 | vbr->out_hdr.sector = 0; | 189 | vbr->out_hdr.sector = 0; |
189 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | 190 | vbr->out_hdr.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(vbr->req)); |
190 | break; | 191 | break; |
191 | case REQ_TYPE_SPECIAL: | 192 | case REQ_TYPE_SPECIAL: |
192 | vbr->out_hdr.type = VIRTIO_BLK_T_GET_ID; | 193 | vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_GET_ID); |
193 | vbr->out_hdr.sector = 0; | 194 | vbr->out_hdr.sector = 0; |
194 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | 195 | vbr->out_hdr.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(vbr->req)); |
195 | break; | 196 | break; |
196 | default: | 197 | default: |
197 | /* We don't put anything else in the queue. */ | 198 | /* 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, | |||
204 | num = blk_rq_map_sg(hctx->queue, vbr->req, vbr->sg); | 205 | num = blk_rq_map_sg(hctx->queue, vbr->req, vbr->sg); |
205 | if (num) { | 206 | if (num) { |
206 | if (rq_data_dir(vbr->req) == WRITE) | 207 | if (rq_data_dir(vbr->req) == WRITE) |
207 | vbr->out_hdr.type |= VIRTIO_BLK_T_OUT; | 208 | vbr->out_hdr.type |= cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_OUT); |
208 | else | 209 | else |
209 | vbr->out_hdr.type |= VIRTIO_BLK_T_IN; | 210 | vbr->out_hdr.type |= cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_IN); |
210 | } | 211 | } |
211 | 212 | ||
212 | spin_lock_irqsave(&vblk->vqs[qid].lock, flags); | 213 | spin_lock_irqsave(&vblk->vqs[qid].lock, flags); |
@@ -476,7 +477,8 @@ static int virtblk_get_cache_mode(struct virtio_device *vdev) | |||
476 | struct virtio_blk_config, wce, | 477 | struct virtio_blk_config, wce, |
477 | &writeback); | 478 | &writeback); |
478 | if (err) | 479 | if (err) |
479 | writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE); | 480 | writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE) || |
481 | virtio_has_feature(vdev, VIRTIO_F_VERSION_1); | ||
480 | 482 | ||
481 | return writeback; | 483 | return writeback; |
482 | } | 484 | } |
@@ -821,25 +823,35 @@ static const struct virtio_device_id id_table[] = { | |||
821 | { 0 }, | 823 | { 0 }, |
822 | }; | 824 | }; |
823 | 825 | ||
824 | static unsigned int features[] = { | 826 | static unsigned int features_legacy[] = { |
825 | VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY, | 827 | VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY, |
826 | VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_SCSI, | 828 | VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_SCSI, |
827 | VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE, | 829 | VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE, |
828 | VIRTIO_BLK_F_MQ, | 830 | VIRTIO_BLK_F_MQ, |
831 | } | ||
832 | ; | ||
833 | static unsigned int features[] = { | ||
834 | VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY, | ||
835 | VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, | ||
836 | VIRTIO_BLK_F_TOPOLOGY, | ||
837 | VIRTIO_BLK_F_MQ, | ||
838 | VIRTIO_F_VERSION_1, | ||
829 | }; | 839 | }; |
830 | 840 | ||
831 | static struct virtio_driver virtio_blk = { | 841 | static struct virtio_driver virtio_blk = { |
832 | .feature_table = features, | 842 | .feature_table = features, |
833 | .feature_table_size = ARRAY_SIZE(features), | 843 | .feature_table_size = ARRAY_SIZE(features), |
834 | .driver.name = KBUILD_MODNAME, | 844 | .feature_table_legacy = features_legacy, |
835 | .driver.owner = THIS_MODULE, | 845 | .feature_table_size_legacy = ARRAY_SIZE(features_legacy), |
836 | .id_table = id_table, | 846 | .driver.name = KBUILD_MODNAME, |
837 | .probe = virtblk_probe, | 847 | .driver.owner = THIS_MODULE, |
838 | .remove = virtblk_remove, | 848 | .id_table = id_table, |
839 | .config_changed = virtblk_config_changed, | 849 | .probe = virtblk_probe, |
850 | .remove = virtblk_remove, | ||
851 | .config_changed = virtblk_config_changed, | ||
840 | #ifdef CONFIG_PM_SLEEP | 852 | #ifdef CONFIG_PM_SLEEP |
841 | .freeze = virtblk_freeze, | 853 | .freeze = virtblk_freeze, |
842 | .restore = virtblk_restore, | 854 | .restore = virtblk_restore, |
843 | #endif | 855 | #endif |
844 | }; | 856 | }; |
845 | 857 | ||