All of lore.kernel.org
 help / color / mirror / Atom feed
From: Doug Anderson <dianders@chromium.org>
To: Lee Jones <lee.jones@linaro.org>
Cc: Andrew Bresticker <abrestic@chromium.org>,
	swarren@wwwdotorg.org, olof@lixom.net,
	Sonny Rao <sonnyrao@chromium.org>,
	linux-samsung-soc@vger.kernel.org,
	Javier Martinez Canillas <javier.martinez@collabora.co.uk>,
	Bill Richardson <wfrichar@chromium.org>,
	sjg@chromium.org, Wolfram Sang <wsa@the-dreams.de>,
	broonie@kernel.org, Doug Anderson <dianders@chromium.org>,
	dmitry.torokhov@gmail.com, sameo@linux.intel.com,
	geert@linux-m68k.org, linux-input@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH v2 10/10] mfd: cros_ec: move EC interrupt to cros_ec_keyb
Date: Wed, 18 Jun 2014 11:14:07 -0700	[thread overview]
Message-ID: <1403115247-8853-11-git-send-email-dianders@chromium.org> (raw)
In-Reply-To: <1403115247-8853-1-git-send-email-dianders@chromium.org>

From: Andrew Bresticker <abrestic@chromium.org>

If we receive EC interrupts after the cros_ec driver has probed, but
before the cros_ec_keyb driver has probed, the cros_ec IRQ handler
will not run the cros_ec_keyb notifier and the EC will leave the IRQ
line asserted.  The cros_ec IRQ handler then returns IRQ_HANDLED and
the resulting flood of interrupts causes the machine to hang.

Since the EC interrupt is currently only used for the keyboard, move
the setup and handling of the EC interrupt to the cros_ec_keyb driver.

Signed-off-by: Andrew Bresticker <abrestic@chromium.org>
Signed-off-by: Doug Anderson <dianders@chromium.org>
---
Changes in v2:
- IRQs should be optional => move EC interrupt to keyboard.

 drivers/input/keyboard/cros_ec_keyb.c | 58 ++++++++++++++++++++---------------
 drivers/mfd/cros_ec.c                 | 35 +--------------------
 include/linux/mfd/cros_ec.h           |  2 --
 3 files changed, 34 insertions(+), 61 deletions(-)

diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index b8341ab..791781a 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -24,8 +24,8 @@
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/input.h>
+#include <linux/interrupt.h>
 #include <linux/kernel.h>
-#include <linux/notifier.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/input/matrix_keypad.h>
@@ -42,7 +42,6 @@
  * @dev: Device pointer
  * @idev: Input device
  * @ec: Top level ChromeOS device to use to talk to EC
- * @event_notifier: interrupt event notifier for transport devices
  */
 struct cros_ec_keyb {
 	unsigned int rows;
@@ -55,7 +54,6 @@ struct cros_ec_keyb {
 	struct device *dev;
 	struct input_dev *idev;
 	struct cros_ec_device *ec;
-	struct notifier_block notifier;
 };
 
 
@@ -173,22 +171,6 @@ static void cros_ec_keyb_process(struct cros_ec_keyb *ckdev,
 	input_sync(ckdev->idev);
 }
 
-static int cros_ec_keyb_open(struct input_dev *dev)
-{
-	struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-
-	return blocking_notifier_chain_register(&ckdev->ec->event_notifier,
-						&ckdev->notifier);
-}
-
-static void cros_ec_keyb_close(struct input_dev *dev)
-{
-	struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
-
-	blocking_notifier_chain_unregister(&ckdev->ec->event_notifier,
-					   &ckdev->notifier);
-}
-
 static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
 {
 	struct cros_ec_command msg = {
@@ -203,19 +185,41 @@ static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t *kb_state)
 	return ckdev->ec->cmd_xfer(ckdev->ec, &msg);
 }
 
-static int cros_ec_keyb_work(struct notifier_block *nb,
-		     unsigned long state, void *_notify)
+static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
 {
+	struct cros_ec_keyb *ckdev = data;
+	struct cros_ec_device *ec = ckdev->ec;
 	int ret;
-	struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
-						    notifier);
 	uint8_t kb_state[ckdev->cols];
 
+	if (device_may_wakeup(ec->dev))
+		pm_wakeup_event(ec->dev, 0);
+
 	ret = cros_ec_keyb_get_state(ckdev, kb_state);
 	if (ret >= 0)
 		cros_ec_keyb_process(ckdev, kb_state, ret);
+	else
+		dev_err(ec->dev, "failed to get keyboard state: %d\n", ret);
 
-	return NOTIFY_DONE;
+	return IRQ_HANDLED;
+}
+
+static int cros_ec_keyb_open(struct input_dev *dev)
+{
+	struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
+	struct cros_ec_device *ec = ckdev->ec;
+
+	return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
+					IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+					"cros_ec_keyb", ckdev);
+}
+
+static void cros_ec_keyb_close(struct input_dev *dev)
+{
+	struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
+	struct cros_ec_device *ec = ckdev->ec;
+
+	free_irq(ec->irq, ckdev);
 }
 
 static int cros_ec_keyb_probe(struct platform_device *pdev)
@@ -246,8 +250,12 @@ static int cros_ec_keyb_probe(struct platform_device *pdev)
 	if (!idev)
 		return -ENOMEM;
 
+	if (!ec->irq) {
+		dev_err(dev, "no EC IRQ specified\n");
+		return -EINVAL;
+	}
+
 	ckdev->ec = ec;
-	ckdev->notifier.notifier_call = cros_ec_keyb_work;
 	ckdev->dev = dev;
 	dev_set_drvdata(&pdev->dev, ckdev);
 
diff --git a/drivers/mfd/cros_ec.c b/drivers/mfd/cros_ec.c
index 83e30c6..4873f9c 100644
--- a/drivers/mfd/cros_ec.c
+++ b/drivers/mfd/cros_ec.c
@@ -62,18 +62,6 @@ int cros_ec_check_result(struct cros_ec_device *ec_dev,
 }
 EXPORT_SYMBOL(cros_ec_check_result);
 
-static irqreturn_t ec_irq_thread(int irq, void *data)
-{
-	struct cros_ec_device *ec_dev = data;
-
-	if (device_may_wakeup(ec_dev->dev))
-		pm_wakeup_event(ec_dev->dev, 0);
-
-	blocking_notifier_call_chain(&ec_dev->event_notifier, 1, ec_dev);
-
-	return IRQ_HANDLED;
-}
-
 static const struct mfd_cell cros_devs[] = {
 	{
 		.name = "cros-ec-keyb",
@@ -92,8 +80,6 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
 	struct device *dev = ec_dev->dev;
 	int err = 0;
 
-	BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier);
-
 	if (ec_dev->din_size) {
 		ec_dev->din = devm_kzalloc(dev, ec_dev->din_size, GFP_KERNEL);
 		if (!ec_dev->din)
@@ -105,42 +91,23 @@ int cros_ec_register(struct cros_ec_device *ec_dev)
 			return -ENOMEM;
 	}
 
-	if (!ec_dev->irq) {
-		dev_dbg(dev, "no valid IRQ: %d\n", ec_dev->irq);
-		return err;
-	}
-
-	err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
-				   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-				   "chromeos-ec", ec_dev);
-	if (err) {
-		dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err);
-		return err;
-	}
-
 	err = mfd_add_devices(dev, 0, cros_devs,
 			      ARRAY_SIZE(cros_devs),
 			      NULL, ec_dev->irq, NULL);
 	if (err) {
 		dev_err(dev, "failed to add mfd devices\n");
-		goto fail_mfd;
+		return err;
 	}
 
 	dev_info(dev, "Chrome EC device registered\n");
 
 	return 0;
-
-fail_mfd:
-	free_irq(ec_dev->irq, ec_dev);
-
-	return err;
 }
 EXPORT_SYMBOL(cros_ec_register);
 
 int cros_ec_remove(struct cros_ec_device *ec_dev)
 {
 	mfd_remove_devices(ec_dev->dev);
-	free_irq(ec_dev->irq, ec_dev);
 
 	return 0;
 }
diff --git a/include/linux/mfd/cros_ec.h b/include/linux/mfd/cros_ec.h
index 0ebf26f..fcbe9d1 100644
--- a/include/linux/mfd/cros_ec.h
+++ b/include/linux/mfd/cros_ec.h
@@ -62,7 +62,6 @@ struct cros_ec_command {
  * @dev: Device pointer
  * @was_wake_device: true if this device was set to wake the system from
  * sleep at the last suspend
- * @event_notifier: interrupt event notifier for transport devices
  * @cmd_xfer: send command to EC and get response
  *     Returns the number of bytes received if the communication succeeded, but
  *     that doesn't mean the EC was happy with the command. The caller
@@ -93,7 +92,6 @@ struct cros_ec_device {
 	struct device *dev;
 	bool was_wake_device;
 	struct class *cros_class;
-	struct blocking_notifier_head event_notifier;
 	int (*cmd_xfer)(struct cros_ec_device *ec,
 			struct cros_ec_command *msg);
 
-- 
2.0.0.526.g5318336


  parent reply	other threads:[~2014-06-18 18:15 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-18 18:13 [PATCH v2 0/10] Batch of cleanup patches for cros_ec Doug Anderson
2014-06-18 18:13 ` [PATCH v2 01/10] mfd: cros_ec: Fix the comment on cros_ec_remove() Doug Anderson
2014-07-03  7:27   ` Lee Jones
2014-06-18 18:13 ` [PATCH v2 02/10] mfd: cros_ec: Allow static din/dout buffers with cros_ec_register() Doug Anderson
2014-06-24 10:16   ` Lee Jones
2014-07-03  7:27   ` Lee Jones
2014-06-18 18:14 ` [PATCH v2 03/10] mfd: cros_ec: Tweak struct cros_ec_device for clarity Doug Anderson
2014-07-03  7:28   ` Lee Jones
2014-06-18 18:14 ` [PATCH v2 04/10] mdf: cros_ec: Detect in-progress commands Doug Anderson
2014-07-03  7:28   ` Lee Jones
2014-06-18 18:14 ` [PATCH v2 05/10] mfd: cros_ec: Use struct cros_ec_command to communicate with the EC Doug Anderson
2014-06-20  3:40   ` Simon Glass
2014-07-03  7:29   ` Lee Jones
2014-06-18 18:14 ` [PATCH v2 06/10] mfd: cros_ec: cleanup: remove unused fields from struct cros_ec_device Doug Anderson
2014-07-03  7:29   ` Lee Jones
2014-06-18 18:14 ` [PATCH v2 07/10] mfd: cros_ec: cleanup: Remove EC wrapper functions Doug Anderson
2014-06-18 18:14   ` Doug Anderson
2014-06-27 12:31   ` Wolfram Sang
2014-06-27 18:47     ` Dmitry Torokhov
2014-06-27 18:47       ` Dmitry Torokhov
2014-07-03  7:30   ` Lee Jones
2014-07-03  7:30     ` Lee Jones
2014-06-18 18:14 ` [PATCH v2 08/10] mfd: cros_ec: Check result code from EC messages Doug Anderson
2014-06-20  3:42   ` Simon Glass
2014-06-24 10:22   ` Lee Jones
2014-07-03  7:31   ` Lee Jones
2014-06-18 18:14 ` [PATCH v2 09/10] mfd: cros_ec: ec_dev->cmd_xfer() returns number of bytes received from EC Doug Anderson
2014-06-27 12:31   ` Wolfram Sang
2014-06-27 12:31     ` Wolfram Sang
2014-07-03  7:31   ` Lee Jones
2014-07-03  7:31     ` Lee Jones
2014-06-18 18:14 ` Doug Anderson [this message]
2014-06-20  3:45   ` [PATCH v2 10/10] mfd: cros_ec: move EC interrupt to cros_ec_keyb Simon Glass
2014-06-24 10:25   ` Lee Jones
2014-06-24 10:25     ` Lee Jones
2014-07-03  7:32   ` Lee Jones

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1403115247-8853-11-git-send-email-dianders@chromium.org \
    --to=dianders@chromium.org \
    --cc=abrestic@chromium.org \
    --cc=broonie@kernel.org \
    --cc=dmitry.torokhov@gmail.com \
    --cc=geert@linux-m68k.org \
    --cc=javier.martinez@collabora.co.uk \
    --cc=lee.jones@linaro.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=olof@lixom.net \
    --cc=sameo@linux.intel.com \
    --cc=sjg@chromium.org \
    --cc=sonnyrao@chromium.org \
    --cc=swarren@wwwdotorg.org \
    --cc=wfrichar@chromium.org \
    --cc=wsa@the-dreams.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.