icnss: Thermal mitigation support in WLAN
Add support for WLAN Host to register as cooling device through icnss platform driver. Change-Id: I9d3c2bfa18ea6b4a473c2d54b3a99cd7b4e62a68 Signed-off-by: Naman Padhiar <npadhiar@codeaurora.org>
This commit is contained in:
parent
3541909b95
commit
7649fde8d3
2 changed files with 118 additions and 0 deletions
|
|
@ -49,6 +49,7 @@
|
|||
#include <soc/qcom/service-notifier.h>
|
||||
#include <soc/qcom/socinfo.h>
|
||||
#include <soc/qcom/ramdump.h>
|
||||
#include <linux/thermal.h>
|
||||
|
||||
#include "wlan_firmware_service_v01.h"
|
||||
|
||||
|
|
@ -481,6 +482,9 @@ static struct icnss_priv {
|
|||
uint32_t fw_early_crash_irq;
|
||||
struct completion unblock_shutdown;
|
||||
bool is_ssr;
|
||||
struct thermal_cooling_device *tcdev;
|
||||
unsigned long curr_thermal_state;
|
||||
unsigned long max_thermal_state;
|
||||
} *penv;
|
||||
|
||||
#ifdef CONFIG_ICNSS_DEBUG
|
||||
|
|
@ -2430,6 +2434,115 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int icnss_tcdev_get_max_state(struct thermal_cooling_device *tcdev,
|
||||
unsigned long *thermal_state)
|
||||
{
|
||||
struct icnss_priv *priv = tcdev->devdata;
|
||||
|
||||
*thermal_state = priv->max_thermal_state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int icnss_tcdev_get_cur_state(struct thermal_cooling_device *tcdev,
|
||||
unsigned long *thermal_state)
|
||||
{
|
||||
struct icnss_priv *priv = tcdev->devdata;
|
||||
|
||||
*thermal_state = priv->curr_thermal_state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int icnss_tcdev_set_cur_state(struct thermal_cooling_device *tcdev,
|
||||
unsigned long thermal_state)
|
||||
{
|
||||
struct icnss_priv *priv = tcdev->devdata;
|
||||
struct device *dev = &priv->pdev->dev;
|
||||
int ret = 0;
|
||||
|
||||
priv->curr_thermal_state = thermal_state;
|
||||
|
||||
if (!priv->ops || !priv->ops->set_therm_state)
|
||||
return 0;
|
||||
|
||||
icnss_pr_vdbg("Cooling device set current state: %ld",
|
||||
thermal_state);
|
||||
|
||||
ret = priv->ops->set_therm_state(dev, thermal_state);
|
||||
|
||||
if (ret)
|
||||
icnss_pr_err("Setting Current Thermal State Failed: %d\n", ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct thermal_cooling_device_ops icnss_cooling_ops = {
|
||||
.get_max_state = icnss_tcdev_get_max_state,
|
||||
.get_cur_state = icnss_tcdev_get_cur_state,
|
||||
.set_cur_state = icnss_tcdev_set_cur_state,
|
||||
};
|
||||
|
||||
int icnss_thermal_register(struct device *dev, unsigned long max_state)
|
||||
{
|
||||
struct icnss_priv *priv = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
priv->max_thermal_state = max_state;
|
||||
|
||||
if (of_find_property(dev->of_node, "#cooling-cells", NULL)) {
|
||||
priv->tcdev = thermal_of_cooling_device_register(dev->of_node,
|
||||
"icnss", priv,
|
||||
&icnss_cooling_ops);
|
||||
if (IS_ERR_OR_NULL(priv->tcdev)) {
|
||||
ret = PTR_ERR(priv->tcdev);
|
||||
icnss_pr_err("Cooling device register failed: %d\n",
|
||||
ret);
|
||||
} else {
|
||||
icnss_pr_vdbg("Cooling device registered");
|
||||
}
|
||||
} else {
|
||||
icnss_pr_dbg("Cooling device registration not supported");
|
||||
ret = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(icnss_thermal_register);
|
||||
|
||||
void icnss_thermal_unregister(struct device *dev)
|
||||
{
|
||||
struct icnss_priv *priv = dev_get_drvdata(dev);
|
||||
|
||||
if (!IS_ERR_OR_NULL(priv->tcdev))
|
||||
thermal_cooling_device_unregister(priv->tcdev);
|
||||
|
||||
priv->tcdev = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(icnss_thermal_unregister);
|
||||
|
||||
int icnss_get_curr_therm_state(struct device *dev,
|
||||
unsigned long *thermal_state)
|
||||
{
|
||||
struct icnss_priv *priv = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (IS_ERR_OR_NULL(priv->tcdev)) {
|
||||
ret = PTR_ERR(priv->tcdev);
|
||||
icnss_pr_err("Get current thermal state failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
icnss_pr_vdbg("Cooling device current state: %ld",
|
||||
priv->curr_thermal_state);
|
||||
|
||||
*thermal_state = priv->curr_thermal_state;
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(icnss_get_curr_therm_state);
|
||||
|
||||
static int icnss_driver_event_register_driver(void *data)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ struct icnss_driver_ops {
|
|||
int (*suspend_noirq)(struct device *dev);
|
||||
int (*resume_noirq)(struct device *dev);
|
||||
int (*uevent)(struct device *dev, struct icnss_uevent_data *uevent);
|
||||
int (*set_therm_state)(struct device *dev, unsigned long thermal_state);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -146,4 +147,8 @@ extern bool icnss_is_rejuvenate(void);
|
|||
extern int icnss_trigger_recovery(struct device *dev);
|
||||
extern void icnss_block_shutdown(bool status);
|
||||
extern bool icnss_is_pdr(void);
|
||||
extern int icnss_thermal_register(struct device *dev, unsigned long max_state);
|
||||
extern void icnss_thermal_unregister(struct device *dev);
|
||||
extern int icnss_get_curr_therm_state(struct device *dev,
|
||||
unsigned long *thermal_state);
|
||||
#endif /* _ICNSS_WLAN_H_ */
|
||||
|
|
|
|||
Loading…
Reference in a new issue