icnss2: Extend thermal mitigation support feature

Add support to register 'n' number of cooling devices
based on host driver ask and DT entry.

Change-Id: I1dd3ab9d3f9fdd6b6707e107be742565f9569c50
Signed-off-by: Naman Padhiar <npadhiar@codeaurora.org>
This commit is contained in:
Naman Padhiar 2020-07-11 01:29:03 +05:30 committed by Gerrit - the friendly Code Review server
parent e6f3b6b364
commit 3f5d3c0819
3 changed files with 107 additions and 58 deletions

View File

@ -1818,9 +1818,9 @@ static int icnss_enable_recovery(struct icnss_priv *priv)
static int icnss_tcdev_get_max_state(struct thermal_cooling_device *tcdev,
unsigned long *thermal_state)
{
struct icnss_priv *priv = tcdev->devdata;
struct icnss_thermal_cdev *icnss_tcdev = tcdev->devdata;
*thermal_state = priv->max_thermal_state;
*thermal_state = icnss_tcdev->max_thermal_state;
return 0;
}
@ -1828,9 +1828,9 @@ static int icnss_tcdev_get_max_state(struct thermal_cooling_device *tcdev,
static int icnss_tcdev_get_cur_state(struct thermal_cooling_device *tcdev,
unsigned long *thermal_state)
{
struct icnss_priv *priv = tcdev->devdata;
struct icnss_thermal_cdev *icnss_tcdev = tcdev->devdata;
*thermal_state = priv->curr_thermal_state;
*thermal_state = icnss_tcdev->curr_thermal_state;
return 0;
}
@ -1838,22 +1838,25 @@ static int icnss_tcdev_get_cur_state(struct thermal_cooling_device *tcdev,
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;
struct icnss_thermal_cdev *icnss_tcdev = tcdev->devdata;
struct device *dev = &penv->pdev->dev;
int ret = 0;
priv->curr_thermal_state = thermal_state;
if (!priv->ops || !priv->ops->set_therm_state)
if (!penv->ops || !penv->ops->set_therm_cdev_state)
return 0;
icnss_pr_vdbg("Cooling device set current state: %ld",
thermal_state);
ret = priv->ops->set_therm_state(dev, thermal_state);
icnss_pr_vdbg("Cooling device set current state: %ld,for cdev id %d",
thermal_state, icnss_tcdev->tcdev_id);
mutex_lock(&penv->tcdev_lock);
icnss_tcdev->curr_thermal_state = thermal_state;
ret = penv->ops->set_therm_cdev_state(dev, thermal_state,
icnss_tcdev->tcdev_id);
mutex_unlock(&penv->tcdev_lock);
if (ret)
icnss_pr_err("Setting Current Thermal State Failed: %d\n", ret);
icnss_pr_err("Setting Current Thermal State Failed: %d,for cdev id %d",
ret, icnss_tcdev->tcdev_id);
return 0;
}
@ -1864,23 +1867,47 @@ static struct thermal_cooling_device_ops icnss_cooling_ops = {
.set_cur_state = icnss_tcdev_set_cur_state,
};
int icnss_thermal_register(struct device *dev, unsigned long max_state)
int icnss_thermal_cdev_register(struct device *dev, unsigned long max_state,
int tcdev_id)
{
struct icnss_priv *priv = dev_get_drvdata(dev);
struct icnss_thermal_cdev *icnss_tcdev = NULL;
char cdev_node_name[THERMAL_NAME_LENGTH] = "";
struct device_node *dev_node;
int ret = 0;
priv->max_thermal_state = max_state;
icnss_tcdev = devm_kzalloc(dev, sizeof(*icnss_tcdev), GFP_KERNEL);
if (!icnss_tcdev)
return -ENOMEM;
if (of_find_property(dev->of_node, "#cooling-cells", NULL)) {
priv->tcdev = thermal_of_cooling_device_register(dev->of_node,
"icnss", priv,
icnss_tcdev->tcdev_id = tcdev_id;
icnss_tcdev->max_thermal_state = max_state;
snprintf(cdev_node_name, THERMAL_NAME_LENGTH,
"qcom,icnss_cdev%d", tcdev_id);
dev_node = of_find_node_by_name(NULL, cdev_node_name);
if (!dev_node) {
icnss_pr_err("Failed to get cooling device node\n");
return -EINVAL;
}
icnss_pr_dbg("tcdev node->name=%s\n", dev_node->name);
if (of_find_property(dev_node, "#cooling-cells", NULL)) {
icnss_tcdev->tcdev = thermal_of_cooling_device_register(
dev_node,
cdev_node_name, icnss_tcdev,
&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);
if (IS_ERR_OR_NULL(icnss_tcdev->tcdev)) {
ret = PTR_ERR(icnss_tcdev->tcdev);
icnss_pr_err("Cooling device register failed: %d, for cdev id %d\n",
ret, icnss_tcdev->tcdev_id);
} else {
icnss_pr_vdbg("Cooling device registered");
icnss_pr_dbg("Cooling device registered for cdev id %d",
icnss_tcdev->tcdev_id);
list_add(&icnss_tcdev->tcdev_list,
&priv->icnss_tcdev_list);
}
} else {
icnss_pr_dbg("Cooling device registration not supported");
@ -1889,38 +1916,44 @@ int icnss_thermal_register(struct device *dev, unsigned long max_state)
return ret;
}
EXPORT_SYMBOL(icnss_thermal_register);
EXPORT_SYMBOL(icnss_thermal_cdev_register);
void icnss_thermal_unregister(struct device *dev)
void icnss_thermal_cdev_unregister(struct device *dev, int tcdev_id)
{
struct icnss_priv *priv = dev_get_drvdata(dev);
struct icnss_thermal_cdev *icnss_tcdev = NULL;
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;
list_for_each_entry(icnss_tcdev, &priv->icnss_tcdev_list, tcdev_list) {
thermal_cooling_device_unregister(icnss_tcdev->tcdev);
list_del(&icnss_tcdev->tcdev_list);
kfree(icnss_tcdev);
}
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);
EXPORT_SYMBOL(icnss_thermal_cdev_unregister);
int icnss_get_curr_therm_cdev_state(struct device *dev,
unsigned long *thermal_state,
int tcdev_id)
{
struct icnss_priv *priv = dev_get_drvdata(dev);
struct icnss_thermal_cdev *icnss_tcdev = NULL;
mutex_lock(&priv->tcdev_lock);
list_for_each_entry(icnss_tcdev, &priv->icnss_tcdev_list, tcdev_list) {
if (icnss_tcdev->tcdev_id != tcdev_id)
continue;
*thermal_state = icnss_tcdev->curr_thermal_state;
mutex_unlock(&priv->tcdev_lock);
icnss_pr_dbg("Cooling device current state: %ld, for cdev id %d",
icnss_tcdev->curr_thermal_state, tcdev_id);
return 0;
}
mutex_unlock(&priv->tcdev_lock);
icnss_pr_dbg("Cooling device ID not found: %d", tcdev_id);
return -EINVAL;
}
EXPORT_SYMBOL(icnss_get_curr_therm_cdev_state);
int icnss_qmi_send(struct device *dev, int type, void *cmd,
int cmd_len, void *cb_ctx,
@ -3072,6 +3105,7 @@ static int icnss_probe(struct platform_device *pdev)
spin_lock_init(&priv->on_off_lock);
spin_lock_init(&priv->soc_wake_msg_lock);
mutex_init(&priv->dev_lock);
mutex_init(&priv->tcdev_lock);
priv->event_wq = alloc_workqueue("icnss_driver_event", WQ_UNBOUND, 1);
if (!priv->event_wq) {
@ -3121,6 +3155,8 @@ static int icnss_probe(struct platform_device *pdev)
icnss_pr_err("ICNSS genl init failed %d\n", ret);
}
INIT_LIST_HEAD(&priv->icnss_tcdev_list);
icnss_pr_info("Platform driver probed successfully\n");
return 0;

View File

@ -18,7 +18,7 @@
#define WCN6750_DEVICE_ID 0x6750
#define ADRASTEA_DEVICE_ID 0xabcd
#define QMI_WLFW_MAX_NUM_MEM_SEG 32
#define THERMAL_NAME_LENGTH 20
extern uint64_t dynamic_feature_mask;
enum icnss_bdf_type {
@ -278,6 +278,15 @@ struct icnss_msi_config {
struct icnss_msi_user *users;
};
struct icnss_thermal_cdev {
struct list_head tcdev_list;
int tcdev_id;
unsigned long curr_thermal_state;
unsigned long max_thermal_state;
struct device_node *dev_node;
struct thermal_cooling_device *tcdev;
};
struct icnss_priv {
uint32_t magic;
struct platform_device *pdev;
@ -363,13 +372,12 @@ struct icnss_priv {
void *get_info_cb_ctx;
int (*get_info_cb)(void *ctx, void *event, int event_len);
atomic_t soc_wake_ref_count;
struct thermal_cooling_device *tcdev;
unsigned long curr_thermal_state;
unsigned long max_thermal_state;
phys_addr_t hang_event_data_pa;
void __iomem *hang_event_data_va;
uint16_t hang_event_data_len;
void *hang_event_data;
struct list_head icnss_tcdev_list;
struct mutex tcdev_lock;
};
struct icnss_reg_info {

View File

@ -52,7 +52,9 @@ struct icnss_driver_ops {
int (*uevent)(struct device *dev, struct icnss_uevent_data *uevent);
int (*idle_shutdown)(struct device *dev);
int (*idle_restart)(struct device *dev);
int (*set_therm_state)(struct device *dev, unsigned long thermal_state);
int (*set_therm_cdev_state)(struct device *dev,
unsigned long thermal_state,
int tcdev_id);
};
@ -179,8 +181,11 @@ extern int icnss_qmi_send(struct device *dev, int type, void *cmd,
extern int icnss_force_wake_request(struct device *dev);
extern int icnss_force_wake_release(struct device *dev);
extern int icnss_is_device_awake(struct device *dev);
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);
extern int icnss_thermal_cdev_register(struct device *dev,
unsigned long max_state,
int tcdev_id);
extern void icnss_thermal_cdev_unregister(struct device *dev, int tcdev_id);
extern int icnss_get_curr_therm_cdev_state(struct device *dev,
unsigned long *thermal_state,
int tcdev_id);
#endif /* _ICNSS_WLAN_H_ */