mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-02-24 17:06:35 -05:00
drivers/hv: introduce vmbus_channel_set_cpu()
The core functionality in target_cpu_store() is also needed in a subsequent patch for automatically changing the CPU when taking a CPU offline. As such, factor out the body of target_cpu_store() into new function vmbus_channel_set_cpu() that can also be used elsewhere. No functional change is intended. Cc: Boqun Feng <boqun.feng@gmail.com> Cc: Michael Kelley <mhklinux@outlook.com> Cc: Wei Liu <wei.liu@kernel.org> Signed-off-by: Hamza Mahfooz <hamzamahfooz@linux.microsoft.com> Reviewed-by: Michael Kelley <mhklinux@outlook.com> Tested-by: Michael Kelley <mhklinux@outlook.com> Link: https://lore.kernel.org/r/20250117203309.192072-2-hamzamahfooz@linux.microsoft.com Signed-off-by: Wei Liu <wei.liu@kernel.org> Message-ID: <20250117203309.192072-2-hamzamahfooz@linux.microsoft.com>
This commit is contained in:
@@ -1611,18 +1611,18 @@ static ssize_t target_cpu_show(struct vmbus_channel *channel, char *buf)
|
||||
{
|
||||
return sprintf(buf, "%u\n", channel->target_cpu);
|
||||
}
|
||||
static ssize_t target_cpu_store(struct vmbus_channel *channel,
|
||||
const char *buf, size_t count)
|
||||
|
||||
int vmbus_channel_set_cpu(struct vmbus_channel *channel, u32 target_cpu)
|
||||
{
|
||||
u32 target_cpu, origin_cpu;
|
||||
ssize_t ret = count;
|
||||
u32 origin_cpu;
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_cpus_held();
|
||||
lockdep_assert_held(&vmbus_connection.channel_mutex);
|
||||
|
||||
if (vmbus_proto_version < VERSION_WIN10_V4_1)
|
||||
return -EIO;
|
||||
|
||||
if (sscanf(buf, "%uu", &target_cpu) != 1)
|
||||
return -EIO;
|
||||
|
||||
/* Validate target_cpu for the cpumask_test_cpu() operation below. */
|
||||
if (target_cpu >= nr_cpumask_bits)
|
||||
return -EINVAL;
|
||||
@@ -1630,22 +1630,17 @@ static ssize_t target_cpu_store(struct vmbus_channel *channel,
|
||||
if (!cpumask_test_cpu(target_cpu, housekeeping_cpumask(HK_TYPE_MANAGED_IRQ)))
|
||||
return -EINVAL;
|
||||
|
||||
/* No CPUs should come up or down during this. */
|
||||
cpus_read_lock();
|
||||
|
||||
if (!cpu_online(target_cpu)) {
|
||||
cpus_read_unlock();
|
||||
if (!cpu_online(target_cpu))
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Synchronizes target_cpu_store() and channel closure:
|
||||
* Synchronizes vmbus_channel_set_cpu() and channel closure:
|
||||
*
|
||||
* { Initially: state = CHANNEL_OPENED }
|
||||
*
|
||||
* CPU1 CPU2
|
||||
*
|
||||
* [target_cpu_store()] [vmbus_disconnect_ring()]
|
||||
* [vmbus_channel_set_cpu()] [vmbus_disconnect_ring()]
|
||||
*
|
||||
* LOCK channel_mutex LOCK channel_mutex
|
||||
* LOAD r1 = state LOAD r2 = state
|
||||
@@ -1660,7 +1655,6 @@ static ssize_t target_cpu_store(struct vmbus_channel *channel,
|
||||
* Note. The host processes the channel messages "sequentially", in
|
||||
* the order in which they are received on a per-partition basis.
|
||||
*/
|
||||
mutex_lock(&vmbus_connection.channel_mutex);
|
||||
|
||||
/*
|
||||
* Hyper-V will ignore MODIFYCHANNEL messages for "non-open" channels;
|
||||
@@ -1668,17 +1662,17 @@ static ssize_t target_cpu_store(struct vmbus_channel *channel,
|
||||
*/
|
||||
if (channel->state != CHANNEL_OPENED_STATE) {
|
||||
ret = -EIO;
|
||||
goto cpu_store_unlock;
|
||||
goto end;
|
||||
}
|
||||
|
||||
origin_cpu = channel->target_cpu;
|
||||
if (target_cpu == origin_cpu)
|
||||
goto cpu_store_unlock;
|
||||
goto end;
|
||||
|
||||
if (vmbus_send_modifychannel(channel,
|
||||
hv_cpu_number_to_vp_number(target_cpu))) {
|
||||
ret = -EIO;
|
||||
goto cpu_store_unlock;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1708,10 +1702,26 @@ static ssize_t target_cpu_store(struct vmbus_channel *channel,
|
||||
origin_cpu, target_cpu);
|
||||
}
|
||||
|
||||
cpu_store_unlock:
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t target_cpu_store(struct vmbus_channel *channel,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
u32 target_cpu;
|
||||
ssize_t ret;
|
||||
|
||||
if (sscanf(buf, "%uu", &target_cpu) != 1)
|
||||
return -EIO;
|
||||
|
||||
cpus_read_lock();
|
||||
mutex_lock(&vmbus_connection.channel_mutex);
|
||||
ret = vmbus_channel_set_cpu(channel, target_cpu);
|
||||
mutex_unlock(&vmbus_connection.channel_mutex);
|
||||
cpus_read_unlock();
|
||||
return ret;
|
||||
|
||||
return ret ?: count;
|
||||
}
|
||||
static VMBUS_CHAN_ATTR(cpu, 0644, target_cpu_show, target_cpu_store);
|
||||
|
||||
|
||||
@@ -1661,6 +1661,7 @@ int vmbus_send_tl_connect_request(const guid_t *shv_guest_servie_id,
|
||||
const guid_t *shv_host_servie_id);
|
||||
int vmbus_send_modifychannel(struct vmbus_channel *channel, u32 target_vp);
|
||||
void vmbus_set_event(struct vmbus_channel *channel);
|
||||
int vmbus_channel_set_cpu(struct vmbus_channel *channel, u32 target_cpu);
|
||||
|
||||
/* Get the start of the ring buffer. */
|
||||
static inline void *
|
||||
|
||||
Reference in New Issue
Block a user