Re: [PATCH v1 2/6] mfd: cros_ec: Add MKBP event support

2016-02-11 Thread Gwendal Grignou
On Thu, Feb 11, 2016 at 6:52 AM, Tomeu Vizoso
 wrote:
>
> On 02/05/2016 06:24 PM, Gwendal Grignou wrote:
> > We should not used kmalloc when get events, these functions are called
> > quite often.
> > Gwendal.
> >
> > On Fri, Feb 5, 2016 at 5:32 AM, Tomeu Vizoso  > > wrote:
> >
> > +static int cros_ec_get_host_command_version_mask(struct
> > cros_ec_device *ec_dev,
> > +   u16 cmd, u32 *mask)
> > +{
> > +   struct ec_params_get_cmd_versions *pver;
> > +   struct ec_response_get_cmd_versions *rver;
> > +   struct cros_ec_command *msg;
> > +   int ret;
> > +
> > +   msg = kmalloc(sizeof(*msg) + max(sizeof(rver), sizeof(pver)),
> > + GFP_KERNEL);
> > +   if (!msg)
> > +   return -ENOMEM;
> >
> >  Victor's version in https://chromium-review.googlesource.com/272954
> > looks cleaner: no malloc, no need to cast rver.
>
> I agree that it looks cleaner, but how would you allocate the payload at
> build time if it has to be max(sizeof(*pver), sizeof(*rver))?
For this one, given cros_ec_get_host_command_version_mask() is called
once, a kmalloc is fine.

Gwendal.


Re: [PATCH v1 2/6] mfd: cros_ec: Add MKBP event support

2016-02-11 Thread Tomeu Vizoso
On 02/05/2016 06:24 PM, Gwendal Grignou wrote:
> We should not used kmalloc when get events, these functions are called
> quite often.
> Gwendal.
> 
> On Fri, Feb 5, 2016 at 5:32 AM, Tomeu Vizoso  > wrote:
> 
> +static int cros_ec_get_host_command_version_mask(struct
> cros_ec_device *ec_dev,
> +   u16 cmd, u32 *mask)
> +{
> +   struct ec_params_get_cmd_versions *pver;
> +   struct ec_response_get_cmd_versions *rver;
> +   struct cros_ec_command *msg;
> +   int ret;
> +
> +   msg = kmalloc(sizeof(*msg) + max(sizeof(rver), sizeof(pver)),
> + GFP_KERNEL);
> +   if (!msg)
> +   return -ENOMEM;
> 
>  Victor's version in https://chromium-review.googlesource.com/272954
> looks cleaner: no malloc, no need to cast rver.

I agree that it looks cleaner, but how would you allocate the payload at
build time if it has to be max(sizeof(*pver), sizeof(*rver))?

> +static int get_next_event(struct cros_ec_device *ec_dev)
> +{
> +   struct cros_ec_command *msg;
> +   int ret;
> +
> +   msg = kmalloc(sizeof(*msg) + sizeof(ec_dev->event_data),
> GFP_KERNEL);
> +   if (!msg)
> +   return -ENOMEM;
> 
> Same grip about malloc(). This function will be called very often when
> sensors are used.

Ok.

> +static int get_keyboard_state_event(struct cros_ec_device *ec_dev)
> +{
> +   struct cros_ec_command *msg;
> +
> +   msg = kmalloc(sizeof(*msg) + sizeof(ec_dev->event_data.data),
> + GFP_KERNEL);
> +   if (!msg)
> +   return -ENOMEM;
> 
> Given this command will be used on every key press, it is better to
> pre-allocate data (like
> in https://chromium-review.googlesource.com/276768) and use msg on the
> stack like Victor's changes.

Ok.

Thanks,

Tomeu


Re: [PATCH v1 2/6] mfd: cros_ec: Add MKBP event support

2016-02-11 Thread Lee Jones
On Wed, 10 Feb 2016, Gwendal Grignou wrote:

> [Resend[We should not used kmalloc when get events, these functions
> are called quite often.
> Gwendal.

Why are you re-sending [again]?  Why are you top posting?  Why aren't
you cutting the 370 lines before your first comment and the 150 lines
after your last?

> On Fri, Feb 5, 2016 at 5:32 AM, Tomeu Vizoso  
> wrote:
> > From: Vic Yang 
> >
> > Newer revisions of the ChromeOS EC add more events besides the keyboard
> > ones. So handle interrupts in the MFD driver and let consumers register
> > for notifications for the events they might care.
> >
> > To keep backward compatibility, if the EC doesn't support MKBP event, we
> > fall back to the old MKBP key matrix host command.
> >
> > Signed-off-by: Vic Yang 
> > [bleung: fixup some context changes going from v3.14 to v3.18]
> > Signed-off-by: Benson Leung 
> > [tomeu: adapted to changes in mainline (in power-supply and 
> > platform/chrome)]
> > Signed-off-by: Tomeu Vizoso 
> > Cc: Randall Spangler 
> > Cc: Vincent Palatin 
> >
> > ---
> >
> >  drivers/input/keyboard/cros_ec_keyb.c   | 135 
> > 
> >  drivers/mfd/cros_ec.c   |  57 +-
> >  drivers/platform/chrome/cros_ec_proto.c | 102 
> >  include/linux/mfd/cros_ec.h |  44 +++
> >  include/linux/mfd/cros_ec_commands.h|  34 
> >  5 files changed, 265 insertions(+), 107 deletions(-)
> >
> > diff --git a/drivers/input/keyboard/cros_ec_keyb.c 
> > b/drivers/input/keyboard/cros_ec_keyb.c
> > index b01966dc7eb3..b891503143dc 100644
> > --- a/drivers/input/keyboard/cros_ec_keyb.c
> > +++ b/drivers/input/keyboard/cros_ec_keyb.c
> > @@ -27,6 +27,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -44,6 +45,7 @@
> >   * @dev: Device pointer
> >   * @idev: Input device
> >   * @ec: Top level ChromeOS device to use to talk to EC
> > + * @notifier: interrupt event notifier for transport devices
> >   */
> >  struct cros_ec_keyb {
> > unsigned int rows;
> > @@ -57,6 +59,7 @@ struct cros_ec_keyb {
> > struct device *dev;
> > struct input_dev *idev;
> > struct cros_ec_device *ec;
> > +   struct notifier_block notifier;
> >  };
> >
> >
> > @@ -146,67 +149,44 @@ static void cros_ec_keyb_process(struct cros_ec_keyb 
> > *ckdev,
> > input_sync(ckdev->idev);
> >  }
> >
> > -static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t 
> > *kb_state)
> > -{
> > -   int ret = 0;
> > -   struct cros_ec_command *msg;
> > -
> > -   msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL);
> > -   if (!msg)
> > -   return -ENOMEM;
> > -
> > -   msg->version = 0;
> > -   msg->command = EC_CMD_MKBP_STATE;
> > -   msg->insize = ckdev->cols;
> > -   msg->outsize = 0;
> > -
> > -   ret = cros_ec_cmd_xfer(ckdev->ec, msg);
> > -   if (ret < 0) {
> > -   dev_err(ckdev->dev, "Error transferring EC message %d\n", 
> > ret);
> > -   goto exit;
> > -   }
> > -
> > -   memcpy(kb_state, msg->data, ckdev->cols);
> > -exit:
> > -   kfree(msg);
> > -   return ret;
> > -}
> > -
> > -static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
> > +static int cros_ec_keyb_open(struct input_dev *dev)
> >  {
> > -   struct cros_ec_keyb *ckdev = data;
> > -   struct cros_ec_device *ec = ckdev->ec;
> > -   int ret;
> > -   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);
> > +   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
> >
> > -   return IRQ_HANDLED;
> > +   return blocking_notifier_chain_register(>ec->event_notifier,
> > +   >notifier);
> >  }
> >
> > -static int cros_ec_keyb_open(struct input_dev *dev)
> > +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;
> >
> > -   return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
> > -   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> > -   "cros_ec_keyb", ckdev);
> > +   blocking_notifier_chain_unregister(>ec->event_notifier,
> > +  >notifier);
> >  }
> >
> > -static void cros_ec_keyb_close(struct input_dev *dev)
> > +static int cros_ec_keyb_work(struct notifier_block *nb,
> > +unsigned long queued_during_suspend, void 
> > *_notify)
> >  {
> > -   struct cros_ec_keyb 

Re: [PATCH v1 2/6] mfd: cros_ec: Add MKBP event support

2016-02-11 Thread Lee Jones
On Wed, 10 Feb 2016, Gwendal Grignou wrote:

> [Resend[We should not used kmalloc when get events, these functions
> are called quite often.
> Gwendal.

Why are you re-sending [again]?  Why are you top posting?  Why aren't
you cutting the 370 lines before your first comment and the 150 lines
after your last?

> On Fri, Feb 5, 2016 at 5:32 AM, Tomeu Vizoso  
> wrote:
> > From: Vic Yang 
> >
> > Newer revisions of the ChromeOS EC add more events besides the keyboard
> > ones. So handle interrupts in the MFD driver and let consumers register
> > for notifications for the events they might care.
> >
> > To keep backward compatibility, if the EC doesn't support MKBP event, we
> > fall back to the old MKBP key matrix host command.
> >
> > Signed-off-by: Vic Yang 
> > [bleung: fixup some context changes going from v3.14 to v3.18]
> > Signed-off-by: Benson Leung 
> > [tomeu: adapted to changes in mainline (in power-supply and 
> > platform/chrome)]
> > Signed-off-by: Tomeu Vizoso 
> > Cc: Randall Spangler 
> > Cc: Vincent Palatin 
> >
> > ---
> >
> >  drivers/input/keyboard/cros_ec_keyb.c   | 135 
> > 
> >  drivers/mfd/cros_ec.c   |  57 +-
> >  drivers/platform/chrome/cros_ec_proto.c | 102 
> >  include/linux/mfd/cros_ec.h |  44 +++
> >  include/linux/mfd/cros_ec_commands.h|  34 
> >  5 files changed, 265 insertions(+), 107 deletions(-)
> >
> > diff --git a/drivers/input/keyboard/cros_ec_keyb.c 
> > b/drivers/input/keyboard/cros_ec_keyb.c
> > index b01966dc7eb3..b891503143dc 100644
> > --- a/drivers/input/keyboard/cros_ec_keyb.c
> > +++ b/drivers/input/keyboard/cros_ec_keyb.c
> > @@ -27,6 +27,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> > @@ -44,6 +45,7 @@
> >   * @dev: Device pointer
> >   * @idev: Input device
> >   * @ec: Top level ChromeOS device to use to talk to EC
> > + * @notifier: interrupt event notifier for transport devices
> >   */
> >  struct cros_ec_keyb {
> > unsigned int rows;
> > @@ -57,6 +59,7 @@ struct cros_ec_keyb {
> > struct device *dev;
> > struct input_dev *idev;
> > struct cros_ec_device *ec;
> > +   struct notifier_block notifier;
> >  };
> >
> >
> > @@ -146,67 +149,44 @@ static void cros_ec_keyb_process(struct cros_ec_keyb 
> > *ckdev,
> > input_sync(ckdev->idev);
> >  }
> >
> > -static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t 
> > *kb_state)
> > -{
> > -   int ret = 0;
> > -   struct cros_ec_command *msg;
> > -
> > -   msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL);
> > -   if (!msg)
> > -   return -ENOMEM;
> > -
> > -   msg->version = 0;
> > -   msg->command = EC_CMD_MKBP_STATE;
> > -   msg->insize = ckdev->cols;
> > -   msg->outsize = 0;
> > -
> > -   ret = cros_ec_cmd_xfer(ckdev->ec, msg);
> > -   if (ret < 0) {
> > -   dev_err(ckdev->dev, "Error transferring EC message %d\n", 
> > ret);
> > -   goto exit;
> > -   }
> > -
> > -   memcpy(kb_state, msg->data, ckdev->cols);
> > -exit:
> > -   kfree(msg);
> > -   return ret;
> > -}
> > -
> > -static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
> > +static int cros_ec_keyb_open(struct input_dev *dev)
> >  {
> > -   struct cros_ec_keyb *ckdev = data;
> > -   struct cros_ec_device *ec = ckdev->ec;
> > -   int ret;
> > -   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);
> > +   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
> >
> > -   return IRQ_HANDLED;
> > +   return blocking_notifier_chain_register(>ec->event_notifier,
> > +   >notifier);
> >  }
> >
> > -static int cros_ec_keyb_open(struct input_dev *dev)
> > +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;
> >
> > -   return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
> > -   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> > -   "cros_ec_keyb", ckdev);
> > +   blocking_notifier_chain_unregister(>ec->event_notifier,
> > +  >notifier);
> >  }
> >
> > -static void cros_ec_keyb_close(struct input_dev *dev)
> > +static int 

Re: [PATCH v1 2/6] mfd: cros_ec: Add MKBP event support

2016-02-11 Thread Tomeu Vizoso
On 02/05/2016 06:24 PM, Gwendal Grignou wrote:
> We should not used kmalloc when get events, these functions are called
> quite often.
> Gwendal.
> 
> On Fri, Feb 5, 2016 at 5:32 AM, Tomeu Vizoso  > wrote:
> 
> +static int cros_ec_get_host_command_version_mask(struct
> cros_ec_device *ec_dev,
> +   u16 cmd, u32 *mask)
> +{
> +   struct ec_params_get_cmd_versions *pver;
> +   struct ec_response_get_cmd_versions *rver;
> +   struct cros_ec_command *msg;
> +   int ret;
> +
> +   msg = kmalloc(sizeof(*msg) + max(sizeof(rver), sizeof(pver)),
> + GFP_KERNEL);
> +   if (!msg)
> +   return -ENOMEM;
> 
>  Victor's version in https://chromium-review.googlesource.com/272954
> looks cleaner: no malloc, no need to cast rver.

I agree that it looks cleaner, but how would you allocate the payload at
build time if it has to be max(sizeof(*pver), sizeof(*rver))?

> +static int get_next_event(struct cros_ec_device *ec_dev)
> +{
> +   struct cros_ec_command *msg;
> +   int ret;
> +
> +   msg = kmalloc(sizeof(*msg) + sizeof(ec_dev->event_data),
> GFP_KERNEL);
> +   if (!msg)
> +   return -ENOMEM;
> 
> Same grip about malloc(). This function will be called very often when
> sensors are used.

Ok.

> +static int get_keyboard_state_event(struct cros_ec_device *ec_dev)
> +{
> +   struct cros_ec_command *msg;
> +
> +   msg = kmalloc(sizeof(*msg) + sizeof(ec_dev->event_data.data),
> + GFP_KERNEL);
> +   if (!msg)
> +   return -ENOMEM;
> 
> Given this command will be used on every key press, it is better to
> pre-allocate data (like
> in https://chromium-review.googlesource.com/276768) and use msg on the
> stack like Victor's changes.

Ok.

Thanks,

Tomeu


Re: [PATCH v1 2/6] mfd: cros_ec: Add MKBP event support

2016-02-11 Thread Gwendal Grignou
On Thu, Feb 11, 2016 at 6:52 AM, Tomeu Vizoso
 wrote:
>
> On 02/05/2016 06:24 PM, Gwendal Grignou wrote:
> > We should not used kmalloc when get events, these functions are called
> > quite often.
> > Gwendal.
> >
> > On Fri, Feb 5, 2016 at 5:32 AM, Tomeu Vizoso  > > wrote:
> >
> > +static int cros_ec_get_host_command_version_mask(struct
> > cros_ec_device *ec_dev,
> > +   u16 cmd, u32 *mask)
> > +{
> > +   struct ec_params_get_cmd_versions *pver;
> > +   struct ec_response_get_cmd_versions *rver;
> > +   struct cros_ec_command *msg;
> > +   int ret;
> > +
> > +   msg = kmalloc(sizeof(*msg) + max(sizeof(rver), sizeof(pver)),
> > + GFP_KERNEL);
> > +   if (!msg)
> > +   return -ENOMEM;
> >
> >  Victor's version in https://chromium-review.googlesource.com/272954
> > looks cleaner: no malloc, no need to cast rver.
>
> I agree that it looks cleaner, but how would you allocate the payload at
> build time if it has to be max(sizeof(*pver), sizeof(*rver))?
For this one, given cros_ec_get_host_command_version_mask() is called
once, a kmalloc is fine.

Gwendal.


Re: [PATCH v1 2/6] mfd: cros_ec: Add MKBP event support

2016-02-10 Thread Gwendal Grignou
[Resend[We should not used kmalloc when get events, these functions
are called quite often.
Gwendal.

On Fri, Feb 5, 2016 at 5:32 AM, Tomeu Vizoso  wrote:
> From: Vic Yang 
>
> Newer revisions of the ChromeOS EC add more events besides the keyboard
> ones. So handle interrupts in the MFD driver and let consumers register
> for notifications for the events they might care.
>
> To keep backward compatibility, if the EC doesn't support MKBP event, we
> fall back to the old MKBP key matrix host command.
>
> Signed-off-by: Vic Yang 
> [bleung: fixup some context changes going from v3.14 to v3.18]
> Signed-off-by: Benson Leung 
> [tomeu: adapted to changes in mainline (in power-supply and platform/chrome)]
> Signed-off-by: Tomeu Vizoso 
> Cc: Randall Spangler 
> Cc: Vincent Palatin 
>
> ---
>
>  drivers/input/keyboard/cros_ec_keyb.c   | 135 
> 
>  drivers/mfd/cros_ec.c   |  57 +-
>  drivers/platform/chrome/cros_ec_proto.c | 102 
>  include/linux/mfd/cros_ec.h |  44 +++
>  include/linux/mfd/cros_ec_commands.h|  34 
>  5 files changed, 265 insertions(+), 107 deletions(-)
>
> diff --git a/drivers/input/keyboard/cros_ec_keyb.c 
> b/drivers/input/keyboard/cros_ec_keyb.c
> index b01966dc7eb3..b891503143dc 100644
> --- a/drivers/input/keyboard/cros_ec_keyb.c
> +++ b/drivers/input/keyboard/cros_ec_keyb.c
> @@ -27,6 +27,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -44,6 +45,7 @@
>   * @dev: Device pointer
>   * @idev: Input device
>   * @ec: Top level ChromeOS device to use to talk to EC
> + * @notifier: interrupt event notifier for transport devices
>   */
>  struct cros_ec_keyb {
> unsigned int rows;
> @@ -57,6 +59,7 @@ struct cros_ec_keyb {
> struct device *dev;
> struct input_dev *idev;
> struct cros_ec_device *ec;
> +   struct notifier_block notifier;
>  };
>
>
> @@ -146,67 +149,44 @@ static void cros_ec_keyb_process(struct cros_ec_keyb 
> *ckdev,
> input_sync(ckdev->idev);
>  }
>
> -static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t 
> *kb_state)
> -{
> -   int ret = 0;
> -   struct cros_ec_command *msg;
> -
> -   msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL);
> -   if (!msg)
> -   return -ENOMEM;
> -
> -   msg->version = 0;
> -   msg->command = EC_CMD_MKBP_STATE;
> -   msg->insize = ckdev->cols;
> -   msg->outsize = 0;
> -
> -   ret = cros_ec_cmd_xfer(ckdev->ec, msg);
> -   if (ret < 0) {
> -   dev_err(ckdev->dev, "Error transferring EC message %d\n", 
> ret);
> -   goto exit;
> -   }
> -
> -   memcpy(kb_state, msg->data, ckdev->cols);
> -exit:
> -   kfree(msg);
> -   return ret;
> -}
> -
> -static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
> +static int cros_ec_keyb_open(struct input_dev *dev)
>  {
> -   struct cros_ec_keyb *ckdev = data;
> -   struct cros_ec_device *ec = ckdev->ec;
> -   int ret;
> -   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);
> +   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
>
> -   return IRQ_HANDLED;
> +   return blocking_notifier_chain_register(>ec->event_notifier,
> +   >notifier);
>  }
>
> -static int cros_ec_keyb_open(struct input_dev *dev)
> +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;
>
> -   return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
> -   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> -   "cros_ec_keyb", ckdev);
> +   blocking_notifier_chain_unregister(>ec->event_notifier,
> +  >notifier);
>  }
>
> -static void cros_ec_keyb_close(struct input_dev *dev)
> +static int cros_ec_keyb_work(struct notifier_block *nb,
> +unsigned long queued_during_suspend, void 
> *_notify)
>  {
> -   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
> -   struct cros_ec_device *ec = ckdev->ec;
> +   struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
> + notifier);
>
> -   free_irq(ec->irq, ckdev);
> +   if (ckdev->ec->event_data.event_type != EC_MKBP_EVENT_KEY_MATRIX)
> +   return NOTIFY_DONE;
> +   /*
> +* If EC is not the wake source, discard key state changes during
> +* suspend.

Re: [PATCH v1 2/6] mfd: cros_ec: Add MKBP event support

2016-02-10 Thread Gwendal Grignou
[Resend[We should not used kmalloc when get events, these functions
are called quite often.
Gwendal.

On Fri, Feb 5, 2016 at 5:32 AM, Tomeu Vizoso  wrote:
> From: Vic Yang 
>
> Newer revisions of the ChromeOS EC add more events besides the keyboard
> ones. So handle interrupts in the MFD driver and let consumers register
> for notifications for the events they might care.
>
> To keep backward compatibility, if the EC doesn't support MKBP event, we
> fall back to the old MKBP key matrix host command.
>
> Signed-off-by: Vic Yang 
> [bleung: fixup some context changes going from v3.14 to v3.18]
> Signed-off-by: Benson Leung 
> [tomeu: adapted to changes in mainline (in power-supply and platform/chrome)]
> Signed-off-by: Tomeu Vizoso 
> Cc: Randall Spangler 
> Cc: Vincent Palatin 
>
> ---
>
>  drivers/input/keyboard/cros_ec_keyb.c   | 135 
> 
>  drivers/mfd/cros_ec.c   |  57 +-
>  drivers/platform/chrome/cros_ec_proto.c | 102 
>  include/linux/mfd/cros_ec.h |  44 +++
>  include/linux/mfd/cros_ec_commands.h|  34 
>  5 files changed, 265 insertions(+), 107 deletions(-)
>
> diff --git a/drivers/input/keyboard/cros_ec_keyb.c 
> b/drivers/input/keyboard/cros_ec_keyb.c
> index b01966dc7eb3..b891503143dc 100644
> --- a/drivers/input/keyboard/cros_ec_keyb.c
> +++ b/drivers/input/keyboard/cros_ec_keyb.c
> @@ -27,6 +27,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -44,6 +45,7 @@
>   * @dev: Device pointer
>   * @idev: Input device
>   * @ec: Top level ChromeOS device to use to talk to EC
> + * @notifier: interrupt event notifier for transport devices
>   */
>  struct cros_ec_keyb {
> unsigned int rows;
> @@ -57,6 +59,7 @@ struct cros_ec_keyb {
> struct device *dev;
> struct input_dev *idev;
> struct cros_ec_device *ec;
> +   struct notifier_block notifier;
>  };
>
>
> @@ -146,67 +149,44 @@ static void cros_ec_keyb_process(struct cros_ec_keyb 
> *ckdev,
> input_sync(ckdev->idev);
>  }
>
> -static int cros_ec_keyb_get_state(struct cros_ec_keyb *ckdev, uint8_t 
> *kb_state)
> -{
> -   int ret = 0;
> -   struct cros_ec_command *msg;
> -
> -   msg = kmalloc(sizeof(*msg) + ckdev->cols, GFP_KERNEL);
> -   if (!msg)
> -   return -ENOMEM;
> -
> -   msg->version = 0;
> -   msg->command = EC_CMD_MKBP_STATE;
> -   msg->insize = ckdev->cols;
> -   msg->outsize = 0;
> -
> -   ret = cros_ec_cmd_xfer(ckdev->ec, msg);
> -   if (ret < 0) {
> -   dev_err(ckdev->dev, "Error transferring EC message %d\n", 
> ret);
> -   goto exit;
> -   }
> -
> -   memcpy(kb_state, msg->data, ckdev->cols);
> -exit:
> -   kfree(msg);
> -   return ret;
> -}
> -
> -static irqreturn_t cros_ec_keyb_irq(int irq, void *data)
> +static int cros_ec_keyb_open(struct input_dev *dev)
>  {
> -   struct cros_ec_keyb *ckdev = data;
> -   struct cros_ec_device *ec = ckdev->ec;
> -   int ret;
> -   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);
> +   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
>
> -   return IRQ_HANDLED;
> +   return blocking_notifier_chain_register(>ec->event_notifier,
> +   >notifier);
>  }
>
> -static int cros_ec_keyb_open(struct input_dev *dev)
> +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;
>
> -   return request_threaded_irq(ec->irq, NULL, cros_ec_keyb_irq,
> -   IRQF_TRIGGER_LOW | IRQF_ONESHOT,
> -   "cros_ec_keyb", ckdev);
> +   blocking_notifier_chain_unregister(>ec->event_notifier,
> +  >notifier);
>  }
>
> -static void cros_ec_keyb_close(struct input_dev *dev)
> +static int cros_ec_keyb_work(struct notifier_block *nb,
> +unsigned long queued_during_suspend, void 
> *_notify)
>  {
> -   struct cros_ec_keyb *ckdev = input_get_drvdata(dev);
> -   struct cros_ec_device *ec = ckdev->ec;
> +   struct cros_ec_keyb *ckdev = container_of(nb, struct cros_ec_keyb,
> + notifier);
>
> -   free_irq(ec->irq, ckdev);
> +   if (ckdev->ec->event_data.event_type !=