cnss2: Add code changes to support thermal mitigation
Add cnss2 code changes to register with thermal framework to support thermal mitigation. Change-Id: I9d427603bfc7e6bb5d732fa3e29ff66c965e153b CRs-Fixed: 3386762
Цей коміт міститься в:

зафіксовано
Madan Koyyalamudi

джерело
8e0ff47179
коміт
6c09e62157
193
cnss2/main.c
193
cnss2/main.c
@@ -17,6 +17,7 @@
|
||||
#include <linux/rwsem.h>
|
||||
#include <linux/suspend.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <linux/version.h>
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0))
|
||||
#include <linux/panic_notifier.h>
|
||||
@@ -4543,6 +4544,195 @@ int cnss_set_wfc_mode(struct device *dev, struct cnss_wfc_cfg cfg)
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_set_wfc_mode);
|
||||
|
||||
static int cnss_tcdev_get_max_state(struct thermal_cooling_device *tcdev,
|
||||
unsigned long *thermal_state)
|
||||
{
|
||||
struct cnss_thermal_cdev *cnss_tcdev = NULL;
|
||||
|
||||
if (!tcdev || !tcdev->devdata) {
|
||||
cnss_pr_err("tcdev or tcdev->devdata is null!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cnss_tcdev = tcdev->devdata;
|
||||
*thermal_state = cnss_tcdev->max_thermal_state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cnss_tcdev_get_cur_state(struct thermal_cooling_device *tcdev,
|
||||
unsigned long *thermal_state)
|
||||
{
|
||||
struct cnss_thermal_cdev *cnss_tcdev = NULL;
|
||||
|
||||
if (!tcdev || !tcdev->devdata) {
|
||||
cnss_pr_err("tcdev or tcdev->devdata is null!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cnss_tcdev = tcdev->devdata;
|
||||
*thermal_state = cnss_tcdev->curr_thermal_state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cnss_tcdev_set_cur_state(struct thermal_cooling_device *tcdev,
|
||||
unsigned long thermal_state)
|
||||
{
|
||||
struct cnss_thermal_cdev *cnss_tcdev = NULL;
|
||||
struct cnss_plat_data *plat_priv = cnss_get_plat_priv(NULL);
|
||||
int ret = 0;
|
||||
|
||||
if (!tcdev || !tcdev->devdata) {
|
||||
cnss_pr_err("tcdev or tcdev->devdata is null!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cnss_tcdev = tcdev->devdata;
|
||||
|
||||
if (thermal_state > cnss_tcdev->max_thermal_state)
|
||||
return -EINVAL;
|
||||
|
||||
cnss_pr_vdbg("Cooling device set current state: %ld,for cdev id %d",
|
||||
thermal_state, cnss_tcdev->tcdev_id);
|
||||
|
||||
mutex_lock(&plat_priv->tcdev_lock);
|
||||
ret = cnss_bus_set_therm_cdev_state(plat_priv,
|
||||
thermal_state,
|
||||
cnss_tcdev->tcdev_id);
|
||||
if (!ret)
|
||||
cnss_tcdev->curr_thermal_state = thermal_state;
|
||||
mutex_unlock(&plat_priv->tcdev_lock);
|
||||
if (ret) {
|
||||
cnss_pr_err("Setting Current Thermal State Failed: %d,for cdev id %d",
|
||||
ret, cnss_tcdev->tcdev_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct thermal_cooling_device_ops cnss_cooling_ops = {
|
||||
.get_max_state = cnss_tcdev_get_max_state,
|
||||
.get_cur_state = cnss_tcdev_get_cur_state,
|
||||
.set_cur_state = cnss_tcdev_set_cur_state,
|
||||
};
|
||||
|
||||
int cnss_thermal_cdev_register(struct device *dev, unsigned long max_state,
|
||||
int tcdev_id)
|
||||
{
|
||||
struct cnss_plat_data *priv = cnss_get_plat_priv(NULL);
|
||||
struct cnss_thermal_cdev *cnss_tcdev = NULL;
|
||||
char cdev_node_name[THERMAL_NAME_LENGTH] = "";
|
||||
struct device_node *dev_node;
|
||||
int ret = 0;
|
||||
|
||||
if (!priv) {
|
||||
cnss_pr_err("Platform driver is not initialized!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
cnss_tcdev = kzalloc(sizeof(*cnss_tcdev), GFP_KERNEL);
|
||||
if (!cnss_tcdev) {
|
||||
cnss_pr_err("Failed to allocate cnss_tcdev object!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
cnss_tcdev->tcdev_id = tcdev_id;
|
||||
cnss_tcdev->max_thermal_state = max_state;
|
||||
|
||||
snprintf(cdev_node_name, THERMAL_NAME_LENGTH,
|
||||
"qcom,cnss_cdev%d", tcdev_id);
|
||||
|
||||
dev_node = of_find_node_by_name(NULL, cdev_node_name);
|
||||
if (!dev_node) {
|
||||
cnss_pr_err("Failed to get cooling device node\n");
|
||||
kfree(cnss_tcdev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cnss_pr_dbg("tcdev node->name=%s\n", dev_node->name);
|
||||
|
||||
if (of_find_property(dev_node, "#cooling-cells", NULL)) {
|
||||
cnss_tcdev->tcdev = thermal_of_cooling_device_register(dev_node,
|
||||
cdev_node_name,
|
||||
cnss_tcdev,
|
||||
&cnss_cooling_ops);
|
||||
if (IS_ERR_OR_NULL(cnss_tcdev->tcdev)) {
|
||||
ret = PTR_ERR(cnss_tcdev->tcdev);
|
||||
cnss_pr_err("Cooling device register failed: %d, for cdev id %d\n",
|
||||
ret, cnss_tcdev->tcdev_id);
|
||||
kfree(cnss_tcdev);
|
||||
} else {
|
||||
cnss_pr_dbg("Cooling device registered for cdev id %d",
|
||||
cnss_tcdev->tcdev_id);
|
||||
mutex_lock(&priv->tcdev_lock);
|
||||
list_add(&cnss_tcdev->tcdev_list,
|
||||
&priv->cnss_tcdev_list);
|
||||
mutex_unlock(&priv->tcdev_lock);
|
||||
}
|
||||
} else {
|
||||
cnss_pr_dbg("Cooling device registration not supported");
|
||||
kfree(cnss_tcdev);
|
||||
ret = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_thermal_cdev_register);
|
||||
|
||||
void cnss_thermal_cdev_unregister(struct device *dev, int tcdev_id)
|
||||
{
|
||||
struct cnss_plat_data *priv = cnss_get_plat_priv(NULL);
|
||||
struct cnss_thermal_cdev *cnss_tcdev = NULL;
|
||||
|
||||
if (!priv) {
|
||||
cnss_pr_err("Platform driver is not initialized!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&priv->tcdev_lock);
|
||||
while (!list_empty(&priv->cnss_tcdev_list)) {
|
||||
cnss_tcdev = list_first_entry(&priv->cnss_tcdev_list,
|
||||
struct cnss_thermal_cdev,
|
||||
tcdev_list);
|
||||
thermal_cooling_device_unregister(cnss_tcdev->tcdev);
|
||||
list_del(&cnss_tcdev->tcdev_list);
|
||||
kfree(cnss_tcdev);
|
||||
}
|
||||
mutex_unlock(&priv->tcdev_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_thermal_cdev_unregister);
|
||||
|
||||
int cnss_get_curr_therm_cdev_state(struct device *dev,
|
||||
unsigned long *thermal_state,
|
||||
int tcdev_id)
|
||||
{
|
||||
struct cnss_plat_data *priv = cnss_get_plat_priv(NULL);
|
||||
struct cnss_thermal_cdev *cnss_tcdev = NULL;
|
||||
|
||||
if (!priv) {
|
||||
cnss_pr_err("Platform driver is not initialized!\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
mutex_lock(&priv->tcdev_lock);
|
||||
list_for_each_entry(cnss_tcdev, &priv->cnss_tcdev_list, tcdev_list) {
|
||||
if (cnss_tcdev->tcdev_id != tcdev_id)
|
||||
continue;
|
||||
|
||||
*thermal_state = cnss_tcdev->curr_thermal_state;
|
||||
mutex_unlock(&priv->tcdev_lock);
|
||||
cnss_pr_dbg("Cooling device current state: %ld, for cdev id %d",
|
||||
cnss_tcdev->curr_thermal_state, tcdev_id);
|
||||
return 0;
|
||||
}
|
||||
mutex_unlock(&priv->tcdev_lock);
|
||||
cnss_pr_dbg("Cooling device ID not found: %d", tcdev_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_get_curr_therm_cdev_state);
|
||||
|
||||
static int cnss_probe(struct platform_device *plat_dev)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -4670,6 +4860,9 @@ static int cnss_probe(struct platform_device *plat_dev)
|
||||
cnss_register_coex_service(plat_priv);
|
||||
cnss_register_ims_service(plat_priv);
|
||||
|
||||
mutex_init(&plat_priv->tcdev_lock);
|
||||
INIT_LIST_HEAD(&plat_priv->cnss_tcdev_list);
|
||||
|
||||
cnss_pr_info("Platform driver probed successfully.\n");
|
||||
|
||||
return 0;
|
||||
|
Посилання в новій задачі
Заблокувати користувача