diff options
| -rw-r--r-- | drivers/acpi/ec.c | 31 | ||||
| -rw-r--r-- | drivers/acpi/scan.c | 70 | ||||
| -rw-r--r-- | drivers/base/power/main.c | 2 | ||||
| -rw-r--r-- | drivers/cpufreq/cpufreq-dt.c | 68 | ||||
| -rw-r--r-- | kernel/power/hibernate.c | 8 |
5 files changed, 126 insertions, 53 deletions
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 3d304ff7f095..5f9b74b9b71f 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c | |||
| @@ -126,6 +126,7 @@ static int EC_FLAGS_MSI; /* Out-of-spec MSI controller */ | |||
| 126 | static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */ | 126 | static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */ |
| 127 | static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */ | 127 | static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */ |
| 128 | static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ | 128 | static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ |
| 129 | static int EC_FLAGS_QUERY_HANDSHAKE; /* Needs QR_EC issued when SCI_EVT set */ | ||
| 129 | 130 | ||
| 130 | /* -------------------------------------------------------------------------- | 131 | /* -------------------------------------------------------------------------- |
| 131 | * Transaction Management | 132 | * Transaction Management |
| @@ -236,13 +237,8 @@ static bool advance_transaction(struct acpi_ec *ec) | |||
| 236 | } | 237 | } |
| 237 | return wakeup; | 238 | return wakeup; |
| 238 | } else { | 239 | } else { |
| 239 | /* | 240 | if (EC_FLAGS_QUERY_HANDSHAKE && |
| 240 | * There is firmware refusing to respond QR_EC when SCI_EVT | 241 | !(status & ACPI_EC_FLAG_SCI) && |
| 241 | * is not set, for which case, we complete the QR_EC | ||
| 242 | * without issuing it to the firmware. | ||
| 243 | * https://bugzilla.kernel.org/show_bug.cgi?id=86211 | ||
| 244 | */ | ||
| 245 | if (!(status & ACPI_EC_FLAG_SCI) && | ||
| 246 | (t->command == ACPI_EC_COMMAND_QUERY)) { | 242 | (t->command == ACPI_EC_COMMAND_QUERY)) { |
| 247 | t->flags |= ACPI_EC_COMMAND_POLL; | 243 | t->flags |= ACPI_EC_COMMAND_POLL; |
| 248 | t->rdata[t->ri++] = 0x00; | 244 | t->rdata[t->ri++] = 0x00; |
| @@ -334,13 +330,13 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, | |||
| 334 | pr_debug("***** Command(%s) started *****\n", | 330 | pr_debug("***** Command(%s) started *****\n", |
| 335 | acpi_ec_cmd_string(t->command)); | 331 | acpi_ec_cmd_string(t->command)); |
| 336 | start_transaction(ec); | 332 | start_transaction(ec); |
| 337 | spin_unlock_irqrestore(&ec->lock, tmp); | ||
| 338 | ret = ec_poll(ec); | ||
| 339 | spin_lock_irqsave(&ec->lock, tmp); | ||
| 340 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) { | 333 | if (ec->curr->command == ACPI_EC_COMMAND_QUERY) { |
| 341 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); | 334 | clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); |
| 342 | pr_debug("***** Event stopped *****\n"); | 335 | pr_debug("***** Event stopped *****\n"); |
| 343 | } | 336 | } |
| 337 | spin_unlock_irqrestore(&ec->lock, tmp); | ||
| 338 | ret = ec_poll(ec); | ||
| 339 | spin_lock_irqsave(&ec->lock, tmp); | ||
| 344 | pr_debug("***** Command(%s) stopped *****\n", | 340 | pr_debug("***** Command(%s) stopped *****\n", |
| 345 | acpi_ec_cmd_string(t->command)); | 341 | acpi_ec_cmd_string(t->command)); |
| 346 | ec->curr = NULL; | 342 | ec->curr = NULL; |
| @@ -1012,6 +1008,18 @@ static int ec_enlarge_storm_threshold(const struct dmi_system_id *id) | |||
| 1012 | } | 1008 | } |
| 1013 | 1009 | ||
| 1014 | /* | 1010 | /* |
| 1011 | * Acer EC firmware refuses to respond QR_EC when SCI_EVT is not set, for | ||
| 1012 | * which case, we complete the QR_EC without issuing it to the firmware. | ||
| 1013 | * https://bugzilla.kernel.org/show_bug.cgi?id=86211 | ||
| 1014 | */ | ||
| 1015 | static int ec_flag_query_handshake(const struct dmi_system_id *id) | ||
| 1016 | { | ||
| 1017 | pr_debug("Detected the EC firmware requiring QR_EC issued when SCI_EVT set\n"); | ||
| 1018 | EC_FLAGS_QUERY_HANDSHAKE = 1; | ||
| 1019 | return 0; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | /* | ||
| 1015 | * On some hardware it is necessary to clear events accumulated by the EC during | 1023 | * On some hardware it is necessary to clear events accumulated by the EC during |
| 1016 | * sleep. These ECs stop reporting GPEs until they are manually polled, if too | 1024 | * sleep. These ECs stop reporting GPEs until they are manually polled, if too |
| 1017 | * many events are accumulated. (e.g. Samsung Series 5/9 notebooks) | 1025 | * many events are accumulated. (e.g. Samsung Series 5/9 notebooks) |
| @@ -1085,6 +1093,9 @@ static struct dmi_system_id ec_dmi_table[] __initdata = { | |||
| 1085 | { | 1093 | { |
| 1086 | ec_clear_on_resume, "Samsung hardware", { | 1094 | ec_clear_on_resume, "Samsung hardware", { |
| 1087 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL}, | 1095 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL}, |
| 1096 | { | ||
| 1097 | ec_flag_query_handshake, "Acer hardware", { | ||
| 1098 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), }, NULL}, | ||
| 1088 | {}, | 1099 | {}, |
| 1089 | }; | 1100 | }; |
| 1090 | 1101 | ||
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index d670158a26c5..0476e90b2091 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
| @@ -142,6 +142,53 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | /* | 144 | /* |
| 145 | * acpi_companion_match() - Can we match via ACPI companion device | ||
| 146 | * @dev: Device in question | ||
| 147 | * | ||
| 148 | * Check if the given device has an ACPI companion and if that companion has | ||
| 149 | * a valid list of PNP IDs, and if the device is the first (primary) physical | ||
| 150 | * device associated with it. | ||
| 151 | * | ||
| 152 | * If multiple physical devices are attached to a single ACPI companion, we need | ||
| 153 | * to be careful. The usage scenario for this kind of relationship is that all | ||
| 154 | * of the physical devices in question use resources provided by the ACPI | ||
| 155 | * companion. A typical case is an MFD device where all the sub-devices share | ||
| 156 | * the parent's ACPI companion. In such cases we can only allow the primary | ||
| 157 | * (first) physical device to be matched with the help of the companion's PNP | ||
| 158 | * IDs. | ||
| 159 | * | ||
| 160 | * Additional physical devices sharing the ACPI companion can still use | ||
| 161 | * resources available from it but they will be matched normally using functions | ||
| 162 | * provided by their bus types (and analogously for their modalias). | ||
| 163 | */ | ||
| 164 | static bool acpi_companion_match(const struct device *dev) | ||
| 165 | { | ||
| 166 | struct acpi_device *adev; | ||
| 167 | bool ret; | ||
| 168 | |||
| 169 | adev = ACPI_COMPANION(dev); | ||
| 170 | if (!adev) | ||
| 171 | return false; | ||
| 172 | |||
| 173 | if (list_empty(&adev->pnp.ids)) | ||
| 174 | return false; | ||
| 175 | |||
| 176 | mutex_lock(&adev->physical_node_lock); | ||
| 177 | if (list_empty(&adev->physical_node_list)) { | ||
| 178 | ret = false; | ||
| 179 | } else { | ||
| 180 | const struct acpi_device_physical_node *node; | ||
| 181 | |||
| 182 | node = list_first_entry(&adev->physical_node_list, | ||
| 183 | struct acpi_device_physical_node, node); | ||
| 184 | ret = node->dev == dev; | ||
| 185 | } | ||
| 186 | mutex_unlock(&adev->physical_node_lock); | ||
| 187 | |||
| 188 | return ret; | ||
| 189 | } | ||
| 190 | |||
| 191 | /* | ||
| 145 | * Creates uevent modalias field for ACPI enumerated devices. | 192 | * Creates uevent modalias field for ACPI enumerated devices. |
| 146 | * Because the other buses does not support ACPI HIDs & CIDs. | 193 | * Because the other buses does not support ACPI HIDs & CIDs. |
| 147 | * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: | 194 | * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: |
| @@ -149,20 +196,14 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, | |||
| 149 | */ | 196 | */ |
| 150 | int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) | 197 | int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) |
| 151 | { | 198 | { |
| 152 | struct acpi_device *acpi_dev; | ||
| 153 | int len; | 199 | int len; |
| 154 | 200 | ||
| 155 | acpi_dev = ACPI_COMPANION(dev); | 201 | if (!acpi_companion_match(dev)) |
| 156 | if (!acpi_dev) | ||
| 157 | return -ENODEV; | ||
| 158 | |||
| 159 | /* Fall back to bus specific way of modalias exporting */ | ||
| 160 | if (list_empty(&acpi_dev->pnp.ids)) | ||
| 161 | return -ENODEV; | 202 | return -ENODEV; |
| 162 | 203 | ||
| 163 | if (add_uevent_var(env, "MODALIAS=")) | 204 | if (add_uevent_var(env, "MODALIAS=")) |
| 164 | return -ENOMEM; | 205 | return -ENOMEM; |
| 165 | len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], | 206 | len = create_modalias(ACPI_COMPANION(dev), &env->buf[env->buflen - 1], |
| 166 | sizeof(env->buf) - env->buflen); | 207 | sizeof(env->buf) - env->buflen); |
| 167 | if (len <= 0) | 208 | if (len <= 0) |
| 168 | return len; | 209 | return len; |
| @@ -179,18 +220,12 @@ EXPORT_SYMBOL_GPL(acpi_device_uevent_modalias); | |||
| 179 | */ | 220 | */ |
| 180 | int acpi_device_modalias(struct device *dev, char *buf, int size) | 221 | int acpi_device_modalias(struct device *dev, char *buf, int size) |
| 181 | { | 222 | { |
| 182 | struct acpi_device *acpi_dev; | ||
| 183 | int len; | 223 | int len; |
| 184 | 224 | ||
| 185 | acpi_dev = ACPI_COMPANION(dev); | 225 | if (!acpi_companion_match(dev)) |
| 186 | if (!acpi_dev) | ||
| 187 | return -ENODEV; | 226 | return -ENODEV; |
| 188 | 227 | ||
| 189 | /* Fall back to bus specific way of modalias exporting */ | 228 | len = create_modalias(ACPI_COMPANION(dev), buf, size -1); |
| 190 | if (list_empty(&acpi_dev->pnp.ids)) | ||
| 191 | return -ENODEV; | ||
| 192 | |||
| 193 | len = create_modalias(acpi_dev, buf, size -1); | ||
| 194 | if (len <= 0) | 229 | if (len <= 0) |
| 195 | return len; | 230 | return len; |
| 196 | buf[len++] = '\n'; | 231 | buf[len++] = '\n'; |
| @@ -853,6 +888,9 @@ const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids, | |||
| 853 | if (!ids || !handle || acpi_bus_get_device(handle, &adev)) | 888 | if (!ids || !handle || acpi_bus_get_device(handle, &adev)) |
| 854 | return NULL; | 889 | return NULL; |
| 855 | 890 | ||
| 891 | if (!acpi_companion_match(dev)) | ||
| 892 | return NULL; | ||
| 893 | |||
| 856 | return __acpi_match_device(adev, ids); | 894 | return __acpi_match_device(adev, ids); |
| 857 | } | 895 | } |
| 858 | EXPORT_SYMBOL_GPL(acpi_match_device); | 896 | EXPORT_SYMBOL_GPL(acpi_match_device); |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 44973196d3fd..9717d5f20139 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
| @@ -1266,6 +1266,8 @@ int dpm_suspend_late(pm_message_t state) | |||
| 1266 | } | 1266 | } |
| 1267 | mutex_unlock(&dpm_list_mtx); | 1267 | mutex_unlock(&dpm_list_mtx); |
| 1268 | async_synchronize_full(); | 1268 | async_synchronize_full(); |
| 1269 | if (!error) | ||
| 1270 | error = async_error; | ||
| 1269 | if (error) { | 1271 | if (error) { |
| 1270 | suspend_stats.failed_suspend_late++; | 1272 | suspend_stats.failed_suspend_late++; |
| 1271 | dpm_save_failed_step(SUSPEND_SUSPEND_LATE); | 1273 | dpm_save_failed_step(SUSPEND_SUSPEND_LATE); |
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 92c162af5045..23aaf40cf37f 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c | |||
| @@ -187,6 +187,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) | |||
| 187 | struct device *cpu_dev; | 187 | struct device *cpu_dev; |
| 188 | struct regulator *cpu_reg; | 188 | struct regulator *cpu_reg; |
| 189 | struct clk *cpu_clk; | 189 | struct clk *cpu_clk; |
| 190 | unsigned long min_uV = ~0, max_uV = 0; | ||
| 190 | unsigned int transition_latency; | 191 | unsigned int transition_latency; |
| 191 | int ret; | 192 | int ret; |
| 192 | 193 | ||
| @@ -206,16 +207,10 @@ static int cpufreq_init(struct cpufreq_policy *policy) | |||
| 206 | /* OPPs might be populated at runtime, don't check for error here */ | 207 | /* OPPs might be populated at runtime, don't check for error here */ |
| 207 | of_init_opp_table(cpu_dev); | 208 | of_init_opp_table(cpu_dev); |
| 208 | 209 | ||
| 209 | ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); | ||
| 210 | if (ret) { | ||
| 211 | dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); | ||
| 212 | goto out_put_node; | ||
| 213 | } | ||
| 214 | |||
| 215 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 210 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
| 216 | if (!priv) { | 211 | if (!priv) { |
| 217 | ret = -ENOMEM; | 212 | ret = -ENOMEM; |
| 218 | goto out_free_table; | 213 | goto out_put_node; |
| 219 | } | 214 | } |
| 220 | 215 | ||
| 221 | of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance); | 216 | of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance); |
| @@ -224,30 +219,51 @@ static int cpufreq_init(struct cpufreq_policy *policy) | |||
| 224 | transition_latency = CPUFREQ_ETERNAL; | 219 | transition_latency = CPUFREQ_ETERNAL; |
| 225 | 220 | ||
| 226 | if (!IS_ERR(cpu_reg)) { | 221 | if (!IS_ERR(cpu_reg)) { |
| 227 | struct dev_pm_opp *opp; | 222 | unsigned long opp_freq = 0; |
| 228 | unsigned long min_uV, max_uV; | ||
| 229 | int i; | ||
| 230 | 223 | ||
| 231 | /* | 224 | /* |
| 232 | * OPP is maintained in order of increasing frequency, and | 225 | * Disable any OPPs where the connected regulator isn't able to |
| 233 | * freq_table initialised from OPP is therefore sorted in the | 226 | * provide the specified voltage and record minimum and maximum |
| 234 | * same order. | 227 | * voltage levels. |
| 235 | */ | 228 | */ |
| 236 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) | 229 | while (1) { |
| 237 | ; | 230 | struct dev_pm_opp *opp; |
| 238 | rcu_read_lock(); | 231 | unsigned long opp_uV, tol_uV; |
| 239 | opp = dev_pm_opp_find_freq_exact(cpu_dev, | 232 | |
| 240 | freq_table[0].frequency * 1000, true); | 233 | rcu_read_lock(); |
| 241 | min_uV = dev_pm_opp_get_voltage(opp); | 234 | opp = dev_pm_opp_find_freq_ceil(cpu_dev, &opp_freq); |
| 242 | opp = dev_pm_opp_find_freq_exact(cpu_dev, | 235 | if (IS_ERR(opp)) { |
| 243 | freq_table[i-1].frequency * 1000, true); | 236 | rcu_read_unlock(); |
| 244 | max_uV = dev_pm_opp_get_voltage(opp); | 237 | break; |
| 245 | rcu_read_unlock(); | 238 | } |
| 239 | opp_uV = dev_pm_opp_get_voltage(opp); | ||
| 240 | rcu_read_unlock(); | ||
| 241 | |||
| 242 | tol_uV = opp_uV * priv->voltage_tolerance / 100; | ||
| 243 | if (regulator_is_supported_voltage(cpu_reg, opp_uV, | ||
| 244 | opp_uV + tol_uV)) { | ||
| 245 | if (opp_uV < min_uV) | ||
| 246 | min_uV = opp_uV; | ||
| 247 | if (opp_uV > max_uV) | ||
| 248 | max_uV = opp_uV; | ||
| 249 | } else { | ||
| 250 | dev_pm_opp_disable(cpu_dev, opp_freq); | ||
| 251 | } | ||
| 252 | |||
| 253 | opp_freq++; | ||
| 254 | } | ||
| 255 | |||
| 246 | ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV); | 256 | ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV); |
| 247 | if (ret > 0) | 257 | if (ret > 0) |
| 248 | transition_latency += ret * 1000; | 258 | transition_latency += ret * 1000; |
| 249 | } | 259 | } |
| 250 | 260 | ||
| 261 | ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); | ||
| 262 | if (ret) { | ||
| 263 | pr_err("failed to init cpufreq table: %d\n", ret); | ||
| 264 | goto out_free_priv; | ||
| 265 | } | ||
| 266 | |||
| 251 | /* | 267 | /* |
| 252 | * For now, just loading the cooling device; | 268 | * For now, just loading the cooling device; |
| 253 | * thermal DT code takes care of matching them. | 269 | * thermal DT code takes care of matching them. |
| @@ -277,7 +293,7 @@ static int cpufreq_init(struct cpufreq_policy *policy) | |||
| 277 | policy->cpuinfo.transition_latency = transition_latency; | 293 | policy->cpuinfo.transition_latency = transition_latency; |
| 278 | 294 | ||
| 279 | pd = cpufreq_get_driver_data(); | 295 | pd = cpufreq_get_driver_data(); |
| 280 | if (pd && !pd->independent_clocks) | 296 | if (!pd || !pd->independent_clocks) |
| 281 | cpumask_setall(policy->cpus); | 297 | cpumask_setall(policy->cpus); |
| 282 | 298 | ||
| 283 | of_node_put(np); | 299 | of_node_put(np); |
| @@ -286,9 +302,9 @@ static int cpufreq_init(struct cpufreq_policy *policy) | |||
| 286 | 302 | ||
| 287 | out_cooling_unregister: | 303 | out_cooling_unregister: |
| 288 | cpufreq_cooling_unregister(priv->cdev); | 304 | cpufreq_cooling_unregister(priv->cdev); |
| 289 | kfree(priv); | ||
| 290 | out_free_table: | ||
| 291 | dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); | 305 | dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); |
| 306 | out_free_priv: | ||
| 307 | kfree(priv); | ||
| 292 | out_put_node: | 308 | out_put_node: |
| 293 | of_node_put(np); | 309 | of_node_put(np); |
| 294 | out_put_reg_clk: | 310 | out_put_reg_clk: |
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index a9dfa79b6bab..1f35a3478f3c 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c | |||
| @@ -502,8 +502,14 @@ int hibernation_restore(int platform_mode) | |||
| 502 | error = dpm_suspend_start(PMSG_QUIESCE); | 502 | error = dpm_suspend_start(PMSG_QUIESCE); |
| 503 | if (!error) { | 503 | if (!error) { |
| 504 | error = resume_target_kernel(platform_mode); | 504 | error = resume_target_kernel(platform_mode); |
| 505 | dpm_resume_end(PMSG_RECOVER); | 505 | /* |
| 506 | * The above should either succeed and jump to the new kernel, | ||
| 507 | * or return with an error. Otherwise things are just | ||
| 508 | * undefined, so let's be paranoid. | ||
| 509 | */ | ||
| 510 | BUG_ON(!error); | ||
| 506 | } | 511 | } |
| 512 | dpm_resume_end(PMSG_RECOVER); | ||
| 507 | pm_restore_gfp_mask(); | 513 | pm_restore_gfp_mask(); |
| 508 | resume_console(); | 514 | resume_console(); |
| 509 | pm_restore_console(); | 515 | pm_restore_console(); |
