static long acpi_thermal_rel_ioctl(struct file *f, unsigned int cmd, unsigned long __arg) { int ret = 0; unsigned long length = 0; int count = 0; char __user *arg = (void __user *)__arg; struct trt *trts = NULL; struct art *arts = NULL; switch (cmd) { case ACPI_THERMAL_GET_TRT_COUNT: ret = acpi_parse_trt(acpi_thermal_rel_handle, &count, &trts, false); kfree(trts); if (!ret) return put_user(count, (unsigned long __user *)__arg); return ret; case ACPI_THERMAL_GET_TRT_LEN: ret = acpi_parse_trt(acpi_thermal_rel_handle, &count, &trts, false); kfree(trts); length = count * sizeof(union trt_object); if (!ret) return put_user(length, (unsigned long __user *)__arg); return ret; case ACPI_THERMAL_GET_TRT: return fill_trt(arg); case ACPI_THERMAL_GET_ART_COUNT: ret = acpi_parse_art(acpi_thermal_rel_handle, &count, &arts, false); kfree(arts); if (!ret) return put_user(count, (unsigned long __user *)__arg); return ret; case ACPI_THERMAL_GET_ART_LEN: ret = acpi_parse_art(acpi_thermal_rel_handle, &count, &arts, false); kfree(arts); length = count * sizeof(union art_object); if (!ret) return put_user(length, (unsigned long __user *)__arg); return ret; case ACPI_THERMAL_GET_ART: return fill_art(arg); default: return -ENOTTY; } }
static int fill_trt(char __user *ubuf) { int i; int ret; int count; int trt_len; struct trt *trts = NULL; union trt_object *trt_user; ret = acpi_parse_trt(acpi_thermal_rel_handle, &count, &trts, false); if (ret) goto free_trt; trt_len = count * sizeof(union trt_object); trt_user = kzalloc(trt_len, GFP_KERNEL); if (!trt_user) { ret = -ENOMEM; goto free_trt; } /* now fill in user trt data */ for (i = 0; i < count; i++) { /* userspace trt needs device name instead of acpi reference */ get_single_name(trts[i].source, trt_user[i].source_device); get_single_name(trts[i].target, trt_user[i].target_device); trt_user[i].sample_period = trts[i].sample_period; trt_user[i].influence = trts[i].influence; } if (copy_to_user(ubuf, trt_user, trt_len)) ret = -EFAULT; kfree(trt_user); free_trt: kfree(trts); return ret; }
static int int3400_thermal_probe(struct platform_device *pdev) { struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); struct int3400_thermal_priv *priv; int result; if (!adev) return -ENODEV; priv = kzalloc(sizeof(struct int3400_thermal_priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->adev = adev; result = int3400_thermal_get_uuids(priv); if (result) goto free_priv; result = acpi_parse_art(priv->adev->handle, &priv->art_count, &priv->arts, true); if (result) dev_dbg(&pdev->dev, "_ART table parsing error\n"); result = acpi_parse_trt(priv->adev->handle, &priv->trt_count, &priv->trts, true); if (result) dev_dbg(&pdev->dev, "_TRT table parsing error\n"); platform_set_drvdata(pdev, priv); if (priv->uuid_bitmap & 1 << INT3400_THERMAL_PASSIVE_1) { int3400_thermal_ops.get_mode = int3400_thermal_get_mode; int3400_thermal_ops.set_mode = int3400_thermal_set_mode; } priv->thermal = thermal_zone_device_register("INT3400 Thermal", 0, 0, priv, &int3400_thermal_ops, &int3400_thermal_params, 0, 0); if (IS_ERR(priv->thermal)) { result = PTR_ERR(priv->thermal); goto free_art_trt; } priv->rel_misc_dev_res = acpi_thermal_rel_misc_device_add( priv->adev->handle); result = sysfs_create_group(&pdev->dev.kobj, &uuid_attribute_group); if (result) goto free_zone; return 0; free_zone: thermal_zone_device_unregister(priv->thermal); free_art_trt: kfree(priv->trts); kfree(priv->arts); free_priv: kfree(priv); return result; }