diff options
Diffstat (limited to 'drivers/lguest')
-rw-r--r-- | drivers/lguest/lguest_device.c | 37 |
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 | */ | ||
115 | static 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 | */ | ||
175 | static 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 | |||
184 | static void lg_set_status(struct virtio_device *vdev, u8 status) | 185 | static 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 | ||
190 | static void lg_reset(struct virtio_device *vdev) | 195 | static 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 | /* |