diff options
Diffstat (limited to 'drivers/block/virtio_blk.c')
-rw-r--r-- | drivers/block/virtio_blk.c | 63 |
1 files changed, 47 insertions, 16 deletions
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 51042f0ba7e1..2138a7ae050c 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -1,5 +1,6 @@ | |||
1 | //#define DEBUG | 1 | //#define DEBUG |
2 | #include <linux/spinlock.h> | 2 | #include <linux/spinlock.h> |
3 | #include <linux/slab.h> | ||
3 | #include <linux/blkdev.h> | 4 | #include <linux/blkdev.h> |
4 | #include <linux/hdreg.h> | 5 | #include <linux/hdreg.h> |
5 | #include <linux/virtio.h> | 6 | #include <linux/virtio.h> |
@@ -243,10 +244,12 @@ static int index_to_minor(int index) | |||
243 | static int __devinit virtblk_probe(struct virtio_device *vdev) | 244 | static int __devinit virtblk_probe(struct virtio_device *vdev) |
244 | { | 245 | { |
245 | struct virtio_blk *vblk; | 246 | struct virtio_blk *vblk; |
247 | struct request_queue *q; | ||
246 | int err; | 248 | int err; |
247 | u64 cap; | 249 | u64 cap; |
248 | u32 v; | 250 | u32 v, blk_size, sg_elems, opt_io_size; |
249 | u32 blk_size, sg_elems; | 251 | u16 min_io_size; |
252 | u8 physical_block_exp, alignment_offset; | ||
250 | 253 | ||
251 | if (index_to_minor(index) >= 1 << MINORBITS) | 254 | if (index_to_minor(index) >= 1 << MINORBITS) |
252 | return -ENOSPC; | 255 | return -ENOSPC; |
@@ -293,13 +296,13 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) | |||
293 | goto out_mempool; | 296 | goto out_mempool; |
294 | } | 297 | } |
295 | 298 | ||
296 | vblk->disk->queue = blk_init_queue(do_virtblk_request, &vblk->lock); | 299 | q = vblk->disk->queue = blk_init_queue(do_virtblk_request, &vblk->lock); |
297 | if (!vblk->disk->queue) { | 300 | if (!q) { |
298 | err = -ENOMEM; | 301 | err = -ENOMEM; |
299 | goto out_put_disk; | 302 | goto out_put_disk; |
300 | } | 303 | } |
301 | 304 | ||
302 | vblk->disk->queue->queuedata = vblk; | 305 | q->queuedata = vblk; |
303 | 306 | ||
304 | if (index < 26) { | 307 | if (index < 26) { |
305 | sprintf(vblk->disk->disk_name, "vd%c", 'a' + index % 26); | 308 | sprintf(vblk->disk->disk_name, "vd%c", 'a' + index % 26); |
@@ -323,10 +326,10 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) | |||
323 | 326 | ||
324 | /* If barriers are supported, tell block layer that queue is ordered */ | 327 | /* If barriers are supported, tell block layer that queue is ordered */ |
325 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) | 328 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) |
326 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_DRAIN_FLUSH, | 329 | blk_queue_ordered(q, QUEUE_ORDERED_DRAIN_FLUSH, |
327 | virtblk_prepare_flush); | 330 | virtblk_prepare_flush); |
328 | else if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) | 331 | else if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) |
329 | blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); | 332 | blk_queue_ordered(q, QUEUE_ORDERED_TAG, NULL); |
330 | 333 | ||
331 | /* If disk is read-only in the host, the guest should obey */ | 334 | /* If disk is read-only in the host, the guest should obey */ |
332 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO)) | 335 | if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO)) |
@@ -345,14 +348,13 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) | |||
345 | set_capacity(vblk->disk, cap); | 348 | set_capacity(vblk->disk, cap); |
346 | 349 | ||
347 | /* We can handle whatever the host told us to handle. */ | 350 | /* We can handle whatever the host told us to handle. */ |
348 | blk_queue_max_phys_segments(vblk->disk->queue, vblk->sg_elems-2); | 351 | blk_queue_max_segments(q, vblk->sg_elems-2); |
349 | blk_queue_max_hw_segments(vblk->disk->queue, vblk->sg_elems-2); | ||
350 | 352 | ||
351 | /* No need to bounce any requests */ | 353 | /* No need to bounce any requests */ |
352 | blk_queue_bounce_limit(vblk->disk->queue, BLK_BOUNCE_ANY); | 354 | blk_queue_bounce_limit(q, BLK_BOUNCE_ANY); |
353 | 355 | ||
354 | /* No real sector limit. */ | 356 | /* No real sector limit. */ |
355 | blk_queue_max_sectors(vblk->disk->queue, -1U); | 357 | blk_queue_max_hw_sectors(q, -1U); |
356 | 358 | ||
357 | /* Host can optionally specify maximum segment size and number of | 359 | /* Host can optionally specify maximum segment size and number of |
358 | * segments. */ | 360 | * segments. */ |
@@ -360,16 +362,45 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) | |||
360 | offsetof(struct virtio_blk_config, size_max), | 362 | offsetof(struct virtio_blk_config, size_max), |
361 | &v); | 363 | &v); |
362 | if (!err) | 364 | if (!err) |
363 | blk_queue_max_segment_size(vblk->disk->queue, v); | 365 | blk_queue_max_segment_size(q, v); |
364 | else | 366 | else |
365 | blk_queue_max_segment_size(vblk->disk->queue, -1U); | 367 | blk_queue_max_segment_size(q, -1U); |
366 | 368 | ||
367 | /* Host can optionally specify the block size of the device */ | 369 | /* Host can optionally specify the block size of the device */ |
368 | err = virtio_config_val(vdev, VIRTIO_BLK_F_BLK_SIZE, | 370 | err = virtio_config_val(vdev, VIRTIO_BLK_F_BLK_SIZE, |
369 | offsetof(struct virtio_blk_config, blk_size), | 371 | offsetof(struct virtio_blk_config, blk_size), |
370 | &blk_size); | 372 | &blk_size); |
371 | if (!err) | 373 | if (!err) |
372 | blk_queue_logical_block_size(vblk->disk->queue, blk_size); | 374 | blk_queue_logical_block_size(q, blk_size); |
375 | else | ||
376 | blk_size = queue_logical_block_size(q); | ||
377 | |||
378 | /* Use topology information if available */ | ||
379 | err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY, | ||
380 | offsetof(struct virtio_blk_config, physical_block_exp), | ||
381 | &physical_block_exp); | ||
382 | if (!err && physical_block_exp) | ||
383 | blk_queue_physical_block_size(q, | ||
384 | blk_size * (1 << physical_block_exp)); | ||
385 | |||
386 | err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY, | ||
387 | offsetof(struct virtio_blk_config, alignment_offset), | ||
388 | &alignment_offset); | ||
389 | if (!err && alignment_offset) | ||
390 | blk_queue_alignment_offset(q, blk_size * alignment_offset); | ||
391 | |||
392 | err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY, | ||
393 | offsetof(struct virtio_blk_config, min_io_size), | ||
394 | &min_io_size); | ||
395 | if (!err && min_io_size) | ||
396 | blk_queue_io_min(q, blk_size * min_io_size); | ||
397 | |||
398 | err = virtio_config_val(vdev, VIRTIO_BLK_F_TOPOLOGY, | ||
399 | offsetof(struct virtio_blk_config, opt_io_size), | ||
400 | &opt_io_size); | ||
401 | if (!err && opt_io_size) | ||
402 | blk_queue_io_opt(q, blk_size * opt_io_size); | ||
403 | |||
373 | 404 | ||
374 | add_disk(vblk->disk); | 405 | add_disk(vblk->disk); |
375 | return 0; | 406 | return 0; |
@@ -404,7 +435,7 @@ static void __devexit virtblk_remove(struct virtio_device *vdev) | |||
404 | kfree(vblk); | 435 | kfree(vblk); |
405 | } | 436 | } |
406 | 437 | ||
407 | static struct virtio_device_id id_table[] = { | 438 | static const struct virtio_device_id id_table[] = { |
408 | { VIRTIO_ID_BLOCK, VIRTIO_DEV_ANY_ID }, | 439 | { VIRTIO_ID_BLOCK, VIRTIO_DEV_ANY_ID }, |
409 | { 0 }, | 440 | { 0 }, |
410 | }; | 441 | }; |
@@ -412,7 +443,7 @@ static struct virtio_device_id id_table[] = { | |||
412 | static unsigned int features[] = { | 443 | static unsigned int features[] = { |
413 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, | 444 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, |
414 | VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, | 445 | VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, |
415 | VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_FLUSH | 446 | VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY |
416 | }; | 447 | }; |
417 | 448 | ||
418 | /* | 449 | /* |