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

Merge branch 'pm-qos'

* pm-qos:
sh_mmcif / PM: Use PM QoS latency constraint
tmio_mmc / PM: Use PM QoS latency constraint
PM / QoS: Make it possible to expose PM QoS latency constraints

+150
+18
Documentation/ABI/testing/sysfs-devices-power
··· 165 165 166 166 Not all drivers support this attribute. If it isn't supported, 167 167 attempts to read or write it will yield I/O errors. 168 + 169 + What: /sys/devices/.../power/pm_qos_latency_us 170 + Date: March 2012 171 + Contact: Rafael J. Wysocki <rjw@sisk.pl> 172 + Description: 173 + The /sys/devices/.../power/pm_qos_resume_latency_us attribute 174 + contains the PM QoS resume latency limit for the given device, 175 + which is the maximum allowed time it can take to resume the 176 + device, after it has been suspended at run time, from a resume 177 + request to the moment the device will be ready to process I/O, 178 + in microseconds. If it is equal to 0, however, this means that 179 + the PM QoS resume latency may be arbitrary. 180 + 181 + Not all drivers support this attribute. If it isn't supported, 182 + it is not present. 183 + 184 + This attribute has no effect on system-wide suspend/resume and 185 + hibernation.
+4
drivers/base/power/power.h
··· 71 71 extern void rpm_sysfs_remove(struct device *dev); 72 72 extern int wakeup_sysfs_add(struct device *dev); 73 73 extern void wakeup_sysfs_remove(struct device *dev); 74 + extern int pm_qos_sysfs_add(struct device *dev); 75 + extern void pm_qos_sysfs_remove(struct device *dev); 74 76 75 77 #else /* CONFIG_PM */ 76 78 ··· 81 79 static inline void rpm_sysfs_remove(struct device *dev) {} 82 80 static inline int wakeup_sysfs_add(struct device *dev) { return 0; } 83 81 static inline void wakeup_sysfs_remove(struct device *dev) {} 82 + static inline int pm_qos_sysfs_add(struct device *dev) { return 0; } 83 + static inline void pm_qos_sysfs_remove(struct device *dev) {} 84 84 85 85 #endif
+61
drivers/base/power/qos.c
··· 41 41 #include <linux/mutex.h> 42 42 #include <linux/export.h> 43 43 44 + #include "power.h" 44 45 45 46 static DEFINE_MUTEX(dev_pm_qos_mtx); 46 47 ··· 166 165 { 167 166 struct dev_pm_qos_request *req, *tmp; 168 167 struct pm_qos_constraints *c; 168 + 169 + /* 170 + * If the device's PM QoS resume latency limit has been exposed to user 171 + * space, it has to be hidden at this point. 172 + */ 173 + dev_pm_qos_hide_latency_limit(dev); 169 174 170 175 mutex_lock(&dev_pm_qos_mtx); 171 176 ··· 452 445 return error; 453 446 } 454 447 EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request); 448 + 449 + #ifdef CONFIG_PM_RUNTIME 450 + static void __dev_pm_qos_drop_user_request(struct device *dev) 451 + { 452 + dev_pm_qos_remove_request(dev->power.pq_req); 453 + dev->power.pq_req = 0; 454 + } 455 + 456 + /** 457 + * dev_pm_qos_expose_latency_limit - Expose PM QoS latency limit to user space. 458 + * @dev: Device whose PM QoS latency limit is to be exposed to user space. 459 + * @value: Initial value of the latency limit. 460 + */ 461 + int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value) 462 + { 463 + struct dev_pm_qos_request *req; 464 + int ret; 465 + 466 + if (!device_is_registered(dev) || value < 0) 467 + return -EINVAL; 468 + 469 + if (dev->power.pq_req) 470 + return -EEXIST; 471 + 472 + req = kzalloc(sizeof(*req), GFP_KERNEL); 473 + if (!req) 474 + return -ENOMEM; 475 + 476 + ret = dev_pm_qos_add_request(dev, req, value); 477 + if (ret < 0) 478 + return ret; 479 + 480 + dev->power.pq_req = req; 481 + ret = pm_qos_sysfs_add(dev); 482 + if (ret) 483 + __dev_pm_qos_drop_user_request(dev); 484 + 485 + return ret; 486 + } 487 + EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit); 488 + 489 + /** 490 + * dev_pm_qos_hide_latency_limit - Hide PM QoS latency limit from user space. 491 + * @dev: Device whose PM QoS latency limit is to be hidden from user space. 492 + */ 493 + void dev_pm_qos_hide_latency_limit(struct device *dev) 494 + { 495 + if (dev->power.pq_req) { 496 + pm_qos_sysfs_remove(dev); 497 + __dev_pm_qos_drop_user_request(dev); 498 + } 499 + } 500 + EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit); 501 + #endif /* CONFIG_PM_RUNTIME */
+47
drivers/base/power/sysfs.c
··· 5 5 #include <linux/device.h> 6 6 #include <linux/string.h> 7 7 #include <linux/export.h> 8 + #include <linux/pm_qos.h> 8 9 #include <linux/pm_runtime.h> 9 10 #include <linux/atomic.h> 10 11 #include <linux/jiffies.h> ··· 218 217 static DEVICE_ATTR(autosuspend_delay_ms, 0644, autosuspend_delay_ms_show, 219 218 autosuspend_delay_ms_store); 220 219 220 + static ssize_t pm_qos_latency_show(struct device *dev, 221 + struct device_attribute *attr, char *buf) 222 + { 223 + return sprintf(buf, "%d\n", dev->power.pq_req->node.prio); 224 + } 225 + 226 + static ssize_t pm_qos_latency_store(struct device *dev, 227 + struct device_attribute *attr, 228 + const char *buf, size_t n) 229 + { 230 + s32 value; 231 + int ret; 232 + 233 + if (kstrtos32(buf, 0, &value)) 234 + return -EINVAL; 235 + 236 + if (value < 0) 237 + return -EINVAL; 238 + 239 + ret = dev_pm_qos_update_request(dev->power.pq_req, value); 240 + return ret < 0 ? ret : n; 241 + } 242 + 243 + static DEVICE_ATTR(pm_qos_resume_latency_us, 0644, 244 + pm_qos_latency_show, pm_qos_latency_store); 221 245 #endif /* CONFIG_PM_RUNTIME */ 222 246 223 247 #ifdef CONFIG_PM_SLEEP ··· 516 490 .attrs = runtime_attrs, 517 491 }; 518 492 493 + static struct attribute *pm_qos_attrs[] = { 494 + #ifdef CONFIG_PM_RUNTIME 495 + &dev_attr_pm_qos_resume_latency_us.attr, 496 + #endif /* CONFIG_PM_RUNTIME */ 497 + NULL, 498 + }; 499 + static struct attribute_group pm_qos_attr_group = { 500 + .name = power_group_name, 501 + .attrs = pm_qos_attrs, 502 + }; 503 + 519 504 int dpm_sysfs_add(struct device *dev) 520 505 { 521 506 int rc; ··· 565 528 void wakeup_sysfs_remove(struct device *dev) 566 529 { 567 530 sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); 531 + } 532 + 533 + int pm_qos_sysfs_add(struct device *dev) 534 + { 535 + return sysfs_merge_group(&dev->kobj, &pm_qos_attr_group); 536 + } 537 + 538 + void pm_qos_sysfs_remove(struct device *dev) 539 + { 540 + sysfs_unmerge_group(&dev->kobj, &pm_qos_attr_group); 568 541 } 569 542 570 543 void rpm_sysfs_remove(struct device *dev)
+5
drivers/mmc/host/sh_mmcif.c
··· 56 56 #include <linux/mmc/sh_mmcif.h> 57 57 #include <linux/pagemap.h> 58 58 #include <linux/platform_device.h> 59 + #include <linux/pm_qos.h> 59 60 #include <linux/pm_runtime.h> 60 61 #include <linux/spinlock.h> 61 62 #include <linux/module.h> ··· 1347 1346 if (ret < 0) 1348 1347 goto clean_up5; 1349 1348 1349 + dev_pm_qos_expose_latency_limit(&pdev->dev, 100); 1350 + 1350 1351 dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION); 1351 1352 dev_dbg(&pdev->dev, "chip ver H'%04x\n", 1352 1353 sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff); ··· 1378 1375 1379 1376 host->dying = true; 1380 1377 pm_runtime_get_sync(&pdev->dev); 1378 + 1379 + dev_pm_qos_hide_latency_limit(&pdev->dev); 1381 1380 1382 1381 mmc_remove_host(host->mmc); 1383 1382 sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
+5
drivers/mmc/host/tmio_mmc_pio.c
··· 39 39 #include <linux/module.h> 40 40 #include <linux/pagemap.h> 41 41 #include <linux/platform_device.h> 42 + #include <linux/pm_qos.h> 42 43 #include <linux/pm_runtime.h> 43 44 #include <linux/scatterlist.h> 44 45 #include <linux/spinlock.h> ··· 956 955 957 956 mmc_add_host(mmc); 958 957 958 + dev_pm_qos_expose_latency_limit(&pdev->dev, 100); 959 + 959 960 /* Unmask the IRQs we want to know about */ 960 961 if (!_host->chan_rx) 961 962 irq_mask |= TMIO_MASK_READOP; ··· 995 992 || host->mmc->caps & MMC_CAP_NEEDS_POLL 996 993 || host->mmc->caps & MMC_CAP_NONREMOVABLE) 997 994 pm_runtime_get_sync(&pdev->dev); 995 + 996 + dev_pm_qos_hide_latency_limit(&pdev->dev); 998 997 999 998 mmc_remove_host(host->mmc); 1000 999 cancel_work_sync(&host->done);
+1
include/linux/pm.h
··· 546 546 unsigned long accounting_timestamp; 547 547 ktime_t suspend_time; 548 548 s64 max_time_suspended_ns; 549 + struct dev_pm_qos_request *pq_req; 549 550 #endif 550 551 struct pm_subsys_data *subsys_data; /* Owned by the subsystem. */ 551 552 struct pm_qos_constraints *constraints;
+9
include/linux/pm_qos.h
··· 137 137 { return 0; } 138 138 #endif 139 139 140 + #ifdef CONFIG_PM_RUNTIME 141 + int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value); 142 + void dev_pm_qos_hide_latency_limit(struct device *dev); 143 + #else 144 + static inline int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value) 145 + { return 0; } 146 + static inline void dev_pm_qos_hide_latency_limit(struct device *dev) {} 147 + #endif 148 + 140 149 #endif