diff options
Diffstat (limited to 'drivers/devfreq/devfreq.c')
-rw-r--r-- | drivers/devfreq/devfreq.c | 90 |
1 files changed, 59 insertions, 31 deletions
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 0ae3de76833b..6b6991f0e873 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c | |||
@@ -29,6 +29,9 @@ | |||
29 | #include <linux/of.h> | 29 | #include <linux/of.h> |
30 | #include "governor.h" | 30 | #include "governor.h" |
31 | 31 | ||
32 | #define CREATE_TRACE_POINTS | ||
33 | #include <trace/events/devfreq.h> | ||
34 | |||
32 | static struct class *devfreq_class; | 35 | static struct class *devfreq_class; |
33 | 36 | ||
34 | /* | 37 | /* |
@@ -228,7 +231,7 @@ static struct devfreq_governor *find_devfreq_governor(const char *name) | |||
228 | * if is not found. This can happen when both drivers (the governor driver | 231 | * if is not found. This can happen when both drivers (the governor driver |
229 | * and the driver that call devfreq_add_device) are built as modules. | 232 | * and the driver that call devfreq_add_device) are built as modules. |
230 | * devfreq_list_lock should be held by the caller. Returns the matched | 233 | * devfreq_list_lock should be held by the caller. Returns the matched |
231 | * governor's pointer. | 234 | * governor's pointer or an error pointer. |
232 | */ | 235 | */ |
233 | static struct devfreq_governor *try_then_request_governor(const char *name) | 236 | static struct devfreq_governor *try_then_request_governor(const char *name) |
234 | { | 237 | { |
@@ -254,7 +257,7 @@ static struct devfreq_governor *try_then_request_governor(const char *name) | |||
254 | /* Restore previous state before return */ | 257 | /* Restore previous state before return */ |
255 | mutex_lock(&devfreq_list_lock); | 258 | mutex_lock(&devfreq_list_lock); |
256 | if (err) | 259 | if (err) |
257 | return NULL; | 260 | return ERR_PTR(err); |
258 | 261 | ||
259 | governor = find_devfreq_governor(name); | 262 | governor = find_devfreq_governor(name); |
260 | } | 263 | } |
@@ -394,6 +397,8 @@ static void devfreq_monitor(struct work_struct *work) | |||
394 | queue_delayed_work(devfreq_wq, &devfreq->work, | 397 | queue_delayed_work(devfreq_wq, &devfreq->work, |
395 | msecs_to_jiffies(devfreq->profile->polling_ms)); | 398 | msecs_to_jiffies(devfreq->profile->polling_ms)); |
396 | mutex_unlock(&devfreq->lock); | 399 | mutex_unlock(&devfreq->lock); |
400 | |||
401 | trace_devfreq_monitor(devfreq); | ||
397 | } | 402 | } |
398 | 403 | ||
399 | /** | 404 | /** |
@@ -528,7 +533,7 @@ void devfreq_interval_update(struct devfreq *devfreq, unsigned int *delay) | |||
528 | mutex_lock(&devfreq->lock); | 533 | mutex_lock(&devfreq->lock); |
529 | if (!devfreq->stop_polling) | 534 | if (!devfreq->stop_polling) |
530 | queue_delayed_work(devfreq_wq, &devfreq->work, | 535 | queue_delayed_work(devfreq_wq, &devfreq->work, |
531 | msecs_to_jiffies(devfreq->profile->polling_ms)); | 536 | msecs_to_jiffies(devfreq->profile->polling_ms)); |
532 | } | 537 | } |
533 | out: | 538 | out: |
534 | mutex_unlock(&devfreq->lock); | 539 | mutex_unlock(&devfreq->lock); |
@@ -537,7 +542,7 @@ EXPORT_SYMBOL(devfreq_interval_update); | |||
537 | 542 | ||
538 | /** | 543 | /** |
539 | * devfreq_notifier_call() - Notify that the device frequency requirements | 544 | * devfreq_notifier_call() - Notify that the device frequency requirements |
540 | * has been changed out of devfreq framework. | 545 | * has been changed out of devfreq framework. |
541 | * @nb: the notifier_block (supposed to be devfreq->nb) | 546 | * @nb: the notifier_block (supposed to be devfreq->nb) |
542 | * @type: not used | 547 | * @type: not used |
543 | * @devp: not used | 548 | * @devp: not used |
@@ -651,7 +656,7 @@ struct devfreq *devfreq_add_device(struct device *dev, | |||
651 | mutex_unlock(&devfreq->lock); | 656 | mutex_unlock(&devfreq->lock); |
652 | err = set_freq_table(devfreq); | 657 | err = set_freq_table(devfreq); |
653 | if (err < 0) | 658 | if (err < 0) |
654 | goto err_out; | 659 | goto err_dev; |
655 | mutex_lock(&devfreq->lock); | 660 | mutex_lock(&devfreq->lock); |
656 | } | 661 | } |
657 | 662 | ||
@@ -683,16 +688,27 @@ struct devfreq *devfreq_add_device(struct device *dev, | |||
683 | goto err_out; | 688 | goto err_out; |
684 | } | 689 | } |
685 | 690 | ||
686 | devfreq->trans_table = | 691 | devfreq->trans_table = devm_kzalloc(&devfreq->dev, |
687 | devm_kzalloc(&devfreq->dev, | 692 | array3_size(sizeof(unsigned int), |
688 | array3_size(sizeof(unsigned int), | 693 | devfreq->profile->max_state, |
689 | devfreq->profile->max_state, | 694 | devfreq->profile->max_state), |
690 | devfreq->profile->max_state), | 695 | GFP_KERNEL); |
691 | GFP_KERNEL); | 696 | if (!devfreq->trans_table) { |
697 | mutex_unlock(&devfreq->lock); | ||
698 | err = -ENOMEM; | ||
699 | goto err_devfreq; | ||
700 | } | ||
701 | |||
692 | devfreq->time_in_state = devm_kcalloc(&devfreq->dev, | 702 | devfreq->time_in_state = devm_kcalloc(&devfreq->dev, |
693 | devfreq->profile->max_state, | 703 | devfreq->profile->max_state, |
694 | sizeof(unsigned long), | 704 | sizeof(unsigned long), |
695 | GFP_KERNEL); | 705 | GFP_KERNEL); |
706 | if (!devfreq->time_in_state) { | ||
707 | mutex_unlock(&devfreq->lock); | ||
708 | err = -ENOMEM; | ||
709 | goto err_devfreq; | ||
710 | } | ||
711 | |||
696 | devfreq->last_stat_updated = jiffies; | 712 | devfreq->last_stat_updated = jiffies; |
697 | 713 | ||
698 | srcu_init_notifier_head(&devfreq->transition_notifier_list); | 714 | srcu_init_notifier_head(&devfreq->transition_notifier_list); |
@@ -726,7 +742,7 @@ struct devfreq *devfreq_add_device(struct device *dev, | |||
726 | 742 | ||
727 | err_init: | 743 | err_init: |
728 | mutex_unlock(&devfreq_list_lock); | 744 | mutex_unlock(&devfreq_list_lock); |
729 | 745 | err_devfreq: | |
730 | devfreq_remove_device(devfreq); | 746 | devfreq_remove_device(devfreq); |
731 | devfreq = NULL; | 747 | devfreq = NULL; |
732 | err_dev: | 748 | err_dev: |
@@ -1113,7 +1129,7 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr, | |||
1113 | struct devfreq *df = to_devfreq(dev); | 1129 | struct devfreq *df = to_devfreq(dev); |
1114 | int ret; | 1130 | int ret; |
1115 | char str_governor[DEVFREQ_NAME_LEN + 1]; | 1131 | char str_governor[DEVFREQ_NAME_LEN + 1]; |
1116 | struct devfreq_governor *governor; | 1132 | const struct devfreq_governor *governor, *prev_governor; |
1117 | 1133 | ||
1118 | ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor); | 1134 | ret = sscanf(buf, "%" __stringify(DEVFREQ_NAME_LEN) "s", str_governor); |
1119 | if (ret != 1) | 1135 | if (ret != 1) |
@@ -1142,12 +1158,24 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr, | |||
1142 | goto out; | 1158 | goto out; |
1143 | } | 1159 | } |
1144 | } | 1160 | } |
1161 | prev_governor = df->governor; | ||
1145 | df->governor = governor; | 1162 | df->governor = governor; |
1146 | strncpy(df->governor_name, governor->name, DEVFREQ_NAME_LEN); | 1163 | strncpy(df->governor_name, governor->name, DEVFREQ_NAME_LEN); |
1147 | ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL); | 1164 | ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL); |
1148 | if (ret) | 1165 | if (ret) { |
1149 | dev_warn(dev, "%s: Governor %s not started(%d)\n", | 1166 | dev_warn(dev, "%s: Governor %s not started(%d)\n", |
1150 | __func__, df->governor->name, ret); | 1167 | __func__, df->governor->name, ret); |
1168 | df->governor = prev_governor; | ||
1169 | strncpy(df->governor_name, prev_governor->name, | ||
1170 | DEVFREQ_NAME_LEN); | ||
1171 | ret = df->governor->event_handler(df, DEVFREQ_GOV_START, NULL); | ||
1172 | if (ret) { | ||
1173 | dev_err(dev, | ||
1174 | "%s: reverting to Governor %s failed (%d)\n", | ||
1175 | __func__, df->governor_name, ret); | ||
1176 | df->governor = NULL; | ||
1177 | } | ||
1178 | } | ||
1151 | out: | 1179 | out: |
1152 | mutex_unlock(&devfreq_list_lock); | 1180 | mutex_unlock(&devfreq_list_lock); |
1153 | 1181 | ||
@@ -1172,7 +1200,7 @@ static ssize_t available_governors_show(struct device *d, | |||
1172 | */ | 1200 | */ |
1173 | if (df->governor->immutable) { | 1201 | if (df->governor->immutable) { |
1174 | count = scnprintf(&buf[count], DEVFREQ_NAME_LEN, | 1202 | count = scnprintf(&buf[count], DEVFREQ_NAME_LEN, |
1175 | "%s ", df->governor_name); | 1203 | "%s ", df->governor_name); |
1176 | /* | 1204 | /* |
1177 | * The devfreq device shows the registered governor except for | 1205 | * The devfreq device shows the registered governor except for |
1178 | * immutable governors such as passive governor . | 1206 | * immutable governors such as passive governor . |
@@ -1485,8 +1513,8 @@ EXPORT_SYMBOL(devfreq_recommended_opp); | |||
1485 | 1513 | ||
1486 | /** | 1514 | /** |
1487 | * devfreq_register_opp_notifier() - Helper function to get devfreq notified | 1515 | * devfreq_register_opp_notifier() - Helper function to get devfreq notified |
1488 | * for any changes in the OPP availability | 1516 | * for any changes in the OPP availability |
1489 | * changes | 1517 | * changes |
1490 | * @dev: The devfreq user device. (parent of devfreq) | 1518 | * @dev: The devfreq user device. (parent of devfreq) |
1491 | * @devfreq: The devfreq object. | 1519 | * @devfreq: The devfreq object. |
1492 | */ | 1520 | */ |
@@ -1498,8 +1526,8 @@ EXPORT_SYMBOL(devfreq_register_opp_notifier); | |||
1498 | 1526 | ||
1499 | /** | 1527 | /** |
1500 | * devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq | 1528 | * devfreq_unregister_opp_notifier() - Helper function to stop getting devfreq |
1501 | * notified for any changes in the OPP | 1529 | * notified for any changes in the OPP |
1502 | * availability changes anymore. | 1530 | * availability changes anymore. |
1503 | * @dev: The devfreq user device. (parent of devfreq) | 1531 | * @dev: The devfreq user device. (parent of devfreq) |
1504 | * @devfreq: The devfreq object. | 1532 | * @devfreq: The devfreq object. |
1505 | * | 1533 | * |
@@ -1518,8 +1546,8 @@ static void devm_devfreq_opp_release(struct device *dev, void *res) | |||
1518 | } | 1546 | } |
1519 | 1547 | ||
1520 | /** | 1548 | /** |
1521 | * devm_ devfreq_register_opp_notifier() | 1549 | * devm_devfreq_register_opp_notifier() - Resource-managed |
1522 | * - Resource-managed devfreq_register_opp_notifier() | 1550 | * devfreq_register_opp_notifier() |
1523 | * @dev: The devfreq user device. (parent of devfreq) | 1551 | * @dev: The devfreq user device. (parent of devfreq) |
1524 | * @devfreq: The devfreq object. | 1552 | * @devfreq: The devfreq object. |
1525 | */ | 1553 | */ |
@@ -1547,8 +1575,8 @@ int devm_devfreq_register_opp_notifier(struct device *dev, | |||
1547 | EXPORT_SYMBOL(devm_devfreq_register_opp_notifier); | 1575 | EXPORT_SYMBOL(devm_devfreq_register_opp_notifier); |
1548 | 1576 | ||
1549 | /** | 1577 | /** |
1550 | * devm_devfreq_unregister_opp_notifier() | 1578 | * devm_devfreq_unregister_opp_notifier() - Resource-managed |
1551 | * - Resource-managed devfreq_unregister_opp_notifier() | 1579 | * devfreq_unregister_opp_notifier() |
1552 | * @dev: The devfreq user device. (parent of devfreq) | 1580 | * @dev: The devfreq user device. (parent of devfreq) |
1553 | * @devfreq: The devfreq object. | 1581 | * @devfreq: The devfreq object. |
1554 | */ | 1582 | */ |
@@ -1567,8 +1595,8 @@ EXPORT_SYMBOL(devm_devfreq_unregister_opp_notifier); | |||
1567 | * @list: DEVFREQ_TRANSITION_NOTIFIER. | 1595 | * @list: DEVFREQ_TRANSITION_NOTIFIER. |
1568 | */ | 1596 | */ |
1569 | int devfreq_register_notifier(struct devfreq *devfreq, | 1597 | int devfreq_register_notifier(struct devfreq *devfreq, |
1570 | struct notifier_block *nb, | 1598 | struct notifier_block *nb, |
1571 | unsigned int list) | 1599 | unsigned int list) |
1572 | { | 1600 | { |
1573 | int ret = 0; | 1601 | int ret = 0; |
1574 | 1602 | ||
@@ -1674,9 +1702,9 @@ EXPORT_SYMBOL(devm_devfreq_register_notifier); | |||
1674 | * @list: DEVFREQ_TRANSITION_NOTIFIER. | 1702 | * @list: DEVFREQ_TRANSITION_NOTIFIER. |
1675 | */ | 1703 | */ |
1676 | void devm_devfreq_unregister_notifier(struct device *dev, | 1704 | void devm_devfreq_unregister_notifier(struct device *dev, |
1677 | struct devfreq *devfreq, | 1705 | struct devfreq *devfreq, |
1678 | struct notifier_block *nb, | 1706 | struct notifier_block *nb, |
1679 | unsigned int list) | 1707 | unsigned int list) |
1680 | { | 1708 | { |
1681 | WARN_ON(devres_release(dev, devm_devfreq_notifier_release, | 1709 | WARN_ON(devres_release(dev, devm_devfreq_notifier_release, |
1682 | devm_devfreq_dev_match, devfreq)); | 1710 | devm_devfreq_dev_match, devfreq)); |