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 MAX_PROP_SIZE 32
|
||||||
#define NUM_LOG_PAGES 10
|
#define NUM_LOG_PAGES 10
|
||||||
#define NUM_REG_LOG_PAGES 4
|
#define NUM_REG_LOG_PAGES 4
|
||||||
|
#define ICNSS_MAGIC 0x5abc5abc
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Registers: MPM2_PSHOLD
|
* Registers: MPM2_PSHOLD
|
||||||
|
@ -269,6 +270,8 @@ enum icnss_driver_state {
|
||||||
ICNSS_DRIVER_PROBED,
|
ICNSS_DRIVER_PROBED,
|
||||||
ICNSS_FW_TEST_MODE,
|
ICNSS_FW_TEST_MODE,
|
||||||
ICNSS_SUSPEND,
|
ICNSS_SUSPEND,
|
||||||
|
ICNSS_PM_SUSPEND,
|
||||||
|
ICNSS_PM_SUSPEND_NOIRQ,
|
||||||
ICNSS_SSR_ENABLED,
|
ICNSS_SSR_ENABLED,
|
||||||
ICNSS_PDR_ENABLED,
|
ICNSS_PDR_ENABLED,
|
||||||
ICNSS_PD_RESTART,
|
ICNSS_PD_RESTART,
|
||||||
|
@ -324,6 +327,15 @@ struct icnss_stats {
|
||||||
uint32_t disable;
|
uint32_t disable;
|
||||||
} ce_irqs[ICNSS_MAX_IRQ_REGISTRATIONS];
|
} 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_req;
|
||||||
uint32_t ind_register_resp;
|
uint32_t ind_register_resp;
|
||||||
uint32_t ind_register_err;
|
uint32_t ind_register_err;
|
||||||
|
@ -350,6 +362,7 @@ struct icnss_stats {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct icnss_priv {
|
static struct icnss_priv {
|
||||||
|
uint32_t magic;
|
||||||
struct platform_device *pdev;
|
struct platform_device *pdev;
|
||||||
struct icnss_driver_ops *ops;
|
struct icnss_driver_ops *ops;
|
||||||
struct ce_irq_list ce_irq_list[ICNSS_MAX_IRQ_REGISTRATIONS];
|
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:
|
case ICNSS_FW_TEST_MODE:
|
||||||
seq_puts(s, "FW TEST MODE");
|
seq_puts(s, "FW TEST MODE");
|
||||||
continue;
|
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:
|
case ICNSS_SSR_ENABLED:
|
||||||
seq_puts(s, "SSR ENABLED");
|
seq_puts(s, "SSR ENABLED");
|
||||||
continue;
|
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_resp);
|
||||||
ICNSS_STATS_DUMP(s, priv, ini_req_err);
|
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_irqs(s, priv);
|
||||||
|
|
||||||
icnss_stats_show_capability(s, priv);
|
icnss_stats_show_capability(s, priv);
|
||||||
|
@ -3477,6 +3506,7 @@ static int icnss_probe(struct platform_device *pdev)
|
||||||
if (!priv)
|
if (!priv)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
priv->magic = ICNSS_MAGIC;
|
||||||
dev_set_drvdata(dev, priv);
|
dev_set_drvdata(dev, priv);
|
||||||
|
|
||||||
priv->pdev = pdev;
|
priv->pdev = pdev;
|
||||||
|
@ -3725,6 +3755,131 @@ out:
|
||||||
return ret;
|
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[] = {
|
static const struct of_device_id icnss_dt_match[] = {
|
||||||
{.compatible = "qcom,icnss"},
|
{.compatible = "qcom,icnss"},
|
||||||
{}
|
{}
|
||||||
|
@ -3739,6 +3894,7 @@ static struct platform_driver icnss_driver = {
|
||||||
.resume = icnss_resume,
|
.resume = icnss_resume,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "icnss",
|
.name = "icnss",
|
||||||
|
.pm = &icnss_pm_ops,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.of_match_table = icnss_dt_match,
|
.of_match_table = icnss_dt_match,
|
||||||
},
|
},
|
||||||
|
|
|
@ -26,6 +26,10 @@ struct icnss_driver_ops {
|
||||||
void (*crash_shutdown)(void *pdev);
|
void (*crash_shutdown)(void *pdev);
|
||||||
int (*suspend)(struct device *dev, pm_message_t state);
|
int (*suspend)(struct device *dev, pm_message_t state);
|
||||||
int (*resume)(struct device *dev);
|
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