diff options
Diffstat (limited to 'kernel/profile.c')
-rw-r--r-- | kernel/profile.c | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/kernel/profile.c b/kernel/profile.c index 4cb7d68fed82..d18e2d2654f2 100644 --- a/kernel/profile.c +++ b/kernel/profile.c | |||
@@ -45,7 +45,7 @@ static unsigned long prof_len, prof_shift; | |||
45 | int prof_on __read_mostly; | 45 | int prof_on __read_mostly; |
46 | EXPORT_SYMBOL_GPL(prof_on); | 46 | EXPORT_SYMBOL_GPL(prof_on); |
47 | 47 | ||
48 | static cpumask_t prof_cpu_mask = CPU_MASK_ALL; | 48 | static cpumask_var_t prof_cpu_mask; |
49 | #ifdef CONFIG_SMP | 49 | #ifdef CONFIG_SMP |
50 | static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits); | 50 | static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits); |
51 | static DEFINE_PER_CPU(int, cpu_profile_flip); | 51 | static DEFINE_PER_CPU(int, cpu_profile_flip); |
@@ -113,9 +113,13 @@ int __ref profile_init(void) | |||
113 | buffer_bytes = prof_len*sizeof(atomic_t); | 113 | buffer_bytes = prof_len*sizeof(atomic_t); |
114 | if (!slab_is_available()) { | 114 | if (!slab_is_available()) { |
115 | prof_buffer = alloc_bootmem(buffer_bytes); | 115 | prof_buffer = alloc_bootmem(buffer_bytes); |
116 | alloc_bootmem_cpumask_var(&prof_cpu_mask); | ||
116 | return 0; | 117 | return 0; |
117 | } | 118 | } |
118 | 119 | ||
120 | if (!alloc_cpumask_var(&prof_cpu_mask, GFP_KERNEL)) | ||
121 | return -ENOMEM; | ||
122 | |||
119 | prof_buffer = kzalloc(buffer_bytes, GFP_KERNEL); | 123 | prof_buffer = kzalloc(buffer_bytes, GFP_KERNEL); |
120 | if (prof_buffer) | 124 | if (prof_buffer) |
121 | return 0; | 125 | return 0; |
@@ -128,6 +132,7 @@ int __ref profile_init(void) | |||
128 | if (prof_buffer) | 132 | if (prof_buffer) |
129 | return 0; | 133 | return 0; |
130 | 134 | ||
135 | free_cpumask_var(prof_cpu_mask); | ||
131 | return -ENOMEM; | 136 | return -ENOMEM; |
132 | } | 137 | } |
133 | 138 | ||
@@ -386,13 +391,15 @@ out_free: | |||
386 | return NOTIFY_BAD; | 391 | return NOTIFY_BAD; |
387 | case CPU_ONLINE: | 392 | case CPU_ONLINE: |
388 | case CPU_ONLINE_FROZEN: | 393 | case CPU_ONLINE_FROZEN: |
389 | cpu_set(cpu, prof_cpu_mask); | 394 | if (prof_cpu_mask != NULL) |
395 | cpumask_set_cpu(cpu, prof_cpu_mask); | ||
390 | break; | 396 | break; |
391 | case CPU_UP_CANCELED: | 397 | case CPU_UP_CANCELED: |
392 | case CPU_UP_CANCELED_FROZEN: | 398 | case CPU_UP_CANCELED_FROZEN: |
393 | case CPU_DEAD: | 399 | case CPU_DEAD: |
394 | case CPU_DEAD_FROZEN: | 400 | case CPU_DEAD_FROZEN: |
395 | cpu_clear(cpu, prof_cpu_mask); | 401 | if (prof_cpu_mask != NULL) |
402 | cpumask_clear_cpu(cpu, prof_cpu_mask); | ||
396 | if (per_cpu(cpu_profile_hits, cpu)[0]) { | 403 | if (per_cpu(cpu_profile_hits, cpu)[0]) { |
397 | page = virt_to_page(per_cpu(cpu_profile_hits, cpu)[0]); | 404 | page = virt_to_page(per_cpu(cpu_profile_hits, cpu)[0]); |
398 | per_cpu(cpu_profile_hits, cpu)[0] = NULL; | 405 | per_cpu(cpu_profile_hits, cpu)[0] = NULL; |
@@ -430,7 +437,8 @@ void profile_tick(int type) | |||
430 | 437 | ||
431 | if (type == CPU_PROFILING && timer_hook) | 438 | if (type == CPU_PROFILING && timer_hook) |
432 | timer_hook(regs); | 439 | timer_hook(regs); |
433 | if (!user_mode(regs) && cpu_isset(smp_processor_id(), prof_cpu_mask)) | 440 | if (!user_mode(regs) && prof_cpu_mask != NULL && |
441 | cpumask_test_cpu(smp_processor_id(), prof_cpu_mask)) | ||
434 | profile_hit(type, (void *)profile_pc(regs)); | 442 | profile_hit(type, (void *)profile_pc(regs)); |
435 | } | 443 | } |
436 | 444 | ||
@@ -442,7 +450,7 @@ void profile_tick(int type) | |||
442 | static int prof_cpu_mask_read_proc(char *page, char **start, off_t off, | 450 | static int prof_cpu_mask_read_proc(char *page, char **start, off_t off, |
443 | int count, int *eof, void *data) | 451 | int count, int *eof, void *data) |
444 | { | 452 | { |
445 | int len = cpumask_scnprintf(page, count, (cpumask_t *)data); | 453 | int len = cpumask_scnprintf(page, count, data); |
446 | if (count - len < 2) | 454 | if (count - len < 2) |
447 | return -EINVAL; | 455 | return -EINVAL; |
448 | len += sprintf(page + len, "\n"); | 456 | len += sprintf(page + len, "\n"); |
@@ -452,16 +460,20 @@ static int prof_cpu_mask_read_proc(char *page, char **start, off_t off, | |||
452 | static int prof_cpu_mask_write_proc(struct file *file, | 460 | static int prof_cpu_mask_write_proc(struct file *file, |
453 | const char __user *buffer, unsigned long count, void *data) | 461 | const char __user *buffer, unsigned long count, void *data) |
454 | { | 462 | { |
455 | cpumask_t *mask = (cpumask_t *)data; | 463 | struct cpumask *mask = data; |
456 | unsigned long full_count = count, err; | 464 | unsigned long full_count = count, err; |
457 | cpumask_t new_value; | 465 | cpumask_var_t new_value; |
458 | 466 | ||
459 | err = cpumask_parse_user(buffer, count, &new_value); | 467 | if (!alloc_cpumask_var(&new_value, GFP_KERNEL)) |
460 | if (err) | 468 | return -ENOMEM; |
461 | return err; | ||
462 | 469 | ||
463 | *mask = new_value; | 470 | err = cpumask_parse_user(buffer, count, new_value); |
464 | return full_count; | 471 | if (!err) { |
472 | cpumask_copy(mask, new_value); | ||
473 | err = full_count; | ||
474 | } | ||
475 | free_cpumask_var(new_value); | ||
476 | return err; | ||
465 | } | 477 | } |
466 | 478 | ||
467 | void create_prof_cpu_mask(struct proc_dir_entry *root_irq_dir) | 479 | void create_prof_cpu_mask(struct proc_dir_entry *root_irq_dir) |
@@ -472,7 +484,7 @@ void create_prof_cpu_mask(struct proc_dir_entry *root_irq_dir) | |||
472 | entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); | 484 | entry = create_proc_entry("prof_cpu_mask", 0600, root_irq_dir); |
473 | if (!entry) | 485 | if (!entry) |
474 | return; | 486 | return; |
475 | entry->data = (void *)&prof_cpu_mask; | 487 | entry->data = prof_cpu_mask; |
476 | entry->read_proc = prof_cpu_mask_read_proc; | 488 | entry->read_proc = prof_cpu_mask_read_proc; |
477 | entry->write_proc = prof_cpu_mask_write_proc; | 489 | entry->write_proc = prof_cpu_mask_write_proc; |
478 | } | 490 | } |