Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'pm+acpi-3.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull ACPI and power management fixes from Rafael Wysocki:
"These are fixes received after my previous pull request plus one that
has been in the works for quite a while, but its previous version
caused problems to happen, so it's been deferred till now.

Fixed are two recent regressions (MFD enumeration and cpufreq-dt),
ACPI EC regression introduced in 3.17, system suspend error code path
regression introduced in 3.15, an older bug related to recovery from
failing resume from hibernation and a cpufreq-dt driver issue related
to operation performance points.

Specifics:

- Fix a crash on r8a7791/koelsch during resume from system suspend
caused by a recent cpufreq-dt commit (Geert Uytterhoeven).

- Fix an MFD enumeration problem introduced by a recent commit adding
ACPI support to the MFD subsystem that exposed a weakness in the
ACPI core causing ACPI enumeration to be applied to all devices
associated with one ACPI companion object, although it should be
used for one of them only (Mika Westerberg).

- Fix an ACPI EC regression introduced during the 3.17 cycle causing
some Samsung laptops to misbehave as a result of a workaround
targeted at some Acer machines. That includes a revert of a commit
that went too far and a quirk for the Acer machines in question.
From Lv Zheng.

- Fix a regression in the system suspend error code path introduced
during the 3.15 cycle that causes it to fail to take errors from
asychronous execution of "late" suspend callbacks into account
(Imre Deak).

- Fix a long-standing bug in the hibernation resume error code path
that fails to roll back everything correcty on "freeze" callback
errors and leaves some devices in a "suspended" state causing more
breakage to happen subsequently (Imre Deak).

- Make the cpufreq-dt driver disable operation performance points
that are not supported by the VR connected to the CPU voltage plane
with acceptable tolerance instead of constantly failing voltage
scaling later on (Lucas Stach)"

* tag 'pm+acpi-3.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
ACPI / EC: Fix regression due to conflicting firmware behavior between Samsung and Acer.
Revert "ACPI / EC: Add support to disallow QR_EC to be issued before completing previous QR_EC"
cpufreq: cpufreq-dt: Restore default cpumask_setall(policy->cpus)
PM / Sleep: fix recovery during resuming from hibernation
PM / Sleep: fix async suspend_late/freeze_late error handling
ACPI: Use ACPI companion to match only the first physical device
cpufreq: cpufreq-dt: disable unsupported OPPs

+126 -53
+21 -10
drivers/acpi/ec.c
··· 126 126 static int EC_FLAGS_VALIDATE_ECDT; /* ASUStec ECDTs need to be validated */ 127 127 static int EC_FLAGS_SKIP_DSDT_SCAN; /* Not all BIOS survive early DSDT scan */ 128 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 132 * Transaction Management ··· 237 236 } 238 237 return wakeup; 239 238 } else { 240 - /* 241 - * There is firmware refusing to respond QR_EC when SCI_EVT 242 - * is not set, for which case, we complete the QR_EC 243 - * without issuing it to the firmware. 244 - * https://bugzilla.kernel.org/show_bug.cgi?id=86211 245 - */ 246 - if (!(status & ACPI_EC_FLAG_SCI) && 239 + if (EC_FLAGS_QUERY_HANDSHAKE && 240 + !(status & ACPI_EC_FLAG_SCI) && 247 241 (t->command == ACPI_EC_COMMAND_QUERY)) { 248 242 t->flags |= ACPI_EC_COMMAND_POLL; 249 243 t->rdata[t->ri++] = 0x00; ··· 330 334 pr_debug("***** Command(%s) started *****\n", 331 335 acpi_ec_cmd_string(t->command)); 332 336 start_transaction(ec); 333 - spin_unlock_irqrestore(&ec->lock, tmp); 334 - ret = ec_poll(ec); 335 - spin_lock_irqsave(&ec->lock, tmp); 336 337 if (ec->curr->command == ACPI_EC_COMMAND_QUERY) { 337 338 clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); 338 339 pr_debug("***** Event stopped *****\n"); 339 340 } 341 + spin_unlock_irqrestore(&ec->lock, tmp); 342 + ret = ec_poll(ec); 343 + spin_lock_irqsave(&ec->lock, tmp); 340 344 pr_debug("***** Command(%s) stopped *****\n", 341 345 acpi_ec_cmd_string(t->command)); 342 346 ec->curr = NULL; ··· 1008 1012 } 1009 1013 1010 1014 /* 1015 + * Acer EC firmware refuses to respond QR_EC when SCI_EVT is not set, for 1016 + * which case, we complete the QR_EC without issuing it to the firmware. 1017 + * https://bugzilla.kernel.org/show_bug.cgi?id=86211 1018 + */ 1019 + static int ec_flag_query_handshake(const struct dmi_system_id *id) 1020 + { 1021 + pr_debug("Detected the EC firmware requiring QR_EC issued when SCI_EVT set\n"); 1022 + EC_FLAGS_QUERY_HANDSHAKE = 1; 1023 + return 0; 1024 + } 1025 + 1026 + /* 1011 1027 * On some hardware it is necessary to clear events accumulated by the EC during 1012 1028 * sleep. These ECs stop reporting GPEs until they are manually polled, if too 1013 1029 * many events are accumulated. (e.g. Samsung Series 5/9 notebooks) ··· 1093 1085 { 1094 1086 ec_clear_on_resume, "Samsung hardware", { 1095 1087 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL}, 1088 + { 1089 + ec_flag_query_handshake, "Acer hardware", { 1090 + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), }, NULL}, 1096 1091 {}, 1097 1092 }; 1098 1093
+54 -16
drivers/acpi/scan.c
··· 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 192 * Creates uevent modalias field for ACPI enumerated devices. 146 193 * Because the other buses does not support ACPI HIDs & CIDs. 147 194 * e.g. for a device with hid:IBM0001 and cid:ACPI0001 you get: ··· 196 149 */ 197 150 int acpi_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) 198 151 { 199 - struct acpi_device *acpi_dev; 200 152 int len; 201 153 202 - acpi_dev = ACPI_COMPANION(dev); 203 - if (!acpi_dev) 204 - return -ENODEV; 205 - 206 - /* Fall back to bus specific way of modalias exporting */ 207 - if (list_empty(&acpi_dev->pnp.ids)) 154 + if (!acpi_companion_match(dev)) 208 155 return -ENODEV; 209 156 210 157 if (add_uevent_var(env, "MODALIAS=")) 211 158 return -ENOMEM; 212 - len = create_modalias(acpi_dev, &env->buf[env->buflen - 1], 159 + len = create_modalias(ACPI_COMPANION(dev), &env->buf[env->buflen - 1], 213 160 sizeof(env->buf) - env->buflen); 214 161 if (len <= 0) 215 162 return len; ··· 220 179 */ 221 180 int acpi_device_modalias(struct device *dev, char *buf, int size) 222 181 { 223 - struct acpi_device *acpi_dev; 224 182 int len; 225 183 226 - acpi_dev = ACPI_COMPANION(dev); 227 - if (!acpi_dev) 184 + if (!acpi_companion_match(dev)) 228 185 return -ENODEV; 229 186 230 - /* Fall back to bus specific way of modalias exporting */ 231 - if (list_empty(&acpi_dev->pnp.ids)) 232 - return -ENODEV; 233 - 234 - len = create_modalias(acpi_dev, buf, size -1); 187 + len = create_modalias(ACPI_COMPANION(dev), buf, size -1); 235 188 if (len <= 0) 236 189 return len; 237 190 buf[len++] = '\n'; ··· 886 851 acpi_handle handle = ACPI_HANDLE(dev); 887 852 888 853 if (!ids || !handle || acpi_bus_get_device(handle, &adev)) 854 + return NULL; 855 + 856 + if (!acpi_companion_match(dev)) 889 857 return NULL; 890 858 891 859 return __acpi_match_device(adev, ids);
+2
drivers/base/power/main.c
··· 1266 1266 } 1267 1267 mutex_unlock(&dpm_list_mtx); 1268 1268 async_synchronize_full(); 1269 + if (!error) 1270 + error = async_error; 1269 1271 if (error) { 1270 1272 suspend_stats.failed_suspend_late++; 1271 1273 dpm_save_failed_step(SUSPEND_SUSPEND_LATE);
+42 -26
drivers/cpufreq/cpufreq-dt.c
··· 187 187 struct device *cpu_dev; 188 188 struct regulator *cpu_reg; 189 189 struct clk *cpu_clk; 190 + unsigned long min_uV = ~0, max_uV = 0; 190 191 unsigned int transition_latency; 191 192 int ret; 192 193 ··· 207 206 /* OPPs might be populated at runtime, don't check for error here */ 208 207 of_init_opp_table(cpu_dev); 209 208 210 - ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); 211 - if (ret) { 212 - dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret); 213 - goto out_put_node; 214 - } 215 - 216 209 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 217 210 if (!priv) { 218 211 ret = -ENOMEM; 219 - goto out_free_table; 212 + goto out_put_node; 220 213 } 221 214 222 215 of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance); ··· 219 224 transition_latency = CPUFREQ_ETERNAL; 220 225 221 226 if (!IS_ERR(cpu_reg)) { 222 - struct dev_pm_opp *opp; 223 - unsigned long min_uV, max_uV; 224 - int i; 227 + unsigned long opp_freq = 0; 225 228 226 229 /* 227 - * OPP is maintained in order of increasing frequency, and 228 - * freq_table initialised from OPP is therefore sorted in the 229 - * same order. 230 + * Disable any OPPs where the connected regulator isn't able to 231 + * provide the specified voltage and record minimum and maximum 232 + * voltage levels. 230 233 */ 231 - for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) 232 - ; 233 - rcu_read_lock(); 234 - opp = dev_pm_opp_find_freq_exact(cpu_dev, 235 - freq_table[0].frequency * 1000, true); 236 - min_uV = dev_pm_opp_get_voltage(opp); 237 - opp = dev_pm_opp_find_freq_exact(cpu_dev, 238 - freq_table[i-1].frequency * 1000, true); 239 - max_uV = dev_pm_opp_get_voltage(opp); 240 - rcu_read_unlock(); 234 + while (1) { 235 + struct dev_pm_opp *opp; 236 + unsigned long opp_uV, tol_uV; 237 + 238 + rcu_read_lock(); 239 + opp = dev_pm_opp_find_freq_ceil(cpu_dev, &opp_freq); 240 + if (IS_ERR(opp)) { 241 + rcu_read_unlock(); 242 + break; 243 + } 244 + opp_uV = dev_pm_opp_get_voltage(opp); 245 + rcu_read_unlock(); 246 + 247 + tol_uV = opp_uV * priv->voltage_tolerance / 100; 248 + if (regulator_is_supported_voltage(cpu_reg, opp_uV, 249 + opp_uV + tol_uV)) { 250 + if (opp_uV < min_uV) 251 + min_uV = opp_uV; 252 + if (opp_uV > max_uV) 253 + max_uV = opp_uV; 254 + } else { 255 + dev_pm_opp_disable(cpu_dev, opp_freq); 256 + } 257 + 258 + opp_freq++; 259 + } 260 + 241 261 ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV); 242 262 if (ret > 0) 243 263 transition_latency += ret * 1000; 264 + } 265 + 266 + ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); 267 + if (ret) { 268 + pr_err("failed to init cpufreq table: %d\n", ret); 269 + goto out_free_priv; 244 270 } 245 271 246 272 /* ··· 293 277 policy->cpuinfo.transition_latency = transition_latency; 294 278 295 279 pd = cpufreq_get_driver_data(); 296 - if (pd && !pd->independent_clocks) 280 + if (!pd || !pd->independent_clocks) 297 281 cpumask_setall(policy->cpus); 298 282 299 283 of_node_put(np); ··· 302 286 303 287 out_cooling_unregister: 304 288 cpufreq_cooling_unregister(priv->cdev); 305 - kfree(priv); 306 - out_free_table: 307 289 dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table); 290 + out_free_priv: 291 + kfree(priv); 308 292 out_put_node: 309 293 of_node_put(np); 310 294 out_put_reg_clk:
+7 -1
kernel/power/hibernate.c
··· 502 502 error = dpm_suspend_start(PMSG_QUIESCE); 503 503 if (!error) { 504 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 513 pm_restore_gfp_mask(); 508 514 resume_console(); 509 515 pm_restore_console();