diff options
author | Kevin Hilman <khilman@linaro.org> | 2015-06-10 15:23:11 -0700 |
---|---|---|
committer | Kevin Hilman <khilman@linaro.org> | 2015-06-10 15:23:11 -0700 |
commit | 2528dbd348dd541e090594b7aac3f62351078388 (patch) | |
tree | a2ddf8323359b85d4be7de3ba498d7ec18e6e3f3 | |
parent | d109c1ac070c962c4332015d06a008345a44a02c (diff) | |
parent | 17b3b28baf84999421d56dce68c4b1c1ec7f1ef3 (diff) |
Merge branch 'linaro-android-3.14-lsk' of git://android.git.linaro.org/kernel/linaro-android into linux-linaro-lsk-v3.14-androidlsk-v3.14-15.06-android
* 'linaro-android-3.14-lsk' of git://android.git.linaro.org/kernel/linaro-android:
fix: align closely to AOSP.
sched: cpufreq: update power usage only if cpufreq_stat is enabled
uid_cputime: Extends the cputime functionality to report power per uid
sched: cpufreq: Adds a field cpu_power in the task_struct
cpufreq_stats: Adds the fucntionality to load current values for each frequency for all the cores.
New Build Breakage in branch: kernel-m-dev-tegra-flounder-3.10 @ 1960706
net/unix: sk_socket can disappear when state is unlocked
selinux: enable genfscon labeling for sysfs and pstore files
ext4: don't save the error information if the block device is read-only
selinux: enable per-file labeling for debugfs files.
cpufreq: interactive: Rearm governor timer at max freq
cpufreq: interactive: Implement cluster-based min_sample_time
cpufreq: interactive: Exercise hispeed settings at a policy level
suspend: Return error when pending wakeup source is found.
proc: uid_cputime: fix show_uid_stat permission
nf: IDLETIMER: Fix broken uid field in the msg
38 files changed, 345 insertions, 347 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 0c2b55e9242a..924ea5bec5bf 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -28,7 +28,7 @@ config ARM select HARDIRQS_SW_RESEND select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL select HAVE_ARCH_KGDB - select HAVE_ARCH_SECCOMP_FILTER + select HAVE_ARCH_SECCOMP_FILTER if (AEABI && !OABI_COMPAT) select HAVE_ARCH_TRACEHOOK select HAVE_BPF_JIT select HAVE_CONTEXT_TRACKING @@ -1763,6 +1763,11 @@ config OABI_COMPAT in memory differs between the legacy ABI and the new ARM EABI (only for non "thumb" binaries). This option adds a tiny overhead to all syscalls and produces a slightly larger kernel. + + The seccomp filter system will not be available when this is + selected, since there is no way yet to sensibly distinguish + between calling conventions during filtering. + If you know you'll be using only pure EABI user space then you can say N here. If this option is not selected and you attempt to execute a legacy ABI binary then the result will be diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 4bd2f2c38f56..f15c22e8bcd5 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -1069,29 +1069,6 @@ void __init sanity_check_meminfo(void) phys_addr_t size_limit; *bank = meminfo.bank[i]; - -#ifdef CONFIG_SPARSEMEM - if (pfn_to_section_nr(bank_pfn_start(bank)) != - pfn_to_section_nr(bank_pfn_end(bank) - 1)) { - phys_addr_t sz; - unsigned long start_pfn = bank_pfn_start(bank); - unsigned long end_pfn = SECTION_ALIGN_UP(start_pfn + 1); - sz = ((phys_addr_t)(end_pfn - start_pfn) << PAGE_SHIFT); - - if (meminfo.nr_banks >= NR_BANKS) { - pr_crit("NR_BANKS too low, ignoring %lld bytes of memory\n", - (unsigned long long)(bank->size - sz)); - } else { - memmove(bank + 1, bank, - (meminfo.nr_banks - i) * sizeof(*bank)); - meminfo.nr_banks++; - bank[1].size -= sz; - bank[1].start = __pfn_to_phys(end_pfn); - } - bank->size = sz; - } -#endif - size_limit = bank->size; if (bank->start >= vmalloc_limit) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index c10c8b3e3959..0c9e4d1086f7 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -371,27 +371,6 @@ config ARCH_WANT_HUGE_PMD_SHARE config HAVE_ARCH_TRANSPARENT_HUGEPAGE def_bool y -config ARMV7_COMPAT - bool "Kernel support for ARMv7 applications" - depends on COMPAT - select SWP_EMULATE - help - This option enables features that allow that ran on an ARMv7 or older - processor to continue functioning. - - If you want to execute ARMv7 applications, say Y - -config ARMV7_COMPAT_CPUINFO - bool "Report backwards compatible cpu features in /proc/cpuinfo" - depends on ARMV7_COMPAT - default y - help - This option makes /proc/cpuinfo list CPU features that an ARMv7 or - earlier kernel would report, but are not optional on an ARMv8 or later - processor. - - If you want to execute ARMv7 applications, say Y - source "mm/Kconfig" config XEN_DOM0 diff --git a/arch/arm64/include/asm/debug-monitors.h b/arch/arm64/include/asm/debug-monitors.h index aab72ce22348..7fb343779498 100644 --- a/arch/arm64/include/asm/debug-monitors.h +++ b/arch/arm64/include/asm/debug-monitors.h @@ -143,14 +143,7 @@ static inline int reinstall_suspended_bps(struct pt_regs *regs) } #endif -#ifdef CONFIG_COMPAT int aarch32_break_handler(struct pt_regs *regs); -#else -static int aarch32_break_handler(struct pt_regs *regs) -{ - return -EFAULT; -} -#endif #endif /* __ASSEMBLY */ #endif /* __KERNEL__ */ diff --git a/arch/mips/include/uapi/asm/unistd.h b/arch/mips/include/uapi/asm/unistd.h index 19244e913837..d6e154a9e6a5 100644 --- a/arch/mips/include/uapi/asm/unistd.h +++ b/arch/mips/include/uapi/asm/unistd.h @@ -1029,15 +1029,17 @@ #define __NR_process_vm_writev (__NR_Linux + 310) #define __NR_kcmp (__NR_Linux + 311) #define __NR_finit_module (__NR_Linux + 312) +#define __NR_sched_setattr (__NR_Linux + 313) +#define __NR_sched_getattr (__NR_Linux + 314) /* * Offset of the last N32 flavoured syscall */ -#define __NR_Linux_syscalls 312 +#define __NR_Linux_syscalls 314 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #define __NR_N32_Linux 6000 -#define __NR_N32_Linux_syscalls 312 +#define __NR_N32_Linux_syscalls 314 #endif /* _UAPI_ASM_UNISTD_H */ diff --git a/drivers/cpufreq/cpufreq_interactive.c b/drivers/cpufreq/cpufreq_interactive.c index b84f709c760e..39e62187cdbc 100644 --- a/drivers/cpufreq/cpufreq_interactive.c +++ b/drivers/cpufreq/cpufreq_interactive.c @@ -47,9 +47,10 @@ struct cpufreq_interactive_cpuinfo { spinlock_t target_freq_lock; /*protects target freq */ unsigned int target_freq; unsigned int floor_freq; - unsigned int max_freq; - u64 floor_validate_time; - u64 hispeed_validate_time; + u64 pol_floor_val_time; /* policy floor_validate_time */ + u64 loc_floor_val_time; /* per-cpu floor_validate_time */ + u64 pol_hispeed_val_time; /* policy hispeed_validate_time */ + u64 loc_hispeed_val_time; /* per-cpu hispeed_validate_time */ struct rw_semaphore enable_sem; int governor_enabled; }; @@ -345,6 +346,7 @@ static void cpufreq_interactive_timer(unsigned long data) unsigned int loadadjfreq; unsigned int index; unsigned long flags; + u64 max_fvtime; if (!down_read_trylock(&pcpu->enable_sem)) return; @@ -367,7 +369,7 @@ static void cpufreq_interactive_timer(unsigned long data) tunables->boosted = tunables->boost_val || now < tunables->boostpulse_endtime; if (cpu_load >= tunables->go_hispeed_load || tunables->boosted) { - if (pcpu->target_freq < tunables->hispeed_freq) { + if (pcpu->policy->cur < tunables->hispeed_freq) { new_freq = tunables->hispeed_freq; } else { new_freq = choose_freq(pcpu, loadadjfreq); @@ -378,14 +380,14 @@ static void cpufreq_interactive_timer(unsigned long data) } else { new_freq = choose_freq(pcpu, loadadjfreq); if (new_freq > tunables->hispeed_freq && - pcpu->target_freq < tunables->hispeed_freq) + pcpu->policy->cur < tunables->hispeed_freq) new_freq = tunables->hispeed_freq; } - if (pcpu->target_freq >= tunables->hispeed_freq && - new_freq > pcpu->target_freq && - now - pcpu->hispeed_validate_time < - freq_to_above_hispeed_delay(tunables, pcpu->target_freq)) { + if (pcpu->policy->cur >= tunables->hispeed_freq && + new_freq > pcpu->policy->cur && + now - pcpu->pol_hispeed_val_time < + freq_to_above_hispeed_delay(tunables, pcpu->policy->cur)) { trace_cpufreq_interactive_notyet( data, cpu_load, pcpu->target_freq, pcpu->policy->cur, new_freq); @@ -393,7 +395,7 @@ static void cpufreq_interactive_timer(unsigned long data) goto rearm; } - pcpu->hispeed_validate_time = now; + pcpu->loc_hispeed_val_time = now; if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table, new_freq, CPUFREQ_RELATION_L, @@ -408,9 +410,10 @@ static void cpufreq_interactive_timer(unsigned long data) * Do not scale below floor_freq unless we have been at or above the * floor frequency for the minimum sample time since last validated. */ - if (new_freq < pcpu->floor_freq) { - if (now - pcpu->floor_validate_time < - tunables->min_sample_time) { + max_fvtime = max(pcpu->pol_floor_val_time, pcpu->loc_floor_val_time); + if (new_freq < pcpu->floor_freq && + pcpu->target_freq >= pcpu->policy->cur) { + if (now - max_fvtime < tunables->min_sample_time) { trace_cpufreq_interactive_notyet( data, cpu_load, pcpu->target_freq, pcpu->policy->cur, new_freq); @@ -429,7 +432,9 @@ static void cpufreq_interactive_timer(unsigned long data) if (!tunables->boosted || new_freq > tunables->hispeed_freq) { pcpu->floor_freq = new_freq; - pcpu->floor_validate_time = now; + if (pcpu->target_freq >= pcpu->policy->cur || + new_freq >= pcpu->policy->cur) + pcpu->loc_floor_val_time = now; } if (pcpu->target_freq == new_freq && @@ -438,7 +443,7 @@ static void cpufreq_interactive_timer(unsigned long data) data, cpu_load, pcpu->target_freq, pcpu->policy->cur, new_freq); spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); - goto rearm_if_notmax; + goto rearm; } trace_cpufreq_interactive_target(data, cpu_load, pcpu->target_freq, @@ -451,14 +456,6 @@ static void cpufreq_interactive_timer(unsigned long data) spin_unlock_irqrestore(&speedchange_cpumask_lock, flags); wake_up_process(speedchange_task); -rearm_if_notmax: - /* - * Already set max speed and don't see a need to change that, - * wait until next idle to re-evaluate, don't need timer. - */ - if (pcpu->target_freq == pcpu->policy->max) - goto exit; - rearm: if (!timer_pending(&pcpu->cpu_timer)) cpufreq_interactive_timer_resched(pcpu); @@ -468,37 +465,6 @@ exit: return; } -static void cpufreq_interactive_idle_start(void) -{ - struct cpufreq_interactive_cpuinfo *pcpu = - &per_cpu(cpuinfo, smp_processor_id()); - int pending; - - if (!down_read_trylock(&pcpu->enable_sem)) - return; - if (!pcpu->governor_enabled) { - up_read(&pcpu->enable_sem); - return; - } - - pending = timer_pending(&pcpu->cpu_timer); - - if (pcpu->target_freq != pcpu->policy->min) { - /* - * Entering idle while not at lowest speed. On some - * platforms this can hold the other CPU(s) at that speed - * even though the CPU is idle. Set a timer to re-evaluate - * speed so this idle CPU doesn't hold the other CPUs above - * min indefinitely. This should probably be a quirk of - * the CPUFreq driver. - */ - if (!pending) - cpufreq_interactive_timer_resched(pcpu); - } - - up_read(&pcpu->enable_sem); -} - static void cpufreq_interactive_idle_end(void) { struct cpufreq_interactive_cpuinfo *pcpu = @@ -553,6 +519,8 @@ static int cpufreq_interactive_speedchange_task(void *data) for_each_cpu(cpu, &tmp_mask) { unsigned int j; unsigned int max_freq = 0; + struct cpufreq_interactive_cpuinfo *pjcpu; + u64 hvt = ~0ULL, fvt = 0; pcpu = &per_cpu(cpuinfo, cpu); if (!down_read_trylock(&pcpu->enable_sem)) @@ -563,17 +531,30 @@ static int cpufreq_interactive_speedchange_task(void *data) } for_each_cpu(j, pcpu->policy->cpus) { - struct cpufreq_interactive_cpuinfo *pjcpu = - &per_cpu(cpuinfo, j); + pjcpu = &per_cpu(cpuinfo, j); - if (pjcpu->target_freq > max_freq) + fvt = max(fvt, pjcpu->loc_floor_val_time); + if (pjcpu->target_freq > max_freq) { max_freq = pjcpu->target_freq; + hvt = pjcpu->loc_hispeed_val_time; + } else if (pjcpu->target_freq == max_freq) { + hvt = min(hvt, pjcpu->loc_hispeed_val_time); + } + } + for_each_cpu(j, pcpu->policy->cpus) { + pjcpu = &per_cpu(cpuinfo, j); + pjcpu->pol_floor_val_time = fvt; } - if (max_freq != pcpu->policy->cur) + if (max_freq != pcpu->policy->cur) { __cpufreq_driver_target(pcpu->policy, max_freq, CPUFREQ_RELATION_H); + for_each_cpu(j, pcpu->policy->cpus) { + pjcpu = &per_cpu(cpuinfo, j); + pjcpu->pol_hispeed_val_time = hvt; + } + } trace_cpufreq_interactive_setspeed(cpu, pcpu->target_freq, pcpu->policy->cur); @@ -605,7 +586,7 @@ static void cpufreq_interactive_boost(struct cpufreq_interactive_tunables *tunab if (pcpu->target_freq < tunables->hispeed_freq) { pcpu->target_freq = tunables->hispeed_freq; cpumask_set_cpu(i, &speedchange_cpumask); - pcpu->hispeed_validate_time = + pcpu->pol_hispeed_val_time = ktime_to_us(ktime_get()); anyboost = 1; } @@ -1108,14 +1089,8 @@ static int cpufreq_interactive_idle_notifier(struct notifier_block *nb, unsigned long val, void *data) { - switch (val) { - case IDLE_START: - cpufreq_interactive_idle_start(); - break; - case IDLE_END: + if (val == IDLE_END) cpufreq_interactive_idle_end(); - break; - } return 0; } @@ -1232,11 +1207,11 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, pcpu->target_freq = policy->cur; pcpu->freq_table = freq_table; pcpu->floor_freq = pcpu->target_freq; - pcpu->floor_validate_time = + pcpu->pol_floor_val_time = ktime_to_us(ktime_get()); - pcpu->hispeed_validate_time = - pcpu->floor_validate_time; - pcpu->max_freq = policy->max; + pcpu->loc_floor_val_time = pcpu->pol_floor_val_time; + pcpu->pol_hispeed_val_time = pcpu->pol_floor_val_time; + pcpu->loc_hispeed_val_time = pcpu->pol_floor_val_time; down_write(&pcpu->enable_sem); del_timer_sync(&pcpu->cpu_timer); del_timer_sync(&pcpu->cpu_slack_timer); @@ -1286,23 +1261,6 @@ static int cpufreq_governor_interactive(struct cpufreq_policy *policy, spin_unlock_irqrestore(&pcpu->target_freq_lock, flags); up_read(&pcpu->enable_sem); - - /* Reschedule timer only if policy->max is raised. - * Delete the timers, else the timer callback may - * return without re-arm the timer when failed - * acquire the semaphore. This race may cause timer - * stopped unexpectedly. - */ - - if (policy->max > pcpu->max_freq) { - down_write(&pcpu->enable_sem); - del_timer_sync(&pcpu->cpu_timer); - del_timer_sync(&pcpu->cpu_slack_timer); - cpufreq_interactive_timer_start(tunables, j); - up_write(&pcpu->enable_sem); - } - - pcpu->max_freq = policy->max; } break; } diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 1337d99f0c83..3811168bf28d 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -14,7 +14,8 @@ #include <linux/module.h> #include <linux/slab.h> #include <linux/sort.h> -#include <linux/err.h> +#include <linux/of.h> +#include <linux/sched.h> #include <asm/cputime.h> static spinlock_t cpufreq_stats_lock; @@ -39,6 +40,12 @@ struct all_cpufreq_stats { unsigned int *freq_table; }; +struct cpufreq_power_stats { + unsigned int state_num; + unsigned int *curr; + unsigned int *freq_table; +}; + struct all_freq_table { unsigned int *freq_table; unsigned int table_size; @@ -48,6 +55,7 @@ static struct all_freq_table *all_freq_table; static DEFINE_PER_CPU(struct all_cpufreq_stats *, all_cpufreq_stats); static DEFINE_PER_CPU(struct cpufreq_stats *, cpufreq_stats_table); +static DEFINE_PER_CPU(struct cpufreq_power_stats *, cpufreq_power_stats); struct cpufreq_stats_attribute { struct attribute attr; @@ -118,6 +126,47 @@ static int get_index_all_cpufreq_stat(struct all_cpufreq_stats *all_stat, return -1; } +void acct_update_power(struct task_struct *task, cputime_t cputime) { + struct cpufreq_power_stats *powerstats; + struct cpufreq_stats *stats; + unsigned int cpu_num, curr; + + if (!task) + return; + cpu_num = task_cpu(task); + powerstats = per_cpu(cpufreq_power_stats, cpu_num); + stats = per_cpu(cpufreq_stats_table, cpu_num); + if (!powerstats || !stats) + return; + + curr = powerstats->curr[stats->last_index]; + task->cpu_power += curr * cputime_to_usecs(cputime); +} +EXPORT_SYMBOL_GPL(acct_update_power); + +static ssize_t show_current_in_state(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + ssize_t len = 0; + unsigned int i, cpu; + struct cpufreq_power_stats *powerstats; + + spin_lock(&cpufreq_stats_lock); + for_each_possible_cpu(cpu) { + powerstats = per_cpu(cpufreq_power_stats, cpu); + if (!powerstats) + continue; + len += scnprintf(buf + len, PAGE_SIZE - len, "CPU%d:", cpu); + for (i = 0; i < powerstats->state_num; i++) + len += scnprintf(buf + len, PAGE_SIZE - len, + "%d=%d ", powerstats->freq_table[i], + powerstats->curr[i]); + len += scnprintf(buf + len, PAGE_SIZE - len, "\n"); + } + spin_unlock(&cpufreq_stats_lock); + return len; +} + static ssize_t show_all_time_in_state(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { @@ -227,6 +276,9 @@ static struct attribute_group stats_attr_group = { static struct kobj_attribute _attr_all_time_in_state = __ATTR(all_time_in_state, 0444, show_all_time_in_state, NULL); +static struct kobj_attribute _attr_current_in_state = __ATTR(current_in_state, + 0444, show_current_in_state, NULL); + static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq) { int index; @@ -288,10 +340,27 @@ static void cpufreq_allstats_free(void) } } +static void cpufreq_powerstats_free(void) +{ + int cpu; + struct cpufreq_power_stats *powerstats; + + sysfs_remove_file(cpufreq_global_kobject, &_attr_current_in_state.attr); + + for_each_possible_cpu(cpu) { + powerstats = per_cpu(cpufreq_power_stats, cpu); + if (!powerstats) + continue; + kfree(powerstats->curr); + kfree(powerstats); + per_cpu(cpufreq_power_stats, cpu) = NULL; + } +} + static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, - struct cpufreq_frequency_table *table) + struct cpufreq_frequency_table *table, int count) { - unsigned int i, j, count = 0, ret = 0; + unsigned int i, j, ret = 0; struct cpufreq_stats *stat; struct cpufreq_policy *current_policy; unsigned int alloc_size; @@ -315,12 +384,6 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy, stat->cpu = cpu; per_cpu(cpufreq_stats_table, cpu) = stat; - for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { - unsigned int freq = table[i].frequency; - if (freq == CPUFREQ_ENTRY_INVALID) - continue; - count++; - } alloc_size = count * sizeof(int) + count * sizeof(u64); @@ -361,26 +424,6 @@ error_get_fail: return ret; } -static void cpufreq_stats_create_table(unsigned int cpu) -{ - struct cpufreq_policy *policy; - struct cpufreq_frequency_table *table; - - /* - * "likely(!policy)" because normally cpufreq_stats will be registered - * before cpufreq driver - */ - policy = cpufreq_cpu_get(cpu); - if (likely(!policy)) - return; - - table = cpufreq_frequency_get_table(policy->cpu); - if (likely(table)) - __cpufreq_stats_create_table(policy, table); - - cpufreq_cpu_put(policy); -} - static void cpufreq_stats_update_policy_cpu(struct cpufreq_policy *policy) { struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, @@ -394,6 +437,54 @@ static void cpufreq_stats_update_policy_cpu(struct cpufreq_policy *policy) stat->cpu = policy->cpu; } +static void cpufreq_powerstats_create(unsigned int cpu, + struct cpufreq_frequency_table *table, int count) { + unsigned int alloc_size, i = 0, j = 0, ret = 0; + struct cpufreq_power_stats *powerstats; + struct device_node *cpu_node; + char device_path[16]; + + powerstats = kzalloc(sizeof(struct cpufreq_power_stats), + GFP_KERNEL); + if (!powerstats) + return; + + /* Allocate memory for freq table per cpu as well as clockticks per + * freq*/ + alloc_size = count * sizeof(unsigned int) + + count * sizeof(unsigned int); + powerstats->curr = kzalloc(alloc_size, GFP_KERNEL); + if (!powerstats->curr) { + kfree(powerstats); + return; + } + powerstats->freq_table = powerstats->curr + count; + + spin_lock(&cpufreq_stats_lock); + for (i = 0; table[i].frequency != CPUFREQ_TABLE_END && j < count; i++) { + unsigned int freq = table[i].frequency; + + if (freq == CPUFREQ_ENTRY_INVALID) + continue; + powerstats->freq_table[j++] = freq; + } + powerstats->state_num = j; + + snprintf(device_path, sizeof(device_path), "/cpus/cpu@%d", cpu); + cpu_node = of_find_node_by_path(device_path); + if (cpu_node) { + ret = of_property_read_u32_array(cpu_node, "current", + powerstats->curr, count); + if (ret) { + kfree(powerstats->curr); + kfree(powerstats); + powerstats = NULL; + } + } + per_cpu(cpufreq_power_stats, cpu) = powerstats; + spin_unlock(&cpufreq_stats_lock); +} + static int compare_for_sort(const void *lhs_ptr, const void *rhs_ptr) { unsigned int lhs = *(const unsigned int *)(lhs_ptr); @@ -438,24 +529,14 @@ static void add_all_freq_table(unsigned int freq) all_freq_table->freq_table[all_freq_table->table_size++] = freq; } -static void cpufreq_allstats_create(unsigned int cpu) +static void cpufreq_allstats_create(unsigned int cpu, + struct cpufreq_frequency_table *table, int count) { int i , j = 0; - unsigned int alloc_size, count = 0; - struct cpufreq_frequency_table *table = cpufreq_frequency_get_table(cpu); + unsigned int alloc_size; struct all_cpufreq_stats *all_stat; bool sort_needed = false; - if (!table) - return; - - for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { - unsigned int freq = table[i].frequency; - if (freq == CPUFREQ_ENTRY_INVALID) - continue; - count++; - } - all_stat = kzalloc(sizeof(struct all_cpufreq_stats), GFP_KERNEL); if (!all_stat) { @@ -494,10 +575,44 @@ static void cpufreq_allstats_create(unsigned int cpu) spin_unlock(&cpufreq_stats_lock); } +static void cpufreq_stats_create_table(unsigned int cpu) +{ + struct cpufreq_policy *policy; + struct cpufreq_frequency_table *table; + int i, count = 0; + /* + * "likely(!policy)" because normally cpufreq_stats will be registered + * before cpufreq driver + */ + policy = cpufreq_cpu_get(cpu); + if (likely(!policy)) + return; + + table = cpufreq_frequency_get_table(policy->cpu); + if (likely(table)) { + for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { + unsigned int freq = table[i].frequency; + + if (freq == CPUFREQ_ENTRY_INVALID) + continue; + count++; + } + + if (!per_cpu(all_cpufreq_stats, cpu)) + cpufreq_allstats_create(cpu, table, count); + + if (!per_cpu(cpufreq_power_stats, cpu)) + cpufreq_powerstats_create(cpu, table, count); + + __cpufreq_stats_create_table(policy, table, count); + } + cpufreq_cpu_put(policy); +} + static int cpufreq_stat_notifier_policy(struct notifier_block *nb, unsigned long val, void *data) { - int ret = 0; + int ret = 0, count = 0, i; struct cpufreq_policy *policy = data; struct cpufreq_frequency_table *table; unsigned int cpu = policy->cpu; @@ -511,11 +626,22 @@ static int cpufreq_stat_notifier_policy(struct notifier_block *nb, if (!table) return 0; + for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { + unsigned int freq = table[i].frequency; + + if (freq == CPUFREQ_ENTRY_INVALID) + continue; + count++; + } + if (!per_cpu(all_cpufreq_stats, cpu)) - cpufreq_allstats_create(cpu); + cpufreq_allstats_create(cpu, table, count); + + if (!per_cpu(cpufreq_power_stats, cpu)) + cpufreq_powerstats_create(cpu, table, count); if (val == CPUFREQ_CREATE_POLICY) - ret = __cpufreq_stats_create_table(policy, table); + ret = __cpufreq_stats_create_table(policy, table, count); else if (val == CPUFREQ_REMOVE_POLICY) __cpufreq_stats_free_table(policy); @@ -595,7 +721,12 @@ static int __init cpufreq_stats_init(void) ret = sysfs_create_file(cpufreq_global_kobject, &_attr_all_time_in_state.attr); if (ret) - pr_warn("Error creating sysfs file for cpufreq stats\n"); + pr_warn("Cannot create sysfs file for cpufreq stats\n"); + + ret = sysfs_create_file(cpufreq_global_kobject, + &_attr_current_in_state.attr); + if (ret) + pr_warn("Cannot create sysfs file for cpufreq current stats\n"); return 0; } @@ -610,6 +741,7 @@ static void __exit cpufreq_stats_exit(void) for_each_online_cpu(cpu) cpufreq_stats_free_table(cpu); cpufreq_allstats_free(); + cpufreq_powerstats_free(); cpufreq_put_global_kobject(); } diff --git a/drivers/misc/uid_cputime.c b/drivers/misc/uid_cputime.c index acd7046ce497..89bfba6c5b6a 100644 --- a/drivers/misc/uid_cputime.c +++ b/drivers/misc/uid_cputime.c @@ -38,6 +38,8 @@ struct uid_entry { cputime_t stime; cputime_t active_utime; cputime_t active_stime; + unsigned long long active_power; + unsigned long long power; struct hlist_node hash; }; @@ -83,6 +85,7 @@ static int uid_stat_show(struct seq_file *m, void *v) hash_for_each(hash_table, bkt, uid_entry, hash) { uid_entry->active_stime = 0; uid_entry->active_utime = 0; + uid_entry->active_power = 0; } read_lock(&tasklist_lock); @@ -100,6 +103,7 @@ static int uid_stat_show(struct seq_file *m, void *v) task_cputime_adjusted(task, &utime, &stime); uid_entry->active_utime += utime; uid_entry->active_stime += stime; + uid_entry->active_power += task->cpu_power; } read_unlock(&tasklist_lock); @@ -108,9 +112,12 @@ static int uid_stat_show(struct seq_file *m, void *v) uid_entry->active_utime; cputime_t total_stime = uid_entry->stime + uid_entry->active_stime; - seq_printf(m, "%d: %u %u\n", uid_entry->uid, + unsigned long long total_power = uid_entry->power + + uid_entry->active_power; + seq_printf(m, "%d: %u %u %llu\n", uid_entry->uid, cputime_to_usecs(total_utime), - cputime_to_usecs(total_stime)); + cputime_to_usecs(total_stime), + total_power); } mutex_unlock(&uid_lock); @@ -203,6 +210,7 @@ static int process_notifier(struct notifier_block *self, task_cputime_adjusted(task, &utime, &stime); uid_entry->utime += utime; uid_entry->stime += stime; + uid_entry->power += task->cpu_power; exit: mutex_unlock(&uid_lock); @@ -226,7 +234,7 @@ static int __init proc_uid_cputime_init(void) proc_create_data("remove_uid_range", S_IWUGO, parent, &uid_remove_fops, NULL); - proc_create_data("show_uid_stat", S_IWUGO, parent, &uid_stat_fops, + proc_create_data("show_uid_stat", S_IRUGO, parent, &uid_stat_fops, NULL); profile_event_register(PROFILE_TASK_EXIT, &process_notifier_block); diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index 2a1cc36b3ace..11655e90be53 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -63,6 +63,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(mmc_blk_rw_end); #define MMC_BKOPS_MAX_TIMEOUT (4 * 60 * 1000) /* max time to wait in ms */ static struct workqueue_struct *workqueue; +static struct wake_lock mmc_delayed_work_wake_lock; static const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; /* @@ -96,6 +97,7 @@ MODULE_PARM_DESC( static int mmc_schedule_delayed_work(struct delayed_work *work, unsigned long delay) { + wake_lock(&mmc_delayed_work_wake_lock); return queue_delayed_work(workqueue, work, delay); } @@ -1726,8 +1728,6 @@ static void _mmc_detect_change(struct mmc_host *host, unsigned long delay, pm_wakeup_event(mmc_dev(host), 5000); host->detect_change = 1; - - wake_lock(&host->detect_wake_lock); mmc_schedule_delayed_work(&host->detect, delay); } @@ -2511,13 +2511,11 @@ void mmc_rescan(struct work_struct *work) out: if (extend_wakelock) - wake_lock_timeout(&host->detect_wake_lock, HZ / 2); + wake_lock_timeout(&mmc_delayed_work_wake_lock, HZ / 2); else - wake_unlock(&host->detect_wake_lock); - if (host->caps & MMC_CAP_NEEDS_POLL) { - wake_lock(&host->detect_wake_lock); + wake_unlock(&mmc_delayed_work_wake_lock); + if (host->caps & MMC_CAP_NEEDS_POLL) mmc_schedule_delayed_work(&host->detect, HZ); - } } void mmc_start_host(struct mmc_host *host) @@ -2541,8 +2539,7 @@ void mmc_stop_host(struct mmc_host *host) #endif host->rescan_disable = 1; - if (cancel_delayed_work_sync(&host->detect)) - wake_unlock(&host->detect_wake_lock); + cancel_delayed_work_sync(&host->detect); mmc_flush_scheduled_work(); /* clear pm flags now and let card drivers set them as needed */ @@ -2699,8 +2696,7 @@ int mmc_pm_notify(struct notifier_block *notify_block, spin_lock_irqsave(&host->lock, flags); host->rescan_disable = 1; spin_unlock_irqrestore(&host->lock, flags); - if (cancel_delayed_work_sync(&host->detect)) - wake_unlock(&host->detect_wake_lock); + cancel_delayed_work_sync(&host->detect); if (!host->bus_ops) break; @@ -2776,6 +2772,9 @@ static int __init mmc_init(void) if (!workqueue) return -ENOMEM; + wake_lock_init(&mmc_delayed_work_wake_lock, WAKE_LOCK_SUSPEND, + "mmc_delayed_work"); + ret = mmc_register_bus(); if (ret) goto destroy_workqueue; @@ -2796,6 +2795,7 @@ unregister_bus: mmc_unregister_bus(); destroy_workqueue: destroy_workqueue(workqueue); + wake_lock_destroy(&mmc_delayed_work_wake_lock); return ret; } @@ -2806,6 +2806,7 @@ static void __exit mmc_exit(void) mmc_unregister_host_class(); mmc_unregister_bus(); destroy_workqueue(workqueue); + wake_lock_destroy(&mmc_delayed_work_wake_lock); } subsys_initcall(mmc_init); diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 2c886ae34198..cc3164a939eb 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -481,8 +481,6 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) spin_lock_init(&host->lock); init_waitqueue_head(&host->wq); - wake_lock_init(&host->detect_wake_lock, WAKE_LOCK_SUSPEND, - kasprintf(GFP_KERNEL, "%s_detect", mmc_hostname(host))); INIT_DELAYED_WORK(&host->detect, mmc_rescan); #ifdef CONFIG_PM host->pm_notify.notifier_call = mmc_pm_notify; @@ -582,7 +580,6 @@ void mmc_free_host(struct mmc_host *host) spin_lock(&mmc_host_lock); idr_remove(&mmc_host_idr, host->index); spin_unlock(&mmc_host_lock); - wake_lock_destroy(&host->detect_wake_lock); put_device(&host->class_dev); } diff --git a/drivers/usb/gadget/f_accessory.c b/drivers/usb/gadget/f_accessory.c index dcedeb4b2fef..0237f1e059b4 100644 --- a/drivers/usb/gadget/f_accessory.c +++ b/drivers/usb/gadget/f_accessory.c @@ -1204,8 +1204,7 @@ err: static void acc_disconnect(void) { /* unregister all HID devices if USB is disconnected */ - if (_acc_dev) - kill_all_hid_devices(_acc_dev); + kill_all_hid_devices(_acc_dev); } static void acc_cleanup(void) diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index bf6589eb7cb5..28b291a4e0e5 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -875,17 +875,6 @@ static int get_ether_addr(const char *str, u8 *dev_addr) return 1; } -static int get_host_ether_addr(u8 *str, u8 *dev_addr) -{ - memcpy(dev_addr, str, ETH_ALEN); - if (is_valid_ether_addr(dev_addr)) - return 0; - - random_ether_addr(dev_addr); - memcpy(str, dev_addr, ETH_ALEN); - return 1; -} - static int get_ether_addr_str(u8 dev_addr[ETH_ALEN], char *str, int len) { if (len < 18) @@ -897,6 +886,17 @@ static int get_ether_addr_str(u8 dev_addr[ETH_ALEN], char *str, int len) return 18; } +static int get_host_ether_addr(u8 *str, u8 *dev_addr) +{ + memcpy(dev_addr, str, ETH_ALEN); + if (is_valid_ether_addr(dev_addr)) + return 0; + + random_ether_addr(dev_addr); + memcpy(str, dev_addr, ETH_ALEN); + return 1; +} + static const struct net_device_ops eth_netdev_ops = { .ndo_open = eth_open, .ndo_stop = eth_stop, diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 9fb3e6c0c578..e0cb26f74842 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -304,6 +304,8 @@ static void __save_error_info(struct super_block *sb, const char *func, struct ext4_super_block *es = EXT4_SB(sb)->s_es; EXT4_SB(sb)->s_mount_state |= EXT4_ERROR_FS; + if (bdev_read_only(sb->s_bdev)) + return; es->s_state |= cpu_to_le16(EXT4_ERROR_FS); es->s_last_error_time = cpu_to_le32(get_seconds()); strncpy(es->s_last_error_func, func, sizeof(es->s_last_error_func)); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index b0d360c87602..a15944d5a06f 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -17,6 +17,8 @@ #include <linux/kobject.h> #include <linux/notifier.h> #include <linux/sysfs.h> +#include <asm/cputime.h> + /********************************************************************* * CPUFREQ INTERFACE * @@ -509,4 +511,10 @@ static inline int cpufreq_generic_exit(struct cpufreq_policy *policy) return 0; } +/********************************************************************* + * CPUFREQ STATS * + *********************************************************************/ + +void acct_update_power(struct task_struct *p, cputime_t cputime); + #endif /* _LINUX_CPUFREQ_H */ diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 1c923ab2dd73..9b92af47577f 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -15,7 +15,6 @@ #include <linux/sched.h> #include <linux/device.h> #include <linux/fault-inject.h> -#include <linux/wakelock.h> #include <linux/mmc/core.h> #include <linux/mmc/pm.h> @@ -330,7 +329,6 @@ struct mmc_host { int claim_cnt; /* "claim" nesting count */ struct delayed_work detect; - struct wake_lock detect_wake_lock; int detect_change; /* card detect flag */ struct mmc_slot slot; diff --git a/include/linux/sched.h b/include/linux/sched.h index 22913f78b829..67f59c1e0c7b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1297,6 +1297,7 @@ struct task_struct { cputime_t utime, stime, utimescaled, stimescaled; cputime_t gtime; + unsigned long long cpu_power; #ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE struct cputime prev_cputime; #endif diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 73a22fd1fd66..66c1cd87bfe7 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1762,9 +1762,6 @@ struct hci_conn_info { __u8 out; __u16 state; __u32 link_mode; - __u32 mtu; - __u32 cnt; - __u32 pkts; }; struct hci_dev_req { diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 6e17a54ac302..f2f0cf5865c4 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -659,7 +659,7 @@ static inline void hci_conn_drop(struct hci_conn *conn) if (conn->state == BT_CONNECTED) { timeo = conn->disc_timeout; if (!conn->out) - timeo *= 20; + timeo *= 2; } else { timeo = msecs_to_jiffies(10); } diff --git a/include/net/netfilter/ipv4/nf_reject.h b/include/net/netfilter/ipv4/nf_reject.h index 99fdd82a1306..931fbf812171 100644 --- a/include/net/netfilter/ipv4/nf_reject.h +++ b/include/net/netfilter/ipv4/nf_reject.h @@ -9,14 +9,6 @@ static inline void nf_send_unreach(struct sk_buff *skb_in, int code) { icmp_send(skb_in, ICMP_DEST_UNREACH, code, 0); -#ifdef CONFIG_IP_NF_TARGET_REJECT_SKERR - if (skb_in->sk) { - skb_in->sk->sk_err = icmp_err_convert[code].errno; - skb_in->sk->sk_error_report(skb_in->sk); - pr_debug("ipt_REJECT: sk_err=%d for skb=%p sk=%p\n", - skb_in->sk->sk_err, skb_in, skb_in->sk); - } -#endif } /* Send RST reply */ diff --git a/include/net/netfilter/ipv6/nf_reject.h b/include/net/netfilter/ipv6/nf_reject.h index 5f9795c8feb6..710d17ed70b4 100644 --- a/include/net/netfilter/ipv6/nf_reject.h +++ b/include/net/netfilter/ipv6/nf_reject.h @@ -15,15 +15,6 @@ nf_send_unreach6(struct net *net, struct sk_buff *skb_in, unsigned char code, skb_in->dev = net->loopback_dev; icmpv6_send(skb_in, ICMPV6_DEST_UNREACH, code, 0); -#ifdef CONFIG_IP6_NF_TARGET_REJECT_SKERR - if (skb_in->sk) { - icmpv6_err_convert(ICMPV6_DEST_UNREACH, code, - &skb_in->sk->sk_err); - skb_in->sk->sk_error_report(skb_in->sk); - pr_debug("ip6t_REJECT: sk_err=%d for skb=%p sk=%p\n", - skb_in->sk->sk_err, skb_in, skb_in->sk); - } -#endif } /* Send RST reply */ diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index 0f74c7bdff3c..f2011a9b37d7 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -696,11 +696,12 @@ __SYSCALL(__NR_finit_module, sys_finit_module) __SYSCALL(__NR_sched_setattr, sys_sched_setattr) #define __NR_sched_getattr 275 __SYSCALL(__NR_sched_getattr, sys_sched_getattr) -#define __NR_seccomp 276 + +#define __NR_seccomp 277 __SYSCALL(__NR_seccomp, sys_seccomp) #undef __NR_syscalls -#define __NR_syscalls 277 +#define __NR_syscalls 278 /* * All syscalls below here should go away really, diff --git a/kernel/fork.c b/kernel/fork.c index 20eaa23152eb..e5d0ede99339 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1301,6 +1301,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->utime = p->stime = p->gtime = 0; p->utimescaled = p->stimescaled = 0; + p->cpu_power = 0; #ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE p->prev_cputime.utime = p->prev_cputime.stime = 0; #endif diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c index f94d703c9f55..da5f2ffa7106 100644 --- a/kernel/irq/pm.c +++ b/kernel/irq/pm.c @@ -100,7 +100,6 @@ EXPORT_SYMBOL_GPL(resume_device_irqs); int check_wakeup_irqs(void) { struct irq_desc *desc; - char __maybe_unused suspend_abort[MAX_SUSPEND_ABORT_LEN]; int irq; for_each_irq_desc(irq, desc) { diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index 2d98d52a8700..2932a43a5659 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -225,10 +225,11 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) if (!(suspend_test(TEST_CORE) || *wakeup)) { error = suspend_ops->enter(state); events_check_enabled = false; - } else { + } else if (*wakeup) { pm_get_active_wakeup_sources(suspend_abort, MAX_SUSPEND_ABORT_LEN); log_suspend_abort_reason(suspend_abort); + error = -EBUSY; } syscore_resume(); } diff --git a/kernel/power/wakelock.c b/kernel/power/wakelock.c index c8fba3380076..8f50de394d22 100644 --- a/kernel/power/wakelock.c +++ b/kernel/power/wakelock.c @@ -9,6 +9,7 @@ * manipulate wakelocks on Android. */ +#include <linux/capability.h> #include <linux/ctype.h> #include <linux/device.h> #include <linux/err.h> @@ -188,6 +189,9 @@ int pm_wake_lock(const char *buf) size_t len; int ret = 0; + if (!capable(CAP_BLOCK_SUSPEND)) + return -EPERM; + while (*str && !isspace(*str)) str++; @@ -231,6 +235,9 @@ int pm_wake_unlock(const char *buf) size_t len; int ret = 0; + if (!capable(CAP_BLOCK_SUSPEND)) + return -EPERM; + len = strlen(buf); if (!len) return -EINVAL; diff --git a/kernel/sched/cputime.c b/kernel/sched/cputime.c index cfe2f268afaa..23c4f2e3bafd 100644 --- a/kernel/sched/cputime.c +++ b/kernel/sched/cputime.c @@ -1,3 +1,4 @@ +#include <linux/cpufreq.h> #include <linux/export.h> #include <linux/sched.h> #include <linux/tsacct_kern.h> @@ -149,6 +150,11 @@ void account_user_time(struct task_struct *p, cputime_t cputime, /* Account for user time used */ acct_account_cputime(p); + +#ifdef CONFIG_CPU_FREQ_STAT + /* Account power usage for user time */ + acct_update_power(p, cputime); +#endif } /* @@ -199,6 +205,11 @@ void __account_system_time(struct task_struct *p, cputime_t cputime, /* Account for system time used */ acct_account_cputime(p); + +#ifdef CONFIG_CPU_FREQ_STAT + /* Account power usage for system time */ + acct_update_power(p, cputime); +#endif } /* diff --git a/kernel/sys.c b/kernel/sys.c index 8ba889e31bea..4bf3cb0f337c 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -2111,26 +2111,6 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, else return -EINVAL; break; - case PR_SET_TIMERSLACK_PID: - if (current->pid != (pid_t)arg3 && - !capable(CAP_SYS_NICE)) - return -EPERM; - rcu_read_lock(); - tsk = find_task_by_pid_ns((pid_t)arg3, &init_pid_ns); - if (tsk == NULL) { - rcu_read_unlock(); - return -EINVAL; - } - get_task_struct(tsk); - rcu_read_unlock(); - if (arg2 <= 0) - tsk->timer_slack_ns = - tsk->default_timer_slack_ns; - else - tsk->timer_slack_ns = arg2; - put_task_struct(tsk); - error = 0; - break; default: return -EINVAL; } diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 3cc58beeff21..1c6e950b9ae7 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -983,15 +983,6 @@ int hci_get_conn_list(void __user *arg) (ci + n)->out = c->out; (ci + n)->state = c->state; (ci + n)->link_mode = c->link_mode; - if (c->type == SCO_LINK) { - (ci + n)->mtu = hdev->sco_mtu; - (ci + n)->cnt = hdev->sco_cnt; - (ci + n)->pkts = hdev->sco_pkts; - } else { - (ci + n)->mtu = hdev->acl_mtu; - (ci + n)->cnt = hdev->acl_cnt; - (ci + n)->pkts = hdev->acl_pkts; - } if (++n >= req.conn_num) break; } @@ -1028,15 +1019,6 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg) ci.out = conn->out; ci.state = conn->state; ci.link_mode = conn->link_mode; - if (req.type == SCO_LINK) { - ci.mtu = hdev->sco_mtu; - ci.cnt = hdev->sco_cnt; - ci.pkts = hdev->sco_pkts; - } else { - ci.mtu = hdev->acl_mtu; - ci.cnt = hdev->acl_cnt; - ci.pkts = hdev->acl_pkts; - } } hci_dev_unlock(hdev); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 3204004a0b91..2e8c5765e5ea 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2905,7 +2905,6 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, break; case 0x0d: /* Connection Rejected due to Limited Resources */ - case 0x10: /* Connection Accept Timeout */ case 0x11: /* Unsupported Feature or Parameter Value */ case 0x1c: /* SCO interval rejected */ case 0x1a: /* Unsupported Remote Feature */ diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index eb8864095898..b08865111024 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -436,6 +436,7 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err) switch (d->state) { case BT_CONNECT: + case BT_CONFIG: if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { set_bit(RFCOMM_AUTH_REJECT, &d->flags); rfcomm_schedule(); diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 526bf56f4d31..afeb8e07ee41 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -332,6 +332,10 @@ static long caif_stream_data_wait(struct sock *sk, long timeo) release_sock(sk); timeo = schedule_timeout(timeo); lock_sock(sk); + + if (sock_flag(sk, SOCK_DEAD)) + break; + clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); } @@ -376,6 +380,10 @@ static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock, struct sk_buff *skb; lock_sock(sk); + if (sock_flag(sk, SOCK_DEAD)) { + err = -ECONNRESET; + goto unlock; + } skb = skb_dequeue(&sk->sk_receive_queue); caif_check_flow_release(sk); diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index 34d630d35cc7..a26ce035e3fa 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -159,18 +159,6 @@ config IP_NF_TARGET_SYNPROXY To compile it as a module, choose M here. If unsure, say N. -config IP_NF_TARGET_REJECT_SKERR - bool "Force socket error when rejecting with icmp*" - depends on IP_NF_TARGET_REJECT - default n - help - This option enables turning a "--reject-with icmp*" into a matching - socket error also. - The REJECT target normally allows sending an ICMP message. But it - leaves the local socket unaware of any ingress rejects. - - If unsure, say N. - config IP_NF_TARGET_ULOG tristate "ULOG target support (obsolete)" default m if NETFILTER_ADVANCED=n diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index c842cd3059c7..4bff1f297e39 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig @@ -196,18 +196,6 @@ config IP6_NF_TARGET_SYNPROXY To compile it as a module, choose M here. If unsure, say N. -config IP6_NF_TARGET_REJECT_SKERR - bool "Force socket error when rejecting with icmp*" - depends on IP6_NF_TARGET_REJECT - default n - help - This option enables turning a "--reject-with icmp*" into a matching - socket error also. - The REJECT target normally allows sending an ICMP message. But it - leaves the local socket unaware of any ingress rejects. - - If unsure, say N. - config IP6_NF_MANGLE tristate "Packet mangling" default m if NETFILTER_ADVANCED=n diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 94404f19f9de..4757f1cf6237 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1893,6 +1893,10 @@ static long unix_stream_data_wait(struct sock *sk, long timeo, unix_state_unlock(sk); timeo = freezable_schedule_timeout(timeo); unix_state_lock(sk); + + if (sock_flag(sk, SOCK_DEAD)) + break; + clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); } @@ -1957,6 +1961,10 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, struct sk_buff *skb, *last; unix_state_lock(sk); + if (sock_flag(sk, SOCK_DEAD)) { + err = -ECONNRESET; + goto unlock; + } last = skb = skb_peek(&sk->sk_receive_queue); again: if (skb == NULL) { diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 4c602d100480..16d08b399210 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -166,14 +166,3 @@ config LIB80211_DEBUG from lib80211. If unsure, say N. - -config CFG80211_ALLOW_RECONNECT - bool "Allow reconnect while already connected" - depends on CFG80211 - default n - help - cfg80211 stack doesn't allow to connect if you are already - connected. This option allows to make a connection in this case. - - Select this option ONLY for wlan drivers that are specifically - built for such purposes. diff --git a/net/wireless/sme.c b/net/wireless/sme.c index efe76c6a320a..760722f9126b 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -428,18 +428,11 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev, if (!rdev->ops->auth || !rdev->ops->assoc) return -EOPNOTSUPP; -#ifndef CONFIG_CFG80211_ALLOW_RECONNECT if (wdev->current_bss) return -EALREADY; if (WARN_ON(wdev->conn)) return -EINPROGRESS; -#else - if (wdev->conn) { - kfree(wdev->conn); - wdev->conn = NULL; - } -#endif wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL); if (!wdev->conn) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a10e0c772fed..6ce2734bcb37 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -731,7 +731,12 @@ static int selinux_set_mnt_opts(struct super_block *sb, } if (strcmp(sb->s_type->name, "proc") == 0) - sbsec->flags |= SE_SBPROC; + sbsec->flags |= SE_SBPROC | SE_SBGENFS; + + if (!strcmp(sb->s_type->name, "debugfs") || + !strcmp(sb->s_type->name, "sysfs") || + !strcmp(sb->s_type->name, "pstore")) + sbsec->flags |= SE_SBGENFS; if (!sbsec->behavior) { /* @@ -1227,12 +1232,13 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc return SECCLASS_SOCKET; } -#ifdef CONFIG_PROC_FS -static int selinux_proc_get_sid(struct dentry *dentry, - u16 tclass, - u32 *sid) +static int selinux_genfs_get_sid(struct dentry *dentry, + u16 tclass, + u16 flags, + u32 *sid) { int rc; + struct super_block *sb = dentry->d_inode->i_sb; char *buffer, *path; buffer = (char *)__get_free_page(GFP_KERNEL); @@ -1243,26 +1249,20 @@ static int selinux_proc_get_sid(struct dentry *dentry, if (IS_ERR(path)) rc = PTR_ERR(path); else { - /* each process gets a /proc/PID/ entry. Strip off the - * PID part to get a valid selinux labeling. - * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */ - while (path[1] >= '0' && path[1] <= '9') { - path[1] = '/'; - path++; + if (flags & SE_SBPROC) { + /* each process gets a /proc/PID/ entry. Strip off the + * PID part to get a valid selinux labeling. + * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */ + while (path[1] >= '0' && path[1] <= '9') { + path[1] = '/'; + path++; + } } - rc = security_genfs_sid("proc", path, tclass, sid); + rc = security_genfs_sid(sb->s_type->name, path, tclass, sid); } free_page((unsigned long)buffer); return rc; } -#else -static int selinux_proc_get_sid(struct dentry *dentry, - u16 tclass, - u32 *sid) -{ - return -EINVAL; -} -#endif /* The inode's security attributes must be initialized before first use. */ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry) @@ -1419,7 +1419,7 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent /* Default to the fs superblock SID. */ isec->sid = sbsec->sid; - if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) { + if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) { /* We must have a dentry to determine the label on * procfs inodes */ if (opt_dentry) @@ -1442,7 +1442,8 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent if (!dentry) goto out_unlock; isec->sclass = inode_mode_to_security_class(inode->i_mode); - rc = selinux_proc_get_sid(dentry, isec->sclass, &sid); + rc = selinux_genfs_get_sid(dentry, isec->sclass, + sbsec->flags, &sid); dput(dentry); if (rc) goto out_unlock; diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index c8bf6735c6f9..be99667c2a21 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h @@ -56,6 +56,7 @@ /* Non-mount related flags */ #define SE_SBINITIALIZED 0x0100 #define SE_SBPROC 0x0200 +#define SE_SBGENFS 0x0400 #define CONTEXT_STR "context=" #define FSCONTEXT_STR "fscontext=" |