• Yurii Pavlovskyi's avatar
    platform/x86: asus-wmi: Support WMI event queue · 1a373d15
    Yurii Pavlovskyi authored
    Event codes are expected to be retrieved from a queue on at least some
    models. Specifically, very likely the ACPI WMI devices with _UID ATK are
    queued whereas those with ASUSWMI are not [1].
    
    The WMI event codes are pushed into a circular buffer queue. After the INIT
    method is called, ACPI code is allowed to push events into this buffer.
    The INIT method cannot be reverted. If the module is unloaded and an event
    (such as hotkey press) gets emitted before inserting it back the events get
    processed delayed by one or if the queue overflows, additionally delayed by
    about 3 seconds.
    
    It might be considered a minor issue and no normal user would likely
    observe this (there is little reason unloading the driver), but it does
    significantly frustrate a developer who is unlucky enough to encounter
    this. Therefore, the fallback to unqueued behavior occurs whenever
    something unexpected happens.
    
    The fix flushes the old key codes out of the queue on load. After receiving
    event the queue is read until either ..FFFF or 1 is encountered. Also as
    noted in [1] it is checked whether notify code is equal to 0xFF before
    enabling queue processing in WMI notify handler.
    
    DSDT examples:
    
    FX505GM
    Device (ATKD)
    { ..
        Name (ATKQ, Package (0x10)
        {
            0xFFFFFFFF, ..
        }
    
        Method (IANQ, 1, Serialized)
        {
            If ((AQNO >= 0x10))
            {
                Local0 = 0x64
                While ((Local0 && (AQNO >= 0x10)))
                {
                    Local0--
                    Sleep (0x0A)
                }
                ...
            ..
            AQTI++
            AQTI &= 0x0F
            ATKQ [AQTI] = Arg0
            ...
        }
    
        Method (GANQ, 0, Serialized)
        {
            ..
            If (AQNO)
            {
                ...
                Local0 = DerefOf (ATKQ [AQHI])
                AQHI++
                AQHI &= 0x0F
                Return (Local0)
            }
    
            Return (One)
        }
    
    This code is almost identical to K54C, which does return Ones on empty
    queue.
    
    K54C:
    Method (GANQ, 0, Serialized)
    {
        If (AQNO)
        {
            ...
            Return (Local0)
        }
    
        Return (Ones)
    }
    
    [1] Link: https://lkml.org/lkml/2019/4/12/104Signed-off-by: default avatarYurii Pavlovskyi <yurii.pavlovskyi@gmail.com>
    Suggested-by: default avatarDaniel Drake <drake@endlessm.com>
    Signed-off-by: default avatarAndy Shevchenko <andriy.shevchenko@linux.intel.com>
    1a373d15
asus-wmi.c 58.7 KB