Lines Matching +full:entry +full:- +full:method
1 // SPDX-License-Identifier: GPL-2.0-or-later
36 #define DRIVER_NAME "dell-wmi-ddv"
40 #define DELL_DDV_GUID "8A42EA14-4F2A-FD45-6422-0087F7A7E608"
132 static int dell_wmi_ddv_query_type(struct wmi_device *wdev, enum dell_ddv_method method, u32 arg, in dell_wmi_ddv_query_type() argument
143 ret = wmidev_evaluate_method(wdev, 0x0, method, &in, &out); in dell_wmi_ddv_query_type()
145 return -EIO; in dell_wmi_ddv_query_type()
149 return -ENODATA; in dell_wmi_ddv_query_type()
151 if (obj->type != type) { in dell_wmi_ddv_query_type()
153 return -ENOMSG; in dell_wmi_ddv_query_type()
161 static int dell_wmi_ddv_query_integer(struct wmi_device *wdev, enum dell_ddv_method method, in dell_wmi_ddv_query_integer() argument
167 ret = dell_wmi_ddv_query_type(wdev, method, arg, &obj, ACPI_TYPE_INTEGER); in dell_wmi_ddv_query_integer()
171 if (obj->integer.value <= U32_MAX) in dell_wmi_ddv_query_integer()
172 *res = (u32)obj->integer.value; in dell_wmi_ddv_query_integer()
174 ret = -ERANGE; in dell_wmi_ddv_query_integer()
181 static int dell_wmi_ddv_query_buffer(struct wmi_device *wdev, enum dell_ddv_method method, in dell_wmi_ddv_query_buffer() argument
188 ret = dell_wmi_ddv_query_type(wdev, method, arg, &obj, ACPI_TYPE_PACKAGE); in dell_wmi_ddv_query_buffer()
192 if (obj->package.count != 2 || in dell_wmi_ddv_query_buffer()
193 obj->package.elements[0].type != ACPI_TYPE_INTEGER || in dell_wmi_ddv_query_buffer()
194 obj->package.elements[1].type != ACPI_TYPE_BUFFER) { in dell_wmi_ddv_query_buffer()
195 ret = -ENOMSG; in dell_wmi_ddv_query_buffer()
200 buffer_size = obj->package.elements[0].integer.value; in dell_wmi_ddv_query_buffer()
203 ret = -ENODATA; in dell_wmi_ddv_query_buffer()
208 if (buffer_size > obj->package.elements[1].buffer.length) { in dell_wmi_ddv_query_buffer()
209 dev_warn(&wdev->dev, in dell_wmi_ddv_query_buffer()
211 buffer_size, obj->package.elements[1].buffer.length); in dell_wmi_ddv_query_buffer()
212 ret = -EMSGSIZE; in dell_wmi_ddv_query_buffer()
227 static int dell_wmi_ddv_query_string(struct wmi_device *wdev, enum dell_ddv_method method, in dell_wmi_ddv_query_string() argument
230 return dell_wmi_ddv_query_type(wdev, method, arg, result, ACPI_TYPE_STRING); in dell_wmi_ddv_query_string()
236 static int dell_wmi_ddv_update_sensors(struct wmi_device *wdev, enum dell_ddv_method method, in dell_wmi_ddv_update_sensors() argument
244 if (sensors->obj) { in dell_wmi_ddv_update_sensors()
245 if (time_before(jiffies, sensors->timestamp + HZ)) in dell_wmi_ddv_update_sensors()
248 kfree(sensors->obj); in dell_wmi_ddv_update_sensors()
249 sensors->obj = NULL; in dell_wmi_ddv_update_sensors()
252 ret = dell_wmi_ddv_query_buffer(wdev, method, 0, &obj); in dell_wmi_ddv_update_sensors()
257 buffer_size = obj->package.elements[0].integer.value; in dell_wmi_ddv_update_sensors()
258 buffer = obj->package.elements[1].buffer.pointer; in dell_wmi_ddv_update_sensors()
260 if (rem != 1 || buffer[buffer_size - 1] != 0xff) { in dell_wmi_ddv_update_sensors()
261 ret = -ENOMSG; in dell_wmi_ddv_update_sensors()
266 ret = -ENODATA; in dell_wmi_ddv_update_sensors()
270 sensors->obj = obj; in dell_wmi_ddv_update_sensors()
271 sensors->entries = entries; in dell_wmi_ddv_update_sensors()
272 sensors->timestamp = jiffies; in dell_wmi_ddv_update_sensors()
291 struct fan_sensor_entry *entry; in dell_wmi_ddv_fan_read_channel() local
294 ret = dell_wmi_ddv_update_sensors(data->wdev, DELL_DDV_FAN_SENSOR_INFORMATION, in dell_wmi_ddv_fan_read_channel()
295 &data->fans, sizeof(*entry)); in dell_wmi_ddv_fan_read_channel()
299 if (channel >= data->fans.entries) in dell_wmi_ddv_fan_read_channel()
300 return -ENXIO; in dell_wmi_ddv_fan_read_channel()
302 entry = (struct fan_sensor_entry *)data->fans.obj->package.elements[1].buffer.pointer; in dell_wmi_ddv_fan_read_channel()
305 *val = get_unaligned_le16(&entry[channel].rpm); in dell_wmi_ddv_fan_read_channel()
311 return -EOPNOTSUPP; in dell_wmi_ddv_fan_read_channel()
317 struct thermal_sensor_entry *entry; in dell_wmi_ddv_temp_read_channel() local
320 ret = dell_wmi_ddv_update_sensors(data->wdev, DELL_DDV_THERMAL_SENSOR_INFORMATION, in dell_wmi_ddv_temp_read_channel()
321 &data->temps, sizeof(*entry)); in dell_wmi_ddv_temp_read_channel()
325 if (channel >= data->temps.entries) in dell_wmi_ddv_temp_read_channel()
326 return -ENXIO; in dell_wmi_ddv_temp_read_channel()
328 entry = (struct thermal_sensor_entry *)data->temps.obj->package.elements[1].buffer.pointer; in dell_wmi_ddv_temp_read_channel()
331 *val = entry[channel].now * 1000; in dell_wmi_ddv_temp_read_channel()
334 *val = entry[channel].min * 1000; in dell_wmi_ddv_temp_read_channel()
337 *val = entry[channel].max * 1000; in dell_wmi_ddv_temp_read_channel()
343 return -EOPNOTSUPP; in dell_wmi_ddv_temp_read_channel()
354 mutex_lock(&data->fans.lock); in dell_wmi_ddv_read()
356 mutex_unlock(&data->fans.lock); in dell_wmi_ddv_read()
359 mutex_lock(&data->temps.lock); in dell_wmi_ddv_read()
361 mutex_unlock(&data->temps.lock); in dell_wmi_ddv_read()
367 return -EOPNOTSUPP; in dell_wmi_ddv_read()
373 struct fan_sensor_entry *entry; in dell_wmi_ddv_fan_read_string() local
377 ret = dell_wmi_ddv_update_sensors(data->wdev, DELL_DDV_FAN_SENSOR_INFORMATION, in dell_wmi_ddv_fan_read_string()
378 &data->fans, sizeof(*entry)); in dell_wmi_ddv_fan_read_string()
382 if (channel >= data->fans.entries) in dell_wmi_ddv_fan_read_string()
383 return -ENXIO; in dell_wmi_ddv_fan_read_string()
385 entry = (struct fan_sensor_entry *)data->fans.obj->package.elements[1].buffer.pointer; in dell_wmi_ddv_fan_read_string()
386 type = entry[channel].type; in dell_wmi_ddv_fan_read_string()
392 *str = fan_dock_labels[type - 0x11]; in dell_wmi_ddv_fan_read_string()
405 struct thermal_sensor_entry *entry; in dell_wmi_ddv_temp_read_string() local
408 ret = dell_wmi_ddv_update_sensors(data->wdev, DELL_DDV_THERMAL_SENSOR_INFORMATION, in dell_wmi_ddv_temp_read_string()
409 &data->temps, sizeof(*entry)); in dell_wmi_ddv_temp_read_string()
413 if (channel >= data->temps.entries) in dell_wmi_ddv_temp_read_string()
414 return -ENXIO; in dell_wmi_ddv_temp_read_string()
416 entry = (struct thermal_sensor_entry *)data->temps.obj->package.elements[1].buffer.pointer; in dell_wmi_ddv_temp_read_string()
417 switch (entry[channel].type) { in dell_wmi_ddv_temp_read_string()
469 mutex_lock(&data->fans.lock); in dell_wmi_ddv_read_string()
471 mutex_unlock(&data->fans.lock); in dell_wmi_ddv_read_string()
480 mutex_lock(&data->temps.lock); in dell_wmi_ddv_read_string()
482 mutex_unlock(&data->temps.lock); in dell_wmi_ddv_read_string()
492 return -EOPNOTSUPP; in dell_wmi_ddv_read_string()
510 return ERR_PTR(-ENOMEM); in dell_wmi_ddv_channel_create()
512 cinfo->info.type = type; in dell_wmi_ddv_channel_create()
513 cinfo->info.config = cinfo->config; in dell_wmi_ddv_channel_create()
516 cinfo->config[i] = config; in dell_wmi_ddv_channel_create()
518 return &cinfo->info; in dell_wmi_ddv_channel_create()
523 if (!sensors->active) in dell_wmi_ddv_hwmon_cache_invalidate()
526 mutex_lock(&sensors->lock); in dell_wmi_ddv_hwmon_cache_invalidate()
527 kfree(sensors->obj); in dell_wmi_ddv_hwmon_cache_invalidate()
528 sensors->obj = NULL; in dell_wmi_ddv_hwmon_cache_invalidate()
529 mutex_unlock(&sensors->lock); in dell_wmi_ddv_hwmon_cache_invalidate()
536 sensors->active = false; in dell_wmi_ddv_hwmon_cache_destroy()
537 mutex_destroy(&sensors->lock); in dell_wmi_ddv_hwmon_cache_destroy()
538 kfree(sensors->obj); in dell_wmi_ddv_hwmon_cache_destroy()
542 enum dell_ddv_method method, in dell_wmi_ddv_channel_init() argument
551 ret = dell_wmi_ddv_update_sensors(wdev, method, sensors, entry_size); in dell_wmi_ddv_channel_init()
555 mutex_init(&sensors->lock); in dell_wmi_ddv_channel_init()
556 sensors->active = true; in dell_wmi_ddv_channel_init()
558 ret = devm_add_action_or_reset(&wdev->dev, dell_wmi_ddv_hwmon_cache_destroy, sensors); in dell_wmi_ddv_channel_init()
562 info = dell_wmi_ddv_channel_create(&wdev->dev, sensors->entries, type, config); in dell_wmi_ddv_channel_init()
564 devm_release_action(&wdev->dev, dell_wmi_ddv_hwmon_cache_destroy, sensors); in dell_wmi_ddv_channel_init()
571 struct wmi_device *wdev = data->wdev; in dell_wmi_ddv_hwmon_add()
578 if (!devres_open_group(&wdev->dev, dell_wmi_ddv_hwmon_add, GFP_KERNEL)) in dell_wmi_ddv_hwmon_add()
579 return -ENOMEM; in dell_wmi_ddv_hwmon_add()
581 cinfo = devm_kzalloc(&wdev->dev, struct_size(cinfo, info, 4), GFP_KERNEL); in dell_wmi_ddv_hwmon_add()
583 ret = -ENOMEM; in dell_wmi_ddv_hwmon_add()
588 cinfo->chip.ops = &dell_wmi_ddv_ops; in dell_wmi_ddv_hwmon_add()
589 cinfo->chip.info = cinfo->info; in dell_wmi_ddv_hwmon_add()
591 info = dell_wmi_ddv_channel_create(&wdev->dev, 1, hwmon_chip, HWMON_C_REGISTER_TZ); in dell_wmi_ddv_hwmon_add()
598 cinfo->info[index] = info; in dell_wmi_ddv_hwmon_add()
601 info = dell_wmi_ddv_channel_init(wdev, DELL_DDV_FAN_SENSOR_INFORMATION, &data->fans, in dell_wmi_ddv_hwmon_add()
605 cinfo->info[index] = info; in dell_wmi_ddv_hwmon_add()
609 info = dell_wmi_ddv_channel_init(wdev, DELL_DDV_THERMAL_SENSOR_INFORMATION, &data->temps, in dell_wmi_ddv_hwmon_add()
614 cinfo->info[index] = info; in dell_wmi_ddv_hwmon_add()
625 hdev = devm_hwmon_device_register_with_info(&wdev->dev, "dell_ddv", data, &cinfo->chip, in dell_wmi_ddv_hwmon_add()
633 devres_close_group(&wdev->dev, dell_wmi_ddv_hwmon_add); in dell_wmi_ddv_hwmon_add()
638 devres_release_group(&wdev->dev, dell_wmi_ddv_hwmon_add); in dell_wmi_ddv_hwmon_add()
649 return -ENODEV; in dell_wmi_ddv_battery_index()
660 ret = dell_wmi_ddv_battery_index(to_acpi_device(dev->parent), &index); in temp_show()
664 ret = dell_wmi_ddv_query_integer(data->wdev, DELL_DDV_BATTERY_TEMPERATURE, index, &value); in temp_show()
669 return sysfs_emit(buf, "%d\n", value - 2731); in temp_show()
679 ret = dell_wmi_ddv_battery_index(to_acpi_device(dev->parent), &index); in eppid_show()
683 ret = dell_wmi_ddv_query_string(data->wdev, DELL_DDV_BATTERY_EPPID, index, &obj); in eppid_show()
687 if (obj->string.length != DELL_EPPID_LENGTH && obj->string.length != DELL_EPPID_EXT_LENGTH) in eppid_show()
688 dev_info_once(&data->wdev->dev, FW_INFO "Suspicious ePPID length (%d)\n", in eppid_show()
689 obj->string.length); in eppid_show()
691 ret = sysfs_emit(buf, "%s\n", obj->string.pointer); in eppid_show()
705 ret = dell_wmi_ddv_battery_index(to_acpi_device(battery->dev.parent), &index); in dell_wmi_ddv_add_battery()
709 ret = device_create_file(&battery->dev, &data->temp_attr); in dell_wmi_ddv_add_battery()
713 ret = device_create_file(&battery->dev, &data->eppid_attr); in dell_wmi_ddv_add_battery()
715 device_remove_file(&battery->dev, &data->temp_attr); in dell_wmi_ddv_add_battery()
727 device_remove_file(&battery->dev, &data->temp_attr); in dell_wmi_ddv_remove_battery()
728 device_remove_file(&battery->dev, &data->eppid_attr); in dell_wmi_ddv_remove_battery()
742 data->hook.name = "Dell DDV Battery Extension"; in dell_wmi_ddv_battery_add()
743 data->hook.add_battery = dell_wmi_ddv_add_battery; in dell_wmi_ddv_battery_add()
744 data->hook.remove_battery = dell_wmi_ddv_remove_battery; in dell_wmi_ddv_battery_add()
746 sysfs_attr_init(&data->temp_attr.attr); in dell_wmi_ddv_battery_add()
747 data->temp_attr.attr.name = "temp"; in dell_wmi_ddv_battery_add()
748 data->temp_attr.attr.mode = 0444; in dell_wmi_ddv_battery_add()
749 data->temp_attr.show = temp_show; in dell_wmi_ddv_battery_add()
751 sysfs_attr_init(&data->eppid_attr.attr); in dell_wmi_ddv_battery_add()
752 data->eppid_attr.attr.name = "eppid"; in dell_wmi_ddv_battery_add()
753 data->eppid_attr.attr.mode = 0444; in dell_wmi_ddv_battery_add()
754 data->eppid_attr.show = eppid_show; in dell_wmi_ddv_battery_add()
756 battery_hook_register(&data->hook); in dell_wmi_ddv_battery_add()
758 return devm_add_action_or_reset(&data->wdev->dev, dell_wmi_ddv_battery_remove, &data->hook); in dell_wmi_ddv_battery_add()
761 static int dell_wmi_ddv_buffer_read(struct seq_file *seq, enum dell_ddv_method method) in dell_wmi_ddv_buffer_read() argument
763 struct device *dev = seq->private; in dell_wmi_ddv_buffer_read()
770 ret = dell_wmi_ddv_query_buffer(data->wdev, method, 0, &obj); in dell_wmi_ddv_buffer_read()
774 size = obj->package.elements[0].integer.value; in dell_wmi_ddv_buffer_read()
775 buf = obj->package.elements[1].buffer.pointer; in dell_wmi_ddv_buffer_read()
794 struct dentry *entry = data; in dell_wmi_ddv_debugfs_remove() local
796 debugfs_remove(entry); in dell_wmi_ddv_debugfs_remove()
801 struct dentry *entry; in dell_wmi_ddv_debugfs_init() local
804 scnprintf(name, ARRAY_SIZE(name), "%s-%s", DRIVER_NAME, dev_name(&wdev->dev)); in dell_wmi_ddv_debugfs_init()
805 entry = debugfs_create_dir(name, NULL); in dell_wmi_ddv_debugfs_init()
807 debugfs_create_devm_seqfile(&wdev->dev, "fan_sensor_information", entry, in dell_wmi_ddv_debugfs_init()
809 debugfs_create_devm_seqfile(&wdev->dev, "thermal_sensor_information", entry, in dell_wmi_ddv_debugfs_init()
812 devm_add_action_or_reset(&wdev->dev, dell_wmi_ddv_debugfs_remove, entry); in dell_wmi_ddv_debugfs_init()
825 dev_dbg(&wdev->dev, "WMI interface version: %d\n", version); in dell_wmi_ddv_probe()
828 return -ENODEV; in dell_wmi_ddv_probe()
830 dev_warn(&wdev->dev, "Loading despite unsupported WMI interface version (%u)\n", in dell_wmi_ddv_probe()
834 data = devm_kzalloc(&wdev->dev, sizeof(*data), GFP_KERNEL); in dell_wmi_ddv_probe()
836 return -ENOMEM; in dell_wmi_ddv_probe()
838 dev_set_drvdata(&wdev->dev, data); in dell_wmi_ddv_probe()
839 data->wdev = wdev; in dell_wmi_ddv_probe()
846 dev_warn(&wdev->dev, "Unable to register ACPI battery hook: %d\n", ret); in dell_wmi_ddv_probe()
852 dev_warn(&wdev->dev, "Unable to register hwmon interface: %d\n", ret); in dell_wmi_ddv_probe()
862 /* Force re-reading of all active sensors */ in dell_wmi_ddv_resume()
863 dell_wmi_ddv_hwmon_cache_invalidate(&data->fans); in dell_wmi_ddv_resume()
864 dell_wmi_ddv_hwmon_cache_invalidate(&data->temps); in dell_wmi_ddv_resume()