aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/lguest/lguest_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/lguest/lguest_device.c')
-rw-r--r--drivers/lguest/lguest_device.c37
1 files changed, 22 insertions, 15 deletions
diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c
index 69c84a1d88ea..5289ffa2e500 100644
--- a/drivers/lguest/lguest_device.c
+++ b/drivers/lguest/lguest_device.c
@@ -109,6 +109,17 @@ static u32 lg_get_features(struct virtio_device *vdev)
109} 109}
110 110
111/* 111/*
112 * To notify on reset or feature finalization, we (ab)use the NOTIFY
113 * hypercall, with the descriptor address of the device.
114 */
115static void status_notify(struct virtio_device *vdev)
116{
117 unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices;
118
119 hcall(LHCALL_NOTIFY, (max_pfn << PAGE_SHIFT) + offset, 0, 0, 0);
120}
121
122/*
112 * The virtio core takes the features the Host offers, and copies the ones 123 * The virtio core takes the features the Host offers, and copies the ones
113 * supported by the driver into the vdev->features array. Once that's all 124 * supported by the driver into the vdev->features array. Once that's all
114 * sorted out, this routine is called so we can tell the Host which features we 125 * sorted out, this routine is called so we can tell the Host which features we
@@ -135,6 +146,9 @@ static void lg_finalize_features(struct virtio_device *vdev)
135 if (test_bit(i, vdev->features)) 146 if (test_bit(i, vdev->features))
136 out_features[i / 8] |= (1 << (i % 8)); 147 out_features[i / 8] |= (1 << (i % 8));
137 } 148 }
149
150 /* Tell Host we've finished with this device's feature negotiation */
151 status_notify(vdev);
138} 152}
139 153
140/* Once they've found a field, getting a copy of it is easy. */ 154/* Once they've found a field, getting a copy of it is easy. */
@@ -168,28 +182,21 @@ static u8 lg_get_status(struct virtio_device *vdev)
168 return to_lgdev(vdev)->desc->status; 182 return to_lgdev(vdev)->desc->status;
169} 183}
170 184
171/*
172 * To notify on status updates, we (ab)use the NOTIFY hypercall, with the
173 * descriptor address of the device. A zero status means "reset".
174 */
175static void set_status(struct virtio_device *vdev, u8 status)
176{
177 unsigned long offset = (void *)to_lgdev(vdev)->desc - lguest_devices;
178
179 /* We set the status. */
180 to_lgdev(vdev)->desc->status = status;
181 hcall(LHCALL_NOTIFY, (max_pfn << PAGE_SHIFT) + offset, 0, 0, 0);
182}
183
184static void lg_set_status(struct virtio_device *vdev, u8 status) 185static void lg_set_status(struct virtio_device *vdev, u8 status)
185{ 186{
186 BUG_ON(!status); 187 BUG_ON(!status);
187 set_status(vdev, status); 188 to_lgdev(vdev)->desc->status = status;
189
190 /* Tell Host immediately if we failed. */
191 if (status & VIRTIO_CONFIG_S_FAILED)
192 status_notify(vdev);
188} 193}
189 194
190static void lg_reset(struct virtio_device *vdev) 195static void lg_reset(struct virtio_device *vdev)
191{ 196{
192 set_status(vdev, 0); 197 /* 0 status means "reset" */
198 to_lgdev(vdev)->desc->status = 0;
199 status_notify(vdev);
193} 200}
194 201
195/* 202/*