Commit 5e4304ff authored by Hamza Mahfooz's avatar Hamza Mahfooz Committed by Wei Liu
Browse files

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: default avatarHamza Mahfooz <hamzamahfooz@linux.microsoft.com>
Reviewed-by: default avatarMichael Kelley <mhklinux@outlook.com>
Tested-by: default avatarMichael Kelley <mhklinux@outlook.com>
Link: https://lore.kernel.org/r/20250117203309.192072-2-hamzamahfooz@linux.microsoft.com


Signed-off-by: default avatarWei Liu <wei.liu@kernel.org>
Message-ID: <20250117203309.192072-2-hamzamahfooz@linux.microsoft.com>
parent 7c0db8a4
Loading
Loading
Loading
Loading
+31 −21
Original line number Diff line number Diff line
@@ -1611,16 +1611,16 @@ 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;

	if (vmbus_proto_version < VERSION_WIN10_V4_1)
		return -EIO;
	lockdep_assert_cpus_held();
	lockdep_assert_held(&vmbus_connection.channel_mutex);

	if (sscanf(buf, "%uu", &target_cpu) != 1)
	if (vmbus_proto_version < VERSION_WIN10_V4_1)
		return -EIO;

	/* Validate target_cpu for the cpumask_test_cpu() operation below. */
@@ -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);

+1 −0
Original line number Diff line number Diff line
@@ -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 *