Commit 19c1c5a6 authored by Michael S. Tsirkin's avatar Michael S. Tsirkin

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: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>


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