Message ID | 20170404144309.31357-1-lee.jones@linaro.org (mailing list archive) |
---|---|
State | Rejected, archived |
Delegated to: | Hans Verkuil |
Headers |
Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.84_2) (envelope-from <linux-media-owner@vger.kernel.org>) id 1cvPgb-0000zD-QN; Tue, 04 Apr 2017 14:43:57 +0000 X-tubIT-Incoming-IP: 209.132.180.67 Received: from vger.kernel.org ([209.132.180.67]) by mail.tu-berlin.de (exim-4.84_2/mailfrontend-7) with esmtp id 1cvPgZ-0001Rx-2D; Tue, 04 Apr 2017 16:43:57 +0200 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753344AbdDDOnU (ORCPT <rfc822;mkrufky@linuxtv.org> + 1 other); Tue, 4 Apr 2017 10:43:20 -0400 Received: from mail-wm0-f42.google.com ([74.125.82.42]:37650 "EHLO mail-wm0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752935AbdDDOnT (ORCPT <rfc822; linux-media@vger.kernel.org>); Tue, 4 Apr 2017 10:43:19 -0400 Received: by mail-wm0-f42.google.com with SMTP id x124so30076403wmf.0 for <linux-media@vger.kernel.org>; Tue, 04 Apr 2017 07:43:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=zKoKQs+CJdDJ56k6UiAV7sQ+Re4BpS9+cOFzhuD0TcM=; b=LqNuplcGtlZL4EnH1Wvm/zJwySdh0YWfcuagjOa3bVYTlrT26ksBvb9yxD0ih9piQw F5KZ7K6A0lQvDZNSU8JWE0LbjeaePBk4lwt1Zkzps/aOsTwaMR1knXOoVmoRfr5ZOZMS oHJk9/2kdxsQwPJ4RvGK4uFOEcmWRDD/H0cAU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=zKoKQs+CJdDJ56k6UiAV7sQ+Re4BpS9+cOFzhuD0TcM=; b=Lp4AHdfnN3ZcFjDQI4pgLthgDmf0aswUw+GGoUTmEOKCKvL6hw6TtvEJtNXF77SuF2 JfZFVikNpFjYx/epTRO8CnbJMfy+voVU5eH1ymzddg/MQqpm1d1RH6TEPZHH71PQ3QhX F7zwHkyEHhfbNMBFNP5UJpqjuRj3m/wz3HgS0Rc8ga0RYgHStuzX6/Z6A6rG3DxvTplz oYV7TyI1SM9VOL/2IAHH6RzsWt66u0lxFL6LvzDaodn3ZahIQ36YL2iJVS/xhol1fQ1K HozwMHxwqpu9CPY5hOMntKTxkZnzqSz3p414GNzr0EOCmMqwIG9wmkucapv4zWggk3AF PW/w== X-Gm-Message-State: AFeK/H2Y/WrI6TLJTWNHBXiyQ5+vV9wzcbFWkyqUqM/ltGaUfjzPtslB LMihXM7THCD+S6nD X-Received: by 10.28.72.7 with SMTP id v7mr14001835wma.42.1491316998129; Tue, 04 Apr 2017 07:43:18 -0700 (PDT) Received: from localhost.localdomain ([2.31.167.174]) by smtp.gmail.com with ESMTPSA id d4sm3056816wrb.24.2017.04.04.07.43.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Apr 2017 07:43:16 -0700 (PDT) From: Lee Jones <lee.jones@linaro.org> To: hans.verkuil@cisco.com, mchehab@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, kernel@stlinux.com, patrice.chotard@st.com, linux-media@vger.kernel.org, benjamin.gaignard@st.com, Lee Jones <lee.jones@linaro.org> Subject: [PATCH] [media] cec: Handle RC capability more elegantly Date: Tue, 4 Apr 2017 15:43:09 +0100 Message-Id: <20170404144309.31357-1-lee.jones@linaro.org> X-Mailer: git-send-email 2.9.3 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: <linux-media.vger.kernel.org> X-Mailing-List: linux-media@vger.kernel.org X-PMX-Version: 6.0.0.2142326, Antispam-Engine: 2.7.2.2107409, Antispam-Data: 2017.4.4.143317 X-PMX-Spam: Gauge=IIIIIIII, Probability=8%, Report=' MULTIPLE_RCPTS 0.1, HTML_00_01 0.05, HTML_00_10 0.05, BODY_SIZE_3000_3999 0, BODY_SIZE_5000_LESS 0, BODY_SIZE_7000_LESS 0, DKIM_SIGNATURE 0, LEGITIMATE_SIGNS 0, MULTIPLE_REAL_RCPTS 0, NO_URI_HTTPS 0, __ANY_URI 0, __CC_NAME 0, __CC_NAME_DIFF_FROM_ACC 0, __CC_REAL_NAMES 0, __FROM_DOMAIN_IN_ANY_CC2 0, __FROM_DOMAIN_IN_RCPT 0, __HAS_CC_HDR 0, __HAS_FROM 0, __HAS_LIST_ID 0, __HAS_MSGID 0, __HAS_X_MAILER 0, __HAS_X_MAILING_LIST 0, __MIME_TEXT_ONLY 0, __MIME_TEXT_P 0, __MIME_TEXT_P1 0, __MULTIPLE_RCPTS_CC_X2 0, __NO_HTML_TAG_RAW 0, __SANE_MSGID 0, __SUBJ_ALPHA_END 0, __TO_MALFORMED_2 0, __TO_NO_NAME 0, __URI_NO_WWW 0, __URI_NS , __YOUTUBE_RCVD 0' |
Commit Message
Lee Jones
April 4, 2017, 2:43 p.m. UTC
If a user specifies the use of RC as a capability, they should
really be enabling RC Core code. If they do not we WARN() them
of this and disable the capability for them.
Once we know RC Core code has not been enabled, we can update
the user's capabilities and use them as a term of reference for
other RC-only calls. This is preferable to having ugly #ifery
scattered throughout C code.
Most of the functions are actually safe to call, since they
sensibly check for a NULL RC pointer before they attempt to
deference it.
Signed-off-by: Lee Jones <lee.jones@linaro.org>
---
drivers/media/cec/cec-core.c | 19 +++++++------------
1 file changed, 7 insertions(+), 12 deletions(-)
Comments
On 04/04/2017 04:43 PM, Lee Jones wrote: > If a user specifies the use of RC as a capability, they should > really be enabling RC Core code. If they do not we WARN() them > of this and disable the capability for them. > > Once we know RC Core code has not been enabled, we can update > the user's capabilities and use them as a term of reference for > other RC-only calls. This is preferable to having ugly #ifery > scattered throughout C code. > > Most of the functions are actually safe to call, since they > sensibly check for a NULL RC pointer before they attempt to > deference it. > > Signed-off-by: Lee Jones <lee.jones@linaro.org> > --- > drivers/media/cec/cec-core.c | 19 +++++++------------ > 1 file changed, 7 insertions(+), 12 deletions(-) > > diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c > index cfe414a..51be8d6 100644 > --- a/drivers/media/cec/cec-core.c > +++ b/drivers/media/cec/cec-core.c > @@ -208,9 +208,13 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, > return ERR_PTR(-EINVAL); > if (WARN_ON(!available_las || available_las > CEC_MAX_LOG_ADDRS)) > return ERR_PTR(-EINVAL); > + if (WARN_ON(caps & CEC_CAP_RC && !IS_REACHABLE(CONFIG_RC_CORE))) > + caps &= ~CEC_CAP_RC; Don't use WARN_ON, this is not an error of any kind. Neither do you need to add the 'caps & CEC_CAP_RC' test. Really, it's just simpler to do what I suggested before with an #if. > + > adap = kzalloc(sizeof(*adap), GFP_KERNEL); > if (!adap) > return ERR_PTR(-ENOMEM); > + > strlcpy(adap->name, name, sizeof(adap->name)); > adap->phys_addr = CEC_PHYS_ADDR_INVALID; > adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0; > @@ -237,7 +241,6 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, > if (!(caps & CEC_CAP_RC)) > return adap; > > -#if IS_REACHABLE(CONFIG_RC_CORE) Huh? If CONFIG_RC_CORE is undefined, all these rc_ calls will fail when linking! Regards, Hans > /* Prepare the RC input device */ > adap->rc = rc_allocate_device(RC_DRIVER_SCANCODE); > if (!adap->rc) { > @@ -264,9 +267,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, > adap->rc->priv = adap; > adap->rc->map_name = RC_MAP_CEC; > adap->rc->timeout = MS_TO_NS(100); > -#else > - adap->capabilities &= ~CEC_CAP_RC; > -#endif > + > return adap; > } > EXPORT_SYMBOL_GPL(cec_allocate_adapter); > @@ -285,7 +286,6 @@ int cec_register_adapter(struct cec_adapter *adap, > adap->owner = parent->driver->owner; > adap->devnode.dev.parent = parent; > > -#if IS_REACHABLE(CONFIG_RC_CORE) > if (adap->capabilities & CEC_CAP_RC) { > adap->rc->dev.parent = parent; > res = rc_register_device(adap->rc); > @@ -298,15 +298,13 @@ int cec_register_adapter(struct cec_adapter *adap, > return res; > } > } > -#endif > > res = cec_devnode_register(&adap->devnode, adap->owner); > if (res) { > -#if IS_REACHABLE(CONFIG_RC_CORE) > /* Note: rc_unregister also calls rc_free */ > rc_unregister_device(adap->rc); > adap->rc = NULL; > -#endif > + > return res; > } > > @@ -337,11 +335,10 @@ void cec_unregister_adapter(struct cec_adapter *adap) > if (IS_ERR_OR_NULL(adap)) > return; > > -#if IS_REACHABLE(CONFIG_RC_CORE) > /* Note: rc_unregister also calls rc_free */ > rc_unregister_device(adap->rc); > adap->rc = NULL; > -#endif > + > debugfs_remove_recursive(adap->cec_dir); > cec_devnode_unregister(&adap->devnode); > } > @@ -357,9 +354,7 @@ void cec_delete_adapter(struct cec_adapter *adap) > kthread_stop(adap->kthread); > if (adap->kthread_config) > kthread_stop(adap->kthread_config); > -#if IS_REACHABLE(CONFIG_RC_CORE) > rc_free_device(adap->rc); > -#endif > kfree(adap); > } > EXPORT_SYMBOL_GPL(cec_delete_adapter); >
On Tue, 04 Apr 2017, Hans Verkuil wrote: > On 04/04/2017 04:43 PM, Lee Jones wrote: > > If a user specifies the use of RC as a capability, they should > > really be enabling RC Core code. If they do not we WARN() them > > of this and disable the capability for them. > > > > Once we know RC Core code has not been enabled, we can update > > the user's capabilities and use them as a term of reference for > > other RC-only calls. This is preferable to having ugly #ifery > > scattered throughout C code. > > > > Most of the functions are actually safe to call, since they > > sensibly check for a NULL RC pointer before they attempt to > > deference it. > > > > Signed-off-by: Lee Jones <lee.jones@linaro.org> > > --- > > drivers/media/cec/cec-core.c | 19 +++++++------------ > > 1 file changed, 7 insertions(+), 12 deletions(-) > > > > diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c > > index cfe414a..51be8d6 100644 > > --- a/drivers/media/cec/cec-core.c > > +++ b/drivers/media/cec/cec-core.c > > @@ -208,9 +208,13 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, > > return ERR_PTR(-EINVAL); > > if (WARN_ON(!available_las || available_las > CEC_MAX_LOG_ADDRS)) > > return ERR_PTR(-EINVAL); > > + if (WARN_ON(caps & CEC_CAP_RC && !IS_REACHABLE(CONFIG_RC_CORE))) > > + caps &= ~CEC_CAP_RC; > > Don't use WARN_ON, this is not an error of any kind. Right, this is not an error. That's why we are warning the user instead of bombing out. > Neither do you need to add the > 'caps & CEC_CAP_RC' test. Really, it's just simpler to do what I suggested before > with an #if. This does exactly what you asked. Just to clarify, can you explain to me when asking for RC support, but not enabling it would ever be a valid configuration? > > + > > adap = kzalloc(sizeof(*adap), GFP_KERNEL); > > if (!adap) > > return ERR_PTR(-ENOMEM); > > + > > strlcpy(adap->name, name, sizeof(adap->name)); > > adap->phys_addr = CEC_PHYS_ADDR_INVALID; > > adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0; > > @@ -237,7 +241,6 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, > > if (!(caps & CEC_CAP_RC)) > > return adap; > > > > -#if IS_REACHABLE(CONFIG_RC_CORE) > > Huh? If CONFIG_RC_CORE is undefined, all these rc_ calls will fail when linking! I thought I'd tested for that, but it turns out that *my* CONFIG_RC_CORE=n config was being over-ridden by the build system. If it will really fail when linking, it sounds like the RC subsystem is not written properly. I guess that explains why all these drivers are riddled with ugly #ifery. Will fix that too, bear with. > > /* Prepare the RC input device */ > > adap->rc = rc_allocate_device(RC_DRIVER_SCANCODE); > > if (!adap->rc) { > > @@ -264,9 +267,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, > > adap->rc->priv = adap; > > adap->rc->map_name = RC_MAP_CEC; > > adap->rc->timeout = MS_TO_NS(100); > > -#else > > - adap->capabilities &= ~CEC_CAP_RC; > > -#endif > > + > > return adap; > > } > > EXPORT_SYMBOL_GPL(cec_allocate_adapter); > > @@ -285,7 +286,6 @@ int cec_register_adapter(struct cec_adapter *adap, > > adap->owner = parent->driver->owner; > > adap->devnode.dev.parent = parent; > > > > -#if IS_REACHABLE(CONFIG_RC_CORE) > > if (adap->capabilities & CEC_CAP_RC) { > > adap->rc->dev.parent = parent; > > res = rc_register_device(adap->rc); > > @@ -298,15 +298,13 @@ int cec_register_adapter(struct cec_adapter *adap, > > return res; > > } > > } > > -#endif > > > > res = cec_devnode_register(&adap->devnode, adap->owner); > > if (res) { > > -#if IS_REACHABLE(CONFIG_RC_CORE) > > /* Note: rc_unregister also calls rc_free */ > > rc_unregister_device(adap->rc); > > adap->rc = NULL; > > -#endif > > + > > return res; > > } > > > > @@ -337,11 +335,10 @@ void cec_unregister_adapter(struct cec_adapter *adap) > > if (IS_ERR_OR_NULL(adap)) > > return; > > > > -#if IS_REACHABLE(CONFIG_RC_CORE) > > /* Note: rc_unregister also calls rc_free */ > > rc_unregister_device(adap->rc); > > adap->rc = NULL; > > -#endif > > + > > debugfs_remove_recursive(adap->cec_dir); > > cec_devnode_unregister(&adap->devnode); > > } > > @@ -357,9 +354,7 @@ void cec_delete_adapter(struct cec_adapter *adap) > > kthread_stop(adap->kthread); > > if (adap->kthread_config) > > kthread_stop(adap->kthread_config); > > -#if IS_REACHABLE(CONFIG_RC_CORE) > > rc_free_device(adap->rc); > > -#endif > > kfree(adap); > > } > > EXPORT_SYMBOL_GPL(cec_delete_adapter); > > >
On Tue, Apr 04, 2017 at 04:19:39PM +0100, Lee Jones wrote: > On Tue, 04 Apr 2017, Hans Verkuil wrote: > > > On 04/04/2017 04:43 PM, Lee Jones wrote: > > > If a user specifies the use of RC as a capability, they should > > > really be enabling RC Core code. If they do not we WARN() them > > > of this and disable the capability for them. > > > > > > Once we know RC Core code has not been enabled, we can update > > > the user's capabilities and use them as a term of reference for > > > other RC-only calls. This is preferable to having ugly #ifery > > > scattered throughout C code. > > > > > > Most of the functions are actually safe to call, since they > > > sensibly check for a NULL RC pointer before they attempt to > > > deference it. > > > > > > Signed-off-by: Lee Jones <lee.jones@linaro.org> > > > --- > > > drivers/media/cec/cec-core.c | 19 +++++++------------ > > > 1 file changed, 7 insertions(+), 12 deletions(-) > > > > > > diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c > > > index cfe414a..51be8d6 100644 > > > --- a/drivers/media/cec/cec-core.c > > > +++ b/drivers/media/cec/cec-core.c > > > @@ -208,9 +208,13 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, > > > return ERR_PTR(-EINVAL); > > > if (WARN_ON(!available_las || available_las > CEC_MAX_LOG_ADDRS)) > > > return ERR_PTR(-EINVAL); > > > + if (WARN_ON(caps & CEC_CAP_RC && !IS_REACHABLE(CONFIG_RC_CORE))) > > > + caps &= ~CEC_CAP_RC; > > > > Don't use WARN_ON, this is not an error of any kind. > > Right, this is not an error. > > That's why we are warning the user instead of bombing out. Please print warning using pr_warn() or dev_warn(). Using WARN_ON() because something is not configured is _really_ not nice behaviour. Consider how useful a stack trace is to the user for this situation - it's completely meaningless. A message that prompts the user to enable RC_CORE would make more sense, and be much more informative to the user. Maybe something like this: + if (caps & CEC_CAP_RC && !IS_REACHABLE(CONFIG_RC_CORE)) { + pr_warn("CEC: driver %pf requests RC, please enable CONFIG_RC_CORE\n", + __builtin_return_address(0)); + caps &= ~CEC_CAP_RC; + } It could be much more informative by using dev_warn() if we had the 'struct device' passed in to this function, and then we wouldn't need to use __builtin_return_address().
On 04/04/2017 05:19 PM, Lee Jones wrote: > On Tue, 04 Apr 2017, Hans Verkuil wrote: > >> On 04/04/2017 04:43 PM, Lee Jones wrote: >>> If a user specifies the use of RC as a capability, they should >>> really be enabling RC Core code. If they do not we WARN() them >>> of this and disable the capability for them. >>> >>> Once we know RC Core code has not been enabled, we can update >>> the user's capabilities and use them as a term of reference for >>> other RC-only calls. This is preferable to having ugly #ifery >>> scattered throughout C code. >>> >>> Most of the functions are actually safe to call, since they >>> sensibly check for a NULL RC pointer before they attempt to >>> deference it. >>> >>> Signed-off-by: Lee Jones <lee.jones@linaro.org> >>> --- >>> drivers/media/cec/cec-core.c | 19 +++++++------------ >>> 1 file changed, 7 insertions(+), 12 deletions(-) >>> >>> diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c >>> index cfe414a..51be8d6 100644 >>> --- a/drivers/media/cec/cec-core.c >>> +++ b/drivers/media/cec/cec-core.c >>> @@ -208,9 +208,13 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, >>> return ERR_PTR(-EINVAL); >>> if (WARN_ON(!available_las || available_las > CEC_MAX_LOG_ADDRS)) >>> return ERR_PTR(-EINVAL); >>> + if (WARN_ON(caps & CEC_CAP_RC && !IS_REACHABLE(CONFIG_RC_CORE))) >>> + caps &= ~CEC_CAP_RC; >> >> Don't use WARN_ON, this is not an error of any kind. > > Right, this is not an error. > > That's why we are warning the user instead of bombing out. > >> Neither do you need to add the >> 'caps & CEC_CAP_RC' test. Really, it's just simpler to do what I suggested before >> with an #if. > > This does exactly what you asked. > > Just to clarify, can you explain to me when asking for RC support, but > not enabling it would ever be a valid configuration? Drivers can decide not to enable RC support. This is more likely to happen with out-of-tree drivers or when you patch the driver for an embedded system. Using the RC subsystem for CEC remote control may not be what you want, especially in an embedded system. Not all CEC RC messages can be handled by the rc subsystem, and you may not want to have them end up in the rc subsystem at all. So I decided to make this a capability that drivers have to explicitly set when they create the CEC adapter. Of course, if they set it (and all in-tree drivers do set it) but the whole subsystem is not enabled, then that's not an error, nor a warning. Instead we simply drop that capability silently here. In the future I might decide to change this (e.g. have it as a CEC config option), but I'd like to wait and see how this works out. > >>> + >>> adap = kzalloc(sizeof(*adap), GFP_KERNEL); >>> if (!adap) >>> return ERR_PTR(-ENOMEM); >>> + >>> strlcpy(adap->name, name, sizeof(adap->name)); >>> adap->phys_addr = CEC_PHYS_ADDR_INVALID; >>> adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0; >>> @@ -237,7 +241,6 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, >>> if (!(caps & CEC_CAP_RC)) >>> return adap; >>> >>> -#if IS_REACHABLE(CONFIG_RC_CORE) >> >> Huh? If CONFIG_RC_CORE is undefined, all these rc_ calls will fail when linking! > > I thought I'd tested for that, but it turns out that *my* > CONFIG_RC_CORE=n config was being over-ridden by the build system. > > If it will really fail when linking, it sounds like the RC subsystem > is not written properly. I guess that explains why all these drivers > are riddled with ugly #ifery. The rc subsystem doesn't provide you with empty stubs for these functions in the header if RC_CORE isn't defined. > > Will fix that too, bear with. Please just keep this patch simple. Just clean up the confusing control flow. Anything else can be done afterwards. Hans > >>> /* Prepare the RC input device */ >>> adap->rc = rc_allocate_device(RC_DRIVER_SCANCODE); >>> if (!adap->rc) { >>> @@ -264,9 +267,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, >>> adap->rc->priv = adap; >>> adap->rc->map_name = RC_MAP_CEC; >>> adap->rc->timeout = MS_TO_NS(100); >>> -#else >>> - adap->capabilities &= ~CEC_CAP_RC; >>> -#endif >>> + >>> return adap; >>> } >>> EXPORT_SYMBOL_GPL(cec_allocate_adapter); >>> @@ -285,7 +286,6 @@ int cec_register_adapter(struct cec_adapter *adap, >>> adap->owner = parent->driver->owner; >>> adap->devnode.dev.parent = parent; >>> >>> -#if IS_REACHABLE(CONFIG_RC_CORE) >>> if (adap->capabilities & CEC_CAP_RC) { >>> adap->rc->dev.parent = parent; >>> res = rc_register_device(adap->rc); >>> @@ -298,15 +298,13 @@ int cec_register_adapter(struct cec_adapter *adap, >>> return res; >>> } >>> } >>> -#endif >>> >>> res = cec_devnode_register(&adap->devnode, adap->owner); >>> if (res) { >>> -#if IS_REACHABLE(CONFIG_RC_CORE) >>> /* Note: rc_unregister also calls rc_free */ >>> rc_unregister_device(adap->rc); >>> adap->rc = NULL; >>> -#endif >>> + >>> return res; >>> } >>> >>> @@ -337,11 +335,10 @@ void cec_unregister_adapter(struct cec_adapter *adap) >>> if (IS_ERR_OR_NULL(adap)) >>> return; >>> >>> -#if IS_REACHABLE(CONFIG_RC_CORE) >>> /* Note: rc_unregister also calls rc_free */ >>> rc_unregister_device(adap->rc); >>> adap->rc = NULL; >>> -#endif >>> + >>> debugfs_remove_recursive(adap->cec_dir); >>> cec_devnode_unregister(&adap->devnode); >>> } >>> @@ -357,9 +354,7 @@ void cec_delete_adapter(struct cec_adapter *adap) >>> kthread_stop(adap->kthread); >>> if (adap->kthread_config) >>> kthread_stop(adap->kthread_config); >>> -#if IS_REACHABLE(CONFIG_RC_CORE) >>> rc_free_device(adap->rc); >>> -#endif >>> kfree(adap); >>> } >>> EXPORT_SYMBOL_GPL(cec_delete_adapter); >>> >> >
On 04/04/2017 05:36 PM, Russell King - ARM Linux wrote: > On Tue, Apr 04, 2017 at 04:19:39PM +0100, Lee Jones wrote: >> On Tue, 04 Apr 2017, Hans Verkuil wrote: >> >>> On 04/04/2017 04:43 PM, Lee Jones wrote: >>>> If a user specifies the use of RC as a capability, they should >>>> really be enabling RC Core code. If they do not we WARN() them >>>> of this and disable the capability for them. >>>> >>>> Once we know RC Core code has not been enabled, we can update >>>> the user's capabilities and use them as a term of reference for >>>> other RC-only calls. This is preferable to having ugly #ifery >>>> scattered throughout C code. >>>> >>>> Most of the functions are actually safe to call, since they >>>> sensibly check for a NULL RC pointer before they attempt to >>>> deference it. >>>> >>>> Signed-off-by: Lee Jones <lee.jones@linaro.org> >>>> --- >>>> drivers/media/cec/cec-core.c | 19 +++++++------------ >>>> 1 file changed, 7 insertions(+), 12 deletions(-) >>>> >>>> diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c >>>> index cfe414a..51be8d6 100644 >>>> --- a/drivers/media/cec/cec-core.c >>>> +++ b/drivers/media/cec/cec-core.c >>>> @@ -208,9 +208,13 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, >>>> return ERR_PTR(-EINVAL); >>>> if (WARN_ON(!available_las || available_las > CEC_MAX_LOG_ADDRS)) >>>> return ERR_PTR(-EINVAL); >>>> + if (WARN_ON(caps & CEC_CAP_RC && !IS_REACHABLE(CONFIG_RC_CORE))) >>>> + caps &= ~CEC_CAP_RC; >>> >>> Don't use WARN_ON, this is not an error of any kind. >> >> Right, this is not an error. >> >> That's why we are warning the user instead of bombing out. > > Please print warning using pr_warn() or dev_warn(). Using WARN_ON() > because something is not configured is _really_ not nice behaviour. > Consider how useful a stack trace is to the user for this situation - > it's completely meaningless. > > A message that prompts the user to enable RC_CORE would make more sense, > and be much more informative to the user. Maybe something like this: > > + if (caps & CEC_CAP_RC && !IS_REACHABLE(CONFIG_RC_CORE)) { > + pr_warn("CEC: driver %pf requests RC, please enable CONFIG_RC_CORE\n", > + __builtin_return_address(0)); > + caps &= ~CEC_CAP_RC; > + } > > It could be much more informative by using dev_warn() if we had the > 'struct device' passed in to this function, and then we wouldn't need > to use __builtin_return_address(). > I don't want to see a message logged because of this. In the current design it is perfectly valid to compile without RC_CORE. I think eventually this should be redesigned a bit (a separate CEC config option that enables or disables RC support), but for now I prefer to leave this as-is until I have a bit more experience with this. After the CEC notifier work is in I will take another look at this. Regards, Hans
On Tue, 04 Apr 2017, Russell King - ARM Linux wrote: > On Tue, Apr 04, 2017 at 04:19:39PM +0100, Lee Jones wrote: > > On Tue, 04 Apr 2017, Hans Verkuil wrote: > > > > > On 04/04/2017 04:43 PM, Lee Jones wrote: > > > > If a user specifies the use of RC as a capability, they should > > > > really be enabling RC Core code. If they do not we WARN() them > > > > of this and disable the capability for them. > > > > > > > > Once we know RC Core code has not been enabled, we can update > > > > the user's capabilities and use them as a term of reference for > > > > other RC-only calls. This is preferable to having ugly #ifery > > > > scattered throughout C code. > > > > > > > > Most of the functions are actually safe to call, since they > > > > sensibly check for a NULL RC pointer before they attempt to > > > > deference it. > > > > > > > > Signed-off-by: Lee Jones <lee.jones@linaro.org> > > > > --- > > > > drivers/media/cec/cec-core.c | 19 +++++++------------ > > > > 1 file changed, 7 insertions(+), 12 deletions(-) > > > > > > > > diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c > > > > index cfe414a..51be8d6 100644 > > > > --- a/drivers/media/cec/cec-core.c > > > > +++ b/drivers/media/cec/cec-core.c > > > > @@ -208,9 +208,13 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, > > > > return ERR_PTR(-EINVAL); > > > > if (WARN_ON(!available_las || available_las > CEC_MAX_LOG_ADDRS)) > > > > return ERR_PTR(-EINVAL); > > > > + if (WARN_ON(caps & CEC_CAP_RC && !IS_REACHABLE(CONFIG_RC_CORE))) > > > > + caps &= ~CEC_CAP_RC; > > > > > > Don't use WARN_ON, this is not an error of any kind. > > > > Right, this is not an error. > > > > That's why we are warning the user instead of bombing out. > > Please print warning using pr_warn() or dev_warn(). Using WARN_ON() > because something is not configured is _really_ not nice behaviour. > Consider how useful a stack trace is to the user for this situation - > it's completely meaningless. > > A message that prompts the user to enable RC_CORE would make more sense, > and be much more informative to the user. Maybe something like this: > > + if (caps & CEC_CAP_RC && !IS_REACHABLE(CONFIG_RC_CORE)) { > + pr_warn("CEC: driver %pf requests RC, please enable CONFIG_RC_CORE\n", > + __builtin_return_address(0)); > + caps &= ~CEC_CAP_RC; > + } > > It could be much more informative by using dev_warn() if we had the > 'struct device' passed in to this function, and then we wouldn't need > to use __builtin_return_address(). Understood. I *would* fix, but Hans has made it pretty clear that this is not the way he wants to go. I still think a warning is the correct solution, but for some reason we are to support out-of-tree drivers which might be doing weird stuff.
On Tue, 04 Apr 2017, Hans Verkuil wrote: > On 04/04/2017 05:36 PM, Russell King - ARM Linux wrote: > > On Tue, Apr 04, 2017 at 04:19:39PM +0100, Lee Jones wrote: > >> On Tue, 04 Apr 2017, Hans Verkuil wrote: > >> > >>> On 04/04/2017 04:43 PM, Lee Jones wrote: > >>>> If a user specifies the use of RC as a capability, they should > >>>> really be enabling RC Core code. If they do not we WARN() them > >>>> of this and disable the capability for them. > >>>> > >>>> Once we know RC Core code has not been enabled, we can update > >>>> the user's capabilities and use them as a term of reference for > >>>> other RC-only calls. This is preferable to having ugly #ifery > >>>> scattered throughout C code. > >>>> > >>>> Most of the functions are actually safe to call, since they > >>>> sensibly check for a NULL RC pointer before they attempt to > >>>> deference it. > >>>> > >>>> Signed-off-by: Lee Jones <lee.jones@linaro.org> > >>>> --- > >>>> drivers/media/cec/cec-core.c | 19 +++++++------------ > >>>> 1 file changed, 7 insertions(+), 12 deletions(-) > >>>> > >>>> diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c > >>>> index cfe414a..51be8d6 100644 > >>>> --- a/drivers/media/cec/cec-core.c > >>>> +++ b/drivers/media/cec/cec-core.c > >>>> @@ -208,9 +208,13 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, > >>>> return ERR_PTR(-EINVAL); > >>>> if (WARN_ON(!available_las || available_las > CEC_MAX_LOG_ADDRS)) > >>>> return ERR_PTR(-EINVAL); > >>>> + if (WARN_ON(caps & CEC_CAP_RC && !IS_REACHABLE(CONFIG_RC_CORE))) > >>>> + caps &= ~CEC_CAP_RC; > >>> > >>> Don't use WARN_ON, this is not an error of any kind. > >> > >> Right, this is not an error. > >> > >> That's why we are warning the user instead of bombing out. > > > > Please print warning using pr_warn() or dev_warn(). Using WARN_ON() > > because something is not configured is _really_ not nice behaviour. > > Consider how useful a stack trace is to the user for this situation - > > it's completely meaningless. > > > > A message that prompts the user to enable RC_CORE would make more sense, > > and be much more informative to the user. Maybe something like this: > > > > + if (caps & CEC_CAP_RC && !IS_REACHABLE(CONFIG_RC_CORE)) { > > + pr_warn("CEC: driver %pf requests RC, please enable CONFIG_RC_CORE\n", > > + __builtin_return_address(0)); > > + caps &= ~CEC_CAP_RC; > > + } > > > > It could be much more informative by using dev_warn() if we had the > > 'struct device' passed in to this function, and then we wouldn't need > > to use __builtin_return_address(). > > > > I don't want to see a message logged because of this. In the current design it > is perfectly valid to compile without RC_CORE. > > I think eventually this should be redesigned a bit (a separate CEC config option > that enables or disables RC support), but for now I prefer to leave this as-is > until I have a bit more experience with this. > > After the CEC notifier work is in I will take another look at this. Well at least I bought it to your attention. I guess that's a 50% win. I'll rework the patch accordingly.
diff --git a/drivers/media/cec/cec-core.c b/drivers/media/cec/cec-core.c index cfe414a..51be8d6 100644 --- a/drivers/media/cec/cec-core.c +++ b/drivers/media/cec/cec-core.c @@ -208,9 +208,13 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, return ERR_PTR(-EINVAL); if (WARN_ON(!available_las || available_las > CEC_MAX_LOG_ADDRS)) return ERR_PTR(-EINVAL); + if (WARN_ON(caps & CEC_CAP_RC && !IS_REACHABLE(CONFIG_RC_CORE))) + caps &= ~CEC_CAP_RC; + adap = kzalloc(sizeof(*adap), GFP_KERNEL); if (!adap) return ERR_PTR(-ENOMEM); + strlcpy(adap->name, name, sizeof(adap->name)); adap->phys_addr = CEC_PHYS_ADDR_INVALID; adap->log_addrs.cec_version = CEC_OP_CEC_VERSION_2_0; @@ -237,7 +241,6 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, if (!(caps & CEC_CAP_RC)) return adap; -#if IS_REACHABLE(CONFIG_RC_CORE) /* Prepare the RC input device */ adap->rc = rc_allocate_device(RC_DRIVER_SCANCODE); if (!adap->rc) { @@ -264,9 +267,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops, adap->rc->priv = adap; adap->rc->map_name = RC_MAP_CEC; adap->rc->timeout = MS_TO_NS(100); -#else - adap->capabilities &= ~CEC_CAP_RC; -#endif + return adap; } EXPORT_SYMBOL_GPL(cec_allocate_adapter); @@ -285,7 +286,6 @@ int cec_register_adapter(struct cec_adapter *adap, adap->owner = parent->driver->owner; adap->devnode.dev.parent = parent; -#if IS_REACHABLE(CONFIG_RC_CORE) if (adap->capabilities & CEC_CAP_RC) { adap->rc->dev.parent = parent; res = rc_register_device(adap->rc); @@ -298,15 +298,13 @@ int cec_register_adapter(struct cec_adapter *adap, return res; } } -#endif res = cec_devnode_register(&adap->devnode, adap->owner); if (res) { -#if IS_REACHABLE(CONFIG_RC_CORE) /* Note: rc_unregister also calls rc_free */ rc_unregister_device(adap->rc); adap->rc = NULL; -#endif + return res; } @@ -337,11 +335,10 @@ void cec_unregister_adapter(struct cec_adapter *adap) if (IS_ERR_OR_NULL(adap)) return; -#if IS_REACHABLE(CONFIG_RC_CORE) /* Note: rc_unregister also calls rc_free */ rc_unregister_device(adap->rc); adap->rc = NULL; -#endif + debugfs_remove_recursive(adap->cec_dir); cec_devnode_unregister(&adap->devnode); } @@ -357,9 +354,7 @@ void cec_delete_adapter(struct cec_adapter *adap) kthread_stop(adap->kthread); if (adap->kthread_config) kthread_stop(adap->kthread_config); -#if IS_REACHABLE(CONFIG_RC_CORE) rc_free_device(adap->rc); -#endif kfree(adap); } EXPORT_SYMBOL_GPL(cec_delete_adapter);