On 2018-12-19 7:19 p.m., Lyude Paul wrote: > Up until now, freeing payloads on remote MST hubs that just had ports > removed has almost never worked because we've been relying on port > validation in order to stop us from accessing ports that have already > been freed from memory, but ports which need their payloads released due > to being removed will never be a valid part of the topology after > they've been removed. > > Since we've introduced malloc refs, we can replace all of the validation > logic in payload helpers which are used for deallocation with some > well-placed malloc krefs. This ensures that regardless of whether or not > the ports are still valid and in the topology, any port which has an > allocated payload will remain allocated in memory until it's payloads > have been removed - finally allowing us to actually release said > payloads correctly. > > Signed-off-by: Lyude Paul <lyude@xxxxxxxxxx> > Reviewed-by: Daniel Vetter <daniel.vetter@xxxxxxxx> > Cc: David Airlie <airlied@xxxxxxxxxx> > Cc: Jerry Zuo <Jerry.Zuo@xxxxxxx> > Cc: Harry Wentland <harry.wentland@xxxxxxx> > Cc: Juston Li <juston.li@xxxxxxxxx> Reviewed-by: Harry Wentland <harry.wentland@xxxxxxx> Harry > --- > drivers/gpu/drm/drm_dp_mst_topology.c | 54 +++++++++++++++------------ > 1 file changed, 30 insertions(+), 24 deletions(-) > > diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c > index ef8637f37564..11dd3ede7b7d 100644 > --- a/drivers/gpu/drm/drm_dp_mst_topology.c > +++ b/drivers/gpu/drm/drm_dp_mst_topology.c > @@ -2100,10 +2100,6 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, > u8 sinks[DRM_DP_MAX_SDP_STREAMS]; > int i; > > - port = drm_dp_mst_topology_get_port_validated(mgr, port); > - if (!port) > - return -EINVAL; > - > port_num = port->port_num; > mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent); > if (!mstb) { > @@ -2111,10 +2107,8 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, > port->parent, > &port_num); > > - if (!mstb) { > - drm_dp_mst_topology_put_port(port); > + if (!mstb) > return -EINVAL; > - } > } > > txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); > @@ -2151,7 +2145,6 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, > kfree(txmsg); > fail_put: > drm_dp_mst_topology_put_mstb(mstb); > - drm_dp_mst_topology_put_port(port); > return ret; > } > > @@ -2256,15 +2249,16 @@ static int drm_dp_destroy_payload_step2(struct drm_dp_mst_topology_mgr *mgr, > */ > int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) > { > - int i, j; > - int cur_slots = 1; > struct drm_dp_payload req_payload; > struct drm_dp_mst_port *port; > + int i, j; > + int cur_slots = 1; > > mutex_lock(&mgr->payload_lock); > for (i = 0; i < mgr->max_payloads; i++) { > struct drm_dp_vcpi *vcpi = mgr->proposed_vcpis[i]; > struct drm_dp_payload *payload = &mgr->payloads[i]; > + bool put_port = false; > > /* solve the current payloads - compare to the hw ones > - update the hw view */ > @@ -2272,12 +2266,20 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) > if (vcpi) { > port = container_of(vcpi, struct drm_dp_mst_port, > vcpi); > - port = drm_dp_mst_topology_get_port_validated(mgr, > - port); > - if (!port) { > - mutex_unlock(&mgr->payload_lock); > - return -EINVAL; > + > + /* Validated ports don't matter if we're releasing > + * VCPI > + */ > + if (vcpi->num_slots) { > + port = drm_dp_mst_topology_get_port_validated( > + mgr, port); > + if (!port) { > + mutex_unlock(&mgr->payload_lock); > + return -EINVAL; > + } > + put_port = true; > } > + > req_payload.num_slots = vcpi->num_slots; > req_payload.vcpi = vcpi->vcpi; > } else { > @@ -2309,7 +2311,7 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) > } > cur_slots += req_payload.num_slots; > > - if (port) > + if (put_port) > drm_dp_mst_topology_put_port(port); > } > > @@ -3124,6 +3126,8 @@ bool drm_dp_mst_allocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, > DRM_DEBUG_KMS("initing vcpi for pbn=%d slots=%d\n", > pbn, port->vcpi.num_slots); > > + /* Keep port allocated until it's payload has been removed */ > + drm_dp_mst_get_port_malloc(port); > drm_dp_mst_topology_put_port(port); > return true; > out: > @@ -3153,11 +3157,12 @@ EXPORT_SYMBOL(drm_dp_mst_get_vcpi_slots); > */ > void drm_dp_mst_reset_vcpi_slots(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port) > { > - port = drm_dp_mst_topology_get_port_validated(mgr, port); > - if (!port) > - return; > + /* > + * A port with VCPI will remain allocated until it's VCPI is > + * released, no verified ref needed > + */ > + > port->vcpi.num_slots = 0; > - drm_dp_mst_topology_put_port(port); > } > EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots); > > @@ -3169,16 +3174,17 @@ EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots); > void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, > struct drm_dp_mst_port *port) > { > - port = drm_dp_mst_topology_get_port_validated(mgr, port); > - if (!port) > - return; > + /* > + * A port with VCPI will remain allocated until it's VCPI is > + * released, no verified ref needed > + */ > > drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi); > port->vcpi.num_slots = 0; > port->vcpi.pbn = 0; > port->vcpi.aligned_pbn = 0; > port->vcpi.vcpi = 0; > - drm_dp_mst_topology_put_port(port); > + drm_dp_mst_put_port_malloc(port); > } > EXPORT_SYMBOL(drm_dp_mst_deallocate_vcpi); > > _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel