aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/virtio_blk.c
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2014-10-07 10:39:49 -0400
committerMichael S. Tsirkin <mst@redhat.com>2014-12-09 05:05:26 -0500
commit19c1c5a64c3b8eeb65b63abba248b880dd584589 (patch)
treed0c2ae46d54dbde97cb167613e3f732b15c3b6e1 /drivers/block/virtio_blk.c
parentfdd819b21576c361bf0dcdd9522df4ccabf7aaa8 (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.c70
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,
119static inline void virtblk_request_done(struct request *req) 119static 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
824static unsigned int features[] = { 826static 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;
833static 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
831static struct virtio_driver virtio_blk = { 841static 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