示例#1
0
static void __ref acpi_processor_hotplug_notify(acpi_handle handle,
						u32 event, void *data)
{
	struct acpi_processor *pr;
	struct acpi_device *device = NULL;
	int result;


	switch (event) {
	case ACPI_NOTIFY_BUS_CHECK:
	case ACPI_NOTIFY_DEVICE_CHECK:
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
		"Processor driver received %s event\n",
		       (event == ACPI_NOTIFY_BUS_CHECK) ?
		       "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK"));

		if (!is_processor_present(handle))
			break;

		if (acpi_bus_get_device(handle, &device)) {
			result = acpi_processor_device_add(handle, &device);
			if (result)
				printk(KERN_ERR PREFIX
					    "Unable to add the device\n");
			break;
		}
		pr = acpi_driver_data(device);
		if (processor_cntl_external() && pr)
			processor_notify_external(pr,
					PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD);
		break;
	case ACPI_NOTIFY_EJECT_REQUEST:
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "received ACPI_NOTIFY_EJECT_REQUEST\n"));

		if (acpi_bus_get_device(handle, &device)) {
			printk(KERN_ERR PREFIX
				    "Device don't exist, dropping EJECT\n");
			break;
		}
		pr = acpi_driver_data(device);
		if (!pr) {
			printk(KERN_ERR PREFIX
				    "Driver data is NULL, dropping EJECT\n");
			return;
		}
		if (processor_cntl_external())
			processor_notify_external(pr, PROCESSOR_HOTPLUG,
						HOTPLUG_TYPE_REMOVE);
		break;
	default:
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "Unsupported event [0x%x]\n", event));
		break;
	}

	return;
}
示例#2
0
static
int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
{
	acpi_handle phandle;
	struct acpi_device *pdev;


	if (acpi_get_parent(handle, &phandle)) {
		return -ENODEV;
	}

	if (acpi_bus_get_device(phandle, &pdev)) {
		return -ENODEV;
	}

	if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) {
		return -ENODEV;
	}

	if (processor_cntl_external() && acpi_driver_data(*device))
		processor_notify_external(acpi_driver_data(*device),
			PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD);

	return 0;
}
示例#3
0
static
int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device)
{
	acpi_handle phandle;
	struct acpi_device *pdev;
	struct acpi_processor *pr;


	if (acpi_get_parent(handle, &phandle)) {
		return -ENODEV;
	}

	if (acpi_bus_get_device(phandle, &pdev)) {
		return -ENODEV;
	}

	if (acpi_bus_add(device, pdev, handle, ACPI_BUS_TYPE_PROCESSOR)) {
		return -ENODEV;
	}

	acpi_bus_start(*device);

	pr = acpi_driver_data(*device);
	if (!pr)
		return -ENODEV;

	if (processor_cntl_external())
		processor_notify_external(pr,
			PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD);

	if ((pr->id >= 0) && (pr->id < NR_CPUS)) {
		kobject_uevent(&(*device)->kobj, KOBJ_ONLINE);
	}
	return 0;
}
示例#4
0
int acpi_processor_ppc_has_changed(struct acpi_processor *pr)
{
	int ret;

#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
	/* Xen hypervisor can handle cpufreq _PPC event */
	if (ignore_ppc < 0 && processor_pmperf_external())
		ignore_ppc = 0;
#endif

	if (ignore_ppc)
		return 0;

	ret = acpi_processor_get_platform_limit(pr);

	if (ret < 0)
		return (ret);
	else
#ifdef CONFIG_CPU_FREQ
		return cpufreq_update_policy(pr->id);
#elif defined(CONFIG_PROCESSOR_EXTERNAL_CONTROL)
		return processor_notify_external(pr,
				PROCESSOR_PM_CHANGE, PM_TYPE_PERF);
#endif
}
示例#5
0
/*
 * Existing ACPI module does parse performance states at some point,
 * when acpi-cpufreq driver is loaded which however is something
 * we'd like to disable to avoid confliction with external control
 * logic. So we have to collect raw performance information here 
 * when ACPI processor object is found and started.
 */
static int processor_extcntl_get_performance(struct acpi_processor *pr)
{
	int ret;
	struct acpi_processor_performance *perf;
	struct acpi_psd_package *pdomain;

	if (pr->performance)
		return -EBUSY;

	perf = kzalloc(sizeof(struct acpi_processor_performance), GFP_KERNEL);
	if (!perf)
		return -ENOMEM;

	pr->performance = perf;
	/* Get basic performance state information */
	ret = acpi_processor_get_performance_info(pr);
	if (ret < 0)
		goto err_out;

	/*
	 * Well, here we need retrieve performance dependency information
	 * from _PSD object. The reason why existing interface is not used
	 * is due to the reason that existing interface sticks to Linux cpu
	 * id to construct some bitmap, however we want to split ACPI 
	 * processor objects from Linux cpu id logic. For example, even
	 * when Linux is configured as UP, we still want to parse all ACPI
	 * processor objects to external logic. In this case, it's preferred
	 * to use ACPI ID instead.
	 */
	pdomain = &pr->performance->domain_info;
	pdomain->num_processors = 0;
	ret = acpi_processor_get_psd(pr);
	if (ret < 0) {
		/*
		 * _PSD is optional - assume no coordination if absent (or
		 * broken), matching native kernels' behavior.
		 */
		pdomain->num_entries = ACPI_PSD_REV0_ENTRIES;
		pdomain->revision = ACPI_PSD_REV0_REVISION;
		pdomain->domain = pr->acpi_id;
		pdomain->coord_type = DOMAIN_COORD_TYPE_SW_ALL;
		pdomain->num_processors = 1;
	}

	/* Some sanity check */
	if ((pdomain->revision != ACPI_PSD_REV0_REVISION) ||
	    (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) ||
	    ((pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL) &&
	     (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY) &&
	     (pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL))) {
		ret = -EINVAL;
		goto err_out;
	}

	/* Last step is to notify BIOS that external logic exists */
	processor_notify_smm();

	processor_notify_external(pr, PROCESSOR_PM_INIT, PM_TYPE_PERF);

	return 0;
err_out:
	pr->performance = NULL;
	kfree(perf);
	return ret;
}
示例#6
0
static void
acpi_processor_hotplug_notify(acpi_handle handle, u32 event, void *data)
{
	struct acpi_processor *pr;
	struct acpi_device *device = NULL;
	int result;


	switch (event) {
	case ACPI_NOTIFY_BUS_CHECK:
	case ACPI_NOTIFY_DEVICE_CHECK:
		printk("Processor driver received %s event\n",
		       (event == ACPI_NOTIFY_BUS_CHECK) ?
		       "ACPI_NOTIFY_BUS_CHECK" : "ACPI_NOTIFY_DEVICE_CHECK");

		if (!is_processor_present(handle))
			break;

		if (acpi_bus_get_device(handle, &device)) {
			result = acpi_processor_device_add(handle, &device);
			if (result)
				printk(KERN_ERR PREFIX
					    "Unable to add the device\n");
			break;
		}

		pr = acpi_driver_data(device);
		if (!pr) {
			printk(KERN_ERR PREFIX "Driver data is NULL\n");
			break;
		}

		if (processor_cntl_external())
			processor_notify_external(pr,
					PROCESSOR_HOTPLUG, HOTPLUG_TYPE_ADD);

		if (pr->id >= 0 && (pr->id < NR_CPUS)) {
			kobject_uevent(&device->kobj, KOBJ_OFFLINE);
			break;
		}

		result = acpi_processor_start(device);
		if ((!result) && ((pr->id >= 0) && (pr->id < NR_CPUS))) {
			kobject_uevent(&device->kobj, KOBJ_ONLINE);
		} else {
			printk(KERN_ERR PREFIX "Device [%s] failed to start\n",
				    acpi_device_bid(device));
		}
		break;
	case ACPI_NOTIFY_EJECT_REQUEST:
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "received ACPI_NOTIFY_EJECT_REQUEST\n"));

		if (acpi_bus_get_device(handle, &device)) {
			printk(KERN_ERR PREFIX
				    "Device don't exist, dropping EJECT\n");
			break;
		}
		pr = acpi_driver_data(device);
		if (!pr) {
			printk(KERN_ERR PREFIX
				    "Driver data is NULL, dropping EJECT\n");
			return;
		}

		if ((pr->id < NR_CPUS) && (cpu_present(pr->id)))
			kobject_uevent(&device->kobj, KOBJ_OFFLINE);

		if (processor_cntl_external())
			processor_notify_external(pr, PROCESSOR_HOTPLUG,
							HOTPLUG_TYPE_REMOVE);

		break;
	default:
		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "Unsupported event [0x%x]\n", event));
		break;
	}

	return;
}