• Daniel Stone's avatar
    component: remove device from master match list on failed add · 8e7199c2
    Daniel Stone authored
    Calling component_add() may result in the completion of a set of
    devices, which will try to bring up a master. In bringing the master
    up, we populate its match array with the current set of children.
    
    If binding any of the devices fails, component_add() itself will fail,
    free the struct component entry, and return to the caller. The
    now-freed entry is never removed from the master's match array, and
    will later be used in a futile attempt to bind to freed memory.
    
    Bring component_add's behaviour on failure to bring up a master into
    line with component_del by removing the (to-be-freed) component from
    the master's match array.
    
    The specific case which broke was:
      - rockchip_drm_drv adds a component master
      - dwhdmi_rockchip adds a child component in probe (master incomplete)
      - rockchip_drm_vop adds two children in probe, which completes the
        set
      - inside component_add, we try to bring up the master, having
        populated the master's match array, and fail with EPROBE_DEFER from
        dwhdmi_rockchip; we delete the putative component
      - rockchip_drm_vop's probe fails and returns EPROBE_DEFER
      - we later re-probe rockchip_drm_vop and add the component; the
        master is complete, so we attempt to bring it up again
      - walking the match array, we find the previous child, whose master
        pointer doesn't match (as it has been freed in the meantime)
      - rockchip_drm_vop probe fails, and will never be attempted again
    
    Fixes: ffc30b74Signed-off-by: default avatarDaniel Stone <daniels@collabora.com>
    Cc: Russell King <rmk+kernel@arm.linux.org.uk>
    Cc: Thierry Reding <treding@nvidia.com>
    Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
    Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
    8e7199c2
component.c 11.8 KB