Re: [PATCH 4.7 172/186] Input: i8042 - break load dependency between atkbd/psmouse and i8042

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Aug 18, 2016 at 6:59 AM, Greg Kroah-Hartman
<gregkh@xxxxxxxxxxxxxxxxxxx> wrote:
> 4.7-stable review patch.  If anyone has any objections, please let me know.

Greg, please hold this patch off till your next cycle. I will be
sending a fixup for it to Linus today or tomorrow.

Thanks!

>
> ------------------
>
> From: Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx>
>
> commit 4097461897df91041382ff6fcd2bfa7ee6b2448c upstream.
>
> As explained in 1407814240-4275-1-git-send-email-decui@xxxxxxxxxxxxx we
> have a hard load dependency between i8042 and atkbd which prevents
> keyboard from working on Gen2 Hyper-V VMs.
>
>> hyperv_keyboard invokes serio_interrupt(), which needs a valid serio
>> driver like atkbd.c.  atkbd.c depends on libps2.c because it invokes
>> ps2_command().  libps2.c depends on i8042.c because it invokes
>> i8042_check_port_owner().  As a result, hyperv_keyboard actually
>> depends on i8042.c.
>>
>> For a Generation 2 Hyper-V VM (meaning no i8042 device emulated), if a
>> Linux VM (like Arch Linux) happens to configure CONFIG_SERIO_I8042=m
>> rather than =y, atkbd.ko can't load because i8042.ko can't load(due to
>> no i8042 device emulated) and finally hyperv_keyboard can't work and
>> the user can't input: https://bugs.archlinux.org/task/39820
>> (Ubuntu/RHEL/SUSE aren't affected since they use CONFIG_SERIO_I8042=y)
>
> To break the dependency we move away from using i8042_check_port_owner()
> and instead allow serio port owner specify a mutex that clients should use
> to serialize PS/2 command stream.
>
> Reported-by: Mark Laws <mdl@xxxxxxxx>
> Tested-by: Mark Laws <mdl@xxxxxxxx>
> Signed-off-by: Dmitry Torokhov <dmitry.torokhov@xxxxxxxxx>
> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
>
> ---
>  drivers/input/serio/i8042.c  |   16 +---------------
>  drivers/input/serio/libps2.c |   10 ++++------
>  include/linux/i8042.h        |    6 ------
>  include/linux/serio.h        |   24 +++++++++++++++++++-----
>  4 files changed, 24 insertions(+), 32 deletions(-)
>
> --- a/drivers/input/serio/i8042.c
> +++ b/drivers/input/serio/i8042.c
> @@ -1277,6 +1277,7 @@ static int __init i8042_create_kbd_port(
>         serio->start            = i8042_start;
>         serio->stop             = i8042_stop;
>         serio->close            = i8042_port_close;
> +       serio->ps2_cmd_mutex    = &i8042_mutex;
>         serio->port_data        = port;
>         serio->dev.parent       = &i8042_platform_device->dev;
>         strlcpy(serio->name, "i8042 KBD port", sizeof(serio->name));
> @@ -1373,21 +1374,6 @@ static void i8042_unregister_ports(void)
>         }
>  }
>
> -/*
> - * Checks whether port belongs to i8042 controller.
> - */
> -bool i8042_check_port_owner(const struct serio *port)
> -{
> -       int i;
> -
> -       for (i = 0; i < I8042_NUM_PORTS; i++)
> -               if (i8042_ports[i].serio == port)
> -                       return true;
> -
> -       return false;
> -}
> -EXPORT_SYMBOL(i8042_check_port_owner);
> -
>  static void i8042_free_irqs(void)
>  {
>         if (i8042_aux_irq_registered)
> --- a/drivers/input/serio/libps2.c
> +++ b/drivers/input/serio/libps2.c
> @@ -56,19 +56,17 @@ EXPORT_SYMBOL(ps2_sendbyte);
>
>  void ps2_begin_command(struct ps2dev *ps2dev)
>  {
> -       mutex_lock(&ps2dev->cmd_mutex);
> +       struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex;
>
> -       if (i8042_check_port_owner(ps2dev->serio))
> -               i8042_lock_chip();
> +       mutex_lock(m);
>  }
>  EXPORT_SYMBOL(ps2_begin_command);
>
>  void ps2_end_command(struct ps2dev *ps2dev)
>  {
> -       if (i8042_check_port_owner(ps2dev->serio))
> -               i8042_unlock_chip();
> +       struct mutex *m = ps2dev->serio->ps2_cmd_mutex ?: &ps2dev->cmd_mutex;
>
> -       mutex_unlock(&ps2dev->cmd_mutex);
> +       mutex_unlock(m);
>  }
>  EXPORT_SYMBOL(ps2_end_command);
>
> --- a/include/linux/i8042.h
> +++ b/include/linux/i8042.h
> @@ -62,7 +62,6 @@ struct serio;
>  void i8042_lock_chip(void);
>  void i8042_unlock_chip(void);
>  int i8042_command(unsigned char *param, int command);
> -bool i8042_check_port_owner(const struct serio *);
>  int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
>                                         struct serio *serio));
>  int i8042_remove_filter(bool (*filter)(unsigned char data, unsigned char str,
> @@ -83,11 +82,6 @@ static inline int i8042_command(unsigned
>         return -ENODEV;
>  }
>
> -static inline bool i8042_check_port_owner(const struct serio *serio)
> -{
> -       return false;
> -}
> -
>  static inline int i8042_install_filter(bool (*filter)(unsigned char data, unsigned char str,
>                                         struct serio *serio))
>  {
> --- a/include/linux/serio.h
> +++ b/include/linux/serio.h
> @@ -31,7 +31,8 @@ struct serio {
>
>         struct serio_device_id id;
>
> -       spinlock_t lock;                /* protects critical sections from port's interrupt handler */
> +       /* Protects critical sections from port's interrupt handler */
> +       spinlock_t lock;
>
>         int (*write)(struct serio *, unsigned char);
>         int (*open)(struct serio *);
> @@ -40,16 +41,29 @@ struct serio {
>         void (*stop)(struct serio *);
>
>         struct serio *parent;
> -       struct list_head child_node;    /* Entry in parent->children list */
> +       /* Entry in parent->children list */
> +       struct list_head child_node;
>         struct list_head children;
> -       unsigned int depth;             /* level of nesting in serio hierarchy */
> +       /* Level of nesting in serio hierarchy */
> +       unsigned int depth;
>
> -       struct serio_driver *drv;       /* accessed from interrupt, must be protected by serio->lock and serio->sem */
> -       struct mutex drv_mutex;         /* protects serio->drv so attributes can pin driver */
> +       /*
> +        * serio->drv is accessed from interrupt handlers; when modifying
> +        * caller should acquire serio->drv_mutex and serio->lock.
> +        */
> +       struct serio_driver *drv;
> +       /* Protects serio->drv so attributes can pin current driver */
> +       struct mutex drv_mutex;
>
>         struct device dev;
>
>         struct list_head node;
> +
> +       /*
> +        * For use by PS/2 layer when several ports share hardware and
> +        * may get indigestion when exposed to concurrent access (i8042).
> +        */
> +       struct mutex *ps2_cmd_mutex;
>  };
>  #define to_serio_port(d)       container_of(d, struct serio, dev)
>
>
>



-- 
Dmitry
--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]