aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hv/connection.c33
-rw-r--r--drivers/scsi/storvsc_drv.c9
2 files changed, 23 insertions, 19 deletions
diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c
index eca7afd366d6..9dc27e5d367a 100644
--- a/drivers/hv/connection.c
+++ b/drivers/hv/connection.c
@@ -431,34 +431,29 @@ struct vmbus_channel *relid2channel(u32 relid)
void vmbus_on_event(unsigned long data)
{
struct vmbus_channel *channel = (void *) data;
- unsigned long time_limit = jiffies + 2;
+ void (*callback_fn)(void *context);
trace_vmbus_on_event(channel);
hv_debug_delay_test(channel, INTERRUPT_DELAY);
- do {
- void (*callback_fn)(void *);
- /* A channel once created is persistent even when
- * there is no driver handling the device. An
- * unloading driver sets the onchannel_callback to NULL.
- */
- callback_fn = READ_ONCE(channel->onchannel_callback);
- if (unlikely(callback_fn == NULL))
- return;
-
- (*callback_fn)(channel->channel_callback_context);
+ /* A channel once created is persistent even when
+ * there is no driver handling the device. An
+ * unloading driver sets the onchannel_callback to NULL.
+ */
+ callback_fn = READ_ONCE(channel->onchannel_callback);
+ if (unlikely(!callback_fn))
+ return;
- if (channel->callback_mode != HV_CALL_BATCHED)
- return;
+ (*callback_fn)(channel->channel_callback_context);
- if (likely(hv_end_read(&channel->inbound) == 0))
- return;
+ if (channel->callback_mode != HV_CALL_BATCHED)
+ return;
- hv_begin_read(&channel->inbound);
- } while (likely(time_before(jiffies, time_limit)));
+ if (likely(hv_end_read(&channel->inbound) == 0))
+ return;
- /* The time limit (2 jiffies) has been reached */
+ hv_begin_read(&channel->inbound);
tasklet_schedule(&channel->callback_event);
}
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 8ced292c4b96..398777d3ec15 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -60,6 +60,9 @@
#define VMSTOR_PROTO_VERSION_WIN8_1 VMSTOR_PROTO_VERSION(6, 0)
#define VMSTOR_PROTO_VERSION_WIN10 VMSTOR_PROTO_VERSION(6, 2)
+/* channel callback timeout in ms */
+#define CALLBACK_TIMEOUT 2
+
/* Packet structure describing virtual storage requests. */
enum vstor_packet_operation {
VSTOR_OPERATION_COMPLETE_IO = 1,
@@ -1204,6 +1207,7 @@ static void storvsc_on_channel_callback(void *context)
struct hv_device *device;
struct storvsc_device *stor_device;
struct Scsi_Host *shost;
+ unsigned long time_limit = jiffies + msecs_to_jiffies(CALLBACK_TIMEOUT);
if (channel->primary_channel != NULL)
device = channel->primary_channel->device_obj;
@@ -1224,6 +1228,11 @@ static void storvsc_on_channel_callback(void *context)
u32 minlen = rqst_id ? sizeof(struct vstor_packet) :
sizeof(enum vstor_packet_operation);
+ if (unlikely(time_after(jiffies, time_limit))) {
+ hv_pkt_iter_close(channel);
+ return;
+ }
+
if (pktlen < minlen) {
dev_err(&device->device,
"Invalid pkt: id=%llu, len=%u, minlen=%u\n",