[PATCH 07/10] opp: Add OPP sharing information to OPP library
Stephen Boyd
sboyd at codeaurora.org
Fri Jul 17 15:51:09 PDT 2015
On 06/15/2015 04:57 AM, Viresh Kumar wrote:
> @@ -112,12 +129,14 @@ struct dev_pm_opp {
> struct device_opp {
> struct list_head node;
>
> - struct device *dev;
> struct srcu_notifier_head srcu_head;
> struct rcu_head rcu_head;
> + struct list_head dev_list;
> struct list_head opp_list;
>
> + struct device_node *np;
> unsigned long clock_latency_ns_max;
> + bool shared_opp;
> };
>
> /*
> @@ -137,6 +156,40 @@ do { \
> "dev_opp_list_lock protection"); \
> } while (0)
>
> +static struct device_list_opp *_find_list_dev(struct device *dev,
const device?
> + struct device_opp *dev_opp)
> +{
> + struct device_list_opp *list_dev;
> +
> + list_for_each_entry(list_dev, &dev_opp->dev_list, node)
> + if (list_dev->dev == dev)
> + return list_dev;
> +
> + return NULL;
> +}
> +
> +static struct device_opp *_managed_opp(struct device_node *np)
const device_node?
> +{
> + struct device_opp *dev_opp;
> +
> + list_for_each_entry_rcu(dev_opp, &dev_opp_list, node)
> + if (dev_opp->np == np) {
> + /*
> + * Multiple devices can point to the same OPP table and
> + * so will have same node-pointer, np.
> + *
> + * But the OPPs will be considered as shared only if the
> + * OPP table contains a "opp-shared" property.
> + */
> + if (dev_opp->shared_opp)
> + return dev_opp;
> + else
> + return NULL;
> + }
> +
> + return NULL;
> +}
> +
> /**
> * _find_device_opp() - find device_opp struct using device pointer
> * @dev: device pointer used to lookup device OPPs
> @@ -454,6 +504,39 @@ struct dev_pm_opp *dev_pm_opp_find_freq_floor(struct device *dev,
> }
> EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
>
> +/* List-dev Helpers */
> +static void _kfree_list_dev_rcu(struct rcu_head *head)
> +{
> + struct device_list_opp *list_dev;
> +
> + list_dev = container_of(head, struct device_list_opp, rcu_head);
> + kfree_rcu(list_dev, rcu_head);
> +}
> +
> +static void _remove_list_dev(struct device_list_opp *list_dev,
> + struct device_opp *dev_opp)
> +{
> + list_del(&list_dev->node);
> + call_srcu(&dev_opp->srcu_head.srcu, &list_dev->rcu_head,
> + _kfree_list_dev_rcu);
> +}
> +
> +static struct device_list_opp *_add_list_dev(struct device *dev,
Can dev be const here too?
> + struct device_opp *dev_opp)
> +{
> + struct device_list_opp *list_dev;
> +
> + list_dev = kzalloc(sizeof(*list_dev), GFP_KERNEL);
> + if (!list_dev)
> + return NULL;
> +
> + /* Initialize list-dev */
> + list_add_rcu(&list_dev->node, &dev_opp->dev_list);
> + list_dev->dev = dev;
> +
> + return list_dev;
> +}
> +
> /**
> * _add_device_opp() - Returns device OPP table
> * @dev: device for which we do this operation
> @@ -466,6 +549,7 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_find_freq_floor);
> static struct device_opp *_add_device_opp(struct device *dev)
> {
> struct device_opp *dev_opp;
> + struct device_list_opp *list_dev;
>
> /* Check for existing list for 'dev' first */
> dev_opp = _find_device_opp(dev);
> @@ -621,7 +722,8 @@ static struct dev_pm_opp *_allocate_opp(struct device *dev,
> return opp;
> }
>
> -static int _opp_add(struct dev_pm_opp *new_opp, struct device_opp *dev_opp)
> +static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
> + struct device_opp *dev_opp)
> {
> struct dev_pm_opp *opp = NULL;
> struct list_head *head = &dev_opp->opp_list;
>
>
>
> @@ -1100,8 +1217,19 @@ static int _of_init_opp_table_v2(struct device *dev,
> if (WARN_ON(!count))
> goto put_opp_np;
>
> - if (ret)
> + if (!ret) {
> + if (!dev_opp) {
> + dev_opp = _find_device_opp(dev);
> + if (WARN_ON(!dev_opp))
> + goto put_opp_np;
> + }
> +
> + dev_opp->np = opp_np;
> + if (of_get_property(opp_np, "opp-shared", NULL))
dev_opp->shared_opp = of_property_read_bool(opp_np, "opp-shared")?
> + dev_opp->shared_opp = true;
> + } else {
> of_free_opp_table(dev);
> + }
>
> put_opp_np:
> of_node_put(opp_np);
--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
More information about the linux-arm-kernel
mailing list