Merge "icnss: Add support of suspend_noirq/resume_noirq"
This commit is contained in:
commit
b7bf6d2b63
2 changed files with 160 additions and 0 deletions
|
@ -49,6 +49,7 @@
|
|||
#define MAX_PROP_SIZE 32
|
||||
#define NUM_LOG_PAGES 10
|
||||
#define NUM_REG_LOG_PAGES 4
|
||||
#define ICNSS_MAGIC 0x5abc5abc
|
||||
|
||||
/*
|
||||
* Registers: MPM2_PSHOLD
|
||||
|
@ -269,6 +270,8 @@ enum icnss_driver_state {
|
|||
ICNSS_DRIVER_PROBED,
|
||||
ICNSS_FW_TEST_MODE,
|
||||
ICNSS_SUSPEND,
|
||||
ICNSS_PM_SUSPEND,
|
||||
ICNSS_PM_SUSPEND_NOIRQ,
|
||||
ICNSS_SSR_ENABLED,
|
||||
ICNSS_PDR_ENABLED,
|
||||
ICNSS_PD_RESTART,
|
||||
|
@ -324,6 +327,15 @@ struct icnss_stats {
|
|||
uint32_t disable;
|
||||
} ce_irqs[ICNSS_MAX_IRQ_REGISTRATIONS];
|
||||
|
||||
uint32_t pm_suspend;
|
||||
uint32_t pm_suspend_err;
|
||||
uint32_t pm_resume;
|
||||
uint32_t pm_resume_err;
|
||||
uint32_t pm_suspend_noirq;
|
||||
uint32_t pm_suspend_noirq_err;
|
||||
uint32_t pm_resume_noirq;
|
||||
uint32_t pm_resume_noirq_err;
|
||||
|
||||
uint32_t ind_register_req;
|
||||
uint32_t ind_register_resp;
|
||||
uint32_t ind_register_err;
|
||||
|
@ -350,6 +362,7 @@ struct icnss_stats {
|
|||
};
|
||||
|
||||
static struct icnss_priv {
|
||||
uint32_t magic;
|
||||
struct platform_device *pdev;
|
||||
struct icnss_driver_ops *ops;
|
||||
struct ce_irq_list ce_irq_list[ICNSS_MAX_IRQ_REGISTRATIONS];
|
||||
|
@ -3302,6 +3315,12 @@ static int icnss_stats_show_state(struct seq_file *s, struct icnss_priv *priv)
|
|||
case ICNSS_FW_TEST_MODE:
|
||||
seq_puts(s, "FW TEST MODE");
|
||||
continue;
|
||||
case ICNSS_PM_SUSPEND:
|
||||
seq_puts(s, "PM SUSPEND");
|
||||
continue;
|
||||
case ICNSS_PM_SUSPEND_NOIRQ:
|
||||
seq_puts(s, "PM SUSPEND_NOIRQ");
|
||||
continue;
|
||||
case ICNSS_SSR_ENABLED:
|
||||
seq_puts(s, "SSR ENABLED");
|
||||
continue;
|
||||
|
@ -3402,6 +3421,16 @@ static int icnss_stats_show(struct seq_file *s, void *data)
|
|||
ICNSS_STATS_DUMP(s, priv, ini_resp);
|
||||
ICNSS_STATS_DUMP(s, priv, ini_req_err);
|
||||
|
||||
seq_puts(s, "\n<------------------ PM stats ------------------->\n");
|
||||
ICNSS_STATS_DUMP(s, priv, pm_suspend);
|
||||
ICNSS_STATS_DUMP(s, priv, pm_suspend_err);
|
||||
ICNSS_STATS_DUMP(s, priv, pm_resume);
|
||||
ICNSS_STATS_DUMP(s, priv, pm_resume_err);
|
||||
ICNSS_STATS_DUMP(s, priv, pm_suspend_noirq);
|
||||
ICNSS_STATS_DUMP(s, priv, pm_suspend_noirq_err);
|
||||
ICNSS_STATS_DUMP(s, priv, pm_resume_noirq);
|
||||
ICNSS_STATS_DUMP(s, priv, pm_resume_noirq_err);
|
||||
|
||||
icnss_stats_show_irqs(s, priv);
|
||||
|
||||
icnss_stats_show_capability(s, priv);
|
||||
|
@ -3477,6 +3506,7 @@ static int icnss_probe(struct platform_device *pdev)
|
|||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->magic = ICNSS_MAGIC;
|
||||
dev_set_drvdata(dev, priv);
|
||||
|
||||
priv->pdev = pdev;
|
||||
|
@ -3725,6 +3755,131 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int icnss_pm_suspend(struct device *dev)
|
||||
{
|
||||
struct icnss_priv *priv = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (priv->magic != ICNSS_MAGIC) {
|
||||
icnss_pr_err("Invalid drvdata for pm suspend: dev %p, data %p, magic 0x%x\n",
|
||||
dev, priv, priv->magic);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
icnss_pr_dbg("PM Suspend, state: 0x%lx\n", priv->state);
|
||||
|
||||
if (!priv->ops || !priv->ops->pm_suspend ||
|
||||
!test_bit(ICNSS_DRIVER_PROBED, &priv->state))
|
||||
goto out;
|
||||
|
||||
ret = priv->ops->pm_suspend(dev);
|
||||
|
||||
out:
|
||||
if (ret == 0) {
|
||||
priv->stats.pm_suspend++;
|
||||
set_bit(ICNSS_PM_SUSPEND, &priv->state);
|
||||
} else {
|
||||
priv->stats.pm_suspend_err++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int icnss_pm_resume(struct device *dev)
|
||||
{
|
||||
struct icnss_priv *priv = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (priv->magic != ICNSS_MAGIC) {
|
||||
icnss_pr_err("Invalid drvdata for pm resume: dev %p, data %p, magic 0x%x\n",
|
||||
dev, priv, priv->magic);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
icnss_pr_dbg("PM resume, state: 0x%lx\n", priv->state);
|
||||
|
||||
if (!priv->ops || !priv->ops->pm_resume ||
|
||||
!test_bit(ICNSS_DRIVER_PROBED, &priv->state))
|
||||
goto out;
|
||||
|
||||
ret = priv->ops->pm_resume(dev);
|
||||
|
||||
out:
|
||||
if (ret == 0) {
|
||||
priv->stats.pm_resume++;
|
||||
clear_bit(ICNSS_PM_SUSPEND, &priv->state);
|
||||
} else {
|
||||
priv->stats.pm_resume_err++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int icnss_pm_suspend_noirq(struct device *dev)
|
||||
{
|
||||
struct icnss_priv *priv = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (priv->magic != ICNSS_MAGIC) {
|
||||
icnss_pr_err("Invalid drvdata for pm suspend_noirq: dev %p, data %p, magic 0x%x\n",
|
||||
dev, priv, priv->magic);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
icnss_pr_dbg("PM suspend_noirq, state: 0x%lx\n", priv->state);
|
||||
|
||||
if (!priv->ops || !priv->ops->suspend_noirq ||
|
||||
!test_bit(ICNSS_DRIVER_PROBED, &priv->state))
|
||||
goto out;
|
||||
|
||||
ret = priv->ops->suspend_noirq(dev);
|
||||
|
||||
out:
|
||||
if (ret == 0) {
|
||||
priv->stats.pm_suspend_noirq++;
|
||||
set_bit(ICNSS_PM_SUSPEND_NOIRQ, &priv->state);
|
||||
} else {
|
||||
priv->stats.pm_suspend_noirq_err++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int icnss_pm_resume_noirq(struct device *dev)
|
||||
{
|
||||
struct icnss_priv *priv = dev_get_drvdata(dev);
|
||||
int ret = 0;
|
||||
|
||||
if (priv->magic != ICNSS_MAGIC) {
|
||||
icnss_pr_err("Invalid drvdata for pm resume_noirq: dev %p, data %p, magic 0x%x\n",
|
||||
dev, priv, priv->magic);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
icnss_pr_dbg("PM resume_noirq, state: 0x%lx\n", priv->state);
|
||||
|
||||
if (!priv->ops || !priv->ops->resume_noirq ||
|
||||
!test_bit(ICNSS_DRIVER_PROBED, &priv->state))
|
||||
goto out;
|
||||
|
||||
ret = priv->ops->resume_noirq(dev);
|
||||
|
||||
out:
|
||||
if (ret == 0) {
|
||||
priv->stats.pm_resume_noirq++;
|
||||
clear_bit(ICNSS_PM_SUSPEND_NOIRQ, &priv->state);
|
||||
} else {
|
||||
priv->stats.pm_resume_noirq_err++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct dev_pm_ops icnss_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(icnss_pm_suspend,
|
||||
icnss_pm_resume)
|
||||
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(icnss_pm_suspend_noirq,
|
||||
icnss_pm_resume_noirq)
|
||||
};
|
||||
|
||||
static const struct of_device_id icnss_dt_match[] = {
|
||||
{.compatible = "qcom,icnss"},
|
||||
{}
|
||||
|
@ -3739,6 +3894,7 @@ static struct platform_driver icnss_driver = {
|
|||
.resume = icnss_resume,
|
||||
.driver = {
|
||||
.name = "icnss",
|
||||
.pm = &icnss_pm_ops,
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = icnss_dt_match,
|
||||
},
|
||||
|
|
|
@ -26,6 +26,10 @@ struct icnss_driver_ops {
|
|||
void (*crash_shutdown)(void *pdev);
|
||||
int (*suspend)(struct device *dev, pm_message_t state);
|
||||
int (*resume)(struct device *dev);
|
||||
int (*pm_suspend)(struct device *dev);
|
||||
int (*pm_resume)(struct device *dev);
|
||||
int (*suspend_noirq)(struct device *dev);
|
||||
int (*resume_noirq)(struct device *dev);
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue