summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrea Parri (Microsoft) <parri.andrea@gmail.com>2020-04-06 02:15:08 +0200
committerWei Liu <wei.liu@kernel.org>2020-04-23 13:17:11 +0000
commit238d2ed8f7d1b1ca0c13334bb8197a42654af946 (patch)
treea158a1982bd4b0e85cae1d26110706bbeb457dc4
parentac5047671758ad4be9f93898247b3a8b6dfde4c7 (diff)
hv_utils: Always execute the fcopy and vss callbacks in a tasklet
The fcopy and vss callback functions could be running in a tasklet at the same time they are called in hv_poll_channel(). Current code serializes the invocations of these functions, and their accesses to the channel ring buffer, by sending an IPI to the CPU that is allowed to access the ring buffer, cf. hv_poll_channel(). This IPI mechanism becomes infeasible if we allow changing the CPU that a channel will interrupt. Instead modify the callback wrappers to always execute the fcopy and vss callbacks in a tasklet, thus mirroring the solution for the kvp callback functions adopted since commit a3ade8cc474d8 ("HV: properly delay KVP packets when negotiation is in progress"). This will ensure that the callback function can't run on two CPUs at the same time. Suggested-by: Michael Kelley <mikelley@microsoft.com> Signed-off-by: Andrea Parri (Microsoft) <parri.andrea@gmail.com> Link: https://lore.kernel.org/r/20200406001514.19876-6-parri.andrea@gmail.com Reviewed-by: Michael Kelley <mikelley@microsoft.com> Signed-off-by: Wei Liu <wei.liu@kernel.org>
-rw-r--r--drivers/hv/hv_fcopy.c2
-rw-r--r--drivers/hv/hv_snapshot.c2
-rw-r--r--drivers/hv/hyperv_vmbus.h7
3 files changed, 3 insertions, 8 deletions
diff --git a/drivers/hv/hv_fcopy.c b/drivers/hv/hv_fcopy.c
index bb9ba3f7c794..5040d7e0cd9e 100644
--- a/drivers/hv/hv_fcopy.c
+++ b/drivers/hv/hv_fcopy.c
@@ -71,7 +71,7 @@ static void fcopy_poll_wrapper(void *channel)
{
/* Transaction is finished, reset the state here to avoid races. */
fcopy_transaction.state = HVUTIL_READY;
- hv_fcopy_onchannelcallback(channel);
+ tasklet_schedule(&((struct vmbus_channel *)channel)->callback_event);
}
static void fcopy_timeout_func(struct work_struct *dummy)
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c
index 1c75b38f0d6d..783779e4cc1a 100644
--- a/drivers/hv/hv_snapshot.c
+++ b/drivers/hv/hv_snapshot.c
@@ -80,7 +80,7 @@ static void vss_poll_wrapper(void *channel)
{
/* Transaction is finished, reset the state here to avoid races. */
vss_transaction.state = HVUTIL_READY;
- hv_vss_onchannelcallback(channel);
+ tasklet_schedule(&((struct vmbus_channel *)channel)->callback_event);
}
/*
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index 3edf993b0fd9..5e5cebe5d048 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -378,12 +378,7 @@ static inline void hv_poll_channel(struct vmbus_channel *channel,
{
if (!channel)
return;
-
- if (in_interrupt() && (channel->target_cpu == smp_processor_id())) {
- cb(channel);
- return;
- }
- smp_call_function_single(channel->target_cpu, cb, channel, true);
+ cb(channel);
}
enum hvutil_device_state {