Example #1
0
/*
 * register cpu under node
 */
int register_cpu_under_node(unsigned int cpu, unsigned int nid)
{
	int ret;
	struct sys_device *obj;

	if (!node_online(nid))
		return 0;

	obj = get_cpu_sysdev(cpu);
	if (!obj)
		return 0;

	ret = sysfs_create_link(&node_devices[nid].sysdev.kobj,
				&obj->kobj,
				kobject_name(&obj->kobj));
	if (ret)
		return ret;

	return sysfs_create_link(&obj->kobj,
				 &node_devices[nid].sysdev.kobj,
				 kobject_name(&node_devices[nid].sysdev.kobj));
}
Example #2
0
/**
 * __cpuidle_register_device - internal register function called before register
 * and enable routines
 * @dev: the cpu
 *
 * cpuidle_lock mutex must be held before this is called
 */
static int __cpuidle_register_device(struct cpuidle_device *dev)
{
	int ret;
	struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
	struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();

	if (!sys_dev)
		return -EINVAL;
	if (!try_module_get(cpuidle_driver->owner))
		return -EINVAL;

	init_completion(&dev->kobj_unregister);

	per_cpu(cpuidle_devices, dev->cpu) = dev;
	list_add(&dev->device_list, &cpuidle_detected_devices);
	if ((ret = cpuidle_add_sysfs(sys_dev))) {
		module_put(cpuidle_driver->owner);
		return ret;
	}

	dev->registered = 1;
	return 0;
}
Example #3
0
/**
 * cpuidle_unregister_device - unregisters a CPU's idle PM feature
 * @dev: the cpu
 */
void cpuidle_unregister_device(struct cpuidle_device *dev)
{
    struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
    struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();

    if (dev->registered == 0)
        return;

    cpuidle_pause_and_lock();

    cpuidle_disable_device(dev);

    cpuidle_remove_sysfs(sys_dev);
    list_del(&dev->device_list);
    wait_for_completion(&dev->kobj_unregister);
    per_cpu(cpuidle_devices, dev->cpu) = NULL;

    cpuidle_coupled_unregister_device(dev);

    cpuidle_resume_and_unlock();

    module_put(cpuidle_driver->owner);
}
Example #4
0
static __init int thermal_throttle_init_device(void)
{
	unsigned int cpu = 0;
	int err;

	if (!atomic_read(&therm_throt_en))
		return 0;

	register_hotcpu_notifier(&thermal_throttle_cpu_notifier);

#ifdef CONFIG_HOTPLUG_CPU
	mutex_lock(&therm_cpu_lock);
#endif
	/* connect live CPUs to sysfs */
	for_each_online_cpu(cpu) {
		err = thermal_throttle_add_dev(get_cpu_sysdev(cpu));
		WARN_ON(err);
	}
#ifdef CONFIG_HOTPLUG_CPU
	mutex_unlock(&therm_cpu_lock);
#endif

	return 0;
}
Example #5
0
/* Get notified when a cpu comes on/off. Be hotplug friendly. */
static __cpuinit int thermal_throttle_cpu_callback(struct notifier_block *nfb,
						   unsigned long action,
						   void *hcpu)
{
	unsigned int cpu = (unsigned long)hcpu;
	struct sys_device *sys_dev;
	int err;

	sys_dev = get_cpu_sysdev(cpu);
	mutex_lock(&therm_cpu_lock);
	switch (action) {
	case CPU_ONLINE:
	case CPU_ONLINE_FROZEN:
		err = thermal_throttle_add_dev(sys_dev);
		WARN_ON(err);
		break;
	case CPU_DEAD:
	case CPU_DEAD_FROZEN:
		thermal_throttle_remove_dev(sys_dev);
		break;
	}
	mutex_unlock(&therm_cpu_lock);
	return NOTIFY_OK;
}
Example #6
0
static int __cpuinit acpi_processor_add(struct acpi_device *device)
{
	struct acpi_processor *pr = NULL;
	int result = 0;
	struct sys_device *sysdev;

	pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
	if (!pr)
		return -ENOMEM;

	if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
		kfree(pr);
		return -ENOMEM;
	}

	pr->handle = device->handle;
	strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
	strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
	device->driver_data = pr;

	result = acpi_processor_get_info(device);
	if (result) {
		/* Processor is physically not present */
		return 0;
	}

	BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));

	/*
	 * Buggy BIOS check
	 * ACPI id of processors can be reported wrongly by the BIOS.
	 * Don't trust it blindly
	 */
	if (per_cpu(processor_device_array, pr->id) != NULL &&
	    per_cpu(processor_device_array, pr->id) != device) {
		printk(KERN_WARNING "BIOS reported wrong ACPI id "
			"for the processor\n");
		result = -ENODEV;
		goto err_free_cpumask;
	}
	per_cpu(processor_device_array, pr->id) = device;

	per_cpu(processors, pr->id) = pr;

	result = acpi_processor_add_fs(device);
	if (result)
		goto err_free_cpumask;

	sysdev = get_cpu_sysdev(pr->id);
	if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
		result = -EFAULT;
		goto err_remove_fs;
	}

	/* _PDC call should be done before doing anything else (if reqd.). */
	arch_acpi_processor_init_pdc(pr);
	acpi_processor_set_pdc(pr);
	arch_acpi_processor_cleanup_pdc(pr);

#ifdef CONFIG_CPU_FREQ
	acpi_processor_ppc_has_changed(pr);
#endif
	acpi_processor_get_throttling_info(pr);
	acpi_processor_get_limit_info(pr);


	acpi_processor_power_init(pr, device);

	pr->cdev = thermal_cooling_device_register("Processor", device,
						&processor_cooling_ops);
	if (IS_ERR(pr->cdev)) {
		result = PTR_ERR(pr->cdev);
		goto err_power_exit;
	}

	dev_info(&device->dev, "registered as cooling_device%d\n",
		 pr->cdev->id);

	result = sysfs_create_link(&device->dev.kobj,
				   &pr->cdev->device.kobj,
				   "thermal_cooling");
	if (result) {
		printk(KERN_ERR PREFIX "Create sysfs link\n");
		goto err_thermal_unregister;
	}
	result = sysfs_create_link(&pr->cdev->device.kobj,
				   &device->dev.kobj,
				   "device");
	if (result) {
		printk(KERN_ERR PREFIX "Create sysfs link\n");
		goto err_remove_sysfs;
	}

	return 0;

err_remove_sysfs:
	sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
err_thermal_unregister:
	thermal_cooling_device_unregister(pr->cdev);
err_power_exit:
	acpi_processor_power_exit(pr, device);
err_remove_fs:
	acpi_processor_remove_fs(device);
err_free_cpumask:
	free_cpumask_var(pr->throttling.shared_cpu_map);

	return result;
}
static int init_rq_attribs(void)
{
    int i;
    int err = 0;
    const int attr_count = 4;

    struct attribute **attribs =
        kzalloc(sizeof(struct attribute *) * attr_count, GFP_KERNEL);

    if (!attribs) {
        pr_err("%s: Allocate attribs failed!\n", __func__);
        goto rel;
    }

    rq_info.rq_avg = 0;

    attribs[0] = MSM_RQ_STATS_RW_ATTRIB(def_timer_ms);
    attribs[1] = MSM_RQ_STATS_RO_ATTRIB(run_queue_avg);
    attribs[2] = MSM_RQ_STATS_RW_ATTRIB(run_queue_poll_ms);
    attribs[3] = NULL;

    for (i = 0; i < attr_count - 1 ; i++) {
        if (!attribs[i]) {
            pr_err("%s: Allocate attribs[%d] failed!\n", __func__, i);
            goto rel2;
        }
    }

    rq_info.attr_group = kzalloc(sizeof(struct attribute_group),
                                 GFP_KERNEL);
    if (!rq_info.attr_group) {
        pr_err("%s: Allocate rq_info.attr_group failed!\n", __func__);
        goto rel3;
    }
    rq_info.attr_group->attrs = attribs;

    /* Create /sys/devices/system/cpu/cpu0/rq-stats/... */
    rq_info.kobj = kobject_create_and_add("rq-stats",
                                          &get_cpu_sysdev(0)->kobj);
    if (!rq_info.kobj) {
        pr_err("%s: Create rq_info.kobj failed!\n", __func__);
        goto rel3;
    }

    err = sysfs_create_group(rq_info.kobj, rq_info.attr_group);
    if (err)
        kobject_put(rq_info.kobj);
    else
        kobject_uevent(rq_info.kobj, KOBJ_ADD);

    if (!err) {
        pr_info("%s: Initialize done.\n", __func__);
        init_done = 1;
        return err;
    }

rel3:
    kfree(rq_info.attr_group);
    kfree(rq_info.kobj);
rel2:
    for (i = 0; i < attr_count - 1; i++)
        kfree(attribs[i]);
rel:
    kfree(attribs);

    return -ENOMEM;
}
static int __cpuinit acpi_processor_start(struct acpi_device *device)
{
	int result = 0;
	struct acpi_processor *pr;
	struct sys_device *sysdev;

	pr = acpi_driver_data(device);

	result = acpi_processor_get_info(device);
	if (result) {
		/* Processor is physically not present */
		return 0;
	}

	BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0));

	/*
	 * Buggy BIOS check
	 * ACPI id of processors can be reported wrongly by the BIOS.
	 * Don't trust it blindly
	 */
	if (per_cpu(processor_device_array, pr->id) != NULL &&
	    per_cpu(processor_device_array, pr->id) != device) {
		printk(KERN_WARNING "BIOS reported wrong ACPI id "
			"for the processor\n");
		return -ENODEV;
	}
	per_cpu(processor_device_array, pr->id) = device;

	per_cpu(processors, pr->id) = pr;

	result = acpi_processor_add_fs(device);
	if (result)
		goto end;

	sysdev = get_cpu_sysdev(pr->id);
	if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev"))
		return -EFAULT;

	/* _PDC call should be done before doing anything else (if reqd.). */
	arch_acpi_processor_init_pdc(pr);
	acpi_processor_set_pdc(pr);
#ifdef CONFIG_CPU_FREQ
	acpi_processor_ppc_has_changed(pr);
#endif
	acpi_processor_get_throttling_info(pr);
	acpi_processor_get_limit_info(pr);


	acpi_processor_power_init(pr, device);

	pr->cdev = thermal_cooling_device_register("Processor", device,
						&processor_cooling_ops);
	if (IS_ERR(pr->cdev)) {
		result = PTR_ERR(pr->cdev);
		goto end;
	}

	dev_info(&device->dev, "registered as cooling_device%d\n",
		 pr->cdev->id);

	result = sysfs_create_link(&device->dev.kobj,
				   &pr->cdev->device.kobj,
				   "thermal_cooling");
	if (result)
		printk(KERN_ERR PREFIX "Create sysfs link\n");
	result = sysfs_create_link(&pr->cdev->device.kobj,
				   &device->dev.kobj,
				   "device");
	if (result)
		printk(KERN_ERR PREFIX "Create sysfs link\n");

	if (pr->flags.throttling) {
		printk(KERN_INFO PREFIX "%s [%s] (supports",
		       acpi_device_name(device), acpi_device_bid(device));
		printk(" %d throttling states", pr->throttling.state_count);
		printk(")\n");
	}

      end:

	return result;
}
Example #9
0
static void __cpuinit topology_remove_dev(unsigned int cpu)
{
    struct sys_device *sys_dev = get_cpu_sysdev(cpu);

    sysfs_remove_group(&sys_dev->kobj, &topology_attr_group);
}
Example #10
0
/* Add/Remove cpu_topology interface for CPU device */
static int __cpuinit topology_add_dev(unsigned int cpu)
{
    struct sys_device *sys_dev = get_cpu_sysdev(cpu);

    return sysfs_create_group(&sys_dev->kobj, &topology_attr_group);
}
Example #11
0
/**
 * __cpuidle_register_device - internal register function called before register
 * and enable routines
 * @dev: the cpu
 *
 * cpuidle_lock mutex must be held before this is called
 */
static int __cpuidle_register_device(struct cpuidle_device *dev)
{
	int ret;
	struct sys_device *sys_dev = get_cpu_sysdev((unsigned long)dev->cpu);
	struct cpuidle_driver *cpuidle_driver = cpuidle_get_driver();

	if (!sys_dev)
		return -EINVAL;
	if (!try_module_get(cpuidle_driver->owner))
		return -EINVAL;

	init_completion(&dev->kobj_unregister);

	/*
	 * cpuidle driver should set the dev->power_specified bit
	 * before registering the device if the driver provides
	 * power_usage numbers.
	 *
	 * For those devices whose ->power_specified is not set,
	 * we fill in power_usage with decreasing values as the
	 * cpuidle code has an implicit assumption that state Cn
	 * uses less power than C(n-1).
	 *
	 * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
	 * an power value of -1.  So we use -2, -3, etc, for other
	 * c-states.
	 */
	if (!dev->power_specified) {
		int i;
		for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++)
			dev->states[i].power_usage = -1 - i;
	}

	/*
	 * cpuidle driver should set the dev->power_specified bit
	 * before registering the device if the driver provides
	 * power_usage numbers.
	 *
	 * For those devices whose ->power_specified is not set,
	 * we fill in power_usage with decreasing values as the
	 * cpuidle code has an implicit assumption that state Cn
	 * uses less power than C(n-1).
	 *
	 * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
	 * an power value of -1.  So we use -2, -3, etc, for other
	 * c-states.
	 */
	if (!dev->power_specified) {
		int i;
		for (i = CPUIDLE_DRIVER_STATE_START; i < dev->state_count; i++)
			dev->states[i].power_usage = -1 - i;
	}

	per_cpu(cpuidle_devices, dev->cpu) = dev;
	list_add(&dev->device_list, &cpuidle_detected_devices);
	if ((ret = cpuidle_add_sysfs(sys_dev))) {
		module_put(cpuidle_driver->owner);
		return ret;
	}

	dev->registered = 1;
	return 0;
}
Example #12
0
static int __cpuinit acpi_processor_add(struct acpi_device *device)
{
	struct acpi_processor *pr = NULL;
	int result = 0;
	struct sys_device *sysdev;

	pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL);
	if (!pr)
		return -ENOMEM;

	if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) {
		kfree(pr);
		return -ENOMEM;
	}

	pr->handle = device->handle;
	strcpy(acpi_device_name(device), ACPI_PROCESSOR_DEVICE_NAME);
	strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS);
	device->driver_data = pr;

 	processor_extcntl_init();

	result = acpi_processor_get_info(device);
	if (result ||
	    ((pr->id == -1) && !processor_cntl_external())) {
		/* Processor is physically not present */
		return 0;
	}

	BUG_ON(!processor_cntl_external() &&
	       ((pr->id >= nr_cpu_ids) || (pr->id < 0)));

	/*
	 * Buggy BIOS check
	 * ACPI id of processors can be reported wrongly by the BIOS.
	 * Don't trust it blindly
	 */
#ifndef CONFIG_XEN
	if (per_cpu(processor_device_array, pr->id) != NULL &&
	    per_cpu(processor_device_array, pr->id) != device) {
#else
	BUG_ON(pr->acpi_id >= NR_ACPI_CPUS);
	if (processor_device_array[pr->acpi_id] != NULL &&
	    processor_device_array[pr->acpi_id] != device) {
#endif
		printk(KERN_WARNING "BIOS reported wrong ACPI id "
			"for the processor\n");
		result = -ENODEV;
		goto err_free_cpumask;
	}
#ifndef CONFIG_XEN
	per_cpu(processor_device_array, pr->id) = device;

	per_cpu(processors, pr->id) = pr;
#else
	processor_device_array[pr->acpi_id] = device;
	if (pr->id != -1)
		per_cpu(processors, pr->id) = pr;
#endif

	result = acpi_processor_add_fs(device);
	if (result)
		goto err_free_cpumask;

	if (pr->id != -1) {
		sysdev = get_cpu_sysdev(pr->id);
		if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) {
			result = -EFAULT;
			goto err_remove_fs;
		}
	}

	/* _PDC call should be done before doing anything else (if reqd.). */
	arch_acpi_processor_init_pdc(pr);
	acpi_processor_set_pdc(pr);
	arch_acpi_processor_cleanup_pdc(pr);

#if defined(CONFIG_CPU_FREQ) || defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL)
	acpi_processor_ppc_has_changed(pr);
#endif

	/*
	 * pr->id may equal to -1 while processor_cntl_external enabled.
	 * throttle and thermal module don't support this case.
	 * Tx only works when dom0 vcpu == pcpu num by far, as we give
	 * control to dom0.
	 */
	if (pr->id != -1) {
		acpi_processor_get_throttling_info(pr);
		acpi_processor_get_limit_info(pr);
	}

	acpi_processor_power_init(pr, device);

	result = processor_extcntl_prepare(pr);
	if (result)
		goto err_power_exit;

	pr->cdev = thermal_cooling_device_register("Processor", device,
						&processor_cooling_ops);
	if (IS_ERR(pr->cdev)) {
		result = PTR_ERR(pr->cdev);
		goto err_power_exit;
	}

	dev_info(&device->dev, "registered as cooling_device%d\n",
		 pr->cdev->id);

	result = sysfs_create_link(&device->dev.kobj,
				   &pr->cdev->device.kobj,
				   "thermal_cooling");
	if (result) {
		printk(KERN_ERR PREFIX "Create sysfs link\n");
		goto err_thermal_unregister;
	}
	result = sysfs_create_link(&pr->cdev->device.kobj,
				   &device->dev.kobj,
				   "device");
	if (result) {
		printk(KERN_ERR PREFIX "Create sysfs link\n");
		goto err_remove_sysfs;
	}

	return 0;

err_remove_sysfs:
	sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
err_thermal_unregister:
	thermal_cooling_device_unregister(pr->cdev);
err_power_exit:
	acpi_processor_power_exit(pr, device);
err_remove_fs:
	acpi_processor_remove_fs(device);
err_free_cpumask:
	free_cpumask_var(pr->throttling.shared_cpu_map);

	return result;
}

static int acpi_processor_remove(struct acpi_device *device, int type)
{
	struct acpi_processor *pr = NULL;


	if (!device || !acpi_driver_data(device))
		return -EINVAL;

	pr = acpi_driver_data(device);

	if (!processor_cntl_external() && pr->id >= nr_cpu_ids)
		goto free;

	if (type == ACPI_BUS_REMOVAL_EJECT) {
		if (acpi_processor_handle_eject(pr))
			return -EINVAL;
	}

	acpi_processor_power_exit(pr, device);

	if (pr->id != -1)
		sysfs_remove_link(&device->dev.kobj, "sysdev");

	acpi_processor_remove_fs(device);

	if (pr->cdev) {
		sysfs_remove_link(&device->dev.kobj, "thermal_cooling");
		sysfs_remove_link(&pr->cdev->device.kobj, "device");
		thermal_cooling_device_unregister(pr->cdev);
		pr->cdev = NULL;
	}

#ifndef CONFIG_XEN
	per_cpu(processors, pr->id) = NULL;
	per_cpu(processor_device_array, pr->id) = NULL;
#else
	if (pr->id != -1)
		per_cpu(processors, pr->id) = NULL;
	processor_device_array[pr->acpi_id] = NULL;
#endif

free:
	free_cpumask_var(pr->throttling.shared_cpu_map);
	kfree(pr);

	return 0;
}

#ifdef CONFIG_ACPI_HOTPLUG_CPU
/****************************************************************************
 * 	Acpi processor hotplug support 				       	    *
 ****************************************************************************/

static int is_processor_present(acpi_handle handle)
{
	acpi_status status;
	unsigned long long sta = 0;


	status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);

	if (ACPI_SUCCESS(status) && (sta & ACPI_STA_DEVICE_PRESENT))
		return 1;

	/*
	 * _STA is mandatory for a processor that supports hot plug
	 */
	if (status == AE_NOT_FOUND)
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				"Processor does not support hot plug\n"));
	else
		ACPI_EXCEPTION((AE_INFO, status,
				"Processor Device is not present"));
	return 0;
}