Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F158236424
D7229.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D7229.id.diff
View Options
Index: head/sys/dev/hyperv/include/hyperv.h
===================================================================
--- head/sys/dev/hyperv/include/hyperv.h
+++ head/sys/dev/hyperv/include/hyperv.h
@@ -281,8 +281,6 @@
vmbus_chan_callback_t cb, void *cbarg);
void hv_vmbus_channel_close(hv_vmbus_channel *channel);
-struct hv_vmbus_channel* vmbus_select_outgoing_channel(struct hv_vmbus_channel *promary);
-
/**
* @brief Get physical address from virtual
*/
Index: head/sys/dev/hyperv/include/vmbus.h
===================================================================
--- head/sys/dev/hyperv/include/vmbus.h
+++ head/sys/dev/hyperv/include/vmbus.h
@@ -96,13 +96,14 @@
void vmbus_chan_cpu_set(struct hv_vmbus_channel *chan, int cpu);
void vmbus_chan_cpu_rr(struct hv_vmbus_channel *chan);
+struct hv_vmbus_channel *
+ vmbus_chan_cpu2chan(struct hv_vmbus_channel *chan, int cpu);
struct hv_vmbus_channel **
vmbus_subchan_get(struct hv_vmbus_channel *pri_chan, int subchan_cnt);
void vmbus_subchan_rel(struct hv_vmbus_channel **subchan, int subchan_cnt);
void vmbus_subchan_drain(struct hv_vmbus_channel *pri_chan);
-
int vmbus_chan_recv(struct hv_vmbus_channel *chan, void *data, int *dlen,
uint64_t *xactid);
int vmbus_chan_recv_pkt(struct hv_vmbus_channel *chan,
Index: head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
===================================================================
--- head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
+++ head/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
@@ -147,6 +147,8 @@
struct hv_storvsc_request hs_init_req;
struct hv_storvsc_request hs_reset_req;
device_t hs_dev;
+
+ struct hv_vmbus_channel *hs_cpu2chan[MAXCPU];
};
@@ -664,7 +666,7 @@
vstor_packet->operation = VSTOR_OPERATION_EXECUTESRB;
- outgoing_channel = vmbus_select_outgoing_channel(sc->hs_chan);
+ outgoing_channel = sc->hs_cpu2chan[curcpu];
mtx_unlock(&request->softc->hs_lock);
if (request->prp_list.gpa_range.gpa_len) {
@@ -870,6 +872,20 @@
return (ret);
}
+static void
+storvsc_create_cpu2chan(struct storvsc_softc *sc)
+{
+ int cpu;
+
+ CPU_FOREACH(cpu) {
+ sc->hs_cpu2chan[cpu] = vmbus_chan_cpu2chan(sc->hs_chan, cpu);
+ if (bootverbose) {
+ device_printf(sc->hs_dev, "cpu%d -> chan%u\n",
+ cpu, sc->hs_cpu2chan[cpu]->ch_id);
+ }
+ }
+}
+
/**
* @brief StorVSC attach function
*
@@ -967,6 +983,9 @@
goto cleanup;
}
+ /* Construct cpu to channel mapping */
+ storvsc_create_cpu2chan(sc);
+
/*
* Create the device queue.
* Hyper-V maps each target to one SCSI HBA
Index: head/sys/dev/hyperv/vmbus/hv_channel.c
===================================================================
--- head/sys/dev/hyperv/vmbus/hv_channel.c
+++ head/sys/dev/hyperv/vmbus/hv_channel.c
@@ -1250,61 +1250,63 @@
mtx_unlock(&sc->vmbus_prichan_lock);
}
-/**
- * @brief Select the best outgoing channel
- *
+/*
* The channel whose vcpu binding is closest to the currect vcpu will
* be selected.
- * If no multi-channel, always select primary channel
- *
- * @param primary - primary channel
+ * If no multi-channel, always select primary channel.
*/
struct hv_vmbus_channel *
-vmbus_select_outgoing_channel(struct hv_vmbus_channel *primary)
+vmbus_chan_cpu2chan(struct hv_vmbus_channel *prichan, int cpu)
{
- hv_vmbus_channel *new_channel = NULL;
- hv_vmbus_channel *outgoing_channel = primary;
- int old_cpu_distance = 0;
- int new_cpu_distance = 0;
- int cur_vcpu = 0;
- int smp_pro_id = PCPU_GET(cpuid);
+ struct hv_vmbus_channel *sel, *chan;
+ uint32_t vcpu, sel_dist;
- if (TAILQ_EMPTY(&primary->ch_subchans)) {
- return outgoing_channel;
- }
+ KASSERT(cpu >= 0 && cpu < mp_ncpus, ("invalid cpuid %d", cpu));
+ if (TAILQ_EMPTY(&prichan->ch_subchans))
+ return prichan;
- if (smp_pro_id >= MAXCPU) {
- return outgoing_channel;
- }
+ vcpu = VMBUS_PCPU_GET(prichan->vmbus_sc, vcpuid, cpu);
- cur_vcpu = VMBUS_PCPU_GET(primary->vmbus_sc, vcpuid, smp_pro_id);
-
- /* XXX need lock */
- TAILQ_FOREACH(new_channel, &primary->ch_subchans, ch_sublink) {
- if ((new_channel->ch_stflags & VMBUS_CHAN_ST_OPENED) == 0) {
- continue;
- }
+#define CHAN_VCPU_DIST(ch, vcpu) \
+ (((ch)->ch_vcpuid > (vcpu)) ? \
+ ((ch)->ch_vcpuid - (vcpu)) : ((vcpu) - (ch)->ch_vcpuid))
- if (new_channel->ch_vcpuid == cur_vcpu){
- return new_channel;
- }
+#define CHAN_SELECT(ch) \
+do { \
+ sel = ch; \
+ sel_dist = CHAN_VCPU_DIST(ch, vcpu); \
+} while (0)
- old_cpu_distance = ((outgoing_channel->ch_vcpuid > cur_vcpu) ?
- (outgoing_channel->ch_vcpuid - cur_vcpu) :
- (cur_vcpu - outgoing_channel->ch_vcpuid));
-
- new_cpu_distance = ((new_channel->ch_vcpuid > cur_vcpu) ?
- (new_channel->ch_vcpuid - cur_vcpu) :
- (cur_vcpu - new_channel->ch_vcpuid));
+ CHAN_SELECT(prichan);
- if (old_cpu_distance < new_cpu_distance) {
+ mtx_lock(&prichan->ch_subchan_lock);
+ TAILQ_FOREACH(chan, &prichan->ch_subchans, ch_sublink) {
+ uint32_t dist;
+
+ KASSERT(chan->ch_stflags & VMBUS_CHAN_ST_OPENED,
+ ("chan%u is not opened", chan->ch_id));
+
+ if (chan->ch_vcpuid == vcpu) {
+ /* Exact match; done */
+ CHAN_SELECT(chan);
+ break;
+ }
+
+ dist = CHAN_VCPU_DIST(chan, vcpu);
+ if (sel_dist <= dist) {
+ /* Far or same distance; skip */
continue;
}
- outgoing_channel = new_channel;
+ /* Select the closer channel. */
+ CHAN_SELECT(chan);
}
+ mtx_unlock(&prichan->ch_subchan_lock);
+
+#undef CHAN_SELECT
+#undef CHAN_VCPU_DIST
- return(outgoing_channel);
+ return sel;
}
struct hv_vmbus_channel **
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, May 31, 4:23 AM (19 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33638020
Default Alt Text
D7229.id.diff (5 KB)
Attached To
Mode
D7229: hyperv/vmbus: Cleanup cpu based channel selection.
Attached
Detach File
Event Timeline
Log In to Comment