mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus
* git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus: (25 commits) virtio: balloon driver virtio: Use PCI revision field to indicate virtio PCI ABI version virtio: PCI device virtio_blk: implement naming for vda-vdz,vdaa-vdzz,vdaaa-vdzzz virtio_blk: Dont waste major numbers virtio_blk: provide getgeo virtio_net: parametrize the napi_weight for virtio receive queue. virtio: free transmit skbs when notified, not on next xmit. virtio: flush buffers on open virtnet: remove double ether_setup virtio: Allow virtio to be modular and used by modules virtio: Use the sg_phys convenience function. virtio: Put the virtio under the virtualization menu virtio: handle interrupts after callbacks turned off virtio: reset function virtio: populate network rings in the probe routine, not open virtio: Tweak virtio_net defines virtio: Net header needs hdr_len virtio: remove unused id field from struct virtio_blk_outhdr virtio: clarify NO_NOTIFY flag usage ...
This commit is contained in:
commit
93890b71a3
26 changed files with 1422 additions and 421 deletions
|
|
@ -440,6 +440,7 @@ config VIRTIO_BLK
|
|||
tristate "Virtio block driver (EXPERIMENTAL)"
|
||||
depends on EXPERIMENTAL && VIRTIO
|
||||
---help---
|
||||
This is the virtual block driver for lguest. Say Y or M.
|
||||
This is the virtual block driver for virtio. It can be used with
|
||||
lguest or QEMU based VMMs (like KVM or Xen). Say Y or M.
|
||||
|
||||
endif # BLK_DEV
|
||||
|
|
|
|||
|
|
@ -7,8 +7,10 @@
|
|||
#include <linux/scatterlist.h>
|
||||
|
||||
#define VIRTIO_MAX_SG (3+MAX_PHYS_SEGMENTS)
|
||||
#define PART_BITS 4
|
||||
|
||||
static int major, index;
|
||||
|
||||
static unsigned char virtblk_index = 'a';
|
||||
struct virtio_blk
|
||||
{
|
||||
spinlock_t lock;
|
||||
|
|
@ -36,7 +38,7 @@ struct virtblk_req
|
|||
struct virtio_blk_inhdr in_hdr;
|
||||
};
|
||||
|
||||
static bool blk_done(struct virtqueue *vq)
|
||||
static void blk_done(struct virtqueue *vq)
|
||||
{
|
||||
struct virtio_blk *vblk = vq->vdev->priv;
|
||||
struct virtblk_req *vbr;
|
||||
|
|
@ -65,7 +67,6 @@ static bool blk_done(struct virtqueue *vq)
|
|||
/* In case queue is stopped waiting for more buffers. */
|
||||
blk_start_queue(vblk->disk->queue);
|
||||
spin_unlock_irqrestore(&vblk->lock, flags);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
|
||||
|
|
@ -153,20 +154,37 @@ static int virtblk_ioctl(struct inode *inode, struct file *filp,
|
|||
(void __user *)data);
|
||||
}
|
||||
|
||||
/* We provide getgeo only to please some old bootloader/partitioning tools */
|
||||
static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
|
||||
{
|
||||
/* some standard values, similar to sd */
|
||||
geo->heads = 1 << 6;
|
||||
geo->sectors = 1 << 5;
|
||||
geo->cylinders = get_capacity(bd->bd_disk) >> 11;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct block_device_operations virtblk_fops = {
|
||||
.ioctl = virtblk_ioctl,
|
||||
.owner = THIS_MODULE,
|
||||
.ioctl = virtblk_ioctl,
|
||||
.owner = THIS_MODULE,
|
||||
.getgeo = virtblk_getgeo,
|
||||
};
|
||||
|
||||
static int index_to_minor(int index)
|
||||
{
|
||||
return index << PART_BITS;
|
||||
}
|
||||
|
||||
static int virtblk_probe(struct virtio_device *vdev)
|
||||
{
|
||||
struct virtio_blk *vblk;
|
||||
int err, major;
|
||||
void *token;
|
||||
unsigned int len;
|
||||
int err;
|
||||
u64 cap;
|
||||
u32 v;
|
||||
|
||||
if (index_to_minor(index) >= 1 << MINORBITS)
|
||||
return -ENOSPC;
|
||||
|
||||
vdev->priv = vblk = kmalloc(sizeof(*vblk), GFP_KERNEL);
|
||||
if (!vblk) {
|
||||
err = -ENOMEM;
|
||||
|
|
@ -178,7 +196,7 @@ static int virtblk_probe(struct virtio_device *vdev)
|
|||
vblk->vdev = vdev;
|
||||
|
||||
/* We expect one virtqueue, for output. */
|
||||
vblk->vq = vdev->config->find_vq(vdev, blk_done);
|
||||
vblk->vq = vdev->config->find_vq(vdev, 0, blk_done);
|
||||
if (IS_ERR(vblk->vq)) {
|
||||
err = PTR_ERR(vblk->vq);
|
||||
goto out_free_vblk;
|
||||
|
|
@ -190,17 +208,11 @@ static int virtblk_probe(struct virtio_device *vdev)
|
|||
goto out_free_vq;
|
||||
}
|
||||
|
||||
major = register_blkdev(0, "virtblk");
|
||||
if (major < 0) {
|
||||
err = major;
|
||||
goto out_mempool;
|
||||
}
|
||||
|
||||
/* FIXME: How many partitions? How long is a piece of string? */
|
||||
vblk->disk = alloc_disk(1 << 4);
|
||||
vblk->disk = alloc_disk(1 << PART_BITS);
|
||||
if (!vblk->disk) {
|
||||
err = -ENOMEM;
|
||||
goto out_unregister_blkdev;
|
||||
goto out_mempool;
|
||||
}
|
||||
|
||||
vblk->disk->queue = blk_init_queue(do_virtblk_request, &vblk->lock);
|
||||
|
|
@ -209,22 +221,32 @@ static int virtblk_probe(struct virtio_device *vdev)
|
|||
goto out_put_disk;
|
||||
}
|
||||
|
||||
sprintf(vblk->disk->disk_name, "vd%c", virtblk_index++);
|
||||
if (index < 26) {
|
||||
sprintf(vblk->disk->disk_name, "vd%c", 'a' + index % 26);
|
||||
} else if (index < (26 + 1) * 26) {
|
||||
sprintf(vblk->disk->disk_name, "vd%c%c",
|
||||
'a' + index / 26 - 1, 'a' + index % 26);
|
||||
} else {
|
||||
const unsigned int m1 = (index / 26 - 1) / 26 - 1;
|
||||
const unsigned int m2 = (index / 26 - 1) % 26;
|
||||
const unsigned int m3 = index % 26;
|
||||
sprintf(vblk->disk->disk_name, "vd%c%c%c",
|
||||
'a' + m1, 'a' + m2, 'a' + m3);
|
||||
}
|
||||
|
||||
vblk->disk->major = major;
|
||||
vblk->disk->first_minor = 0;
|
||||
vblk->disk->first_minor = index_to_minor(index);
|
||||
vblk->disk->private_data = vblk;
|
||||
vblk->disk->fops = &virtblk_fops;
|
||||
index++;
|
||||
|
||||
/* If barriers are supported, tell block layer that queue is ordered */
|
||||
token = vdev->config->find(vdev, VIRTIO_CONFIG_BLK_F, &len);
|
||||
if (virtio_use_bit(vdev, token, len, VIRTIO_BLK_F_BARRIER))
|
||||
if (vdev->config->feature(vdev, VIRTIO_BLK_F_BARRIER))
|
||||
blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL);
|
||||
|
||||
err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_CAPACITY, &cap);
|
||||
if (err) {
|
||||
dev_err(&vdev->dev, "Bad/missing capacity in config\n");
|
||||
goto out_cleanup_queue;
|
||||
}
|
||||
/* Host must always specify the capacity. */
|
||||
__virtio_config_val(vdev, offsetof(struct virtio_blk_config, capacity),
|
||||
&cap);
|
||||
|
||||
/* If capacity is too big, truncate with warning. */
|
||||
if ((sector_t)cap != cap) {
|
||||
|
|
@ -234,31 +256,25 @@ static int virtblk_probe(struct virtio_device *vdev)
|
|||
}
|
||||
set_capacity(vblk->disk, cap);
|
||||
|
||||
err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_SIZE_MAX, &v);
|
||||
/* Host can optionally specify maximum segment size and number of
|
||||
* segments. */
|
||||
err = virtio_config_val(vdev, VIRTIO_BLK_F_SIZE_MAX,
|
||||
offsetof(struct virtio_blk_config, size_max),
|
||||
&v);
|
||||
if (!err)
|
||||
blk_queue_max_segment_size(vblk->disk->queue, v);
|
||||
else if (err != -ENOENT) {
|
||||
dev_err(&vdev->dev, "Bad SIZE_MAX in config\n");
|
||||
goto out_cleanup_queue;
|
||||
}
|
||||
|
||||
err = virtio_config_val(vdev, VIRTIO_CONFIG_BLK_F_SEG_MAX, &v);
|
||||
err = virtio_config_val(vdev, VIRTIO_BLK_F_SEG_MAX,
|
||||
offsetof(struct virtio_blk_config, seg_max),
|
||||
&v);
|
||||
if (!err)
|
||||
blk_queue_max_hw_segments(vblk->disk->queue, v);
|
||||
else if (err != -ENOENT) {
|
||||
dev_err(&vdev->dev, "Bad SEG_MAX in config\n");
|
||||
goto out_cleanup_queue;
|
||||
}
|
||||
|
||||
add_disk(vblk->disk);
|
||||
return 0;
|
||||
|
||||
out_cleanup_queue:
|
||||
blk_cleanup_queue(vblk->disk->queue);
|
||||
out_put_disk:
|
||||
put_disk(vblk->disk);
|
||||
out_unregister_blkdev:
|
||||
unregister_blkdev(major, "virtblk");
|
||||
out_mempool:
|
||||
mempool_destroy(vblk->pool);
|
||||
out_free_vq:
|
||||
|
|
@ -274,12 +290,16 @@ static void virtblk_remove(struct virtio_device *vdev)
|
|||
struct virtio_blk *vblk = vdev->priv;
|
||||
int major = vblk->disk->major;
|
||||
|
||||
/* Nothing should be pending. */
|
||||
BUG_ON(!list_empty(&vblk->reqs));
|
||||
|
||||
/* Stop all the virtqueues. */
|
||||
vdev->config->reset(vdev);
|
||||
|
||||
blk_cleanup_queue(vblk->disk->queue);
|
||||
put_disk(vblk->disk);
|
||||
unregister_blkdev(major, "virtblk");
|
||||
mempool_destroy(vblk->pool);
|
||||
/* There should be nothing in the queue now, so no need to shutdown */
|
||||
vdev->config->del_vq(vblk->vq);
|
||||
kfree(vblk);
|
||||
}
|
||||
|
|
@ -299,11 +319,15 @@ static struct virtio_driver virtio_blk = {
|
|||
|
||||
static int __init init(void)
|
||||
{
|
||||
major = register_blkdev(0, "virtblk");
|
||||
if (major < 0)
|
||||
return major;
|
||||
return register_virtio_driver(&virtio_blk);
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
unregister_blkdev(major, "virtblk");
|
||||
unregister_virtio_driver(&virtio_blk);
|
||||
}
|
||||
module_init(init);
|
||||
|
|
|
|||
Loading…
Reference in a new issue