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 branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux

Pull thermal updates from Zhang Rui:

- Fix a race condition when updating cooling device, which may lead to
a situation where a thermal governor never updates the cooling
device. From Michele Di Giorgio.

- Fix a zero division error when disabling the forced idle injection
from the intel powerclamp. From Petr Mladek.

- Add suspend/resume callback for intel_pch_thermal thermal driver.
From Srinivas Pandruvada.

- Another two fixes for clocking cooling driver and hwmon sysfs I/F.
From Michele Di Giorgio and Kuninori Morimoto.

[ Hmm. That suspend/resume callback for intel_pch_thermal doesn't look
like a fix, but I'm letting it slide.. - Linus ]

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux:
thermal: clock_cooling: Fix missing mutex_init()
thermal: hwmon: EXPORT_SYMBOL_GPL for thermal hwmon sysfs
thermal: fix race condition when updating cooling device
thermal/powerclamp: Prevent division by zero when counting interval
thermal: intel_pch_thermal: Add suspend/resume callback

+86 -10
+1
drivers/thermal/clock_cooling.c
··· 426 426 if (!ccdev) 427 427 return ERR_PTR(-ENOMEM); 428 428 429 + mutex_init(&ccdev->lock); 429 430 ccdev->dev = dev; 430 431 ccdev->clk = devm_clk_get(dev, clock_name); 431 432 if (IS_ERR(ccdev->clk))
+2
drivers/thermal/fair_share.c
··· 116 116 instance->target = get_target_state(tz, cdev, percentage, 117 117 cur_trip_level); 118 118 119 + mutex_lock(&instance->cdev->lock); 119 120 instance->cdev->updated = false; 121 + mutex_unlock(&instance->cdev->lock); 120 122 thermal_cdev_update(cdev); 121 123 } 122 124 return 0;
+2
drivers/thermal/gov_bang_bang.c
··· 71 71 dev_dbg(&instance->cdev->device, "target=%d\n", 72 72 (int)instance->target); 73 73 74 + mutex_lock(&instance->cdev->lock); 74 75 instance->cdev->updated = false; /* cdev needs update */ 76 + mutex_unlock(&instance->cdev->lock); 75 77 } 76 78 77 79 mutex_unlock(&tz->lock);
+59 -1
drivers/thermal/intel_pch_thermal.c
··· 21 21 #include <linux/init.h> 22 22 #include <linux/pci.h> 23 23 #include <linux/thermal.h> 24 + #include <linux/pm.h> 24 25 25 26 /* Intel PCH thermal Device IDs */ 26 27 #define PCH_THERMAL_DID_WPT 0x9CA4 /* Wildcat Point */ ··· 66 65 unsigned long crt_temp; 67 66 int hot_trip_id; 68 67 unsigned long hot_temp; 68 + bool bios_enabled; 69 69 }; 70 70 71 71 static int pch_wpt_init(struct pch_thermal_device *ptd, int *nr_trips) ··· 77 75 *nr_trips = 0; 78 76 79 77 /* Check if BIOS has already enabled thermal sensor */ 80 - if (WPT_TSS_TSDSS & readb(ptd->hw_base + WPT_TSS)) 78 + if (WPT_TSS_TSDSS & readb(ptd->hw_base + WPT_TSS)) { 79 + ptd->bios_enabled = true; 81 80 goto read_trips; 81 + } 82 82 83 83 tsel = readb(ptd->hw_base + WPT_TSEL); 84 84 /* ··· 134 130 return 0; 135 131 } 136 132 133 + static int pch_wpt_suspend(struct pch_thermal_device *ptd) 134 + { 135 + u8 tsel; 136 + 137 + if (ptd->bios_enabled) 138 + return 0; 139 + 140 + tsel = readb(ptd->hw_base + WPT_TSEL); 141 + 142 + writeb(tsel & 0xFE, ptd->hw_base + WPT_TSEL); 143 + 144 + return 0; 145 + } 146 + 147 + static int pch_wpt_resume(struct pch_thermal_device *ptd) 148 + { 149 + u8 tsel; 150 + 151 + if (ptd->bios_enabled) 152 + return 0; 153 + 154 + tsel = readb(ptd->hw_base + WPT_TSEL); 155 + 156 + writeb(tsel | WPT_TSEL_ETS, ptd->hw_base + WPT_TSEL); 157 + 158 + return 0; 159 + } 160 + 137 161 struct pch_dev_ops { 138 162 int (*hw_init)(struct pch_thermal_device *ptd, int *nr_trips); 139 163 int (*get_temp)(struct pch_thermal_device *ptd, int *temp); 164 + int (*suspend)(struct pch_thermal_device *ptd); 165 + int (*resume)(struct pch_thermal_device *ptd); 140 166 }; 141 167 142 168 ··· 174 140 static const struct pch_dev_ops pch_dev_ops_wpt = { 175 141 .hw_init = pch_wpt_init, 176 142 .get_temp = pch_wpt_get_temp, 143 + .suspend = pch_wpt_suspend, 144 + .resume = pch_wpt_resume, 177 145 }; 178 146 179 147 static int pch_thermal_get_temp(struct thermal_zone_device *tzd, int *temp) ··· 305 269 pci_disable_device(pdev); 306 270 } 307 271 272 + static int intel_pch_thermal_suspend(struct device *device) 273 + { 274 + struct pci_dev *pdev = to_pci_dev(device); 275 + struct pch_thermal_device *ptd = pci_get_drvdata(pdev); 276 + 277 + return ptd->ops->suspend(ptd); 278 + } 279 + 280 + static int intel_pch_thermal_resume(struct device *device) 281 + { 282 + struct pci_dev *pdev = to_pci_dev(device); 283 + struct pch_thermal_device *ptd = pci_get_drvdata(pdev); 284 + 285 + return ptd->ops->resume(ptd); 286 + } 287 + 308 288 static struct pci_device_id intel_pch_thermal_id[] = { 309 289 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_WPT) }, 310 290 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCH_THERMAL_DID_SKL) }, ··· 328 276 }; 329 277 MODULE_DEVICE_TABLE(pci, intel_pch_thermal_id); 330 278 279 + static const struct dev_pm_ops intel_pch_pm_ops = { 280 + .suspend = intel_pch_thermal_suspend, 281 + .resume = intel_pch_thermal_resume, 282 + }; 283 + 331 284 static struct pci_driver intel_pch_thermal_driver = { 332 285 .name = "intel_pch_thermal", 333 286 .id_table = intel_pch_thermal_id, 334 287 .probe = intel_pch_thermal_probe, 335 288 .remove = intel_pch_thermal_remove, 289 + .driver.pm = &intel_pch_pm_ops, 336 290 }; 337 291 338 292 module_pci_driver(intel_pch_thermal_driver);
+7 -4
drivers/thermal/intel_powerclamp.c
··· 388 388 int sleeptime; 389 389 unsigned long target_jiffies; 390 390 unsigned int guard; 391 - unsigned int compensation = 0; 391 + unsigned int compensated_ratio; 392 392 int interval; /* jiffies to sleep for each attempt */ 393 393 unsigned int duration_jiffies = msecs_to_jiffies(duration); 394 394 unsigned int window_size_now; ··· 409 409 * c-states, thus we need to compensate the injected idle ratio 410 410 * to achieve the actual target reported by the HW. 411 411 */ 412 - compensation = get_compensation(target_ratio); 413 - interval = duration_jiffies*100/(target_ratio+compensation); 412 + compensated_ratio = target_ratio + 413 + get_compensation(target_ratio); 414 + if (compensated_ratio <= 0) 415 + compensated_ratio = 1; 416 + interval = duration_jiffies * 100 / compensated_ratio; 414 417 415 418 /* align idle time */ 416 419 target_jiffies = roundup(jiffies, interval); ··· 650 647 goto exit_set; 651 648 } else if (set_target_ratio > 0 && new_target_ratio == 0) { 652 649 pr_info("Stop forced idle injection\n"); 653 - set_target_ratio = 0; 654 650 end_power_clamp(); 651 + set_target_ratio = 0; 655 652 } else /* adjust currently running */ { 656 653 set_target_ratio = new_target_ratio; 657 654 /* make new set_target_ratio visible to other cpus */
+2
drivers/thermal/power_allocator.c
··· 529 529 continue; 530 530 531 531 instance->target = 0; 532 + mutex_lock(&instance->cdev->lock); 532 533 instance->cdev->updated = false; 534 + mutex_unlock(&instance->cdev->lock); 533 535 thermal_cdev_update(instance->cdev); 534 536 } 535 537 }
+2
drivers/thermal/step_wise.c
··· 175 175 update_passive_instance(tz, trip_type, -1); 176 176 177 177 instance->initialized = true; 178 + mutex_lock(&instance->cdev->lock); 178 179 instance->cdev->updated = false; /* cdev needs update */ 180 + mutex_unlock(&instance->cdev->lock); 179 181 } 180 182 181 183 mutex_unlock(&tz->lock);
+9 -5
drivers/thermal/thermal_core.c
··· 1093 1093 return ret; 1094 1094 1095 1095 instance->target = state; 1096 + mutex_lock(&cdev->lock); 1096 1097 cdev->updated = false; 1098 + mutex_unlock(&cdev->lock); 1097 1099 thermal_cdev_update(cdev); 1098 1100 1099 1101 return 0; ··· 1625 1623 struct thermal_instance *instance; 1626 1624 unsigned long target = 0; 1627 1625 1628 - /* cooling device is updated*/ 1629 - if (cdev->updated) 1630 - return; 1631 - 1632 1626 mutex_lock(&cdev->lock); 1627 + /* cooling device is updated*/ 1628 + if (cdev->updated) { 1629 + mutex_unlock(&cdev->lock); 1630 + return; 1631 + } 1632 + 1633 1633 /* Make sure cdev enters the deepest cooling state */ 1634 1634 list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) { 1635 1635 dev_dbg(&cdev->device, "zone%d->target=%lu\n", ··· 1641 1637 if (instance->target > target) 1642 1638 target = instance->target; 1643 1639 } 1644 - mutex_unlock(&cdev->lock); 1645 1640 cdev->ops->set_cur_state(cdev, target); 1646 1641 cdev->updated = true; 1642 + mutex_unlock(&cdev->lock); 1647 1643 trace_cdev_update(cdev, target); 1648 1644 dev_dbg(&cdev->device, "set to state %lu\n", target); 1649 1645 }
+2
drivers/thermal/thermal_hwmon.c
··· 232 232 233 233 return result; 234 234 } 235 + EXPORT_SYMBOL_GPL(thermal_add_hwmon_sysfs); 235 236 236 237 void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) 237 238 { ··· 271 270 hwmon_device_unregister(hwmon->device); 272 271 kfree(hwmon); 273 272 } 273 + EXPORT_SYMBOL_GPL(thermal_remove_hwmon_sysfs);