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: ffc30b74fd
Signed-off-by: Daniel 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: Russell King <rmk+kernel@arm.linux.org.uk>
component_master_add_with_match calls find_components which, if any
components already exist, it attaches to the master struct. However, if
we later encounter an error the master struct is deleted, leaving
components with a dangling pointer to it.
If the error was a temporary one, e.g. for probe deferral, then when
the master device is re-probed, it will fail to find the required
components as they appear to already be attached to a master.
Fix this by nulling components pointers to the master struct when it is
deleted. This code is factored out into a separate function so it can be
shared with component_master_del.
Signed-off-by: Jon Medhurst <tixy@linaro.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Maarten reports that the addition of releasing match data to the
component helper results in a general protection fault on x86_64.
This is caused by the devm resources being freed in reverse order
to their allocation, which caused a use-after-free of the match
array.
Switch the match array to be a more conventional kmalloc/kfree()
affair, explicitly freeing it along with the parent match data
structure.
Reported-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Fixes: ce657b1cdd ("component: add support for releasing match data")
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
The component helper treats the void match data pointer as an opaque
object which needs no further management. When device nodes being
passed, this is not true: the caller should pass its refcount to the
component helper, and there should be a way to drop the refcount when
the matching information is destroyed.
This patch provides a per-match release method in addition to the match
method to solve this issue. Rather than using component_match_add(),
users should use component_match_add_release() which takes an additional
function pointer for releasing this reference.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Since we now have an array which defines each component, maintain the
components to be bound in the array rather than a separate list. We
also need duplicate tracking so we can eliminate multiple bind calls
for the same component: we preserve the list-based component order in
that the first match which adds the component determines its position.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Clean up the code a little; we don't need to check that the master is
unbound for every invocation of try_to_bring_up_master(), so let's move
it to where it's really needed - try_to_bring_up_masters(), where we may
encounter already bound masters.
Reviewed-by: Thierry Reding <treding@nvidia.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Now that drivers create an array of component matches at probe time, we
can retire the old methods. This involves removing the add_components
master method, and removing component_master_add_child() from public
view. We also remove component_add_master() as that interface is no
longer useful.
Acked-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Sachin Kamat reports that "component: add support for component match
array" broke Exynos DRM due to a NULL pointer deref. Fix this.
Reported-by: Sachin Kamat <sachin.kamat@samsung.com>
Tested-by: Sachin Kamat <sachin.kamat@samsung.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Add support for generating a set of component matches at master probe
time, and submitting them to the component layer. This allows the
component layer to perform the matches internally without needing to
call into the master driver, and allows for further restructuring of
the component helper.
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Permit masters to call component_master_add_child() and match the same
child multiple times. This may happen if there's multiple connections
to a single component device from other devices. In such scenarios,
we should not return a failure, but instead ignore the attempt.
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
In try_to_bring_up_master(), we tear down the master's component list
for each error case, except for devres group failure. Fix this
oversight by making the code less prone to such mistakes.
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
We weren't handling the devres issues for the master device failing a
bind, or being unbound properly. Add a devres group to contain these,
and release the resources at the appropriate points.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Subsystems such as ALSA, DRM and others require a single card-level
device structure to represent a subsystem. However, firmware tends to
describe the individual devices and the connections between them.
Therefore, we need a way to gather up the individual component devices
together, and indicate when we have all the component devices.
We do this in DT by providing a "superdevice" node which specifies
the components, eg:
imx-drm {
compatible = "fsl,drm";
crtcs = <&ipu1>;
connectors = <&hdmi>;
};
The superdevice is declared into the component support, along with the
subcomponents. The superdevice receives callbacks to locate the
subcomponents, and identify when all components are present. At this
point, we bind the superdevice, which causes the appropriate subsystem
to be initialised in the conventional way.
When any of the components or superdevice are removed from the system,
we unbind the superdevice, thereby taking the subsystem down.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>