Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756333AbcKBRHB (ORCPT ); Wed, 2 Nov 2016 13:07:01 -0400 Received: from mail-qt0-f178.google.com ([209.85.216.178]:32825 "EHLO mail-qt0-f178.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755593AbcKBRHA (ORCPT ); Wed, 2 Nov 2016 13:07:00 -0400 MIME-Version: 1.0 In-Reply-To: <1478027672-4857-2-git-send-email-atull@opensource.altera.com> References: <1478027672-4857-1-git-send-email-atull@opensource.altera.com> <1478027672-4857-2-git-send-email-atull@opensource.altera.com> From: Moritz Fischer Date: Wed, 2 Nov 2016 11:06:58 -0600 Message-ID: Subject: Re: [[PATCH repost v21] 01/11] of/overlay: add of overlay notifications To: Alan Tull Cc: Greg Kroah-Hartman , Rob Herring , Linux Kernel Mailing List , Dinh Nguyen , Alan Tull Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5728 Lines: 177 On Tue, Nov 1, 2016 at 1:14 PM, Alan Tull wrote: > This patch add of overlay notifications. > > When DT overlays are being added, some drivers/subsystems > need to see device tree overlays before the changes go into > the live tree. > > This is distinct from reconfig notifiers that are > post-apply or post-remove and which issue very granular > notifications without providing access to the context > of a whole overlay. > > The following 4 notificatons are issued: > OF_OVERLAY_PRE_APPLY > OF_OVERLAY_POST_APPLY > OF_OVERLAY_PRE_REMOVE > OF_OVERLAY_POST_REMOVE > > In the case of pre-apply notification, if the notifier > returns error, the overlay will be rejected. > > This patch exports two functions for registering/unregistering > notifications: > of_overlay_notifier_register(struct notifier_block *nb) > of_overlay_notifier_unregister(struct notifier_block *nb) > > The of_mutex is held during these notifications. The > notification data includes pointers to the overlay target > and the overlay: > > struct of_overlay_notify_data { > struct device_node *overlay; > struct device_node *target; > }; > > Signed-off-by: Alan Tull > Acked-by: Rob Herring Acked-by: Moritz Fischer > --- > drivers/of/overlay.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- > include/linux/of.h | 25 +++++++++++++++++++++++++ > 2 files changed, 71 insertions(+), 1 deletion(-) > > diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c > index 318dbb5..0d4cda7 100644 > --- a/drivers/of/overlay.c > +++ b/drivers/of/overlay.c > @@ -58,6 +58,41 @@ struct of_overlay { > static int of_overlay_apply_one(struct of_overlay *ov, > struct device_node *target, const struct device_node *overlay); > > +static BLOCKING_NOTIFIER_HEAD(of_overlay_chain); > + > +int of_overlay_notifier_register(struct notifier_block *nb) > +{ > + return blocking_notifier_chain_register(&of_overlay_chain, nb); > +} > +EXPORT_SYMBOL_GPL(of_overlay_notifier_register); > + > +int of_overlay_notifier_unregister(struct notifier_block *nb) > +{ > + return blocking_notifier_chain_unregister(&of_overlay_chain, nb); > +} > +EXPORT_SYMBOL_GPL(of_overlay_notifier_unregister); > + > +static int of_overlay_notify(struct of_overlay *ov, > + enum of_overlay_notify_action action) > +{ > + struct of_overlay_notify_data nd; > + int i, ret; > + > + for (i = 0; i < ov->count; i++) { > + struct of_overlay_info *ovinfo = &ov->ovinfo_tab[i]; > + > + nd.target = ovinfo->target; > + nd.overlay = ovinfo->overlay; > + > + ret = blocking_notifier_call_chain(&of_overlay_chain, > + action, &nd); > + if (ret) > + return notifier_to_errno(ret); > + } > + > + return 0; > +} > + > static int of_overlay_apply_single_property(struct of_overlay *ov, > struct device_node *target, struct property *prop) > { > @@ -368,6 +403,13 @@ int of_overlay_create(struct device_node *tree) > goto err_free_idr; > } > > + err = of_overlay_notify(ov, OF_OVERLAY_PRE_APPLY); > + if (err < 0) { > + pr_err("%s: Pre-apply notifier failed (err=%d)\n", > + __func__, err); > + goto err_free_idr; > + } > + > /* apply the overlay */ > err = of_overlay_apply(ov); > if (err) > @@ -382,6 +424,8 @@ int of_overlay_create(struct device_node *tree) > /* add to the tail of the overlay list */ > list_add_tail(&ov->node, &ov_list); > > + of_overlay_notify(ov, OF_OVERLAY_POST_APPLY); > + > mutex_unlock(&of_mutex); > > return id; > @@ -498,9 +542,10 @@ int of_overlay_destroy(int id) > goto out; > } > > - > + of_overlay_notify(ov, OF_OVERLAY_PRE_REMOVE); > list_del(&ov->node); > __of_changeset_revert(&ov->cset); > + of_overlay_notify(ov, OF_OVERLAY_POST_REMOVE); > of_free_overlay_info(ov); > idr_remove(&ov_idr, id); > of_changeset_destroy(&ov->cset); > diff --git a/include/linux/of.h b/include/linux/of.h > index 299aeb1..d72f010 100644 > --- a/include/linux/of.h > +++ b/include/linux/of.h > @@ -1266,6 +1266,18 @@ static inline bool of_device_is_system_power_controller(const struct device_node > * Overlay support > */ > > +enum of_overlay_notify_action { > + OF_OVERLAY_PRE_APPLY, > + OF_OVERLAY_POST_APPLY, > + OF_OVERLAY_PRE_REMOVE, > + OF_OVERLAY_POST_REMOVE, > +}; > + > +struct of_overlay_notify_data { > + struct device_node *overlay; > + struct device_node *target; > +}; > + > #ifdef CONFIG_OF_OVERLAY > > /* ID based overlays; the API for external users */ > @@ -1273,6 +1285,9 @@ static inline bool of_device_is_system_power_controller(const struct device_node > int of_overlay_destroy(int id); > int of_overlay_destroy_all(void); > > +int of_overlay_notifier_register(struct notifier_block *nb); > +int of_overlay_notifier_unregister(struct notifier_block *nb); > + > #else > > static inline int of_overlay_create(struct device_node *tree) > @@ -1290,6 +1305,16 @@ static inline int of_overlay_destroy_all(void) > return -ENOTSUPP; > } > > +static inline int of_overlay_notifier_register(struct notifier_block *nb) > +{ > + return 0; > +} > + > +static inline int of_overlay_notifier_unregister(struct notifier_block *nb) > +{ > + return 0; > +} > + > #endif > > #endif /* _LINUX_OF_H */ > -- > 1.9.1 >