Re: [PATCH v2 2/4] drm/dp_mst: Start tracking per-port VCPI allocations

2018-10-30 Thread Daniel Vetter
On Mon, Oct 29, 2018 at 03:24:29PM +0100, Daniel Vetter wrote:
> On Fri, Oct 26, 2018 at 04:35:47PM -0400, Lyude Paul wrote:
> > There has been a TODO waiting for quite a long time in
> > drm_dp_mst_topology.c:
> > 
> > /* We cannot rely on port->vcpi.num_slots to update
> >  * topology_state->avail_slots as the port may not exist if the parent
> >  * branch device was unplugged. This should be fixed by tracking
> >  * per-port slot allocation in drm_dp_mst_topology_state instead of
> >  * depending on the caller to tell us how many slots to release.
> >  */
> > 
> > That's not the only reason we should fix this: forcing the driver to
> > track the VCPI allocations throughout a state's atomic check is
> > error prone, because it means that extra care has to be taken with the
> > order that drm_dp_atomic_find_vcpi_slots() and
> > drm_dp_atomic_release_vcpi_slots() are called in in order to ensure
> > idempotency. Currently the only driver actually using these helpers,
> > i915, doesn't even do this correctly: multiple ->best_encoder() checks
> > with i915's current implementation would not be idempotent and would
> > over-allocate VCPI slots, something I learned trying to implement
> > fallback retraining in MST.
> > 
> > So: simplify this whole mess, and teach drm_dp_atomic_find_vcpi_slots()
> > and drm_dp_atomic_release_vcpi_slots() to track the VCPI allocations for
> > each port. This allows us to ensure idempotency without having to rely
> > on the driver as much. Additionally: the driver doesn't need to do any
> > kind of VCPI slot tracking anymore if it doesn't need it for it's own
> > internal state.
> > 
> > Additionally; this adds a new drm_dp_mst_atomic_check() helper which
> > must be used by atomic drivers to perform validity checks for the new
> > VCPI allocations incurred by a state.
> > 
> > Also: update the documentation and make it more obvious that these
> > /must/ be called by /all/ atomic drivers supporting MST.
> > 
> > Changes since v1:
> >  - Don't use the now-removed ->atomic_check() for private objects hook,
> >just give drivers a function to call themselves
> > 
> > Signed-off-by: Lyude Paul 
> > Cc: Daniel Vetter 
> > ---
> >  drivers/gpu/drm/drm_dp_mst_topology.c | 190 +-
> >  drivers/gpu/drm/i915/intel_display.c  |   8 ++
> >  drivers/gpu/drm/i915/intel_dp_mst.c   |  31 +++--
> >  include/drm/drm_dp_mst_helper.h   |  11 +-
> >  4 files changed, 192 insertions(+), 48 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
> > b/drivers/gpu/drm/drm_dp_mst_topology.c
> > index 8c3cfac437f4..dcfab7536914 100644
> > --- a/drivers/gpu/drm/drm_dp_mst_topology.c
> > +++ b/drivers/gpu/drm/drm_dp_mst_topology.c
> > @@ -2614,21 +2614,33 @@ static int drm_dp_init_vcpi(struct 
> > drm_dp_mst_topology_mgr *mgr,
> >  }
> >  
> >  /**
> > - * drm_dp_atomic_find_vcpi_slots() - Find and add vcpi slots to the state
> > + * drm_dp_atomic_find_vcpi_slots() - Find and add VCPI slots to the state
> >   * @state: global atomic state
> >   * @mgr: MST topology manager for the port
> >   * @port: port to find vcpi slots for
> >   * @pbn: bandwidth required for the mode in PBN
> >   *
> > + * Allocates VCPI slots to @port, replacing any previous VCPI allocations 
> > it
> > + * may have had. Any atomic drivers which support MST must call this 
> > function
> > + * in their atomic_check() handlers to change the current VCPI allocation 
> > for
> 
> Maybe do a nice kerneldoc reference to the right atomic_check here.
> 
> > + * the new state. After the ->atomic_check() hooks of the driver and all 
> > other
> 
> This will upset the kerneldoc parser I think.
> 
> > + * mode objects in the state have been called, DRM will check the final 
> > VCPI
> > + * allocations to ensure that they will fit into the available bandwidth on
> > + * the topology.
> > + *
> > + * See also: drm_dp_atomic_release_vcpi_slots()
> 
> Also need to reference drm_dp_mst_atomic_check() here and that drivers
> must call it or nothing happens.
> > + *
> >   * RETURNS:
> > - * Total slots in the atomic state assigned for this port or error
> > + * Total slots in the atomic state assigned for this port, or a negative 
> > error
> > + * code if the port no longer exists
> >   */
> >  int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
> >   struct drm_dp_mst_topology_mgr *mgr,
> >   struct drm_dp_mst_port *port, int pbn)
> >  {
> > struct drm_dp_mst_topology_state *topology_state;
> > -   int req_slots;
> > +   struct drm_dp_vcpi_allocation *pos, *vcpi = NULL;
> > +   int prev_slots, req_slots, ret;
> >  
> > topology_state = drm_atomic_get_mst_topology_state(state, mgr);
> > if (IS_ERR(topology_state))
> > @@ -2637,20 +2649,41 @@ int drm_dp_atomic_find_vcpi_slots(struct 
> > drm_atomic_state *state,
> > port = drm_dp_get_validated_port_ref(mgr, port);
> > if (port == NULL)
> > 

Re: [PATCH v2 2/4] drm/dp_mst: Start tracking per-port VCPI allocations

2018-10-29 Thread Lyude Paul
On Mon, 2018-10-29 at 15:24 +0100, Daniel Vetter wrote:
> On Fri, Oct 26, 2018 at 04:35:47PM -0400, Lyude Paul wrote:
> > There has been a TODO waiting for quite a long time in
> > drm_dp_mst_topology.c:
> > 
> > /* We cannot rely on port->vcpi.num_slots to update
> >  * topology_state->avail_slots as the port may not exist if the parent
> >  * branch device was unplugged. This should be fixed by tracking
> >  * per-port slot allocation in drm_dp_mst_topology_state instead of
> >  * depending on the caller to tell us how many slots to release.
> >  */
> > 
> > That's not the only reason we should fix this: forcing the driver to
> > track the VCPI allocations throughout a state's atomic check is
> > error prone, because it means that extra care has to be taken with the
> > order that drm_dp_atomic_find_vcpi_slots() and
> > drm_dp_atomic_release_vcpi_slots() are called in in order to ensure
> > idempotency. Currently the only driver actually using these helpers,
> > i915, doesn't even do this correctly: multiple ->best_encoder() checks
> > with i915's current implementation would not be idempotent and would
> > over-allocate VCPI slots, something I learned trying to implement
> > fallback retraining in MST.
> > 
> > So: simplify this whole mess, and teach drm_dp_atomic_find_vcpi_slots()
> > and drm_dp_atomic_release_vcpi_slots() to track the VCPI allocations for
> > each port. This allows us to ensure idempotency without having to rely
> > on the driver as much. Additionally: the driver doesn't need to do any
> > kind of VCPI slot tracking anymore if it doesn't need it for it's own
> > internal state.
> > 
> > Additionally; this adds a new drm_dp_mst_atomic_check() helper which
> > must be used by atomic drivers to perform validity checks for the new
> > VCPI allocations incurred by a state.
> > 
> > Also: update the documentation and make it more obvious that these
> > /must/ be called by /all/ atomic drivers supporting MST.
> > 
> > Changes since v1:
> >  - Don't use the now-removed ->atomic_check() for private objects hook,
> >just give drivers a function to call themselves
> > 
> > Signed-off-by: Lyude Paul 
> > Cc: Daniel Vetter 
> > ---
> >  drivers/gpu/drm/drm_dp_mst_topology.c | 190 +-
> >  drivers/gpu/drm/i915/intel_display.c  |   8 ++
> >  drivers/gpu/drm/i915/intel_dp_mst.c   |  31 +++--
> >  include/drm/drm_dp_mst_helper.h   |  11 +-
> >  4 files changed, 192 insertions(+), 48 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c
> > b/drivers/gpu/drm/drm_dp_mst_topology.c
> > index 8c3cfac437f4..dcfab7536914 100644
> > --- a/drivers/gpu/drm/drm_dp_mst_topology.c
> > +++ b/drivers/gpu/drm/drm_dp_mst_topology.c
> > @@ -2614,21 +2614,33 @@ static int drm_dp_init_vcpi(struct
> > drm_dp_mst_topology_mgr *mgr,
> >  }
> >  
> >  /**
> > - * drm_dp_atomic_find_vcpi_slots() - Find and add vcpi slots to the state
> > + * drm_dp_atomic_find_vcpi_slots() - Find and add VCPI slots to the state
> >   * @state: global atomic state
> >   * @mgr: MST topology manager for the port
> >   * @port: port to find vcpi slots for
> >   * @pbn: bandwidth required for the mode in PBN
> >   *
> > + * Allocates VCPI slots to @port, replacing any previous VCPI allocations
> > it
> > + * may have had. Any atomic drivers which support MST must call this
> > function
> > + * in their atomic_check() handlers to change the current VCPI allocation
> > for
> 
> Maybe do a nice kerneldoc reference to the right atomic_check here.
> 
> > + * the new state. After the ->atomic_check() hooks of the driver and all
> > other
> 
> This will upset the kerneldoc parser I think.
> 
> > + * mode objects in the state have been called, DRM will check the final
> > VCPI
> > + * allocations to ensure that they will fit into the available bandwidth
> > on
> > + * the topology.
> > + *
> > + * See also: drm_dp_atomic_release_vcpi_slots()
> 
> Also need to reference drm_dp_mst_atomic_check() here and that drivers
> must call it or nothing happens.
> > + *
> >   * RETURNS:
> > - * Total slots in the atomic state assigned for this port or error
> > + * Total slots in the atomic state assigned for this port, or a negative
> > error
> > + * code if the port no longer exists
> >   */
> >  int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
> >   struct drm_dp_mst_topology_mgr *mgr,
> >   struct drm_dp_mst_port *port, int pbn)
> >  {
> > struct drm_dp_mst_topology_state *topology_state;
> > -   int req_slots;
> > +   struct drm_dp_vcpi_allocation *pos, *vcpi = NULL;
> > +   int prev_slots, req_slots, ret;
> >  
> > topology_state = drm_atomic_get_mst_topology_state(state, mgr);
> > if (IS_ERR(topology_state))
> > @@ -2637,20 +2649,41 @@ int drm_dp_atomic_find_vcpi_slots(struct
> > drm_atomic_state *state,
> > port = drm_dp_get_validated_port_ref(mgr, port);
> > if (port == NULL)
> > 

Re: [PATCH v2 2/4] drm/dp_mst: Start tracking per-port VCPI allocations

2018-10-29 Thread Daniel Vetter
On Fri, Oct 26, 2018 at 04:35:47PM -0400, Lyude Paul wrote:
> There has been a TODO waiting for quite a long time in
> drm_dp_mst_topology.c:
> 
>   /* We cannot rely on port->vcpi.num_slots to update
>* topology_state->avail_slots as the port may not exist if the parent
>* branch device was unplugged. This should be fixed by tracking
>* per-port slot allocation in drm_dp_mst_topology_state instead of
>* depending on the caller to tell us how many slots to release.
>*/
> 
> That's not the only reason we should fix this: forcing the driver to
> track the VCPI allocations throughout a state's atomic check is
> error prone, because it means that extra care has to be taken with the
> order that drm_dp_atomic_find_vcpi_slots() and
> drm_dp_atomic_release_vcpi_slots() are called in in order to ensure
> idempotency. Currently the only driver actually using these helpers,
> i915, doesn't even do this correctly: multiple ->best_encoder() checks
> with i915's current implementation would not be idempotent and would
> over-allocate VCPI slots, something I learned trying to implement
> fallback retraining in MST.
> 
> So: simplify this whole mess, and teach drm_dp_atomic_find_vcpi_slots()
> and drm_dp_atomic_release_vcpi_slots() to track the VCPI allocations for
> each port. This allows us to ensure idempotency without having to rely
> on the driver as much. Additionally: the driver doesn't need to do any
> kind of VCPI slot tracking anymore if it doesn't need it for it's own
> internal state.
> 
> Additionally; this adds a new drm_dp_mst_atomic_check() helper which
> must be used by atomic drivers to perform validity checks for the new
> VCPI allocations incurred by a state.
> 
> Also: update the documentation and make it more obvious that these
> /must/ be called by /all/ atomic drivers supporting MST.
> 
> Changes since v1:
>  - Don't use the now-removed ->atomic_check() for private objects hook,
>just give drivers a function to call themselves
> 
> Signed-off-by: Lyude Paul 
> Cc: Daniel Vetter 
> ---
>  drivers/gpu/drm/drm_dp_mst_topology.c | 190 +-
>  drivers/gpu/drm/i915/intel_display.c  |   8 ++
>  drivers/gpu/drm/i915/intel_dp_mst.c   |  31 +++--
>  include/drm/drm_dp_mst_helper.h   |  11 +-
>  4 files changed, 192 insertions(+), 48 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
> b/drivers/gpu/drm/drm_dp_mst_topology.c
> index 8c3cfac437f4..dcfab7536914 100644
> --- a/drivers/gpu/drm/drm_dp_mst_topology.c
> +++ b/drivers/gpu/drm/drm_dp_mst_topology.c
> @@ -2614,21 +2614,33 @@ static int drm_dp_init_vcpi(struct 
> drm_dp_mst_topology_mgr *mgr,
>  }
>  
>  /**
> - * drm_dp_atomic_find_vcpi_slots() - Find and add vcpi slots to the state
> + * drm_dp_atomic_find_vcpi_slots() - Find and add VCPI slots to the state
>   * @state: global atomic state
>   * @mgr: MST topology manager for the port
>   * @port: port to find vcpi slots for
>   * @pbn: bandwidth required for the mode in PBN
>   *
> + * Allocates VCPI slots to @port, replacing any previous VCPI allocations it
> + * may have had. Any atomic drivers which support MST must call this function
> + * in their atomic_check() handlers to change the current VCPI allocation for

Maybe do a nice kerneldoc reference to the right atomic_check here.

> + * the new state. After the ->atomic_check() hooks of the driver and all 
> other

This will upset the kerneldoc parser I think.

> + * mode objects in the state have been called, DRM will check the final VCPI
> + * allocations to ensure that they will fit into the available bandwidth on
> + * the topology.
> + *
> + * See also: drm_dp_atomic_release_vcpi_slots()

Also need to reference drm_dp_mst_atomic_check() here and that drivers
must call it or nothing happens.
> + *
>   * RETURNS:
> - * Total slots in the atomic state assigned for this port or error
> + * Total slots in the atomic state assigned for this port, or a negative 
> error
> + * code if the port no longer exists
>   */
>  int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
> struct drm_dp_mst_topology_mgr *mgr,
> struct drm_dp_mst_port *port, int pbn)
>  {
>   struct drm_dp_mst_topology_state *topology_state;
> - int req_slots;
> + struct drm_dp_vcpi_allocation *pos, *vcpi = NULL;
> + int prev_slots, req_slots, ret;
>  
>   topology_state = drm_atomic_get_mst_topology_state(state, mgr);
>   if (IS_ERR(topology_state))
> @@ -2637,20 +2649,41 @@ int drm_dp_atomic_find_vcpi_slots(struct 
> drm_atomic_state *state,
>   port = drm_dp_get_validated_port_ref(mgr, port);
>   if (port == NULL)
>   return -EINVAL;
> - req_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
> - DRM_DEBUG_KMS("vcpi slots req=%d, avail=%d\n",
> - req_slots, topology_state->avail_slots);
>  
> - if (req_slots > topology_state->avail_slots) {
> -  

[PATCH v2 2/4] drm/dp_mst: Start tracking per-port VCPI allocations

2018-10-26 Thread Lyude Paul
There has been a TODO waiting for quite a long time in
drm_dp_mst_topology.c:

/* We cannot rely on port->vcpi.num_slots to update
 * topology_state->avail_slots as the port may not exist if the parent
 * branch device was unplugged. This should be fixed by tracking
 * per-port slot allocation in drm_dp_mst_topology_state instead of
 * depending on the caller to tell us how many slots to release.
 */

That's not the only reason we should fix this: forcing the driver to
track the VCPI allocations throughout a state's atomic check is
error prone, because it means that extra care has to be taken with the
order that drm_dp_atomic_find_vcpi_slots() and
drm_dp_atomic_release_vcpi_slots() are called in in order to ensure
idempotency. Currently the only driver actually using these helpers,
i915, doesn't even do this correctly: multiple ->best_encoder() checks
with i915's current implementation would not be idempotent and would
over-allocate VCPI slots, something I learned trying to implement
fallback retraining in MST.

So: simplify this whole mess, and teach drm_dp_atomic_find_vcpi_slots()
and drm_dp_atomic_release_vcpi_slots() to track the VCPI allocations for
each port. This allows us to ensure idempotency without having to rely
on the driver as much. Additionally: the driver doesn't need to do any
kind of VCPI slot tracking anymore if it doesn't need it for it's own
internal state.

Additionally; this adds a new drm_dp_mst_atomic_check() helper which
must be used by atomic drivers to perform validity checks for the new
VCPI allocations incurred by a state.

Also: update the documentation and make it more obvious that these
/must/ be called by /all/ atomic drivers supporting MST.

Changes since v1:
 - Don't use the now-removed ->atomic_check() for private objects hook,
   just give drivers a function to call themselves

Signed-off-by: Lyude Paul 
Cc: Daniel Vetter 
---
 drivers/gpu/drm/drm_dp_mst_topology.c | 190 +-
 drivers/gpu/drm/i915/intel_display.c  |   8 ++
 drivers/gpu/drm/i915/intel_dp_mst.c   |  31 +++--
 include/drm/drm_dp_mst_helper.h   |  11 +-
 4 files changed, 192 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 8c3cfac437f4..dcfab7536914 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -2614,21 +2614,33 @@ static int drm_dp_init_vcpi(struct 
drm_dp_mst_topology_mgr *mgr,
 }
 
 /**
- * drm_dp_atomic_find_vcpi_slots() - Find and add vcpi slots to the state
+ * drm_dp_atomic_find_vcpi_slots() - Find and add VCPI slots to the state
  * @state: global atomic state
  * @mgr: MST topology manager for the port
  * @port: port to find vcpi slots for
  * @pbn: bandwidth required for the mode in PBN
  *
+ * Allocates VCPI slots to @port, replacing any previous VCPI allocations it
+ * may have had. Any atomic drivers which support MST must call this function
+ * in their atomic_check() handlers to change the current VCPI allocation for
+ * the new state. After the ->atomic_check() hooks of the driver and all other
+ * mode objects in the state have been called, DRM will check the final VCPI
+ * allocations to ensure that they will fit into the available bandwidth on
+ * the topology.
+ *
+ * See also: drm_dp_atomic_release_vcpi_slots()
+ *
  * RETURNS:
- * Total slots in the atomic state assigned for this port or error
+ * Total slots in the atomic state assigned for this port, or a negative error
+ * code if the port no longer exists
  */
 int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
  struct drm_dp_mst_topology_mgr *mgr,
  struct drm_dp_mst_port *port, int pbn)
 {
struct drm_dp_mst_topology_state *topology_state;
-   int req_slots;
+   struct drm_dp_vcpi_allocation *pos, *vcpi = NULL;
+   int prev_slots, req_slots, ret;
 
topology_state = drm_atomic_get_mst_topology_state(state, mgr);
if (IS_ERR(topology_state))
@@ -2637,20 +2649,41 @@ int drm_dp_atomic_find_vcpi_slots(struct 
drm_atomic_state *state,
port = drm_dp_get_validated_port_ref(mgr, port);
if (port == NULL)
return -EINVAL;
-   req_slots = DIV_ROUND_UP(pbn, mgr->pbn_div);
-   DRM_DEBUG_KMS("vcpi slots req=%d, avail=%d\n",
-   req_slots, topology_state->avail_slots);
 
-   if (req_slots > topology_state->avail_slots) {
-   drm_dp_put_port(port);
-   return -ENOSPC;
+   /* Find the current allocation for this port, if any */
+   list_for_each_entry(pos, &topology_state->vcpis, next) {
+   if (pos->port == port) {
+   vcpi = pos;
+   prev_slots = vcpi->vcpi;
+   break;
+   }
}
+   if (!vcpi)
+   prev_slots = 0;
+
+   req_slot