aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hv/channel_mgmt.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 16:57:13 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-21 16:57:13 -0500
commit7ed214ac2095f561a94335ca672b6c42a1ea40ff (patch)
treeda41901bff1d0d8d61170bf362384fdc61deb3ab /drivers/hv/channel_mgmt.c
parent21eaab6d19ed43e82ed39c8deb7f192134fb4a0e (diff)
parent29e5507ae4ab34397f538f06b7070c81a4e4a2bf (diff)
Merge tag 'char-misc-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc
Pull char/misc driver patches from Greg Kroah-Hartman: "Here's the big char/misc driver patches for 3.9-rc1. Nothing major here, just lots of different driver updates (mei, hyperv, ipack, extcon, vmci, etc.). All of these have been in the linux-next tree for a while." * tag 'char-misc-3.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: (209 commits) w1: w1_therm: Add force-pullup option for "broken" sensors w1: ds2482: Added 1-Wire pull-up support to the driver vme: add missing put_device() after device_register() fails extcon: max8997: Use workqueue to check cable state after completing boot of platform extcon: max8997: Set default UART/USB path on probe extcon: max8997: Consolidate duplicate code for checking ADC/CHG cable type extcon: max8997: Set default of ADC debounce time during initialization extcon: max8997: Remove duplicate code related to set H/W line path extcon: max8997: Move defined constant to header file extcon: max77693: Make max77693_extcon_cable static extcon: max8997: Remove unreachable code extcon: max8997: Make max8997_extcon_cable static extcon: max77693: Remove unnecessary goto statement to improve readability extcon: max77693: Convert to devm_input_allocate_device() extcon: gpio: Rename filename of extcon-gpio.c according to kernel naming style CREDITS: update email and address of Harald Hoyer extcon: arizona: Use MICDET for final microphone identification extcon: arizona: Always take the first HPDET reading as the final one extcon: arizona: Clear _trig_sts bits after jack detection extcon: arizona: Don't HPDET magic when headphones are enabled ...
Diffstat (limited to 'drivers/hv/channel_mgmt.c')
-rw-r--r--drivers/hv/channel_mgmt.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c
index 2f84c5cff8d4..53a8600162a5 100644
--- a/drivers/hv/channel_mgmt.c
+++ b/drivers/hv/channel_mgmt.c
@@ -257,6 +257,70 @@ static void vmbus_process_offer(struct work_struct *work)
257 } 257 }
258} 258}
259 259
260enum {
261 IDE = 0,
262 SCSI,
263 NIC,
264 MAX_PERF_CHN,
265};
266
267/*
268 * This is an array of device_ids (device types) that are performance critical.
269 * We attempt to distribute the interrupt load for these devices across
270 * all available CPUs.
271 */
272static const struct hv_vmbus_device_id hp_devs[] = {
273 /* IDE */
274 { HV_IDE_GUID, },
275 /* Storage - SCSI */
276 { HV_SCSI_GUID, },
277 /* Network */
278 { HV_NIC_GUID, },
279};
280
281
282/*
283 * We use this state to statically distribute the channel interrupt load.
284 */
285static u32 next_vp;
286
287/*
288 * Starting with Win8, we can statically distribute the incoming
289 * channel interrupt load by binding a channel to VCPU. We
290 * implement here a simple round robin scheme for distributing
291 * the interrupt load.
292 * We will bind channels that are not performance critical to cpu 0 and
293 * performance critical channels (IDE, SCSI and Network) will be uniformly
294 * distributed across all available CPUs.
295 */
296static u32 get_vp_index(uuid_le *type_guid)
297{
298 u32 cur_cpu;
299 int i;
300 bool perf_chn = false;
301 u32 max_cpus = num_online_cpus();
302
303 for (i = IDE; i < MAX_PERF_CHN; i++) {
304 if (!memcmp(type_guid->b, hp_devs[i].guid,
305 sizeof(uuid_le))) {
306 perf_chn = true;
307 break;
308 }
309 }
310 if ((vmbus_proto_version == VERSION_WS2008) ||
311 (vmbus_proto_version == VERSION_WIN7) || (!perf_chn)) {
312 /*
313 * Prior to win8, all channel interrupts are
314 * delivered on cpu 0.
315 * Also if the channel is not a performance critical
316 * channel, bind it to cpu 0.
317 */
318 return 0;
319 }
320 cur_cpu = (++next_vp % max_cpus);
321 return 0;
322}
323
260/* 324/*
261 * vmbus_onoffer - Handler for channel offers from vmbus in parent partition. 325 * vmbus_onoffer - Handler for channel offers from vmbus in parent partition.
262 * 326 *
@@ -275,6 +339,35 @@ static void vmbus_onoffer(struct vmbus_channel_message_header *hdr)
275 return; 339 return;
276 } 340 }
277 341
342 /*
343 * By default we setup state to enable batched
344 * reading. A specific service can choose to
345 * disable this prior to opening the channel.
346 */
347 newchannel->batched_reading = true;
348
349 /*
350 * Setup state for signalling the host.
351 */
352 newchannel->sig_event = (struct hv_input_signal_event *)
353 (ALIGN((unsigned long)
354 &newchannel->sig_buf,
355 HV_HYPERCALL_PARAM_ALIGN));
356
357 newchannel->sig_event->connectionid.asu32 = 0;
358 newchannel->sig_event->connectionid.u.id = VMBUS_EVENT_CONNECTION_ID;
359 newchannel->sig_event->flag_number = 0;
360 newchannel->sig_event->rsvdz = 0;
361
362 if (vmbus_proto_version != VERSION_WS2008) {
363 newchannel->is_dedicated_interrupt =
364 (offer->is_dedicated_interrupt != 0);
365 newchannel->sig_event->connectionid.u.id =
366 offer->connection_id;
367 }
368
369 newchannel->target_vp = get_vp_index(&offer->offer.if_type);
370
278 memcpy(&newchannel->offermsg, offer, 371 memcpy(&newchannel->offermsg, offer,
279 sizeof(struct vmbus_channel_offer_channel)); 372 sizeof(struct vmbus_channel_offer_channel));
280 newchannel->monitor_grp = (u8)offer->monitorid / 32; 373 newchannel->monitor_grp = (u8)offer->monitorid / 32;