Commit bbb544f3 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'thermal-int340x', 'thermal-pch' and 'thermal-misc'

Merge int340x thermal driver updates, PCH thermal driver updates and
miscellaneous thermal control updates for 5.19-rc1:

 - Clean up _OSC handling in int340x (Davidlohr Bueso).

 - Improve overheat condition handling during suspend-to-idle in the
   Intel PCH thermal driver (Zhang Rui).

 - Use local ops instead of global ops in devfreq_cooling (Kant Fan).

 - Switch hisi_termal from CONFIG_PM_SLEEP guards to pm_sleep_ptr()
   (Hesham Almatary)

* thermal-int340x:
  thermal: int340x: Clean up _OSC context init
  thermal: int340x: Consolidate freeing of acpi_buffer pointer
  thermal: int340x: Clean up unnecessary acpi_buffer pointer freeing

* thermal-pch:
  thermal: intel: pch: improve the cooling delay log
  thermal: intel: pch: enhance overheat handling
  thermal: intel: pch: move cooling delay to suspend_noirq phase
  PM: wakeup: expose pm_wakeup_pending to modules

* thermal-misc:
  thermal: devfreq_cooling: use local ops instead of global ops
  thermal: hisi_termal: Switch from CONFIG_PM_SLEEP guards to pm_sleep_ptr()
...@@ -930,6 +930,7 @@ bool pm_wakeup_pending(void) ...@@ -930,6 +930,7 @@ bool pm_wakeup_pending(void)
return ret || atomic_read(&pm_abort_suspend) > 0; return ret || atomic_read(&pm_abort_suspend) > 0;
} }
EXPORT_SYMBOL_GPL(pm_wakeup_pending);
void pm_system_wakeup(void) void pm_system_wakeup(void)
{ {
......
...@@ -358,21 +358,28 @@ of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df, ...@@ -358,21 +358,28 @@ of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,
struct thermal_cooling_device *cdev; struct thermal_cooling_device *cdev;
struct device *dev = df->dev.parent; struct device *dev = df->dev.parent;
struct devfreq_cooling_device *dfc; struct devfreq_cooling_device *dfc;
struct thermal_cooling_device_ops *ops;
char *name; char *name;
int err, num_opps; int err, num_opps;
dfc = kzalloc(sizeof(*dfc), GFP_KERNEL); ops = kmemdup(&devfreq_cooling_ops, sizeof(*ops), GFP_KERNEL);
if (!dfc) if (!ops)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
dfc = kzalloc(sizeof(*dfc), GFP_KERNEL);
if (!dfc) {
err = -ENOMEM;
goto free_ops;
}
dfc->devfreq = df; dfc->devfreq = df;
dfc->em_pd = em_pd_get(dev); dfc->em_pd = em_pd_get(dev);
if (dfc->em_pd) { if (dfc->em_pd) {
devfreq_cooling_ops.get_requested_power = ops->get_requested_power =
devfreq_cooling_get_requested_power; devfreq_cooling_get_requested_power;
devfreq_cooling_ops.state2power = devfreq_cooling_state2power; ops->state2power = devfreq_cooling_state2power;
devfreq_cooling_ops.power2state = devfreq_cooling_power2state; ops->power2state = devfreq_cooling_power2state;
dfc->power_ops = dfc_power; dfc->power_ops = dfc_power;
...@@ -407,8 +414,7 @@ of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df, ...@@ -407,8 +414,7 @@ of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,
if (!name) if (!name)
goto remove_qos_req; goto remove_qos_req;
cdev = thermal_of_cooling_device_register(np, name, dfc, cdev = thermal_of_cooling_device_register(np, name, dfc, ops);
&devfreq_cooling_ops);
kfree(name); kfree(name);
if (IS_ERR(cdev)) { if (IS_ERR(cdev)) {
...@@ -429,6 +435,8 @@ of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df, ...@@ -429,6 +435,8 @@ of_devfreq_cooling_register_power(struct device_node *np, struct devfreq *df,
kfree(dfc->freq_table); kfree(dfc->freq_table);
free_dfc: free_dfc:
kfree(dfc); kfree(dfc);
free_ops:
kfree(ops);
return ERR_PTR(err); return ERR_PTR(err);
} }
...@@ -510,11 +518,13 @@ EXPORT_SYMBOL_GPL(devfreq_cooling_em_register); ...@@ -510,11 +518,13 @@ EXPORT_SYMBOL_GPL(devfreq_cooling_em_register);
void devfreq_cooling_unregister(struct thermal_cooling_device *cdev) void devfreq_cooling_unregister(struct thermal_cooling_device *cdev)
{ {
struct devfreq_cooling_device *dfc; struct devfreq_cooling_device *dfc;
const struct thermal_cooling_device_ops *ops;
struct device *dev; struct device *dev;
if (IS_ERR_OR_NULL(cdev)) if (IS_ERR_OR_NULL(cdev))
return; return;
ops = cdev->ops;
dfc = cdev->devdata; dfc = cdev->devdata;
dev = dfc->devfreq->dev.parent; dev = dfc->devfreq->dev.parent;
...@@ -525,5 +535,6 @@ void devfreq_cooling_unregister(struct thermal_cooling_device *cdev) ...@@ -525,5 +535,6 @@ void devfreq_cooling_unregister(struct thermal_cooling_device *cdev)
kfree(dfc->freq_table); kfree(dfc->freq_table);
kfree(dfc); kfree(dfc);
kfree(ops);
} }
EXPORT_SYMBOL_GPL(devfreq_cooling_unregister); EXPORT_SYMBOL_GPL(devfreq_cooling_unregister);
...@@ -629,7 +629,6 @@ static int hisi_thermal_remove(struct platform_device *pdev) ...@@ -629,7 +629,6 @@ static int hisi_thermal_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM_SLEEP
static int hisi_thermal_suspend(struct device *dev) static int hisi_thermal_suspend(struct device *dev)
{ {
struct hisi_thermal_data *data = dev_get_drvdata(dev); struct hisi_thermal_data *data = dev_get_drvdata(dev);
...@@ -651,15 +650,14 @@ static int hisi_thermal_resume(struct device *dev) ...@@ -651,15 +650,14 @@ static int hisi_thermal_resume(struct device *dev)
return ret; return ret;
} }
#endif
static SIMPLE_DEV_PM_OPS(hisi_thermal_pm_ops, static DEFINE_SIMPLE_DEV_PM_OPS(hisi_thermal_pm_ops,
hisi_thermal_suspend, hisi_thermal_resume); hisi_thermal_suspend, hisi_thermal_resume);
static struct platform_driver hisi_thermal_driver = { static struct platform_driver hisi_thermal_driver = {
.driver = { .driver = {
.name = "hisi_thermal", .name = "hisi_thermal",
.pm = &hisi_thermal_pm_ops, .pm = pm_sleep_ptr(&hisi_thermal_pm_ops),
.of_match_table = of_hisi_thermal_match, .of_match_table = of_hisi_thermal_match,
}, },
.probe = hisi_thermal_probe, .probe = hisi_thermal_probe,
......
...@@ -169,28 +169,25 @@ static int int3400_thermal_run_osc(acpi_handle handle, char *uuid_str, int *enab ...@@ -169,28 +169,25 @@ static int int3400_thermal_run_osc(acpi_handle handle, char *uuid_str, int *enab
acpi_status status; acpi_status status;
int result = 0; int result = 0;
struct acpi_osc_context context = { struct acpi_osc_context context = {
.uuid_str = NULL, .uuid_str = uuid_str,
.rev = 1, .rev = 1,
.cap.length = 8, .cap.length = 8,
.cap.pointer = buf,
}; };
context.uuid_str = uuid_str;
buf[OSC_QUERY_DWORD] = 0; buf[OSC_QUERY_DWORD] = 0;
buf[OSC_SUPPORT_DWORD] = *enable; buf[OSC_SUPPORT_DWORD] = *enable;
context.cap.pointer = buf;
status = acpi_run_osc(handle, &context); status = acpi_run_osc(handle, &context);
if (ACPI_SUCCESS(status)) { if (ACPI_SUCCESS(status)) {
ret = *((u32 *)(context.ret.pointer + 4)); ret = *((u32 *)(context.ret.pointer + 4));
if (ret != *enable) if (ret != *enable)
result = -EPERM; result = -EPERM;
kfree(context.ret.pointer);
} else } else
result = -EPERM; result = -EPERM;
kfree(context.ret.pointer);
return result; return result;
} }
...@@ -524,21 +521,18 @@ static void int3400_setup_gddv(struct int3400_thermal_priv *priv) ...@@ -524,21 +521,18 @@ static void int3400_setup_gddv(struct int3400_thermal_priv *priv)
obj = buffer.pointer; obj = buffer.pointer;
if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count != 1 if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count != 1
|| obj->package.elements[0].type != ACPI_TYPE_BUFFER) { || obj->package.elements[0].type != ACPI_TYPE_BUFFER)
kfree(buffer.pointer); goto out_free;
return;
}
priv->data_vault = kmemdup(obj->package.elements[0].buffer.pointer, priv->data_vault = kmemdup(obj->package.elements[0].buffer.pointer,
obj->package.elements[0].buffer.length, obj->package.elements[0].buffer.length,
GFP_KERNEL); GFP_KERNEL);
if (!priv->data_vault) { if (!priv->data_vault)
kfree(buffer.pointer); goto out_free;
return;
}
bin_attr_data_vault.private = priv->data_vault; bin_attr_data_vault.private = priv->data_vault;
bin_attr_data_vault.size = obj->package.elements[0].buffer.length; bin_attr_data_vault.size = obj->package.elements[0].buffer.length;
out_free:
kfree(buffer.pointer); kfree(buffer.pointer);
} }
......
...@@ -70,8 +70,8 @@ static unsigned int delay_timeout = 100; ...@@ -70,8 +70,8 @@ static unsigned int delay_timeout = 100;
module_param(delay_timeout, int, 0644); module_param(delay_timeout, int, 0644);
MODULE_PARM_DESC(delay_timeout, "amount of time delay for each iteration."); MODULE_PARM_DESC(delay_timeout, "amount of time delay for each iteration.");
/* Number of iterations for cooling delay, 10 counts by default for now */ /* Number of iterations for cooling delay, 600 counts by default for now */
static unsigned int delay_cnt = 10; static unsigned int delay_cnt = 600;
module_param(delay_cnt, int, 0644); module_param(delay_cnt, int, 0644);
MODULE_PARM_DESC(delay_cnt, "total number of iterations for time delay."); MODULE_PARM_DESC(delay_cnt, "total number of iterations for time delay.");
...@@ -193,10 +193,11 @@ static int pch_wpt_get_temp(struct pch_thermal_device *ptd, int *temp) ...@@ -193,10 +193,11 @@ static int pch_wpt_get_temp(struct pch_thermal_device *ptd, int *temp)
return 0; return 0;
} }
/* Cool the PCH when it's overheat in .suspend_noirq phase */
static int pch_wpt_suspend(struct pch_thermal_device *ptd) static int pch_wpt_suspend(struct pch_thermal_device *ptd)
{ {
u8 tsel; u8 tsel;
u8 pch_delay_cnt = 1; int pch_delay_cnt = 0;
u16 pch_thr_temp, pch_cur_temp; u16 pch_thr_temp, pch_cur_temp;
/* Shutdown the thermal sensor if it is not enabled by BIOS */ /* Shutdown the thermal sensor if it is not enabled by BIOS */
...@@ -232,26 +233,38 @@ static int pch_wpt_suspend(struct pch_thermal_device *ptd) ...@@ -232,26 +233,38 @@ static int pch_wpt_suspend(struct pch_thermal_device *ptd)
* temperature stays above threshold, notify the warning message * temperature stays above threshold, notify the warning message
* which helps to indentify the reason why S0ix entry was rejected. * which helps to indentify the reason why S0ix entry was rejected.
*/ */
while (pch_delay_cnt <= delay_cnt) { while (pch_delay_cnt < delay_cnt) {
if (pch_cur_temp <= pch_thr_temp) if (pch_cur_temp < pch_thr_temp)
break; break;
dev_warn(&ptd->pdev->dev, if (pm_wakeup_pending()) {
dev_warn(&ptd->pdev->dev, "Wakeup event detected, abort cooling\n");
return 0;
}
pch_delay_cnt++;
dev_dbg(&ptd->pdev->dev,
"CPU-PCH current temp [%dC] higher than the threshold temp [%dC], sleep %d times for %d ms duration\n", "CPU-PCH current temp [%dC] higher than the threshold temp [%dC], sleep %d times for %d ms duration\n",
pch_cur_temp, pch_thr_temp, pch_delay_cnt, delay_timeout); pch_cur_temp, pch_thr_temp, pch_delay_cnt, delay_timeout);
msleep(delay_timeout); msleep(delay_timeout);
/* Read the PCH current temperature for next cycle. */ /* Read the PCH current temperature for next cycle. */
pch_cur_temp = GET_PCH_TEMP(WPT_TEMP_TSR & readw(ptd->hw_base + WPT_TEMP)); pch_cur_temp = GET_PCH_TEMP(WPT_TEMP_TSR & readw(ptd->hw_base + WPT_TEMP));
pch_delay_cnt++;
} }
if (pch_cur_temp > pch_thr_temp) if (pch_cur_temp >= pch_thr_temp)
dev_warn(&ptd->pdev->dev, dev_warn(&ptd->pdev->dev,
"CPU-PCH is hot [%dC] even after delay, continue to suspend. S0ix might fail\n", "CPU-PCH is hot [%dC] after %d ms delay. S0ix might fail\n",
pch_cur_temp); pch_cur_temp, pch_delay_cnt * delay_timeout);
else else {
dev_info(&ptd->pdev->dev, if (pch_delay_cnt)
"CPU-PCH is cool [%dC], continue to suspend\n", pch_cur_temp); dev_info(&ptd->pdev->dev,
"CPU-PCH is cool [%dC] after %d ms delay\n",
pch_cur_temp, pch_delay_cnt * delay_timeout);
else
dev_info(&ptd->pdev->dev,
"CPU-PCH is cool [%dC]\n",
pch_cur_temp);
}
return 0; return 0;
} }
...@@ -455,7 +468,7 @@ static void intel_pch_thermal_remove(struct pci_dev *pdev) ...@@ -455,7 +468,7 @@ static void intel_pch_thermal_remove(struct pci_dev *pdev)
pci_disable_device(pdev); pci_disable_device(pdev);
} }
static int intel_pch_thermal_suspend(struct device *device) static int intel_pch_thermal_suspend_noirq(struct device *device)
{ {
struct pch_thermal_device *ptd = dev_get_drvdata(device); struct pch_thermal_device *ptd = dev_get_drvdata(device);
...@@ -495,7 +508,7 @@ static const struct pci_device_id intel_pch_thermal_id[] = { ...@@ -495,7 +508,7 @@ static const struct pci_device_id intel_pch_thermal_id[] = {
MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id); MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id);
static const struct dev_pm_ops intel_pch_pm_ops = { static const struct dev_pm_ops intel_pch_pm_ops = {
.suspend = intel_pch_thermal_suspend, .suspend_noirq = intel_pch_thermal_suspend_noirq,
.resume = intel_pch_thermal_resume, .resume = intel_pch_thermal_resume,
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment