diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index ba2e7d2548429a249a2462cf58a24938245ee047..00b6dfed573cf595594714df451621eb2f991893 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -121,8 +121,9 @@ space, for 2.6.23+ this is /sys/devices/platform/thinkpad_acpi/. Sysfs device attributes for the sensors and fan are on the thinkpad_hwmon device's sysfs attribute space, but you should locate it looking for a hwmon device with the name attribute of "thinkpad", or -better yet, through libsensors. - +better yet, through libsensors. For 4.14+ sysfs attributes were moved to the +hwmon device (/sys/bus/platform/devices/thinkpad_hwmon/hwmon/hwmon? or +/sys/class/hwmon/hwmon?). Driver version -------------- @@ -1478,3 +1479,7 @@ Sysfs interface changelog: 0x020700: Support for mute-only mixers. Volume control in read-only mode by default. Marker for ALSA mixer support. + +0x030000: Thermal and fan sysfs attributes were moved to the hwmon + device instead of being attached to the backing platform + device. diff --git a/drivers/platform/x86/alienware-wmi.c b/drivers/platform/x86/alienware-wmi.c index 0831b428c217549f6d42a6d1543d4ed0cb539535..4eb8e1a472b23821280fae17f91df35a8ce8737e 100644 --- a/drivers/platform/x86/alienware-wmi.c +++ b/drivers/platform/x86/alienware-wmi.c @@ -255,12 +255,13 @@ static int parse_rgb(const char *buf, struct platform_zone *zone) static struct platform_zone *match_zone(struct device_attribute *attr) { - int i; - for (i = 0; i < quirks->num_zones; i++) { - if ((struct device_attribute *)zone_data[i].attr == attr) { + u8 zone; + + for (zone = 0; zone < quirks->num_zones; zone++) { + if ((struct device_attribute *)zone_data[zone].attr == attr) { pr_debug("alienware-wmi: matched zone location: %d\n", - zone_data[i].location); - return &zone_data[i]; + zone_data[zone].location); + return &zone_data[zone]; } } return NULL; @@ -420,7 +421,7 @@ static DEVICE_ATTR(lighting_control_state, 0644, show_control_state, static int alienware_zone_init(struct platform_device *dev) { - int i; + u8 zone; char buffer[10]; char *name; @@ -457,19 +458,19 @@ static int alienware_zone_init(struct platform_device *dev) if (!zone_data) return -ENOMEM; - for (i = 0; i < quirks->num_zones; i++) { - sprintf(buffer, "zone%02X", i); + for (zone = 0; zone < quirks->num_zones; zone++) { + sprintf(buffer, "zone%02hhX", zone); name = kstrdup(buffer, GFP_KERNEL); if (name == NULL) return 1; - sysfs_attr_init(&zone_dev_attrs[i].attr); - zone_dev_attrs[i].attr.name = name; - zone_dev_attrs[i].attr.mode = 0644; - zone_dev_attrs[i].show = zone_show; - zone_dev_attrs[i].store = zone_set; - zone_data[i].location = i; - zone_attrs[i] = &zone_dev_attrs[i].attr; - zone_data[i].attr = &zone_dev_attrs[i]; + sysfs_attr_init(&zone_dev_attrs[zone].attr); + zone_dev_attrs[zone].attr.name = name; + zone_dev_attrs[zone].attr.mode = 0644; + zone_dev_attrs[zone].show = zone_show; + zone_dev_attrs[zone].store = zone_set; + zone_data[zone].location = zone; + zone_attrs[zone] = &zone_dev_attrs[zone].attr; + zone_data[zone].attr = &zone_dev_attrs[zone]; } zone_attrs[quirks->num_zones] = &dev_attr_lighting_control_state.attr; zone_attribute_group.attrs = zone_attrs; @@ -481,12 +482,13 @@ static int alienware_zone_init(struct platform_device *dev) static void alienware_zone_exit(struct platform_device *dev) { + u8 zone; + sysfs_remove_group(&dev->dev.kobj, &zone_attribute_group); led_classdev_unregister(&global_led); if (zone_dev_attrs) { - int i; - for (i = 0; i < quirks->num_zones; i++) - kfree(zone_dev_attrs[i].attr.name); + for (zone = 0; zone < quirks->num_zones; zone++) + kfree(zone_dev_attrs[zone].attr.name); } kfree(zone_dev_attrs); kfree(zone_data); diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 709e3a67391a0b5e79dd5e55e57c4012823a0687..48e1541dc8d4efa3cf24e9c0df5861aeaa431798 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -299,7 +299,7 @@ static int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1, union acpi_object *obj; u32 tmp = 0; - status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1, method_id, + status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 0, method_id, &input, &output); if (ACPI_FAILURE(status)) @@ -1946,7 +1946,7 @@ static int show_call(struct seq_file *m, void *data) acpi_status status; status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, - 1, asus->debug.method_id, + 0, asus->debug.method_id, &input, &output); if (ACPI_FAILURE(status)) diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index dad8f4afa17cd4882a9f5e4f6e816f060e459588..28d9f8696081bcb063a09e9b1c481ede0259e049 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -48,7 +48,6 @@ MODULE_LICENSE("GPL"); #define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492" #define DELL_DESCRIPTOR_GUID "8D9DDCBC-A997-11DA-B012-B622A1EF5492" -static u32 dell_wmi_interface_version; static bool wmi_requires_smbios_request; MODULE_ALIAS("wmi:"DELL_EVENT_GUID); @@ -56,6 +55,7 @@ MODULE_ALIAS("wmi:"DELL_DESCRIPTOR_GUID); struct dell_wmi_priv { struct input_dev *input_dev; + u32 interface_version; }; static int __init dmi_matched(const struct dmi_system_id *dmi) @@ -348,6 +348,7 @@ static void dell_wmi_process_key(struct wmi_device *wdev, int type, int code) static void dell_wmi_notify(struct wmi_device *wdev, union acpi_object *obj) { + struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev); u16 *buffer_entry, *buffer_end; acpi_size buffer_size; int len, i; @@ -376,7 +377,7 @@ static void dell_wmi_notify(struct wmi_device *wdev, * So to prevent reading garbage from buffer we will process only first * one event on devices with WMI interface version 0. */ - if (dell_wmi_interface_version == 0 && buffer_entry < buffer_end) + if (priv->interface_version == 0 && buffer_entry < buffer_end) if (buffer_end > buffer_entry + buffer_entry[0] + 1) buffer_end = buffer_entry + buffer_entry[0] + 1; @@ -626,61 +627,67 @@ static void dell_wmi_input_destroy(struct wmi_device *wdev) * WMI Interface Version 8 4 * WMI buffer length 12 4 4096 */ -static int dell_wmi_check_descriptor_buffer(void) +static int dell_wmi_check_descriptor_buffer(struct wmi_device *wdev) { - struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - acpi_status status; + struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev); + union acpi_object *obj = NULL; + struct wmi_device *desc_dev; u32 *buffer; + int ret; - status = wmi_query_block(DELL_DESCRIPTOR_GUID, 0, &out); - if (ACPI_FAILURE(status)) { - pr_err("Cannot read Dell descriptor buffer - %d\n", status); - return status; + desc_dev = wmidev_get_other_guid(wdev, DELL_DESCRIPTOR_GUID); + if (!desc_dev) { + dev_err(&wdev->dev, "Dell WMI descriptor does not exist\n"); + return -ENODEV; } - obj = (union acpi_object *)out.pointer; + obj = wmidev_block_query(desc_dev, 0); if (!obj) { - pr_err("Dell descriptor buffer is empty\n"); - return -EINVAL; + dev_err(&wdev->dev, "failed to read Dell WMI descriptor\n"); + ret = -EIO; + goto out; } if (obj->type != ACPI_TYPE_BUFFER) { - pr_err("Cannot read Dell descriptor buffer\n"); - kfree(obj); - return -EINVAL; + dev_err(&wdev->dev, "Dell descriptor has wrong type\n"); + ret = -EINVAL; + goto out; } if (obj->buffer.length != 128) { - pr_err("Dell descriptor buffer has invalid length (%d)\n", + dev_err(&wdev->dev, + "Dell descriptor buffer has invalid length (%d)\n", obj->buffer.length); if (obj->buffer.length < 16) { - kfree(obj); - return -EINVAL; + ret = -EINVAL; + goto out; } } buffer = (u32 *)obj->buffer.pointer; if (buffer[0] != 0x4C4C4544 && buffer[1] != 0x494D5720) - pr_warn("Dell descriptor buffer has invalid signature (%*ph)\n", + dev_warn(&wdev->dev, "Dell descriptor buffer has invalid signature (%*ph)\n", 8, buffer); if (buffer[2] != 0 && buffer[2] != 1) - pr_warn("Dell descriptor buffer has unknown version (%d)\n", + dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%d)\n", buffer[2]); if (buffer[3] != 4096) - pr_warn("Dell descriptor buffer has invalid buffer length (%d)\n", + dev_warn(&wdev->dev, "Dell descriptor buffer has invalid buffer length (%d)\n", buffer[3]); - dell_wmi_interface_version = buffer[2]; + priv->interface_version = buffer[2]; + ret = 0; - pr_info("Detected Dell WMI interface version %u\n", - dell_wmi_interface_version); + dev_info(&wdev->dev, "Detected Dell WMI interface version %u\n", + priv->interface_version); +out: kfree(obj); - return 0; + put_device(&desc_dev->dev); + return ret; } /* @@ -717,17 +724,19 @@ static int dell_wmi_events_set_enabled(bool enable) static int dell_wmi_probe(struct wmi_device *wdev) { + struct dell_wmi_priv *priv; int err; - struct dell_wmi_priv *priv = devm_kzalloc( + priv = devm_kzalloc( &wdev->dev, sizeof(struct dell_wmi_priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + dev_set_drvdata(&wdev->dev, priv); - err = dell_wmi_check_descriptor_buffer(); + err = dell_wmi_check_descriptor_buffer(wdev); if (err) return err; - dev_set_drvdata(&wdev->dev, priv); - return dell_wmi_input_setup(wdev); } diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 0df4209648d1380a3e47af5e300913471b5f3f58..b4ed3dc983d5229c7e1726da58789a937a297d39 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -107,13 +107,6 @@ enum hp_wmi_hardware_mask { HPWMI_TABLET_MASK = 0x04, }; -#define BIOS_ARGS_INIT(write, ctype, size) \ - (struct bios_args) { .signature = 0x55434553, \ - .command = (write) ? 0x2 : 0x1, \ - .commandtype = (ctype), \ - .datasize = (size), \ - .data = 0 } - struct bios_return { u32 sigpass; u32 return_code; @@ -188,6 +181,22 @@ struct rfkill2_device { static int rfkill2_count; static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES]; +/* map output size to the corresponding WMI method id */ +static inline int encode_outsize_for_pvsz(int outsize) +{ + if (outsize > 4096) + return -EINVAL; + if (outsize > 1024) + return 5; + if (outsize > 128) + return 4; + if (outsize > 4) + return 3; + if (outsize > 0) + return 2; + return 1; +} + /* * hp_wmi_perform_query * @@ -211,6 +220,7 @@ static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES]; static int hp_wmi_perform_query(int query, enum hp_wmi_command command, void *buffer, int insize, int outsize) { + int mid; struct bios_return *bios_return; int actual_outsize; union acpi_object *obj; @@ -225,11 +235,15 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; int ret = 0; + mid = encode_outsize_for_pvsz(outsize); + if (WARN_ON(mid < 0)) + return mid; + if (WARN_ON(insize > sizeof(args.data))) return -EINVAL; memcpy(&args.data, buffer, insize); - wmi_evaluate_method(HPWMI_BIOS_GUID, 0, 0x3, &input, &output); + wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output); obj = output.pointer; diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c index c62e5e11ca4ba013244cf74d9d38b014fc8740ba..610ac8391caa3f14d0ad66583d965099c5ccf28c 100644 --- a/drivers/platform/x86/ibm_rtl.c +++ b/drivers/platform/x86/ibm_rtl.c @@ -103,7 +103,7 @@ static void rtl_port_unmap(void __iomem *addr) static int ibm_rtl_write(u8 value) { int ret = 0, count = 0; - static u32 cmd_port_val; + u32 cmd_port_val; RTL_DEBUG("%s(%d)\n", __func__, value); diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index 603fc60509713dc818b5612d7b8f6eb6238a53dd..fe98d4ac0df37040c3da8ad470bf7a33c5477fbe 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -42,6 +42,8 @@ #define IDEAPAD_RFKILL_DEV_NUM (3) +#define BM_CONSERVATION_BIT (5) + #define CFG_BT_BIT (16) #define CFG_3G_BIT (17) #define CFG_WIFI_BIT (18) @@ -54,6 +56,11 @@ static const char *const ideapad_wmi_fnesc_events[] = { }; #endif +enum { + BMCMD_CONSERVATION_ON = 3, + BMCMD_CONSERVATION_OFF = 5, +}; + enum { VPCCMD_R_VPC1 = 0x10, VPCCMD_R_BL_MAX, @@ -123,6 +130,23 @@ static int read_method_int(acpi_handle handle, const char *method, int *val) } } +static int method_gbmd(acpi_handle handle, unsigned long *ret) +{ + int result, val; + + result = read_method_int(handle, "GBMD", &val); + *ret = val; + return result; +} + +static int method_sbmc(acpi_handle handle, int cmd) +{ + acpi_status status; + + status = acpi_execute_simple_method(handle, "SBMC", cmd); + return ACPI_FAILURE(status) ? -1 : 0; +} + static int method_vpcr(acpi_handle handle, int cmd, int *ret) { acpi_status status; @@ -250,6 +274,13 @@ static int debugfs_status_show(struct seq_file *s, void *data) if (!read_ec_data(priv->adev->handle, VPCCMD_R_CAMERA, &value)) seq_printf(s, "Camera status:\t%s(%lu)\n", value ? "On" : "Off", value); + seq_puts(s, "=====================\n"); + + if (!method_gbmd(priv->adev->handle, &value)) { + seq_printf(s, "Conservation mode:\t%s(%lu)\n", + test_bit(BM_CONSERVATION_BIT, &value) ? "On" : "Off", + value); + } return 0; } @@ -456,10 +487,45 @@ static ssize_t __maybe_unused touchpad_store(struct device *dev, static DEVICE_ATTR_RO(touchpad); +static ssize_t conservation_mode_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct ideapad_private *priv = dev_get_drvdata(dev); + unsigned long result; + + if (method_gbmd(priv->adev->handle, &result)) + return sprintf(buf, "-1\n"); + return sprintf(buf, "%u\n", test_bit(BM_CONSERVATION_BIT, &result)); +} + +static ssize_t conservation_mode_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ideapad_private *priv = dev_get_drvdata(dev); + bool state; + int ret; + + ret = kstrtobool(buf, &state); + if (ret) + return ret; + + ret = method_sbmc(priv->adev->handle, state ? + BMCMD_CONSERVATION_ON : + BMCMD_CONSERVATION_OFF); + if (ret < 0) + return -EIO; + return count; +} + +static DEVICE_ATTR_RW(conservation_mode); + static struct attribute *ideapad_attributes[] = { &dev_attr_camera_power.attr, &dev_attr_fan_mode.attr, &dev_attr_touchpad.attr, + &dev_attr_conservation_mode.attr, NULL }; @@ -477,6 +543,9 @@ static umode_t ideapad_is_visible(struct kobject *kobj, unsigned long value; supported = !read_ec_data(priv->adev->handle, VPCCMD_R_FAN, &value); + } else if (attr == &dev_attr_conservation_mode.attr) { + supported = acpi_has_method(priv->adev->handle, "GBMD") && + acpi_has_method(priv->adev->handle, "SBMC"); } else supported = true; diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index a782c78e7c638fa9bf3fee2a9c0f2fe1368f69ff..e34fd70b67afe4d2573f8c4c39dcc4e1290ef97e 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -230,7 +230,7 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) if (event != 0xc0) { if (!priv->array || !sparse_keymap_report_event(priv->array, event, 1, true)) - dev_info(&device->dev, "unknown event 0x%x\n", event); + dev_dbg(&device->dev, "unknown event 0x%x\n", event); return; } @@ -241,7 +241,7 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) } if (!sparse_keymap_report_event(priv->input_dev, ev_index, 1, true)) - dev_info(&device->dev, "unknown event index 0x%llx\n", + dev_dbg(&device->dev, "unknown event index 0x%llx\n", ev_index); } diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c index 480926786cb8a39f62208cb55681e698822c1826..58c5ff36523ab9bc4d570ff781f91cd0d9a433ea 100644 --- a/drivers/platform/x86/intel-vbtn.c +++ b/drivers/platform/x86/intel-vbtn.c @@ -83,7 +83,7 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) } else if (sparse_keymap_report_event(priv->input_dev, event, 1, true)) { return; } - dev_info(&device->dev, "unknown event index 0x%x\n", event); + dev_dbg(&device->dev, "unknown event index 0x%x\n", event); } static int intel_vbtn_probe(struct platform_device *device) diff --git a/drivers/platform/x86/intel_mid_powerbtn.c b/drivers/platform/x86/intel_mid_powerbtn.c index 871cfa682519c2256126edae36dffefc9537ed8b..d79fbf924b136823987011664d385e1bdceb927d 100644 --- a/drivers/platform/x86/intel_mid_powerbtn.c +++ b/drivers/platform/x86/intel_mid_powerbtn.c @@ -108,13 +108,13 @@ static irqreturn_t mid_pb_isr(int irq, void *dev_id) return IRQ_HANDLED; } -static struct mid_pb_ddata mfld_ddata = { +static const struct mid_pb_ddata mfld_ddata = { .mirqlvl1_addr = INTEL_MSIC_IRQLVL1MSK, .pbstat_addr = INTEL_MSIC_PBSTATUS, .pbstat_mask = MSIC_PB_LEVEL, }; -static struct mid_pb_ddata mrfld_ddata = { +static const struct mid_pb_ddata mrfld_ddata = { .mirqlvl1_addr = BCOVE_IRQLVL1MSK, .pbstat_addr = BCOVE_PBSTATUS, .pbstat_mask = BCOVE_PB_LEVEL, @@ -142,8 +142,10 @@ static int mid_pb_probe(struct platform_device *pdev) if (!id) return -ENODEV; - if (irq < 0) - return -EINVAL; + if (irq < 0) { + dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq); + return irq; + } input = devm_input_allocate_device(&pdev->dev); if (!input) diff --git a/drivers/platform/x86/intel_pmc_core.c b/drivers/platform/x86/intel_pmc_core.c index 914bcd2edbde6b172ab47dfbec1ddbb2f93880e1..17e08b42b0a97f02c8120f83ed51b4e2cb18d676 100644 --- a/drivers/platform/x86/intel_pmc_core.c +++ b/drivers/platform/x86/intel_pmc_core.c @@ -110,6 +110,13 @@ static const struct pmc_reg_map spt_reg_map = { .pfear_sts = spt_pfear_map, .mphy_sts = spt_mphy_map, .pll_sts = spt_pll_map, + .slp_s0_offset = SPT_PMC_SLP_S0_RES_COUNTER_OFFSET, + .ltr_ignore_offset = SPT_PMC_LTR_IGNORE_OFFSET, + .regmap_length = SPT_PMC_MMIO_REG_LEN, + .ppfear0_offset = SPT_PMC_XRAM_PPFEAR0A, + .ppfear_buckets = SPT_PPFEAR_NUM_ENTRIES, + .pm_cfg_offset = SPT_PMC_PM_CFG_OFFSET, + .pm_read_disable_bit = SPT_PMC_READ_DISABLE_BIT, }; static const struct pci_device_id pmc_pci_ids[] = { @@ -157,12 +164,13 @@ static inline u32 pmc_core_adjust_slp_s0_step(u32 value) int intel_pmc_slp_s0_counter_read(u32 *data) { struct pmc_dev *pmcdev = &pmc; + const struct pmc_reg_map *map = pmcdev->map; u32 value; if (!pmcdev->has_slp_s0_res) return -EACCES; - value = pmc_core_reg_read(pmcdev, SPT_PMC_SLP_S0_RES_COUNTER_OFFSET); + value = pmc_core_reg_read(pmcdev, map->slp_s0_offset); *data = pmc_core_adjust_slp_s0_step(value); return 0; @@ -172,9 +180,10 @@ EXPORT_SYMBOL_GPL(intel_pmc_slp_s0_counter_read); static int pmc_core_dev_state_get(void *data, u64 *val) { struct pmc_dev *pmcdev = data; + const struct pmc_reg_map *map = pmcdev->map; u32 value; - value = pmc_core_reg_read(pmcdev, SPT_PMC_SLP_S0_RES_COUNTER_OFFSET); + value = pmc_core_reg_read(pmcdev, map->slp_s0_offset); *val = pmc_core_adjust_slp_s0_step(value); return 0; @@ -187,8 +196,8 @@ static int pmc_core_check_read_lock_bit(void) struct pmc_dev *pmcdev = &pmc; u32 value; - value = pmc_core_reg_read(pmcdev, SPT_PMC_PM_CFG_OFFSET); - return value & BIT(SPT_PMC_READ_DISABLE_BIT); + value = pmc_core_reg_read(pmcdev, pmcdev->map->pm_cfg_offset); + return value & BIT(pmcdev->map->pm_read_disable_bit); } #if IS_ENABLED(CONFIG_DEBUG_FS) @@ -204,12 +213,13 @@ static int pmc_core_ppfear_sts_show(struct seq_file *s, void *unused) { struct pmc_dev *pmcdev = s->private; const struct pmc_bit_map *map = pmcdev->map->pfear_sts; - u8 pf_regs[NUM_ENTRIES]; + u8 pf_regs[PPFEAR_MAX_NUM_ENTRIES]; int index, iter; - iter = SPT_PMC_XRAM_PPFEAR0A; + iter = pmcdev->map->ppfear0_offset; - for (index = 0; index < NUM_ENTRIES; index++, iter++) + for (index = 0; index < pmcdev->map->ppfear_buckets && + index < PPFEAR_MAX_NUM_ENTRIES; index++, iter++) pf_regs[index] = pmc_core_reg_read_byte(pmcdev, iter); for (index = 0; map[index].name; index++) @@ -376,6 +386,7 @@ static ssize_t pmc_core_ltr_ignore_write(struct file *file, const char __user *userbuf, size_t count, loff_t *ppos) { struct pmc_dev *pmcdev = &pmc; + const struct pmc_reg_map *map = pmcdev->map; u32 val, buf_size, fd; int err = 0; @@ -392,9 +403,9 @@ static ssize_t pmc_core_ltr_ignore_write(struct file *file, const char __user goto out_unlock; } - fd = pmc_core_reg_read(pmcdev, SPT_PMC_LTR_IGNORE_OFFSET); + fd = pmc_core_reg_read(pmcdev, map->ltr_ignore_offset); fd |= (1U << val); - pmc_core_reg_write(pmcdev, SPT_PMC_LTR_IGNORE_OFFSET, fd); + pmc_core_reg_write(pmcdev, map->ltr_ignore_offset, fd); out_unlock: mutex_unlock(&pmcdev->lock); @@ -530,8 +541,8 @@ static int pmc_core_probe(struct pci_dev *dev, const struct pci_device_id *id) } mutex_init(&pmcdev->lock); - pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(); pmcdev->map = map; + pmcdev->pmc_xram_read_bit = pmc_core_check_read_lock_bit(); err = pmc_core_dbgfs_register(pmcdev); if (err < 0) diff --git a/drivers/platform/x86/intel_pmc_core.h b/drivers/platform/x86/intel_pmc_core.h index 5a48e77284795d0b7864452a5c2e0d0b8a4206bd..3d225a9cc09f28dc69228188c54068fff12a8da9 100644 --- a/drivers/platform/x86/intel_pmc_core.h +++ b/drivers/platform/x86/intel_pmc_core.h @@ -38,7 +38,8 @@ #define SPT_PMC_SLP_S0_RES_COUNTER_STEP 0x64 #define PMC_BASE_ADDR_MASK ~(SPT_PMC_MMIO_REG_LEN - 1) #define MTPMC_MASK 0xffff0000 -#define NUM_ENTRIES 5 +#define PPFEAR_MAX_NUM_ENTRIES 5 +#define SPT_PPFEAR_NUM_ENTRIES 5 #define SPT_PMC_READ_DISABLE_BIT 0x16 #define SPT_PMC_MSG_FULL_STS_BIT 0x18 #define NUM_RETRIES 100 @@ -126,10 +127,37 @@ struct pmc_bit_map { u32 bit_mask; }; +/** + * struct pmc_reg_map - Structure used to define parameter unique to a + PCH family + * @pfear_sts: Maps name of IP block to PPFEAR* bit + * @mphy_sts: Maps name of MPHY lane to MPHY status lane status bit + * @pll_sts: Maps name of PLL to corresponding bit status + * @slp_s0_offset: PWRMBASE offset to read SLP_S0 residency + * @ltr_ignore_offset: PWRMBASE offset to read/write LTR ignore bit + * @base_address: Base address of PWRMBASE defined in BIOS writer guide + * @regmap_length: Length of memory to map from PWRMBASE address to access + * @ppfear0_offset: PWRMBASE offset to to read PPFEAR* + * @ppfear_buckets: Number of 8 bits blocks to read all IP blocks from + * PPFEAR + * @pm_cfg_offset: PWRMBASE offset to PM_CFG register + * @pm_read_disable_bit: Bit index to read PMC_READ_DISABLE + * + * Each PCH has unique set of register offsets and bit indexes. This structure + * captures them to have a common implementation. + */ struct pmc_reg_map { const struct pmc_bit_map *pfear_sts; const struct pmc_bit_map *mphy_sts; const struct pmc_bit_map *pll_sts; + const u32 slp_s0_offset; + const u32 ltr_ignore_offset; + const u32 base_address; + const int regmap_length; + const u32 ppfear0_offset; + const int ppfear_buckets; + const u32 pm_cfg_offset; + const int pm_read_disable_bit; }; /** diff --git a/drivers/platform/x86/intel_scu_ipc.c b/drivers/platform/x86/intel_scu_ipc.c index f7cf981502cdcafee779426547547b79aa565039..2c85f75e32b08b27af3c96fa413fc9ebbccc252c 100644 --- a/drivers/platform/x86/intel_scu_ipc.c +++ b/drivers/platform/x86/intel_scu_ipc.c @@ -72,20 +72,20 @@ struct intel_scu_ipc_pdata_t { u8 irq_mode; }; -static struct intel_scu_ipc_pdata_t intel_scu_ipc_lincroft_pdata = { +static const struct intel_scu_ipc_pdata_t intel_scu_ipc_lincroft_pdata = { .i2c_base = 0xff12b000, .i2c_len = 0x10, .irq_mode = 0, }; /* Penwell and Cloverview */ -static struct intel_scu_ipc_pdata_t intel_scu_ipc_penwell_pdata = { +static const struct intel_scu_ipc_pdata_t intel_scu_ipc_penwell_pdata = { .i2c_base = 0xff12b000, .i2c_len = 0x10, .irq_mode = 1, }; -static struct intel_scu_ipc_pdata_t intel_scu_ipc_tangier_pdata = { +static const struct intel_scu_ipc_pdata_t intel_scu_ipc_tangier_pdata = { .i2c_base = 0xff00d000, .i2c_len = 0x10, .irq_mode = 0, diff --git a/drivers/platform/x86/intel_telemetry_debugfs.c b/drivers/platform/x86/intel_telemetry_debugfs.c index cd21df982abd63bbc85bdc39cc309512fcc6ec9f..d4fc42b4cbebfedeeaf39e8c65e28b2d0a8b6c0a 100644 --- a/drivers/platform/x86/intel_telemetry_debugfs.c +++ b/drivers/platform/x86/intel_telemetry_debugfs.c @@ -331,6 +331,7 @@ static struct telemetry_debugfs_conf telem_apl_debugfs_conf = { static const struct x86_cpu_id telemetry_debugfs_cpu_ids[] = { TELEM_DEBUGFS_CPU(INTEL_FAM6_ATOM_GOLDMONT, telem_apl_debugfs_conf), + TELEM_DEBUGFS_CPU(INTEL_FAM6_ATOM_GEMINI_LAKE, telem_apl_debugfs_conf), {} }; diff --git a/drivers/platform/x86/intel_telemetry_pltdrv.c b/drivers/platform/x86/intel_telemetry_pltdrv.c index 6ebdbd2b04fc994e06c683ddd71a3e071cb8a8e4..e0424d5a795a5e0a5baa969546df60252c9a230e 100644 --- a/drivers/platform/x86/intel_telemetry_pltdrv.c +++ b/drivers/platform/x86/intel_telemetry_pltdrv.c @@ -46,7 +46,6 @@ #define TELEM_SAMPLING_DEFAULT_PERIOD 0xD #define TELEM_MAX_EVENTS_SRAM 28 -#define TELEM_MAX_OS_ALLOCATED_EVENTS 20 #define TELEM_SSRAM_STARTTIME_OFFSET 8 #define TELEM_SSRAM_EVTLOG_OFFSET 16 @@ -153,6 +152,30 @@ static struct telemetry_evtmap {"PC2_AND_MEM_SHALLOW_IDLE_RES", 0x1D40}, }; +static struct telemetry_evtmap + telemetry_glk_pss_default_events[TELEM_MAX_OS_ALLOCATED_EVENTS] = { + {"IA_CORE0_C6_RES", 0x0400}, + {"IA_CORE0_C6_CTR", 0x0000}, + {"IA_MODULE0_C7_RES", 0x0410}, + {"IA_MODULE0_C7_CTR", 0x000C}, + {"IA_C0_RES", 0x0805}, + {"PCS_LTR", 0x2801}, + {"PSTATES", 0x2802}, + {"SOC_S0I3_RES", 0x0407}, + {"SOC_S0I3_CTR", 0x0008}, + {"PCS_S0I3_CTR", 0x0007}, + {"PCS_C1E_RES", 0x0414}, + {"PCS_IDLE_STATUS", 0x2806}, + {"IA_PERF_LIMITS", 0x280B}, + {"GT_PERF_LIMITS", 0x280C}, + {"PCS_WAKEUP_S0IX_CTR", 0x0025}, + {"PCS_IDLE_BLOCKED", 0x2C00}, + {"PCS_S0IX_BLOCKED", 0x2C01}, + {"PCS_S0IX_WAKE_REASONS", 0x2C02}, + {"PCS_LTR_BLOCKING", 0x2C03}, + {"PC2_AND_MEM_SHALLOW_IDLE_RES", 0x1D40}, +}; + /* APL specific Data */ static struct telemetry_plt_config telem_apl_config = { .pss_config = { @@ -163,8 +186,19 @@ static struct telemetry_plt_config telem_apl_config = { }, }; +/* GLK specific Data */ +static struct telemetry_plt_config telem_glk_config = { + .pss_config = { + .telem_evts = telemetry_glk_pss_default_events, + }, + .ioss_config = { + .telem_evts = telemetry_apl_ioss_default_events, + }, +}; + static const struct x86_cpu_id telemetry_cpu_ids[] = { TELEM_CPU(INTEL_FAM6_ATOM_GOLDMONT, telem_apl_config), + TELEM_CPU(INTEL_FAM6_ATOM_GEMINI_LAKE, telem_glk_config), {} }; diff --git a/drivers/platform/x86/msi-wmi.c b/drivers/platform/x86/msi-wmi.c index f6209b739ec0fecd007bd5ff78f4780b442676ca..620138236c8943013540aca1b1e5522aeb1102ae 100644 --- a/drivers/platform/x86/msi-wmi.c +++ b/drivers/platform/x86/msi-wmi.c @@ -184,7 +184,7 @@ static const struct backlight_ops msi_backlight_ops = { static void msi_wmi_notify(u32 value, void *context) { struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL }; - static struct key_entry *key; + struct key_entry *key; union acpi_object *obj; acpi_status status; diff --git a/drivers/platform/x86/mxm-wmi.c b/drivers/platform/x86/mxm-wmi.c index f4bad83053a9d5972e504a1cc4c0f80c8f6ba96b..35d8b9a939f9f67a2b4c56a3126061fff4513aff 100644 --- a/drivers/platform/x86/mxm-wmi.c +++ b/drivers/platform/x86/mxm-wmi.c @@ -53,7 +53,7 @@ int mxm_wmi_call_mxds(int adapter) printk("calling mux switch %d\n", adapter); - status = wmi_evaluate_method(MXM_WMMX_GUID, 0x1, adapter, &input, + status = wmi_evaluate_method(MXM_WMMX_GUID, 0x0, adapter, &input, &output); if (ACPI_FAILURE(status)) @@ -78,7 +78,7 @@ int mxm_wmi_call_mxmx(int adapter) printk("calling mux switch %d\n", adapter); - status = wmi_evaluate_method(MXM_WMMX_GUID, 0x1, adapter, &input, + status = wmi_evaluate_method(MXM_WMMX_GUID, 0x0, adapter, &input, &output); if (ACPI_FAILURE(status)) diff --git a/drivers/platform/x86/peaq-wmi.c b/drivers/platform/x86/peaq-wmi.c index 77d1f90b079426dfc4f7cb708c19e09b103fed25..bc98ef95514a1770c285ed54b4913d7c41ff5ad6 100644 --- a/drivers/platform/x86/peaq-wmi.c +++ b/drivers/platform/x86/peaq-wmi.c @@ -39,7 +39,7 @@ static void peaq_wmi_poll(struct input_polled_dev *dev) struct acpi_buffer input = { sizeof(dummy), &dummy }; struct acpi_buffer output = { sizeof(obj), &obj }; - status = wmi_evaluate_method(PEAQ_DOLBY_BUTTON_GUID, 1, + status = wmi_evaluate_method(PEAQ_DOLBY_BUTTON_GUID, 0, PEAQ_DOLBY_BUTTON_METHOD_ID, &input, &output); if (ACPI_FAILURE(status)) @@ -51,7 +51,7 @@ static void peaq_wmi_poll(struct input_polled_dev *dev) return; } - if (peaq_ignore_events_counter && --peaq_ignore_events_counter >= 0) + if (peaq_ignore_events_counter && peaq_ignore_events_counter--) return; if (obj.integer.value) { diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index b22573131e53806c9e6064c7233d193f586e3ed4..2242d6035d9e7e1f8d042855973a2349c6d7eb9f 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -24,7 +24,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define TPACPI_VERSION "0.25" -#define TPACPI_SYSFS_VERSION 0x020700 +#define TPACPI_SYSFS_VERSION 0x030000 /* * Changelog: @@ -6342,7 +6342,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm) switch (thermal_read_mode) { case TPACPI_THERMAL_TPEC_16: - res = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, + res = sysfs_create_group(&tpacpi_hwmon->kobj, &thermal_temp_input16_group); if (res) return res; @@ -6350,7 +6350,7 @@ static int __init thermal_init(struct ibm_init_struct *iibm) case TPACPI_THERMAL_TPEC_8: case TPACPI_THERMAL_ACPI_TMP07: case TPACPI_THERMAL_ACPI_UPDT: - res = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, + res = sysfs_create_group(&tpacpi_hwmon->kobj, &thermal_temp_input8_group); if (res) return res; @@ -6367,13 +6367,13 @@ static void thermal_exit(void) { switch (thermal_read_mode) { case TPACPI_THERMAL_TPEC_16: - sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, + sysfs_remove_group(&tpacpi_hwmon->kobj, &thermal_temp_input16_group); break; case TPACPI_THERMAL_TPEC_8: case TPACPI_THERMAL_ACPI_TMP07: case TPACPI_THERMAL_ACPI_UPDT: - sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, + sysfs_remove_group(&tpacpi_hwmon->kobj, &thermal_temp_input8_group); break; case TPACPI_THERMAL_NONE: @@ -8696,7 +8696,7 @@ static int __init fan_init(struct ibm_init_struct *iibm) fan_attributes[ARRAY_SIZE(fan_attributes)-2] = &dev_attr_fan2_input.attr; } - rc = sysfs_create_group(&tpacpi_sensors_pdev->dev.kobj, + rc = sysfs_create_group(&tpacpi_hwmon->kobj, &fan_attr_group); if (rc < 0) return rc; @@ -8704,7 +8704,7 @@ static int __init fan_init(struct ibm_init_struct *iibm) rc = driver_create_file(&tpacpi_hwmon_pdriver.driver, &driver_attr_fan_watchdog); if (rc < 0) { - sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, + sysfs_remove_group(&tpacpi_hwmon->kobj, &fan_attr_group); return rc; } @@ -8719,7 +8719,7 @@ static void fan_exit(void) "cancelling any pending fan watchdog tasks\n"); /* FIXME: can we really do this unconditionally? */ - sysfs_remove_group(&tpacpi_sensors_pdev->dev.kobj, &fan_attr_group); + sysfs_remove_group(&tpacpi_hwmon->kobj, &fan_attr_group); driver_remove_file(&tpacpi_hwmon_pdriver.driver, &driver_attr_fan_watchdog); @@ -9149,16 +9149,6 @@ static void hotkey_driver_event(const unsigned int scancode) tpacpi_driver_event(TP_HKEY_EV_HOTKEY_BASE + scancode); } -/* sysfs name ---------------------------------------------------------- */ -static ssize_t thinkpad_acpi_pdev_name_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%s\n", TPACPI_NAME); -} - -static DEVICE_ATTR(name, S_IRUGO, thinkpad_acpi_pdev_name_show, NULL); - /* --------------------------------------------------------------------- */ /* /proc support */ @@ -9696,8 +9686,6 @@ static void thinkpad_acpi_module_exit(void) if (tpacpi_hwmon) hwmon_device_unregister(tpacpi_hwmon); - if (tp_features.sensors_pdev_attrs_registered) - device_remove_file(&tpacpi_sensors_pdev->dev, &dev_attr_name); if (tpacpi_sensors_pdev) platform_device_unregister(tpacpi_sensors_pdev); if (tpacpi_pdev) @@ -9818,14 +9806,10 @@ static int __init thinkpad_acpi_module_init(void) thinkpad_acpi_module_exit(); return ret; } - ret = device_create_file(&tpacpi_sensors_pdev->dev, &dev_attr_name); - if (ret) { - pr_err("unable to create sysfs hwmon device attributes\n"); - thinkpad_acpi_module_exit(); - return ret; - } tp_features.sensors_pdev_attrs_registered = 1; - tpacpi_hwmon = hwmon_device_register(&tpacpi_sensors_pdev->dev); + tpacpi_hwmon = hwmon_device_register_with_groups( + &tpacpi_sensors_pdev->dev, TPACPI_NAME, NULL, NULL); + if (IS_ERR(tpacpi_hwmon)) { ret = PTR_ERR(tpacpi_hwmon); tpacpi_hwmon = NULL; diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index e32ba575e8d9e2bfe3f1ff398c90ddbfe87196bf..0765b1797d4c0d35cd58f588d8c4717bf6b1179d 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -218,7 +218,7 @@ u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out) if (!(block->flags & ACPI_WMI_METHOD)) return AE_BAD_DATA; - if (block->instance_count < instance) + if (block->instance_count <= instance) return AE_BAD_PARAMETER; input.count = 2; @@ -265,7 +265,7 @@ static acpi_status __query_block(struct wmi_block *wblock, u8 instance, block = &wblock->gblock; handle = wblock->acpi_device->handle; - if (block->instance_count < instance) + if (block->instance_count <= instance) return AE_BAD_PARAMETER; /* Check GUID is a data block */ @@ -392,7 +392,7 @@ acpi_status wmi_set_block(const char *guid_string, u8 instance, block = &wblock->gblock; handle = wblock->acpi_device->handle; - if (block->instance_count < instance) + if (block->instance_count <= instance) return AE_BAD_PARAMETER; /* Check GUID is a data block */