diff options
Diffstat (limited to 'drivers/soc')
-rw-r--r-- | drivers/soc/bcm/raspberrypi-power.c | 2 | ||||
-rw-r--r-- | drivers/soc/samsung/pm_domains.c | 90 | ||||
-rw-r--r-- | drivers/soc/ti/knav_qmss.h | 14 | ||||
-rw-r--r-- | drivers/soc/ti/knav_qmss_queue.c | 60 |
4 files changed, 50 insertions, 116 deletions
diff --git a/drivers/soc/bcm/raspberrypi-power.c b/drivers/soc/bcm/raspberrypi-power.c index fe96a8b956fb..f7ed1187518b 100644 --- a/drivers/soc/bcm/raspberrypi-power.c +++ b/drivers/soc/bcm/raspberrypi-power.c @@ -45,7 +45,7 @@ struct rpi_power_domains { struct rpi_power_domain_packet { u32 domain; u32 on; -} __packet; +}; /* * Asks the firmware to enable or disable power on a specific power diff --git a/drivers/soc/samsung/pm_domains.c b/drivers/soc/samsung/pm_domains.c index caf45cf7aa8e..ab8582971bfc 100644 --- a/drivers/soc/samsung/pm_domains.c +++ b/drivers/soc/samsung/pm_domains.c @@ -13,14 +13,11 @@ #include <linux/err.h> #include <linux/slab.h> #include <linux/pm_domain.h> -#include <linux/clk.h> #include <linux/delay.h> #include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/sched.h> -#define MAX_CLK_PER_DOMAIN 4 - struct exynos_pm_domain_config { /* Value for LOCAL_PWR_CFG and STATUS fields for each domain */ u32 local_pwr_cfg; @@ -33,10 +30,6 @@ struct exynos_pm_domain { void __iomem *base; bool is_off; struct generic_pm_domain pd; - struct clk *oscclk; - struct clk *clk[MAX_CLK_PER_DOMAIN]; - struct clk *pclk[MAX_CLK_PER_DOMAIN]; - struct clk *asb_clk[MAX_CLK_PER_DOMAIN]; u32 local_pwr_cfg; }; @@ -46,29 +39,10 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) void __iomem *base; u32 timeout, pwr; char *op; - int i; pd = container_of(domain, struct exynos_pm_domain, pd); base = pd->base; - for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) { - if (IS_ERR(pd->asb_clk[i])) - break; - clk_prepare_enable(pd->asb_clk[i]); - } - - /* Set oscclk before powering off a domain*/ - if (!power_on) { - for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) { - if (IS_ERR(pd->clk[i])) - break; - pd->pclk[i] = clk_get_parent(pd->clk[i]); - if (clk_set_parent(pd->clk[i], pd->oscclk)) - pr_err("%s: error setting oscclk as parent to clock %d\n", - domain->name, i); - } - } - pwr = power_on ? pd->local_pwr_cfg : 0; writel_relaxed(pwr, base); @@ -86,26 +60,6 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) usleep_range(80, 100); } - /* Restore clocks after powering on a domain*/ - if (power_on) { - for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) { - if (IS_ERR(pd->clk[i])) - break; - - if (IS_ERR(pd->pclk[i])) - continue; /* Skip on first power up */ - if (clk_set_parent(pd->clk[i], pd->pclk[i])) - pr_err("%s: error setting parent to clock%d\n", - domain->name, i); - } - } - - for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) { - if (IS_ERR(pd->asb_clk[i])) - break; - clk_disable_unprepare(pd->asb_clk[i]); - } - return 0; } @@ -147,12 +101,6 @@ static __init const char *exynos_get_domain_name(struct device_node *node) return kstrdup_const(name, GFP_KERNEL); } -static const char *soc_force_no_clk[] = { - "samsung,exynos5250-clock", - "samsung,exynos5420-clock", - "samsung,exynos5800-clock", -}; - static __init int exynos4_pm_init_power_domain(void) { struct device_node *np; @@ -161,7 +109,7 @@ static __init int exynos4_pm_init_power_domain(void) for_each_matching_node_and_match(np, exynos_pm_domain_of_match, &match) { const struct exynos_pm_domain_config *pm_domain_cfg; struct exynos_pm_domain *pd; - int on, i; + int on; pm_domain_cfg = match->data; @@ -189,42 +137,6 @@ static __init int exynos4_pm_init_power_domain(void) pd->pd.power_on = exynos_pd_power_on; pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg; - for (i = 0; i < ARRAY_SIZE(soc_force_no_clk); i++) - if (of_find_compatible_node(NULL, NULL, - soc_force_no_clk[i])) - goto no_clk; - - for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) { - char clk_name[8]; - - snprintf(clk_name, sizeof(clk_name), "asb%d", i); - pd->asb_clk[i] = of_clk_get_by_name(np, clk_name); - if (IS_ERR(pd->asb_clk[i])) - break; - } - - pd->oscclk = of_clk_get_by_name(np, "oscclk"); - if (IS_ERR(pd->oscclk)) - goto no_clk; - - for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) { - char clk_name[8]; - - snprintf(clk_name, sizeof(clk_name), "clk%d", i); - pd->clk[i] = of_clk_get_by_name(np, clk_name); - if (IS_ERR(pd->clk[i])) - break; - /* - * Skip setting parent on first power up. - * The parent at this time may not be useful at all. - */ - pd->pclk[i] = ERR_PTR(-EINVAL); - } - - if (IS_ERR(pd->clk[0])) - clk_put(pd->oscclk); - -no_clk: on = readl_relaxed(pd->base + 0x4) & pd->local_pwr_cfg; pm_genpd_init(&pd->pd, NULL, !on); diff --git a/drivers/soc/ti/knav_qmss.h b/drivers/soc/ti/knav_qmss.h index 905b974d1bdc..22f409b86107 100644 --- a/drivers/soc/ti/knav_qmss.h +++ b/drivers/soc/ti/knav_qmss.h @@ -19,6 +19,8 @@ #ifndef __KNAV_QMSS_H__ #define __KNAV_QMSS_H__ +#include <linux/percpu.h> + #define THRESH_GTE BIT(7) #define THRESH_LT 0 @@ -162,11 +164,11 @@ struct knav_qmgr_info { * notifies: notifier counts */ struct knav_queue_stats { - atomic_t pushes; - atomic_t pops; - atomic_t push_errors; - atomic_t pop_errors; - atomic_t notifies; + unsigned int pushes; + unsigned int pops; + unsigned int push_errors; + unsigned int pop_errors; + unsigned int notifies; }; /** @@ -283,7 +285,7 @@ struct knav_queue_inst { struct knav_queue { struct knav_reg_queue __iomem *reg_push, *reg_pop, *reg_peek; struct knav_queue_inst *inst; - struct knav_queue_stats stats; + struct knav_queue_stats __percpu *stats; knav_queue_notify_fn notifier_fn; void *notifier_fn_arg; atomic_t notifier_enabled; diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c index 77d6b5c03aae..384d70bd8605 100644 --- a/drivers/soc/ti/knav_qmss_queue.c +++ b/drivers/soc/ti/knav_qmss_queue.c @@ -83,7 +83,7 @@ void knav_queue_notify(struct knav_queue_inst *inst) continue; if (WARN_ON(!qh->notifier_fn)) continue; - atomic_inc(&qh->stats.notifies); + this_cpu_inc(qh->stats->notifies); qh->notifier_fn(qh->notifier_fn_arg); } rcu_read_unlock(); @@ -214,6 +214,12 @@ static struct knav_queue *__knav_queue_open(struct knav_queue_inst *inst, if (!qh) return ERR_PTR(-ENOMEM); + qh->stats = alloc_percpu(struct knav_queue_stats); + if (!qh->stats) { + ret = -ENOMEM; + goto err; + } + qh->flags = flags; qh->inst = inst; id = inst->id - inst->qmgr->start_queue; @@ -229,13 +235,17 @@ static struct knav_queue *__knav_queue_open(struct knav_queue_inst *inst, if (range->ops && range->ops->open_queue) ret = range->ops->open_queue(range, inst, flags); - if (ret) { - devm_kfree(inst->kdev->dev, qh); - return ERR_PTR(ret); - } + if (ret) + goto err; } list_add_tail_rcu(&qh->list, &inst->handles); return qh; + +err: + if (qh->stats) + free_percpu(qh->stats); + devm_kfree(inst->kdev->dev, qh); + return ERR_PTR(ret); } static struct knav_queue * @@ -411,6 +421,12 @@ static void knav_queue_debug_show_instance(struct seq_file *s, { struct knav_device *kdev = inst->kdev; struct knav_queue *qh; + int cpu = 0; + int pushes = 0; + int pops = 0; + int push_errors = 0; + int pop_errors = 0; + int notifies = 0; if (!knav_queue_is_busy(inst)) return; @@ -418,19 +434,22 @@ static void knav_queue_debug_show_instance(struct seq_file *s, seq_printf(s, "\tqueue id %d (%s)\n", kdev->base_id + inst->id, inst->name); for_each_handle_rcu(qh, inst) { - seq_printf(s, "\t\thandle %p: ", qh); - seq_printf(s, "pushes %8d, ", - atomic_read(&qh->stats.pushes)); - seq_printf(s, "pops %8d, ", - atomic_read(&qh->stats.pops)); - seq_printf(s, "count %8d, ", - knav_queue_get_count(qh)); - seq_printf(s, "notifies %8d, ", - atomic_read(&qh->stats.notifies)); - seq_printf(s, "push errors %8d, ", - atomic_read(&qh->stats.push_errors)); - seq_printf(s, "pop errors %8d\n", - atomic_read(&qh->stats.pop_errors)); + for_each_possible_cpu(cpu) { + pushes += per_cpu_ptr(qh->stats, cpu)->pushes; + pops += per_cpu_ptr(qh->stats, cpu)->pops; + push_errors += per_cpu_ptr(qh->stats, cpu)->push_errors; + pop_errors += per_cpu_ptr(qh->stats, cpu)->pop_errors; + notifies += per_cpu_ptr(qh->stats, cpu)->notifies; + } + + seq_printf(s, "\t\thandle %p: pushes %8d, pops %8d, count %8d, notifies %8d, push errors %8d, pop errors %8d\n", + qh, + pushes, + pops, + knav_queue_get_count(qh), + notifies, + push_errors, + pop_errors); } } @@ -547,6 +566,7 @@ void knav_queue_close(void *qhandle) if (range->ops && range->ops->close_queue) range->ops->close_queue(range, inst); } + free_percpu(qh->stats); devm_kfree(inst->kdev->dev, qh); } EXPORT_SYMBOL_GPL(knav_queue_close); @@ -620,7 +640,7 @@ int knav_queue_push(void *qhandle, dma_addr_t dma, val = (u32)dma | ((size / 16) - 1); writel_relaxed(val, &qh->reg_push[0].ptr_size_thresh); - atomic_inc(&qh->stats.pushes); + this_cpu_inc(qh->stats->pushes); return 0; } EXPORT_SYMBOL_GPL(knav_queue_push); @@ -658,7 +678,7 @@ dma_addr_t knav_queue_pop(void *qhandle, unsigned *size) if (size) *size = ((val & DESC_SIZE_MASK) + 1) * 16; - atomic_inc(&qh->stats.pops); + this_cpu_inc(qh->stats->pops); return dma; } EXPORT_SYMBOL_GPL(knav_queue_pop); |