diff mbox series

[2/7] platform/surface: aggregator: Allow enabling of events without notifiers

Message ID 20210603234526.2503590-3-luzmaximilian@gmail.com (mailing list archive)
State Changes Requested, archived
Headers show
Series platform/surface: aggregator: Extend user-space interface for events | expand

Commit Message

Maximilian Luz June 3, 2021, 11:45 p.m. UTC
We can already enable and disable SAM events via one of two ways: either
via a (non-observer) notifier tied to a specific event group, or a
generic event enable/disable request. In some instances, however,
neither method may be desirable.

The first method will tie the event enable request to a specific
notifier, however, when we want to receive notifications for multiple
event groups of the same target category and forward this to the same
notifier callback, we may receive duplicate events, i.e. one event per
registered notifier. The second method will bypass the internal
reference counting mechanism, meaning that a disable request will
disable the event regardless of any other client driver using it, which
may break the functionality of that driver.

To address this problem, add new functions that allow enabling and
disabling of events via the event reference counting mechanism built
into the controller, without needing to register a notifier.

This can then be used in combination with observer notifiers to process
multiple events of the same target category without duplication in the
same callback function.

Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
---
 .../platform/surface/aggregator/controller.c  | 135 ++++++++++++++++++
 include/linux/surface_aggregator/controller.h |   8 ++
 2 files changed, 143 insertions(+)

Comments

kernel test robot June 4, 2021, 5:55 a.m. UTC | #1
Hi Maximilian,

I love your patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.13-rc4 next-20210603]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Maximilian-Luz/platform-surface-aggregator-Extend-user-space-interface-for-events/20210604-074904
base:   https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git f88cd3fb9df228e5ce4e13ec3dbad671ddb2146e
config: x86_64-randconfig-r016-20210604 (attached as .config)
compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project 5c0d1b2f902aa6a9cf47cc7e42c5b83bb2217cf9)
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # install x86_64 cross compiling tool for clang build
        # apt-get install binutils-x86-64-linux-gnu
        # https://github.com/0day-ci/linux/commit/7b6b5a24e7c8e389e231ee547972e871145f5972
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Maximilian-Luz/platform-surface-aggregator-Extend-user-space-interface-for-events/20210604-074904
        git checkout 7b6b5a24e7c8e389e231ee547972e871145f5972
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/platform/surface/aggregator/controller.c:2317:23: warning: variable 'nf_head' set but not used [-Wunused-but-set-variable]
           struct ssam_nf_head *nf_head;
                                ^
   drivers/platform/surface/aggregator/controller.c:2386:23: warning: variable 'nf_head' set but not used [-Wunused-but-set-variable]
           struct ssam_nf_head *nf_head;
                                ^
   2 warnings generated.


vim +/nf_head +2317 drivers/platform/surface/aggregator/controller.c

  2289	
  2290	/**
  2291	 * ssam_controller_event_enable() - Enable the specified event.
  2292	 * @ctrl:  The controller to enable the event for.
  2293	 * @reg:   The event registry to use for enabling the event.
  2294	 * @id:    The event ID specifying the event to be enabled.
  2295	 * @flags: The SAM event flags used for enabling the event.
  2296	 *
  2297	 * Increment the event reference count of the specified event. If the event has
  2298	 * not been enabled previously, it will be enabled by this call.
  2299	 *
  2300	 * Note: In general, ssam_notifier_register() with a non-observer notifier
  2301	 * should be preferred for enabling/disabling events, as this will guarantee
  2302	 * proper ordering and event forwarding in case of errors during event
  2303	 * enabling/disabling.
  2304	 *
  2305	 * Return: Returns zero on success, %-ENOSPC if the reference count for the
  2306	 * specified event has reached its maximum, %-ENOMEM if the corresponding event
  2307	 * entry could not be allocated. If this is the first time that this event has
  2308	 * been enabled (i.e. the reference count was incremented from zero to one by
  2309	 * this call), returns the status of the event-enable EC-command.
  2310	 */
  2311	int ssam_controller_event_enable(struct ssam_controller *ctrl,
  2312					 struct ssam_event_registry reg,
  2313					 struct ssam_event_id id, u8 flags)
  2314	{
  2315		u16 rqid = ssh_tc_to_rqid(id.target_category);
  2316		struct ssam_nf_refcount_entry *entry;
> 2317		struct ssam_nf_head *nf_head;
  2318		struct ssam_nf *nf;
  2319		int status;
  2320	
  2321		if (!ssh_rqid_is_event(rqid))
  2322			return -EINVAL;
  2323	
  2324		nf = &ctrl->cplt.event.notif;
  2325		nf_head = &nf->head[ssh_rqid_to_event(rqid)];
  2326	
  2327		mutex_lock(&nf->lock);
  2328	
  2329		entry = ssam_nf_refcount_inc(nf, reg, id);
  2330		if (IS_ERR(entry)) {
  2331			mutex_unlock(&nf->lock);
  2332			return PTR_ERR(entry);
  2333		}
  2334	
  2335		ssam_dbg(ctrl, "enabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
  2336			 reg.target_category, id.target_category, id.instance,
  2337			 entry->refcount);
  2338	
  2339		if (entry->refcount == 1) {
  2340			status = ssam_ssh_event_enable(ctrl, reg, id, flags);
  2341			if (status) {
  2342				kfree(ssam_nf_refcount_dec(nf, reg, id));
  2343				mutex_unlock(&nf->lock);
  2344				return status;
  2345			}
  2346	
  2347			entry->flags = flags;
  2348	
  2349		} else if (entry->flags != flags) {
  2350			ssam_warn(ctrl,
  2351				  "inconsistent flags when enabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n",
  2352				  flags, entry->flags, reg.target_category,
  2353				  id.target_category, id.instance);
  2354		}
  2355	
  2356		mutex_unlock(&nf->lock);
  2357		return 0;
  2358	}
  2359	EXPORT_SYMBOL_GPL(ssam_controller_event_enable);
  2360	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
index cd3a6b77f48d..49edddea417e 100644
--- a/drivers/platform/surface/aggregator/controller.c
+++ b/drivers/platform/surface/aggregator/controller.c
@@ -2287,6 +2287,141 @@  int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_not
 }
 EXPORT_SYMBOL_GPL(ssam_notifier_unregister);
 
+/**
+ * ssam_controller_event_enable() - Enable the specified event.
+ * @ctrl:  The controller to enable the event for.
+ * @reg:   The event registry to use for enabling the event.
+ * @id:    The event ID specifying the event to be enabled.
+ * @flags: The SAM event flags used for enabling the event.
+ *
+ * Increment the event reference count of the specified event. If the event has
+ * not been enabled previously, it will be enabled by this call.
+ *
+ * Note: In general, ssam_notifier_register() with a non-observer notifier
+ * should be preferred for enabling/disabling events, as this will guarantee
+ * proper ordering and event forwarding in case of errors during event
+ * enabling/disabling.
+ *
+ * Return: Returns zero on success, %-ENOSPC if the reference count for the
+ * specified event has reached its maximum, %-ENOMEM if the corresponding event
+ * entry could not be allocated. If this is the first time that this event has
+ * been enabled (i.e. the reference count was incremented from zero to one by
+ * this call), returns the status of the event-enable EC-command.
+ */
+int ssam_controller_event_enable(struct ssam_controller *ctrl,
+				 struct ssam_event_registry reg,
+				 struct ssam_event_id id, u8 flags)
+{
+	u16 rqid = ssh_tc_to_rqid(id.target_category);
+	struct ssam_nf_refcount_entry *entry;
+	struct ssam_nf_head *nf_head;
+	struct ssam_nf *nf;
+	int status;
+
+	if (!ssh_rqid_is_event(rqid))
+		return -EINVAL;
+
+	nf = &ctrl->cplt.event.notif;
+	nf_head = &nf->head[ssh_rqid_to_event(rqid)];
+
+	mutex_lock(&nf->lock);
+
+	entry = ssam_nf_refcount_inc(nf, reg, id);
+	if (IS_ERR(entry)) {
+		mutex_unlock(&nf->lock);
+		return PTR_ERR(entry);
+	}
+
+	ssam_dbg(ctrl, "enabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
+		 reg.target_category, id.target_category, id.instance,
+		 entry->refcount);
+
+	if (entry->refcount == 1) {
+		status = ssam_ssh_event_enable(ctrl, reg, id, flags);
+		if (status) {
+			kfree(ssam_nf_refcount_dec(nf, reg, id));
+			mutex_unlock(&nf->lock);
+			return status;
+		}
+
+		entry->flags = flags;
+
+	} else if (entry->flags != flags) {
+		ssam_warn(ctrl,
+			  "inconsistent flags when enabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n",
+			  flags, entry->flags, reg.target_category,
+			  id.target_category, id.instance);
+	}
+
+	mutex_unlock(&nf->lock);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(ssam_controller_event_enable);
+
+/**
+ * ssam_controller_event_disable() - Disable the specified event.
+ * @ctrl:  The controller to disable the event for.
+ * @reg:   The event registry to use for disabling the event.
+ * @id:    The event ID specifying the event to be disabled.
+ * @flags: The flags used when enabling the event.
+ *
+ * Decrement the reference count of the specified event. If the reference count
+ * reaches zero, the event will be disabled.
+ *
+ * Note: In general, ssam_notifier_register()/ssam_notifier_unregister() with a
+ * non-observer notifier should be preferred for enabling/disabling events, as
+ * this will guarantee proper ordering and event forwarding in case of errors
+ * during event enabling/disabling.
+ *
+ * Return: Returns zero on success, %-ENOENT if the given event has not been
+ * enabled on the controller. If the reference count of the event reaches zero
+ * during this call, returns the status of the event-disable EC-command.
+ */
+int ssam_controller_event_disable(struct ssam_controller *ctrl,
+				  struct ssam_event_registry reg,
+				  struct ssam_event_id id, u8 flags)
+{
+	u16 rqid = ssh_tc_to_rqid(id.target_category);
+	struct ssam_nf_refcount_entry *entry;
+	struct ssam_nf_head *nf_head;
+	struct ssam_nf *nf;
+	int status = 0;
+
+	if (!ssh_rqid_is_event(rqid))
+		return -EINVAL;
+
+	nf = &ctrl->cplt.event.notif;
+	nf_head = &nf->head[ssh_rqid_to_event(rqid)];
+
+	mutex_lock(&nf->lock);
+
+	entry = ssam_nf_refcount_dec(nf, reg, id);
+	if (WARN_ON(!entry)) {
+		mutex_unlock(&nf->lock);
+		return -ENOENT;
+	}
+
+	ssam_dbg(ctrl, "disabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
+		 reg.target_category, id.target_category, id.instance,
+		 entry->refcount);
+
+	if (entry->flags != flags) {
+		ssam_warn(ctrl,
+			  "inconsistent flags when disabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n",
+			  flags, entry->flags, reg.target_category,
+			  id.target_category, id.instance);
+	}
+
+	if (entry->refcount == 0) {
+		status = ssam_ssh_event_disable(ctrl, reg, id, flags);
+		kfree(entry);
+	}
+
+	mutex_unlock(&nf->lock);
+	return status;
+}
+EXPORT_SYMBOL_GPL(ssam_controller_event_disable);
+
 /**
  * ssam_notifier_disable_registered() - Disable events for all registered
  * notifiers.
diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h
index cf4bb48a850e..7965bdc669c5 100644
--- a/include/linux/surface_aggregator/controller.h
+++ b/include/linux/surface_aggregator/controller.h
@@ -838,4 +838,12 @@  int ssam_notifier_register(struct ssam_controller *ctrl,
 int ssam_notifier_unregister(struct ssam_controller *ctrl,
 			     struct ssam_event_notifier *n);
 
+int ssam_controller_event_enable(struct ssam_controller *ctrl,
+				 struct ssam_event_registry reg,
+				 struct ssam_event_id id, u8 flags);
+
+int ssam_controller_event_disable(struct ssam_controller *ctrl,
+				  struct ssam_event_registry reg,
+				  struct ssam_event_id id, u8 flags);
+
 #endif /* _LINUX_SURFACE_AGGREGATOR_CONTROLLER_H */