Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 72048ec5 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "Merge branch 'google-common/android-3.18' into msm-3.18"

parents db2d1bb2 694027d6
Loading
Loading
Loading
Loading
+177 −45
Original line number Diff line number Diff line
@@ -14,6 +14,8 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/sort.h>
#include <linux/of.h>
#include <linux/sched.h>
#include <linux/cputime.h>

static spinlock_t cpufreq_stats_lock;
@@ -38,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;
@@ -47,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;
@@ -117,6 +126,48 @@ 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];
	if (task->cpu_power != ULLONG_MAX)
		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)
{
@@ -226,6 +277,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;
@@ -287,17 +341,31 @@ static void cpufreq_allstats_free(void)
	}
}

static int __cpufreq_stats_create_table(struct cpufreq_policy *policy)
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, int count)
{
	unsigned int i, count = 0, ret = 0;
	unsigned int i, ret = 0;
	struct cpufreq_stats *stat;
	unsigned int alloc_size;
	unsigned int cpu = policy->cpu;
	struct cpufreq_frequency_table *pos, *table;

	table = cpufreq_frequency_get_table(cpu);
	if (unlikely(!table))
		return 0;
	struct cpufreq_frequency_table *pos;

	if (per_cpu(cpufreq_stats_table, cpu))
		return -EBUSY;
@@ -312,9 +380,6 @@ static int __cpufreq_stats_create_table(struct cpufreq_policy *policy)
	stat->cpu = cpu;
	per_cpu(cpufreq_stats_table, cpu) = stat;

	cpufreq_for_each_valid_entry(pos, table)
		count++;

	alloc_size = count * sizeof(int) + count * sizeof(u64);

#ifdef CONFIG_CPU_FREQ_STAT_DETAILS
@@ -349,23 +414,6 @@ error_out:
	return ret;
}

static void cpufreq_stats_create_table(unsigned int cpu)
{
	struct cpufreq_policy *policy;

	/*
	 * "likely(!policy)" because normally cpufreq_stats will be registered
	 * before cpufreq driver
	 */
	policy = cpufreq_cpu_get(cpu);
	if (likely(!policy))
		return;

	__cpufreq_stats_create_table(policy);

	cpufreq_cpu_put(policy);
}

static void cpufreq_stats_update_policy_cpu(struct cpufreq_policy *policy)
{
	struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table,
@@ -379,6 +427,51 @@ 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, ret = 0;
	struct cpufreq_power_stats *powerstats;
	struct cpufreq_frequency_table *pos;
	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);
	i = 0;
	cpufreq_for_each_valid_entry(pos, table)
		powerstats->freq_table[i++] = pos->frequency;
	powerstats->state_num = i;

	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);
@@ -423,24 +516,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) {
@@ -479,22 +562,65 @@ 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, *pos;
	int 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)) {
		cpufreq_for_each_valid_entry(pos, table)
			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;
	struct cpufreq_policy *policy = data;
	struct cpufreq_frequency_table *table, *pos;
	unsigned int cpu_num, cpu = policy->cpu;

	if (val == CPUFREQ_UPDATE_POLICY_CPU) {
		cpufreq_stats_update_policy_cpu(policy);
		return 0;
	}

	if (!per_cpu(all_cpufreq_stats, policy->cpu))
		cpufreq_allstats_create(policy->cpu);
	table = cpufreq_frequency_get_table(cpu);
	if (!table)
		return 0;

	cpufreq_for_each_valid_entry(pos, table)
		count++;

	if (!per_cpu(all_cpufreq_stats, cpu))
		cpufreq_allstats_create(cpu, table, count);

	for_each_possible_cpu(cpu_num) {
		if (!per_cpu(cpufreq_power_stats, cpu_num))
			cpufreq_powerstats_create(cpu_num, table, count);
	}

	if (val == CPUFREQ_CREATE_POLICY)
		ret = __cpufreq_stats_create_table(policy);
		ret = __cpufreq_stats_create_table(policy, table, count);
	else if (val == CPUFREQ_REMOVE_POLICY)
		__cpufreq_stats_free_table(policy);

@@ -574,7 +700,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;
}
@@ -589,6 +720,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();
}

+16 −2
Original line number Diff line number Diff line
@@ -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);
@@ -97,9 +100,15 @@ static int uid_stat_show(struct seq_file *m, void *v)
				task_uid(task)));
			return -ENOMEM;
		}
		/* if this task is exiting, we have already accounted for the
		 * time and power.
		 */
		if (task->cpu_power == ULLONG_MAX)
			continue;
		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 +117,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 +215,8 @@ 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;
	task->cpu_power = ULLONG_MAX;

exit:
	mutex_unlock(&uid_lock);
+1 −1
Original line number Diff line number Diff line
@@ -446,7 +446,7 @@ ashmem_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
		loff_t start = range->pgstart * PAGE_SIZE;
		loff_t end = (range->pgend + 1) * PAGE_SIZE;

		do_fallocate(range->asma->file,
		range->asma->file->f_op->fallocate(range->asma->file,
				FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
				start, end - start);
		range->purged = ASHMEM_WAS_PURGED;
+69 −1
Original line number Diff line number Diff line
@@ -1608,11 +1608,51 @@ static const struct usb_gadget_driver configfs_driver_template = {
	},
};

#ifdef CONFIG_USB_CONFIGFS_UEVENT
static ssize_t state_show(struct device *pdev, struct device_attribute *attr,
			char *buf)
{
	struct gadget_info *dev = dev_get_drvdata(pdev);
	struct usb_composite_dev *cdev;
	char *state = "DISCONNECTED";
	unsigned long flags;

	if (!dev)
		goto out;

	cdev = &dev->cdev;

	if (!cdev)
		goto out;

	spin_lock_irqsave(&cdev->lock, flags);
	if (cdev->config)
		state = "CONFIGURED";
	else if (dev->connected)
		state = "CONNECTED";
	spin_unlock_irqrestore(&cdev->lock, flags);
out:
	return sprintf(buf, "%s\n", state);
}

static DEVICE_ATTR(state, S_IRUGO, state_show, NULL);

static struct device_attribute *android_usb_attributes[] = {
	&dev_attr_state,
	NULL
};
#endif

static struct config_group *gadgets_make(
		struct config_group *group,
		const char *name)
{
	struct gadget_info *gi;
#ifdef CONFIG_USB_CONFIGFS_UEVENT
	struct device_attribute **attrs;
	struct device_attribute *attr;
	int err;
#endif

	gi = kzalloc(sizeof(*gi), GFP_KERNEL);
	if (!gi)
@@ -1658,10 +1698,19 @@ static struct config_group *gadgets_make(
				MKDEV(0, 0), NULL, "android0");
	if (IS_ERR(android_device))
		goto err;

	dev_set_drvdata(android_device, gi);

	attrs = android_usb_attributes;
	while ((attr = *attrs++)) {
		err = device_create_file(android_device, attr);
		if (err)
			goto err1;
	}
#endif

	if (!gi->composite.gadget_driver.function)
		goto err;
		goto err1;

#ifdef CONFIG_USB_OTG
	gi->otg.bLength = sizeof(struct usb_otg_descriptor);
@@ -1672,15 +1721,34 @@ static struct config_group *gadgets_make(
	config_group_init_type_name(&gi->group, name,
				&gadget_root_type);
	return &gi->group;

err1:
#ifdef CONFIG_USB_CONFIGFS_UEVENT
	attrs = android_usb_attributes;
	while ((attr = *attrs++))
		device_remove_file(android_device, attr);

	device_destroy(android_device->class,
				android_device->devt);
err:
#endif
	kfree(gi);
	return ERR_PTR(-ENOMEM);
}

static void gadgets_drop(struct config_group *group, struct config_item *item)
{
#ifdef CONFIG_USB_CONFIGFS_UEVENT
	struct device_attribute **attrs;
	struct device_attribute *attr;
#endif

	config_item_put(item);

#ifdef CONFIG_USB_CONFIGFS_UEVENT
	attrs = android_usb_attributes;
	while ((attr = *attrs++))
		device_remove_file(android_device, attr);
	device_destroy(android_device->class, android_device->devt);
#endif
}
+2 −0
Original line number Diff line number Diff line
@@ -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));
Loading