cool device(风扇)的注册

在driver/acpi/fan.c 中有注册cool device
module_platform_driver(acpi_fan_driver);
所以我们看看acpi_fan_driver的probe函数
static struct platform_driver acpi_fan_driver = {
	.probe = acpi_fan_probe,
	.remove = acpi_fan_remove,
	.driver = {
		.name = "acpi-fan",
		.acpi_match_table = fan_device_ids,
		.pm = FAN_PM_OPS_PTR,
	},
};
这里的probe函数是acpi_fan_probe
static int acpi_fan_probe(struct platform_device *pdev)
{
	int result = 0;
	struct thermal_cooling_device *cdev;
	struct acpi_fan *fan;
	struct acpi_device *device = ACPI_COMPANION(&pdev->dev);
	char *name;
//这里用struct acpi_fan 代表fan
	fan = devm_kzalloc(&pdev->dev, sizeof(*fan), GFP_KERNEL);
	if (!fan) {
		dev_err(&device->dev, "No memory for fan\n");
		return -ENOMEM;
	}
	device->driver_data = fan;
	platform_set_drvdata(pdev, fan);
//看是否是acpi4,如果是acpi4的话,则fan的控制是在bios中做的,kernel通过runtime service来看之fan设备
	if (acpi_fan_is_acpi4(device)) {
		if (acpi_fan_get_fif(device) || acpi_fan_get_fps(device))
			goto end;
		fan->acpi4 = true;
	} else {
		result = acpi_device_update_power(device, NULL);
		if (result) {
			dev_err(&device->dev, "Failed to set initial power state\n");
			goto end;
		}
	}
//判断name是否是PNP0C0B。如果不是的话,则name是通过acpi_device_bid的到bus id
	if (!strncmp(pdev->name, "PNP0C0B", strlen("PNP0C0B")))
		name = "Fan";
	else
		name = acpi_device_bid(device);
//重点函数,注册cool device。另外一个重点是fan_cooling_ops。最终通过fan_cooling_ops结构体的set_cur_state来设置fan
	cdev = thermal_cooling_device_register(name, device,
						&fan_cooling_ops);
	if (IS_ERR(cdev)) {
		result = PTR_ERR(cdev);
		goto end;
	}

	dev_dbg(&pdev->dev, "registered as cooling_device%d\n", cdev->id);

	fan->cdev = cdev;
//添加sys文件接口
	result = sysfs_create_link(&pdev->dev.kobj,
				   &cdev->device.kobj,
				   "thermal_cooling");
	if (result)
		dev_err(&pdev->dev, "Failed to create sysfs link 'thermal_cooling'\n");

	result = sysfs_create_link(&cdev->device.kobj,
				   &pdev->dev.kobj,
				   "device");
	if (result)
		dev_err(&pdev->dev, "Failed to create sysfs link 'device'\n");

end:
	return result;
}
如何判断是否是acpi4 这个版本呢?
static bool acpi_fan_is_acpi4(struct acpi_device *device)
{
	return acpi_has_method(device->handle, "_FIF") &&
	       acpi_has_method(device->handle, "_FPS") &&
	       acpi_has_method(device->handle, "_FSL") &&
	       acpi_has_method(device->handle, "_FST");
}
原来是看BIOS是否提供个_FIF,_FPS,_FSL,_FST方法
下来看看thermal_cooling_device_register 具体都做了啥
thermal_cooling_device_register->__thermal_cooling_device_register
static struct thermal_cooling_device *
__thermal_cooling_device_register(struct device_node *np,
				  char *type, void *devdata,
				  const struct thermal_cooling_device_ops *ops)
{
	struct thermal_cooling_device *cdev;
	struct thermal_zone_device *pos = NULL;
	int result;

	if (type && strlen(type) >= THERMAL_NAME_LENGTH)
		return ERR_PTR(-EINVAL);

	if (!ops || !ops->get_max_state || !ops->get_cur_state ||
	    !ops->set_cur_state)
		return ERR_PTR(-EINVAL);

	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
	if (!cdev)
		return ERR_PTR(-ENOMEM);

	result = ida_simple_get(&thermal_cdev_ida, 0, 0, GFP_KERNEL);
	if (result < 0) {
		kfree(cdev);
		return ERR_PTR(result);
	}

	cdev->id = result;
	strlcpy(cdev->type, type ? : "", sizeof(cdev->type));
	mutex_init(&cdev->lock);
	INIT_LIST_HEAD(&cdev->thermal_instances);
// 这里用struct thermal_cooling_device *cdev表示一个cool device
	cdev->np = np;
	cdev->ops = ops;
	cdev->updated = false;
	cdev->device.class = &thermal_class;
	thermal_cooling_device_setup_sysfs(cdev);
	cdev->devdata = devdata;
	dev_set_name(&cdev->device, "cooling_device%d", cdev->id);
//注册device
	result = device_register(&cdev->device);
	if (result) {
		ida_simple_remove(&thermal_cdev_ida, cdev->id);
		kfree(cdev);
		return ERR_PTR(result);
	}
//所有的cool device都放在thermal_cdev_list 这个list中
	/* Add 'this' new cdev to the global cdev list */
	mutex_lock(&thermal_list_lock);
	list_add(&cdev->node, &thermal_cdev_list);
	mutex_unlock(&thermal_list_lock);
//如果这个cool device已经绑定了zone device,则重新执行绑定的动作,因为cool device的参数可能有更新
	/* Update binding information for 'this' new cdev */
	bind_cdev(cdev);

	mutex_lock(&thermal_list_lock);
	list_for_each_entry(pos, &thermal_tz_list, node)
		if (atomic_cmpxchg(&pos->need_update, 1, 0))
			thermal_zone_device_update(pos,
						   THERMAL_EVENT_UNSPECIFIED);
	mutex_unlock(&thermal_list_lock);

	return cdev;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值