Virtio patches, mainly hotplugging fixes.
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJQFgcxAAoJENkgDmzRrbjxQKkP/A0Vuz9ltiRuaMys5Q6nwPYz pHB1VfTNhCAI+fW8AY3imZD6RngBRk9frezRGkhTwxM33QRPAfZOLUQd0d6PoVD5 rTw8uuA1PwuQIsKAHrFZ27nrdqKb6bWid7tW8ABfpxQzQrVAm3PeUFfvnTT9BsIU OGiZXQkmojgnuIzJjd1wCBroWCrVyIyR4SJcx6ODYlUNOYdwVbi+jiohsZ23iG5h cAYQna4y4UDK16LmTHg7xxnB7WDCD1ZZ1gBNeJBM+f0F1S2xxK50NSpqGoq367NN 6QRsZM9mqofMRZgpYSe6Yl9wd/STiMFysNiQHwhSkvhnT+Sf2gpAcZZ570gGdNMN CR90RcaK+IDJ9i4XMs2LVcjnt3uEznpKhgpq0Lvnw2S0P7KUCbR8ti+jR8LZR/8F eSVcvEJKOzZSWp6P6BHSHK1K/D/b31/qKXEESAnGGVNRheq4o5jA2TvyzDCAAohH Y70KCNYO/kqiZGM1bbb/VvmiiaD/aYRHQOg8Ef7wjVE/0HoMRR5xQeW7tonw2krZ 35//eT0AJimAhdZCaw+JkANw+wI+bIQGc8IjHZhvWzSRWH0Fb5SJAWhV7urD4O6K Nbzclzx2aB6ZNmIsh9cCaJ4a+/i0jO1ql/VJYwBMmwcRLlrYdjLLX/SXcBCY/KFj yFPzDMqQCOJm9grTxn1m =kIHV -----END PGP SIGNATURE----- Merge tag 'virtio-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus Pull virtio update from Rusty Russell: "Virtio patches, mainly hotplugging fixes." * tag 'virtio-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus: virtio-blk: return VIRTIO_BLK_F_FLUSH to header. virtio-blk: allow toggling host cache between writeback and writethrough virtio-blk: Use block layer provided spinlock virtio-blk: Reset device after blk_cleanup_queue() virtio-blk: Call del_gendisk() before disable guest kick virtio: rng: s3/s4 support virtio: rng: split out common code in probe / remove for s3/s4 ops virtio: rng: don't wait on host when module is going away virtio: rng: allow tasks to be killed that are waiting for rng input virtio ids: fix comment for virtio-rng
This commit is contained in:
commit
95b18e6995
|
@ -21,8 +21,6 @@ struct workqueue_struct *virtblk_wq;
|
|||
|
||||
struct virtio_blk
|
||||
{
|
||||
spinlock_t lock;
|
||||
|
||||
struct virtio_device *vdev;
|
||||
struct virtqueue *vq;
|
||||
|
||||
|
@ -65,7 +63,7 @@ static void blk_done(struct virtqueue *vq)
|
|||
unsigned int len;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&vblk->lock, flags);
|
||||
spin_lock_irqsave(vblk->disk->queue->queue_lock, flags);
|
||||
while ((vbr = virtqueue_get_buf(vblk->vq, &len)) != NULL) {
|
||||
int error;
|
||||
|
||||
|
@ -99,7 +97,7 @@ static void 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);
|
||||
spin_unlock_irqrestore(vblk->disk->queue->queue_lock, flags);
|
||||
}
|
||||
|
||||
static bool do_req(struct request_queue *q, struct virtio_blk *vblk,
|
||||
|
@ -397,6 +395,83 @@ static int virtblk_name_format(char *prefix, int index, char *buf, int buflen)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int virtblk_get_cache_mode(struct virtio_device *vdev)
|
||||
{
|
||||
u8 writeback;
|
||||
int err;
|
||||
|
||||
err = virtio_config_val(vdev, VIRTIO_BLK_F_CONFIG_WCE,
|
||||
offsetof(struct virtio_blk_config, wce),
|
||||
&writeback);
|
||||
if (err)
|
||||
writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE);
|
||||
|
||||
return writeback;
|
||||
}
|
||||
|
||||
static void virtblk_update_cache_mode(struct virtio_device *vdev)
|
||||
{
|
||||
u8 writeback = virtblk_get_cache_mode(vdev);
|
||||
struct virtio_blk *vblk = vdev->priv;
|
||||
|
||||
if (writeback)
|
||||
blk_queue_flush(vblk->disk->queue, REQ_FLUSH);
|
||||
else
|
||||
blk_queue_flush(vblk->disk->queue, 0);
|
||||
|
||||
revalidate_disk(vblk->disk);
|
||||
}
|
||||
|
||||
static const char *const virtblk_cache_types[] = {
|
||||
"write through", "write back"
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
virtblk_cache_type_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
struct virtio_blk *vblk = disk->private_data;
|
||||
struct virtio_device *vdev = vblk->vdev;
|
||||
int i;
|
||||
u8 writeback;
|
||||
|
||||
BUG_ON(!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_CONFIG_WCE));
|
||||
for (i = ARRAY_SIZE(virtblk_cache_types); --i >= 0; )
|
||||
if (sysfs_streq(buf, virtblk_cache_types[i]))
|
||||
break;
|
||||
|
||||
if (i < 0)
|
||||
return -EINVAL;
|
||||
|
||||
writeback = i;
|
||||
vdev->config->set(vdev,
|
||||
offsetof(struct virtio_blk_config, wce),
|
||||
&writeback, sizeof(writeback));
|
||||
|
||||
virtblk_update_cache_mode(vdev);
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
virtblk_cache_type_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct gendisk *disk = dev_to_disk(dev);
|
||||
struct virtio_blk *vblk = disk->private_data;
|
||||
u8 writeback = virtblk_get_cache_mode(vblk->vdev);
|
||||
|
||||
BUG_ON(writeback >= ARRAY_SIZE(virtblk_cache_types));
|
||||
return snprintf(buf, 40, "%s\n", virtblk_cache_types[writeback]);
|
||||
}
|
||||
|
||||
static const struct device_attribute dev_attr_cache_type_ro =
|
||||
__ATTR(cache_type, S_IRUGO,
|
||||
virtblk_cache_type_show, NULL);
|
||||
static const struct device_attribute dev_attr_cache_type_rw =
|
||||
__ATTR(cache_type, S_IRUGO|S_IWUSR,
|
||||
virtblk_cache_type_show, virtblk_cache_type_store);
|
||||
|
||||
static int __devinit virtblk_probe(struct virtio_device *vdev)
|
||||
{
|
||||
struct virtio_blk *vblk;
|
||||
|
@ -431,7 +506,6 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
|
|||
goto out_free_index;
|
||||
}
|
||||
|
||||
spin_lock_init(&vblk->lock);
|
||||
vblk->vdev = vdev;
|
||||
vblk->sg_elems = sg_elems;
|
||||
sg_init_table(vblk->sg, vblk->sg_elems);
|
||||
|
@ -456,7 +530,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
|
|||
goto out_mempool;
|
||||
}
|
||||
|
||||
q = vblk->disk->queue = blk_init_queue(do_virtblk_request, &vblk->lock);
|
||||
q = vblk->disk->queue = blk_init_queue(do_virtblk_request, NULL);
|
||||
if (!q) {
|
||||
err = -ENOMEM;
|
||||
goto out_put_disk;
|
||||
|
@ -474,8 +548,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
|
|||
vblk->index = index;
|
||||
|
||||
/* configure queue flush support */
|
||||
if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH))
|
||||
blk_queue_flush(q, REQ_FLUSH);
|
||||
virtblk_update_cache_mode(vdev);
|
||||
|
||||
/* If disk is read-only in the host, the guest should obey */
|
||||
if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO))
|
||||
|
@ -553,6 +626,14 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
|
|||
if (err)
|
||||
goto out_del_disk;
|
||||
|
||||
if (virtio_has_feature(vdev, VIRTIO_BLK_F_CONFIG_WCE))
|
||||
err = device_create_file(disk_to_dev(vblk->disk),
|
||||
&dev_attr_cache_type_rw);
|
||||
else
|
||||
err = device_create_file(disk_to_dev(vblk->disk),
|
||||
&dev_attr_cache_type_ro);
|
||||
if (err)
|
||||
goto out_del_disk;
|
||||
return 0;
|
||||
|
||||
out_del_disk:
|
||||
|
@ -576,30 +657,20 @@ static void __devexit virtblk_remove(struct virtio_device *vdev)
|
|||
{
|
||||
struct virtio_blk *vblk = vdev->priv;
|
||||
int index = vblk->index;
|
||||
struct virtblk_req *vbr;
|
||||
unsigned long flags;
|
||||
|
||||
/* Prevent config work handler from accessing the device. */
|
||||
mutex_lock(&vblk->config_lock);
|
||||
vblk->config_enable = false;
|
||||
mutex_unlock(&vblk->config_lock);
|
||||
|
||||
del_gendisk(vblk->disk);
|
||||
blk_cleanup_queue(vblk->disk->queue);
|
||||
|
||||
/* Stop all the virtqueues. */
|
||||
vdev->config->reset(vdev);
|
||||
|
||||
flush_work(&vblk->config_work);
|
||||
|
||||
del_gendisk(vblk->disk);
|
||||
|
||||
/* Abort requests dispatched to driver. */
|
||||
spin_lock_irqsave(&vblk->lock, flags);
|
||||
while ((vbr = virtqueue_detach_unused_buf(vblk->vq))) {
|
||||
__blk_end_request_all(vbr->req, -EIO);
|
||||
mempool_free(vbr, vblk->pool);
|
||||
}
|
||||
spin_unlock_irqrestore(&vblk->lock, flags);
|
||||
|
||||
blk_cleanup_queue(vblk->disk->queue);
|
||||
put_disk(vblk->disk);
|
||||
mempool_destroy(vblk->pool);
|
||||
vdev->config->del_vqs(vdev);
|
||||
|
@ -655,7 +726,7 @@ static const struct virtio_device_id id_table[] = {
|
|||
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_SCSI,
|
||||
VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_TOPOLOGY
|
||||
VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -55,6 +55,7 @@ static void register_buffer(u8 *buf, size_t size)
|
|||
|
||||
static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!busy) {
|
||||
busy = true;
|
||||
|
@ -65,7 +66,9 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
|
|||
if (!wait)
|
||||
return 0;
|
||||
|
||||
wait_for_completion(&have_data);
|
||||
ret = wait_for_completion_killable(&have_data);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
busy = false;
|
||||
|
||||
|
@ -85,7 +88,7 @@ static struct hwrng virtio_hwrng = {
|
|||
.read = virtio_read,
|
||||
};
|
||||
|
||||
static int virtrng_probe(struct virtio_device *vdev)
|
||||
static int probe_common(struct virtio_device *vdev)
|
||||
{
|
||||
int err;
|
||||
|
||||
|
@ -103,13 +106,37 @@ static int virtrng_probe(struct virtio_device *vdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void __devexit virtrng_remove(struct virtio_device *vdev)
|
||||
static void remove_common(struct virtio_device *vdev)
|
||||
{
|
||||
vdev->config->reset(vdev);
|
||||
busy = false;
|
||||
hwrng_unregister(&virtio_hwrng);
|
||||
vdev->config->del_vqs(vdev);
|
||||
}
|
||||
|
||||
static int virtrng_probe(struct virtio_device *vdev)
|
||||
{
|
||||
return probe_common(vdev);
|
||||
}
|
||||
|
||||
static void __devexit virtrng_remove(struct virtio_device *vdev)
|
||||
{
|
||||
remove_common(vdev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static int virtrng_freeze(struct virtio_device *vdev)
|
||||
{
|
||||
remove_common(vdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int virtrng_restore(struct virtio_device *vdev)
|
||||
{
|
||||
return probe_common(vdev);
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct virtio_device_id id_table[] = {
|
||||
{ VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID },
|
||||
{ 0 },
|
||||
|
@ -121,6 +148,10 @@ static struct virtio_driver virtio_rng_driver = {
|
|||
.id_table = id_table,
|
||||
.probe = virtrng_probe,
|
||||
.remove = __devexit_p(virtrng_remove),
|
||||
#ifdef CONFIG_PM
|
||||
.freeze = virtrng_freeze,
|
||||
.restore = virtrng_restore,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
|
|
|
@ -37,8 +37,14 @@
|
|||
#define VIRTIO_BLK_F_RO 5 /* Disk is read-only */
|
||||
#define VIRTIO_BLK_F_BLK_SIZE 6 /* Block size of disk is available*/
|
||||
#define VIRTIO_BLK_F_SCSI 7 /* Supports scsi command passthru */
|
||||
#define VIRTIO_BLK_F_FLUSH 9 /* Cache flush command support */
|
||||
#define VIRTIO_BLK_F_WCE 9 /* Writeback mode enabled after reset */
|
||||
#define VIRTIO_BLK_F_TOPOLOGY 10 /* Topology information is available */
|
||||
#define VIRTIO_BLK_F_CONFIG_WCE 11 /* Writeback mode available in config */
|
||||
|
||||
#ifndef __KERNEL__
|
||||
/* Old (deprecated) name for VIRTIO_BLK_F_WCE. */
|
||||
#define VIRTIO_BLK_F_FLUSH VIRTIO_BLK_F_WCE
|
||||
#endif
|
||||
|
||||
#define VIRTIO_BLK_ID_BYTES 20 /* ID string length */
|
||||
|
||||
|
@ -69,6 +75,8 @@ struct virtio_blk_config {
|
|||
/* optimal sustained I/O size in logical blocks. */
|
||||
__u32 opt_io_size;
|
||||
|
||||
/* writeback mode (if VIRTIO_BLK_F_CONFIG_WCE) */
|
||||
__u8 wce;
|
||||
} __attribute__((packed));
|
||||
|
||||
/*
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#define VIRTIO_ID_NET 1 /* virtio net */
|
||||
#define VIRTIO_ID_BLOCK 2 /* virtio block */
|
||||
#define VIRTIO_ID_CONSOLE 3 /* virtio console */
|
||||
#define VIRTIO_ID_RNG 4 /* virtio ring */
|
||||
#define VIRTIO_ID_RNG 4 /* virtio rng */
|
||||
#define VIRTIO_ID_BALLOON 5 /* virtio balloon */
|
||||
#define VIRTIO_ID_RPMSG 7 /* virtio remote processor messaging */
|
||||
#define VIRTIO_ID_SCSI 8 /* virtio scsi */
|
||||
|
|
Loading…
Reference in New Issue