aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/driver-api/uio-howto.rst4
-rw-r--r--drivers/uio/uio_hv_generic.c19
2 files changed, 23 insertions, 0 deletions
diff --git a/Documentation/driver-api/uio-howto.rst b/Documentation/driver-api/uio-howto.rst
index 97e6435b3934..693e3bd84e79 100644
--- a/Documentation/driver-api/uio-howto.rst
+++ b/Documentation/driver-api/uio-howto.rst
@@ -698,6 +698,10 @@ prevents the device from generating further interrupts until the bit is
cleared. The userspace driver should clear this bit before blocking and
waiting for more interrupts.
+When host rescinds a device, the interrupt file descriptor is marked down
+and any reads of the interrupt file descriptor will return -EIO. Similar
+to a closed socket or disconnected serial device.
+
The vmbus device regions are mapped into uio device resources:
0) Channel ring buffers: guest to host and host to guest
1) Guest to host interrupt signalling pages
diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c
index ee6d862ef4bd..8c6b04a26c47 100644
--- a/drivers/uio/uio_hv_generic.c
+++ b/drivers/uio/uio_hv_generic.c
@@ -103,6 +103,23 @@ static void hv_uio_channel_cb(void *context)
uio_event_notify(&pdata->info);
}
+/*
+ * Callback from vmbus_event when channel is rescinded.
+ */
+static void hv_uio_rescind(struct vmbus_channel *channel)
+{
+ struct hv_device *hv_dev = channel->primary_channel->device_obj;
+ struct hv_uio_private_data *pdata = hv_get_drvdata(hv_dev);
+
+ /*
+ * Turn off the interrupt file handle
+ * Next read for event will return -EIO
+ */
+ pdata->info.irq = 0;
+
+ /* Wake up reader */
+ uio_event_notify(&pdata->info);
+}
static void
hv_uio_cleanup(struct hv_device *dev, struct hv_uio_private_data *pdata)
@@ -218,6 +235,8 @@ hv_uio_probe(struct hv_device *dev,
goto fail_close;
}
+ vmbus_set_chn_rescind_callback(dev->channel, hv_uio_rescind);
+
hv_set_drvdata(dev, pdata);
return 0;