CHROMIUM: mfd: chromeos_ec: use threaded irq for EC
authorVincent Palatin <vpalatin@chromium.org>
Wed, 16 May 2012 15:34:20 +0000 (08:34 -0700)
committerOlof Johansson <olofj@chromium.org>
Wed, 20 Jun 2012 19:07:52 +0000 (12:07 -0700)
It suits better the I2C-based MFD model and will let us more room to
implement IRQ muxing with an irqchip and level triggered interrupt.

The irq thread is scheduled by SCHED_FIFO which is higher priority than
SCHED_OTHER used by the current workqueue.

Signed-off-by: Vincent Palatin <vpalatin@chromium.org>
BUG=chrome-os-partner:9594
TEST=on Daisy2 board, test keyboard input in ChromeOS browser.

(cherry picked from commit c370a8a7d19451adac19cb26bcef06620e2f3d3f)

Change-Id: Ieb8af462d89d792b901381d32f13c9ae28f5e48d
Reviewed-on: https://gerrit-int.chromium.org/17854
Tested-by: Vincent Palatin <vpalatin@chromium.org>
Reviewed-by: Luigi Semenzato <semenzato@google.com>
Commit-Ready: Vincent Palatin <vpalatin@chromium.org>

drivers/input/keyboard/mkbp.c
drivers/mfd/chromeos_ec.c
include/linux/mfd/chromeos_ec.h

index 79a4bb7..2fe555a 100644 (file)
@@ -40,7 +40,6 @@ struct mkbp_device {
        struct input_dev *idev;
        struct chromeos_ec_device *ec;
        struct notifier_block notifier;
-       struct work_struct work;
 };
 
 
@@ -219,38 +218,30 @@ static int mkbp_open(struct input_dev *dev)
 {
        struct mkbp_device *mkbp_dev = input_get_drvdata(dev);
 
-       return atomic_notifier_chain_register(&mkbp_dev->ec->event_notifier,
-                                             &mkbp_dev->notifier);
+       return blocking_notifier_chain_register(&mkbp_dev->ec->event_notifier,
+                                               &mkbp_dev->notifier);
 }
 
 static void mkbp_close(struct input_dev *dev)
 {
        struct mkbp_device *mkbp_dev = input_get_drvdata(dev);
 
-       atomic_notifier_chain_unregister(&mkbp_dev->ec->event_notifier,
-                                        &mkbp_dev->notifier);
+       blocking_notifier_chain_unregister(&mkbp_dev->ec->event_notifier,
+                                          &mkbp_dev->notifier);
 }
 
-static void mkbp_work(struct work_struct *work)
+static int mkbp_work(struct notifier_block *nb,
+                    unsigned long state, void *_notify)
 {
        int ret;
-       struct mkbp_device *mkbp_dev =
-                       container_of(work, struct mkbp_device, work);
+       struct mkbp_device *mkbp_dev = container_of(nb, struct mkbp_device,
+                                                   notifier);
        uint8_t kb_state[MKBP_NUM_COLS];
 
        ret = mkbp_dev->ec->send_command(mkbp_dev->ec, MKBP_CMDC_KEY_STATE,
                                    kb_state, MKBP_NUM_COLS);
        if (ret >= 0)
                mkbp_process(mkbp_dev, kb_state, ret);
-}
-
-static int mkbp_notify(struct notifier_block *nb,
-                           unsigned long state, void *_notify)
-{
-       struct mkbp_device *mkbp_dev = container_of(nb, struct mkbp_device,
-                                                   notifier);
-
-       schedule_work(&mkbp_dev->work);
 
        return NOTIFY_DONE;
 }
@@ -275,11 +266,9 @@ static int __devinit mkbp_probe(struct platform_device *pdev)
        }
 
        mkbp_dev->ec = ec;
-       mkbp_dev->notifier.notifier_call = mkbp_notify;
+       mkbp_dev->notifier.notifier_call = mkbp_work;
        mkbp_dev->dev = dev;
 
-       INIT_WORK(&mkbp_dev->work, &mkbp_work);
-
        idev->name = ec->client->name;
        idev->phys = ec->client->adapter->name;
        idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
index db15dd5..559e619 100644 (file)
@@ -111,11 +111,11 @@ static int mkbp_command(struct chromeos_ec_device *ec_dev,
        return ret;
 }
 
-static irqreturn_t mkbp_isr(int irq, void *data)
+static irqreturn_t ec_irq_thread(int irq, void *data)
 {
        struct chromeos_ec_device *ec = data;
 
-       atomic_notifier_call_chain(&ec->event_notifier, 1, ec);
+       blocking_notifier_call_chain(&ec->event_notifier, 1, ec);
 
        return IRQ_HANDLED;
 }
@@ -166,10 +166,11 @@ static int __devinit cros_ec_probe(struct i2c_client *client,
        ec_dev->irq = client->irq;
        ec_dev->send_command = mkbp_command;
 
-       ATOMIC_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier);
+       BLOCKING_INIT_NOTIFIER_HEAD(&ec_dev->event_notifier);
 
-       err = request_irq(ec_dev->irq, mkbp_isr,
-                         IRQF_TRIGGER_FALLING, "chromeos-ec", ec_dev);
+       err = request_threaded_irq(ec_dev->irq, NULL, ec_irq_thread,
+                                  IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                  "chromeos-ec", ec_dev);
        if (err) {
                dev_err(dev, "request irq %d: error %d\n", ec_dev->irq, err);
                goto fail;
index efea4e4..2604a1e 100644 (file)
@@ -46,7 +46,7 @@ struct chromeos_ec_device {
        struct device *dev;
        struct i2c_client *client;
        int irq;
-       struct atomic_notifier_head event_notifier;
+       struct blocking_notifier_head event_notifier;
        int (*send_command)(struct chromeos_ec_device *ec,
                        char cmd, uint8_t *buf, int buf_len);
 };