From ce67355791c0537d8e9b574f73f3287a14a62357 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 2 May 2008 21:50:53 -0500 Subject: [PATCH] --- yaml --- r: 95767 b: refs/heads/master c: a007a751d98fe97142e4724a83a4e31ec66b7532 h: refs/heads/master i: 95765: 117e48b623a147e0bbb4925725f54be7a1b369e0 95763: f69f21891027d5f928e7c4231b27341aabb17aa5 95759: d871c940ed6b66c0c2786739ebd6587174a115c3 v: v3 --- [refs] | 2 +- trunk/Documentation/lguest/lguest.c | 50 +++++++++++++++++++--------- trunk/drivers/lguest/lguest_device.c | 20 +++++++---- 3 files changed, 49 insertions(+), 23 deletions(-) diff --git a/[refs] b/[refs] index f13f17301fb6..650b20873119 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9f3f746741d917fe3c6c544c7d319d533176d90b +refs/heads/master: a007a751d98fe97142e4724a83a4e31ec66b7532 diff --git a/trunk/Documentation/lguest/lguest.c b/trunk/Documentation/lguest/lguest.c index 5cd705c3d75b..3be8ab2a886a 100644 --- a/trunk/Documentation/lguest/lguest.c +++ b/trunk/Documentation/lguest/lguest.c @@ -131,6 +131,9 @@ struct device /* Any queues attached to this device */ struct virtqueue *vq; + /* Handle status being finalized (ie. feature bits stable). */ + void (*ready)(struct device *me); + /* Device-specific data. */ void *priv; }; @@ -925,24 +928,40 @@ static void enable_fd(int fd, struct virtqueue *vq) write(waker_fd, &vq->dev->fd, sizeof(vq->dev->fd)); } -/* When the Guest asks us to reset a device, it's is fairly easy. */ -static void reset_device(struct device *dev) +/* When the Guest tells us they updated the status field, we handle it. */ +static void update_device_status(struct device *dev) { struct virtqueue *vq; - verbose("Resetting device %s\n", dev->name); - /* Clear the status. */ - dev->desc->status = 0; + /* This is a reset. */ + if (dev->desc->status == 0) { + verbose("Resetting device %s\n", dev->name); - /* Clear any features they've acked. */ - memset(get_feature_bits(dev) + dev->desc->feature_len, 0, - dev->desc->feature_len); + /* Clear any features they've acked. */ + memset(get_feature_bits(dev) + dev->desc->feature_len, 0, + dev->desc->feature_len); - /* Zero out the virtqueues. */ - for (vq = dev->vq; vq; vq = vq->next) { - memset(vq->vring.desc, 0, - vring_size(vq->config.num, getpagesize())); - vq->last_avail_idx = 0; + /* Zero out the virtqueues. */ + for (vq = dev->vq; vq; vq = vq->next) { + memset(vq->vring.desc, 0, + vring_size(vq->config.num, getpagesize())); + vq->last_avail_idx = 0; + } + } else if (dev->desc->status & VIRTIO_CONFIG_S_FAILED) { + warnx("Device %s configuration FAILED", dev->name); + } else if (dev->desc->status & VIRTIO_CONFIG_S_DRIVER_OK) { + unsigned int i; + + verbose("Device %s OK: offered", dev->name); + for (i = 0; i < dev->desc->feature_len; i++) + verbose(" %08x", get_feature_bits(dev)[i]); + verbose(", accepted"); + for (i = 0; i < dev->desc->feature_len; i++) + verbose(" %08x", get_feature_bits(dev) + [dev->desc->feature_len+i]); + + if (dev->ready) + dev->ready(dev); } } @@ -954,9 +973,9 @@ static void handle_output(int fd, unsigned long addr) /* Check each device and virtqueue. */ for (i = devices.dev; i; i = i->next) { - /* Notifications to device descriptors reset the device. */ + /* Notifications to device descriptors update device status. */ if (from_guest_phys(addr) == i->desc) { - reset_device(i); + update_device_status(i); return; } @@ -1170,6 +1189,7 @@ static struct device *new_device(const char *name, u16 type, int fd, dev->handle_input = handle_input; dev->name = name; dev->vq = NULL; + dev->ready = NULL; /* Append to device list. Prepending to a single-linked list is * easier, but the user expects the devices to be arranged on the bus diff --git a/trunk/drivers/lguest/lguest_device.c b/trunk/drivers/lguest/lguest_device.c index 7a643a6ee9a1..8080249957af 100644 --- a/trunk/drivers/lguest/lguest_device.c +++ b/trunk/drivers/lguest/lguest_device.c @@ -144,20 +144,26 @@ static u8 lg_get_status(struct virtio_device *vdev) return to_lgdev(vdev)->desc->status; } +/* To notify on status updates, we (ab)use the NOTIFY hypercall, with the + * descriptor address of the device. A zero status means "reset". */ +static void set_status(struct virtio_device *vdev, u8 status) +{ + unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices; + + /* We set the status. */ + to_lgdev(vdev)->desc->status = status; + hcall(LHCALL_NOTIFY, (max_pfn<desc->status = status; + set_status(vdev, status); } -/* To reset the device, we (ab)use the NOTIFY hypercall, with the descriptor - * address of the device. The Host will zero the status and all the - * features. */ static void lg_reset(struct virtio_device *vdev) { - unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices; - - hcall(LHCALL_NOTIFY, (max_pfn<