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
Цей коміт міститься в:
Gangadhar Kavalastramath
2023-02-01 09:57:44 +05:30
зафіксовано Madan Koyyalamudi
джерело 8e0ff47179
коміт 6c09e62157
7 змінених файлів з 257 додано та 0 видалено

Переглянути файл

@@ -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;