diff options
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/virtio_blk.c | 44 |
1 files changed, 32 insertions, 12 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 0cfbe8c594a5..84e064ffee52 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -35,7 +35,7 @@ struct virtblk_req | |||
35 | struct list_head list; | 35 | struct list_head list; |
36 | struct request *req; | 36 | struct request *req; |
37 | struct virtio_blk_outhdr out_hdr; | 37 | struct virtio_blk_outhdr out_hdr; |
38 | struct virtio_blk_inhdr in_hdr; | 38 | u8 status; |
39 | }; | 39 | }; |
40 | 40 | ||
41 | static void blk_done(struct virtqueue *vq) | 41 | static void blk_done(struct virtqueue *vq) |
@@ -48,7 +48,7 @@ static void blk_done(struct virtqueue *vq) | |||
48 | spin_lock_irqsave(&vblk->lock, flags); | 48 | spin_lock_irqsave(&vblk->lock, flags); |
49 | while ((vbr = vblk->vq->vq_ops->get_buf(vblk->vq, &len)) != NULL) { | 49 | while ((vbr = vblk->vq->vq_ops->get_buf(vblk->vq, &len)) != NULL) { |
50 | int uptodate; | 50 | int uptodate; |
51 | switch (vbr->in_hdr.status) { | 51 | switch (vbr->status) { |
52 | case VIRTIO_BLK_S_OK: | 52 | case VIRTIO_BLK_S_OK: |
53 | uptodate = 1; | 53 | uptodate = 1; |
54 | break; | 54 | break; |
@@ -101,7 +101,7 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | |||
101 | sg_init_table(vblk->sg, VIRTIO_MAX_SG); | 101 | sg_init_table(vblk->sg, VIRTIO_MAX_SG); |
102 | sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr)); | 102 | sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr)); |
103 | num = blk_rq_map_sg(q, vbr->req, vblk->sg+1); | 103 | num = blk_rq_map_sg(q, vbr->req, vblk->sg+1); |
104 | sg_set_buf(&vblk->sg[num+1], &vbr->in_hdr, sizeof(vbr->in_hdr)); | 104 | sg_set_buf(&vblk->sg[num+1], &vbr->status, sizeof(vbr->status)); |
105 | 105 | ||
106 | if (rq_data_dir(vbr->req) == WRITE) { | 106 | if (rq_data_dir(vbr->req) == WRITE) { |
107 | vbr->out_hdr.type |= VIRTIO_BLK_T_OUT; | 107 | vbr->out_hdr.type |= VIRTIO_BLK_T_OUT; |
@@ -157,10 +157,25 @@ static int virtblk_ioctl(struct inode *inode, struct file *filp, | |||
157 | /* We provide getgeo only to please some old bootloader/partitioning tools */ | 157 | /* We provide getgeo only to please some old bootloader/partitioning tools */ |
158 | static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) | 158 | static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo) |
159 | { | 159 | { |
160 | /* some standard values, similar to sd */ | 160 | struct virtio_blk *vblk = bd->bd_disk->private_data; |
161 | geo->heads = 1 << 6; | 161 | struct virtio_blk_geometry vgeo; |
162 | geo->sectors = 1 << 5; | 162 | int err; |
163 | geo->cylinders = get_capacity(bd->bd_disk) >> 11; | 163 | |
164 | /* see if the host passed in geometry config */ | ||
165 | err = virtio_config_val(vblk->vdev, VIRTIO_BLK_F_GEOMETRY, | ||
166 | offsetof(struct virtio_blk_config, geometry), | ||
167 | &vgeo); | ||
168 | |||
169 | if (!err) { | ||
170 | geo->heads = vgeo.heads; | ||
171 | geo->sectors = vgeo.sectors; | ||
172 | geo->cylinders = vgeo.cylinders; | ||
173 | } else { | ||
174 | /* some standard values, similar to sd */ | ||
175 | geo->heads = 1 << 6; | ||
176 | geo->sectors = 1 << 5; | ||
177 | geo->cylinders = get_capacity(bd->bd_disk) >> 11; | ||
178 | } | ||
164 | return 0; | 179 | return 0; |
165 | } | 180 | } |
166 | 181 | ||
@@ -242,12 +257,12 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
242 | index++; | 257 | index++; |
243 | 258 | ||
244 | /* If barriers are supported, tell block layer that queue is ordered */ | 259 | /* If barriers are supported, tell block layer that queue is ordered */ |
245 | if (vdev->config->feature(vdev, VIRTIO_BLK_F_BARRIER)) | 260 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) |
246 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); | 261 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); |
247 | 262 | ||
248 | /* Host must always specify the capacity. */ | 263 | /* Host must always specify the capacity. */ |
249 | __virtio_config_val(vdev, offsetof(struct virtio_blk_config, capacity), | 264 | vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity), |
250 | &cap); | 265 | &cap, sizeof(cap)); |
251 | 266 | ||
252 | /* If capacity is too big, truncate with warning. */ | 267 | /* If capacity is too big, truncate with warning. */ |
253 | if ((sector_t)cap != cap) { | 268 | if ((sector_t)cap != cap) { |
@@ -289,7 +304,6 @@ out: | |||
289 | static void virtblk_remove(struct virtio_device *vdev) | 304 | static void virtblk_remove(struct virtio_device *vdev) |
290 | { | 305 | { |
291 | struct virtio_blk *vblk = vdev->priv; | 306 | struct virtio_blk *vblk = vdev->priv; |
292 | int major = vblk->disk->major; | ||
293 | 307 | ||
294 | /* Nothing should be pending. */ | 308 | /* Nothing should be pending. */ |
295 | BUG_ON(!list_empty(&vblk->reqs)); | 309 | BUG_ON(!list_empty(&vblk->reqs)); |
@@ -299,7 +313,6 @@ static void virtblk_remove(struct virtio_device *vdev) | |||
299 | 313 | ||
300 | blk_cleanup_queue(vblk->disk->queue); | 314 | blk_cleanup_queue(vblk->disk->queue); |
301 | put_disk(vblk->disk); | 315 | put_disk(vblk->disk); |
302 | unregister_blkdev(major, "virtblk"); | ||
303 | mempool_destroy(vblk->pool); | 316 | mempool_destroy(vblk->pool); |
304 | vdev->config->del_vq(vblk->vq); | 317 | vdev->config->del_vq(vblk->vq); |
305 | kfree(vblk); | 318 | kfree(vblk); |
@@ -310,7 +323,14 @@ static struct virtio_device_id id_table[] = { | |||
310 | { 0 }, | 323 | { 0 }, |
311 | }; | 324 | }; |
312 | 325 | ||
326 | static unsigned int features[] = { | ||
327 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, | ||
328 | VIRTIO_BLK_F_GEOMETRY, | ||
329 | }; | ||
330 | |||
313 | static struct virtio_driver virtio_blk = { | 331 | static struct virtio_driver virtio_blk = { |
332 | .feature_table = features, | ||
333 | .feature_table_size = ARRAY_SIZE(features), | ||
314 | .driver.name = KBUILD_MODNAME, | 334 | .driver.name = KBUILD_MODNAME, |
315 | .driver.owner = THIS_MODULE, | 335 | .driver.owner = THIS_MODULE, |
316 | .id_table = id_table, | 336 | .id_table = id_table, |