Re: [PATCH v6 5/6] drm/i915/pxp: Trigger the global teardown for before suspending

2023-01-24 Thread Juston Li
On Tue, 2023-01-24 at 10:17 -0500, Rodrigo Vivi wrote:
> On Mon, Jan 23, 2023 at 09:31:49PM -0800, Alan Previn wrote:
> > A driver bug was recently discovered where the security firmware
> > was
> > receiving internal HW signals indicating that session key
> > expirations
> > had occurred. Architecturally, the firmware was expecting a
> > response
> > from the GuC to acknowledge the event with the firmware side.
> > However the OS was in a suspended state and GuC had been reset.
> > 
> > Internal specifications actually required the driver to ensure
> > that all active sessions be properly cleaned up in such cases where
> > the system is suspended and the GuC potentially unable to respond.
> > 
> > This patch adds the global teardown code in i915's suspend_prepare
> > code path.
> > 
> > Signed-off-by: Alan Previn 
> > Reviewed-by: Juston Li 
> 
> it should probably contain some revision history above so the
> reviewer can know what changed from the time he reviewed and now.
> 
> it looks we have another function that I don't remember...
> Juston, could you please confirm your review stands in this version?
> if so feel free to add my ack with that.

Sure, v6 is:
Reviewed-by: Juston Li 

Appreciate the reviews/revisions Rodrigo and Alan!

> 
> > ---
> >  drivers/gpu/drm/i915/pxp/intel_pxp.c | 65
> > +---
> >  drivers/gpu/drm/i915/pxp/intel_pxp.h |  1 +
> >  drivers/gpu/drm/i915/pxp/intel_pxp_pm.c  |  2 +-
> >  drivers/gpu/drm/i915/pxp/intel_pxp_session.c |  6 +-
> >  drivers/gpu/drm/i915/pxp/intel_pxp_session.h |  5 ++
> >  5 files changed, 66 insertions(+), 13 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c
> > b/drivers/gpu/drm/i915/pxp/intel_pxp.c
> > index cfc9af8b3d21..9d4c7724e98e 100644
> > --- a/drivers/gpu/drm/i915/pxp/intel_pxp.c
> > +++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c
> > @@ -270,6 +270,60 @@ static bool pxp_component_bound(struct
> > intel_pxp *pxp)
> > return bound;
> >  }
> >  
> > +static int __pxp_global_teardown_final(struct intel_pxp *pxp)
> > +{
> > +   if (!pxp->arb_is_valid)
> > +   return 0;
> > +   /*
> > +    * To ensure synchronous and coherent session teardown
> > completion
> > +    * in response to suspend or shutdown triggers, don't use a
> > worker.
> > +    */
> > +   intel_pxp_mark_termination_in_progress(pxp);
> > +   intel_pxp_terminate(pxp, false);
> > +
> > +   if (!wait_for_completion_timeout(>termination,
> > msecs_to_jiffies(250)))
> > +   return -ETIMEDOUT;
> > +
> > +   return 0;
> > +}
> > +
> > +static int __pxp_global_teardown_restart(struct intel_pxp *pxp)
> > +{
> > +   if (pxp->arb_is_valid)
> > +   return 0;
> > +   /*
> > +    * The arb-session is currently inactive and we are doing a
> > reset and restart
> > +    * due to a runtime event. Use the worker that was designed
> > for this.
> > +    */
> > +   pxp_queue_termination(pxp);
> > +
> > +   if (!wait_for_completion_timeout(>termination,
> > msecs_to_jiffies(250)))
> > +   return -ETIMEDOUT;
> > +
> > +   return 0;
> > +}
> > +
> > +void intel_pxp_end(struct intel_pxp *pxp)
> > +{
> > +   struct drm_i915_private *i915 = pxp->ctrl_gt->i915;
> > +   intel_wakeref_t wakeref;
> > +
> > +   if (!intel_pxp_is_enabled(pxp))
> > +   return;
> > +
> > +   wakeref = intel_runtime_pm_get(>runtime_pm);
> > +
> > +   mutex_lock(>arb_mutex);
> > +
> > +   if (__pxp_global_teardown_final(pxp))
> > +   drm_dbg(>drm, "PXP end timed out\n");
> > +
> > +   mutex_unlock(>arb_mutex);
> > +
> > +   intel_pxp_fini_hw(pxp);
> > +   intel_runtime_pm_put(>runtime_pm, wakeref);
> > +}
> > +
> >  /*
> >   * the arb session is restarted from the irq work when we receive
> > the
> >   * termination completion interrupt
> > @@ -286,16 +340,9 @@ int intel_pxp_start(struct intel_pxp *pxp)
> >  
> > mutex_lock(>arb_mutex);
> >  
> > -   if (pxp->arb_is_valid)
> > -   goto unlock;
> > -
> > -   pxp_queue_termination(pxp);
> > -
> > -   if (!wait_for_completion_timeout(>termination,
> > - 

Re: [PATCH v3 5/7] drm/i915/pxp: Trigger the global teardown for before suspending

2023-01-04 Thread Juston Li
On Wed, 2022-12-21 at 15:06 -0800, Alan Previn wrote:
> A driver bug was recently discovered where the security firmware was
> receiving internal HW signals indicating that session key expirations
> had occurred. Architecturally, the firmware was expecting a response
> from the GuC to acknowledge the event with the firmware side.
> However the OS was in a suspended state and GuC had been reset.
> 
> Internal specifications actually required the driver to ensure
> that all active sessions be properly cleaned up in such cases where
> the system is suspended and the GuC potentially unable to respond.
> 
> This patch adds the global teardown code in i915's suspend_prepare
> code path.
> 
> Signed-off-by: Alan Previn 
> ---
>  drivers/gpu/drm/i915/pxp/intel_pxp.c | 60 +-
> --
>  drivers/gpu/drm/i915/pxp/intel_pxp.h |  1 +
>  drivers/gpu/drm/i915/pxp/intel_pxp_pm.c  |  2 +-
>  drivers/gpu/drm/i915/pxp/intel_pxp_session.c |  9 ++-
>  drivers/gpu/drm/i915/pxp/intel_pxp_session.h |  5 ++
>  5 files changed, 64 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c
> b/drivers/gpu/drm/i915/pxp/intel_pxp.c
> index cfc9af8b3d21..96a988efd237 100644
> --- a/drivers/gpu/drm/i915/pxp/intel_pxp.c
> +++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c
> @@ -270,6 +270,55 @@ static bool pxp_component_bound(struct intel_pxp
> *pxp)
> return bound;
>  }
>  
> +static int __pxp_global_teardown_locked(struct intel_pxp *pxp, bool
> terminate_for_cleanup)
> +{
> +   if (terminate_for_cleanup) {
> +   if (!pxp->arb_is_valid)
> +   return 0;
> +   /*
> +    * To ensure synchronous and coherent session
> teardown completion
> +    * in response to suspend or shutdown triggers, don't
> user a worker.

nit: typo user -> use

Reviewed-by: Juston Li 

> +    */
> +   intel_pxp_mark_termination_in_progress(pxp);
> +   intel_pxp_terminate(pxp, false);
> +   } else {
> +   if (pxp->arb_is_valid)
> +   return 0;
> +   /*
> +    * If we are not in final termination, and the arb-
> session is currently
> +    * inactive, we are doing a reset and restart due to
> some runtime event.
> +    * Use the worker that was designed for this.
> +    */
> +   pxp_queue_termination(pxp);
> +   }
> +
> +   if (!wait_for_completion_timeout(>termination,
> msecs_to_jiffies(250)))
> +   return -ETIMEDOUT;
> +
> +   return 0;
> +}
> +
> +void intel_pxp_end(struct intel_pxp *pxp)
> +{
> +   struct drm_i915_private *i915 = pxp->ctrl_gt->i915;
> +   intel_wakeref_t wakeref;
> +
> +   if (!intel_pxp_is_enabled(pxp))
> +   return;
> +
> +   wakeref = intel_runtime_pm_get(>runtime_pm);
> +
> +   mutex_lock(>arb_mutex);
> +
> +   if (__pxp_global_teardown_locked(pxp, true))
> +   drm_dbg(>drm, "PXP end timed out\n");
> +
> +   mutex_unlock(>arb_mutex);
> +
> +   intel_pxp_fini_hw(pxp);
> +   intel_runtime_pm_put(>runtime_pm, wakeref);
> +}
> +
>  /*
>   * the arb session is restarted from the irq work when we receive
> the
>   * termination completion interrupt
> @@ -286,16 +335,9 @@ int intel_pxp_start(struct intel_pxp *pxp)
>  
> mutex_lock(>arb_mutex);
>  
> -   if (pxp->arb_is_valid)
> -   goto unlock;
> -
> -   pxp_queue_termination(pxp);
> -
> -   if (!wait_for_completion_timeout(>termination,
> -   msecs_to_jiffies(250))) {
> -   ret = -ETIMEDOUT;
> +   ret = __pxp_global_teardown_locked(pxp, false);
> +   if (ret)
> goto unlock;
> -   }
>  
> /* make sure the compiler doesn't optimize the double access
> */
> barrier();
> diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.h
> b/drivers/gpu/drm/i915/pxp/intel_pxp.h
> index 9658d3005222..3ded0890cd27 100644
> --- a/drivers/gpu/drm/i915/pxp/intel_pxp.h
> +++ b/drivers/gpu/drm/i915/pxp/intel_pxp.h
> @@ -27,6 +27,7 @@ void intel_pxp_mark_termination_in_progress(struct
> intel_pxp *pxp);
>  void intel_pxp_tee_end_arb_fw_session(struct intel_pxp *pxp, u32
> arb_session_id);
>  
>  int intel_pxp_start(struct intel_pxp *pxp);
> +void intel_pxp_end(struct intel_pxp *pxp);
>  
>  int intel_pxp_key_check(struct intel_pxp *pxp,
> struct drm_i915_gem_object *obj,
> diff --git 

Re: [PATCH v3 4/7] drm/i915/pxp: Invalidate all PXP fw sessions during teardown

2023-01-04 Thread Juston Li
On Wed, 2022-12-21 at 15:06 -0800, Alan Previn wrote:
> A gap was recently discovered where if an application did not
> invalidate all of the stream keys (intentionally or not), and the
> driver did a full PXP global teardown on the GT subsystem, we
> find that future session creation would fail on the security
> firmware's side of the equation. i915 is the entity that needs
> ensure the sessions' state across both iGT and security firmware
> are at a known clean point when performing a full global teardown.
> 
> Architecturally speaking, i915 should inspect all active sessions
> and submit the invalidate-stream-key PXP command to the security
> firmware for each of them. However, for the upstream i915 driver
> we only support the arbitration session that can be created
> so that will be the only session we will cleanup.
> 
> Signed-off-by: Alan Previn 

Reviewed-by: Juston Li 

> ---
>  drivers/gpu/drm/i915/pxp/intel_pxp.h  |  1 +
>  .../drm/i915/pxp/intel_pxp_cmd_interface_42.h | 15 
>  .../i915/pxp/intel_pxp_cmd_interface_cmn.h    |  3 ++
>  drivers/gpu/drm/i915/pxp/intel_pxp_session.c  |  2 ++
>  drivers/gpu/drm/i915/pxp/intel_pxp_tee.c  | 35
> +++
>  5 files changed, 56 insertions(+)
> 
> diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.h
> b/drivers/gpu/drm/i915/pxp/intel_pxp.h
> index 04440fada711..9658d3005222 100644
> --- a/drivers/gpu/drm/i915/pxp/intel_pxp.h
> +++ b/drivers/gpu/drm/i915/pxp/intel_pxp.h
> @@ -24,6 +24,7 @@ void intel_pxp_init_hw(struct intel_pxp *pxp);
>  void intel_pxp_fini_hw(struct intel_pxp *pxp);
>  
>  void intel_pxp_mark_termination_in_progress(struct intel_pxp *pxp);
> +void intel_pxp_tee_end_arb_fw_session(struct intel_pxp *pxp, u32
> arb_session_id);
>  
>  int intel_pxp_start(struct intel_pxp *pxp);
>  
> diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_42.h
> b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_42.h
> index 739f9072fa5f..26f7d9f01bf3 100644
> --- a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_42.h
> +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_42.h
> @@ -12,6 +12,9 @@
>  /* PXP-Opcode for Init Session */
>  #define PXP42_CMDID_INIT_SESSION 0x1e
>  
> +/* PXP-Opcode for Invalidate Stream Key */
> +#define PXP42_CMDID_INVALIDATE_STREAM_KEY 0x0007
> +
>  /* PXP-Input-Packet: Init Session (Arb-Session) */
>  struct pxp42_create_arb_in {
> struct pxp_cmd_header header;
> @@ -25,4 +28,16 @@ struct pxp42_create_arb_out {
> struct pxp_cmd_header header;
>  } __packed;
>  
> +/* PXP-Input-Packet: Invalidate Stream Key */
> +struct pxp42_inv_stream_key_in {
> +   struct pxp_cmd_header header;
> +   u32 rsvd[3];
> +} __packed;
> +
> +/* PXP-Output-Packet: Invalidate Stream Key */
> +struct pxp42_inv_stream_key_out {
> +   struct pxp_cmd_header header;
> +   u32 rsvd;
> +} __packed;
> +
>  #endif /* __INTEL_PXP_FW_INTERFACE_42_H__ */
> diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_cmn.h
> b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_cmn.h
> index c2f23394f9b8..69e34ec49e78 100644
> --- a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_cmn.h
> +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_cmn.h
> @@ -27,6 +27,9 @@ struct pxp_cmd_header {
> union {
> u32 status; /* out */
> u32 stream_id; /* in */
> +#define PXP_CMDHDR_EXTDATA_SESSION_VALID GENMASK(0, 0)
> +#define PXP_CMDHDR_EXTDATA_APP_TYPE GENMASK(1, 1)
> +#define PXP_CMDHDR_EXTDATA_SESSION_ID GENMASK(17, 2)
> };
> /* Length of the message (excluding the header) */
> u32 buffer_len;
> diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_session.c
> b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c
> index ae413580b81a..74ed7e16e481 100644
> --- a/drivers/gpu/drm/i915/pxp/intel_pxp_session.c
> +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c
> @@ -110,6 +110,8 @@ static int
> pxp_terminate_arb_session_and_global(struct intel_pxp *pxp)
>  
> intel_uncore_write(gt->uncore, PXP_GLOBAL_TERMINATE, 1);
>  
> +   intel_pxp_tee_end_arb_fw_session(pxp, ARB_SESSION);
> +
> return ret;
>  }
>  
> diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
> b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
> index bef6d7f8ac55..9e247f38f3bd 100644
> --- a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
> +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
> @@ -311,3 +311,38 @@ int intel_pxp_tee_cmd_create_arb_session(struct
> intel_pxp *pxp,
>  
> return ret;
>  }
> +
> +void intel_pxp_tee_end_arb_fw_session(struct intel_pxp *pxp, u32
> session_id)
> +{
> +   stru

[Intel-gfx] [PATCH v3 3/3] drm/i915/hdcp: reuse rx_info for mst stream type1 capability check

2021-08-10 Thread Juston Li
On some MST docking stations, rx_info can only be read after
RepeaterAuth_Send_ReceiverID_List and the RxStatus READY bit is set
otherwise the read will return -EIO.

This behavior causes the mst stream type1 capability test to fail to
read rx_info and determine if the topology supports type1 and fallback
to type0.

To fix this, check for type1 capability when we receive rx_info within
the AKE flow when we read RepeaterAuth_Send_ReceiverID_List instead
of an explicit read just for type1 capability checking.

This does require moving where we set stream_types to after
hdcp2_authenticate_sink() when we get rx_info but this occurs before we
do hdcp2_propagate_stream_management_info.

Also, legacy HDCP 2.0/2.1 are not type 1 capable either so check for
that as well.

Changes since v2:
 - Remove no longer used variables in _intel_hdcp2_enable()

Signed-off-by: Juston Li 
---
 .../drm/i915/display/intel_display_types.h|  2 +
 drivers/gpu/drm/i915/display/intel_dp_hdcp.c  | 39 ---
 drivers/gpu/drm/i915/display/intel_hdcp.c | 49 ---
 3 files changed, 23 insertions(+), 67 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index dbdfe54d0340..c8b687ff0374 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -516,6 +516,8 @@ struct intel_hdcp {
enum transcoder cpu_transcoder;
/* Only used for DP MST stream encryption */
enum transcoder stream_transcoder;
+
+   bool topology_type1_capable;
 };
 
 struct intel_connector {
diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c 
b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
index 526fd58b9b51..2d39af63ec9b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
@@ -478,23 +478,6 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port 
*dig_port,
return size;
 }
 
-static int
-get_rxinfo_hdcp_1_dev_downstream(struct intel_digital_port *dig_port, bool 
*hdcp_1_x)
-{
-   u8 rx_info[HDCP_2_2_RXINFO_LEN];
-   int ret;
-
-   ret = drm_dp_dpcd_read(_port->dp.aux,
-  DP_HDCP_2_2_REG_RXINFO_OFFSET,
-  (void *)rx_info, HDCP_2_2_RXINFO_LEN);
-
-   if (ret != HDCP_2_2_RXINFO_LEN)
-   return ret >= 0 ? -EIO : ret;
-
-   *hdcp_1_x = HDCP_2_2_HDCP1_DEVICE_CONNECTED(rx_info[1]) ? true : false;
-   return 0;
-}
-
 static
 ssize_t get_receiver_id_list_rx_info(struct intel_digital_port *dig_port, u32 
*dev_cnt, u8 *byte)
 {
@@ -664,27 +647,6 @@ int intel_dp_hdcp2_capable(struct intel_digital_port 
*dig_port,
return 0;
 }
 
-static
-int intel_dp_mst_streams_type1_capable(struct intel_connector *connector,
-  bool *capable)
-{
-   struct intel_digital_port *dig_port = 
intel_attached_dig_port(connector);
-   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
-   int ret;
-   bool hdcp_1_x;
-
-   ret = get_rxinfo_hdcp_1_dev_downstream(dig_port, _1_x);
-   if (ret) {
-   drm_dbg_kms(>drm,
-   "[%s:%d] failed to read RxInfo ret=%d\n",
-   connector->base.name, connector->base.base.id, ret);
-   return ret;
-   }
-
-   *capable = !hdcp_1_x;
-   return 0;
-}
-
 static const struct intel_hdcp_shim intel_dp_hdcp_shim = {
.write_an_aksv = intel_dp_hdcp_write_an_aksv,
.read_bksv = intel_dp_hdcp_read_bksv,
@@ -833,7 +795,6 @@ static const struct intel_hdcp_shim intel_dp_mst_hdcp_shim 
= {
.stream_2_2_encryption = intel_dp_mst_hdcp2_stream_encryption,
.check_2_2_link = intel_dp_mst_hdcp2_check_link,
.hdcp_2_2_capable = intel_dp_hdcp2_capable,
-   .streams_type1_capable = intel_dp_mst_streams_type1_capable,
.protocol = HDCP_PROTOCOL_DP,
 };
 
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c 
b/drivers/gpu/drm/i915/display/intel_hdcp.c
index ebc2e32aec0b..1a2a98e2c6e3 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -33,21 +33,6 @@ static int intel_conn_to_vcpi(struct intel_connector 
*connector)
return connector->port  ? connector->port->vcpi.vcpi : 0;
 }
 
-static bool
-intel_streams_type1_capable(struct intel_connector *connector)
-{
-   const struct intel_hdcp_shim *shim = connector->hdcp.shim;
-   bool capable = false;
-
-   if (!shim)
-   return capable;
-
-   if (shim->streams_type1_capable)
-   shim->streams_type1_capable(connector, );
-
-   return capable;
-}
-
 /*
  * intel_hdcp_required_content_stream selects the most highest common possible 
HDCP
  * content_type for all streams in DP MST topology because security f/w doesn't
@@ -86,7 +71,

[Intel-gfx] [PATCH v3 2/3] drm/i915/hdcp: read RxInfo once when reading RepeaterAuth_Send_ReceiverID_List

2021-08-10 Thread Juston Li
When reading RepeaterAuth_Send_ReceiverID_List, RxInfo is read by itself
once to retrieve the DEVICE_COUNT to calculate the size of the
ReceiverID list then read a second time as a part of reading ReceiverID
list.

On some MST docking stations, RxInfo can only be read after the RxStatus
READY bit is set otherwise the read will return -EIO. The spec states that
the READY bit should be cleared as soon as RxInfo has been read.

In this case, the first RxInfo read succeeds but after the READY bit is
cleared, the second read fails.

Fix it by reading RxInfo once and storing it before reading the rest of
RepeaterAuth_Send_ReceiverID_List once we know the size.

Modify get_receiver_id_list_size() to read and store RxInfo in the
message buffer and also parse DEVICE_COUNT so we know the size of
RepeaterAuth_Send_ReceiverID_List.

Afterwards, retrieve the rest of the message at the offset for
seq_num_V.

Changes in v4:
- rebase and edit commit message

Changes in v3:
- remove comment

Changes in v2:
- remove unnecessary moving of drm_i915_private from patch 1

Signed-off-by: Juston Li 
Acked-by: Anshuman Gupta 
---
 drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 30 ++--
 include/drm/drm_dp_helper.h  |  2 +-
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c 
b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
index 1d0096654776..526fd58b9b51 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
@@ -496,11 +496,10 @@ get_rxinfo_hdcp_1_dev_downstream(struct 
intel_digital_port *dig_port, bool *hdcp
 }
 
 static
-ssize_t get_receiver_id_list_size(struct intel_digital_port *dig_port)
+ssize_t get_receiver_id_list_rx_info(struct intel_digital_port *dig_port, u32 
*dev_cnt, u8 *byte)
 {
-   u8 rx_info[HDCP_2_2_RXINFO_LEN];
-   u32 dev_cnt;
ssize_t ret;
+   u8 *rx_info = byte;
 
ret = drm_dp_dpcd_read(_port->dp.aux,
   DP_HDCP_2_2_REG_RXINFO_OFFSET,
@@ -508,15 +507,11 @@ ssize_t get_receiver_id_list_size(struct 
intel_digital_port *dig_port)
if (ret != HDCP_2_2_RXINFO_LEN)
return ret >= 0 ? -EIO : ret;
 
-   dev_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 |
+   *dev_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 |
   HDCP_2_2_DEV_COUNT_LO(rx_info[1]));
 
-   if (dev_cnt > HDCP_2_2_MAX_DEVICE_COUNT)
-   dev_cnt = HDCP_2_2_MAX_DEVICE_COUNT;
-
-   ret = sizeof(struct hdcp2_rep_send_receiverid_list) -
-   HDCP_2_2_RECEIVER_IDS_MAX_LEN +
-   (dev_cnt * HDCP_2_2_RECEIVER_ID_LEN);
+   if (*dev_cnt > HDCP_2_2_MAX_DEVICE_COUNT)
+   *dev_cnt = HDCP_2_2_MAX_DEVICE_COUNT;
 
return ret;
 }
@@ -534,6 +529,7 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port 
*dig_port,
const struct hdcp2_dp_msg_data *hdcp2_msg_data;
ktime_t msg_end = ktime_set(0, 0);
bool msg_expired;
+   u32 dev_cnt;
 
hdcp2_msg_data = get_hdcp2_dp_msg_data(msg_id);
if (!hdcp2_msg_data)
@@ -546,17 +542,21 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port 
*dig_port,
 
hdcp->cp_irq_count_cached = atomic_read(>cp_irq_count);
 
+   /* DP adaptation msgs has no msg_id */
+   byte++;
+
if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST) {
-   ret = get_receiver_id_list_size(dig_port);
+   ret = get_receiver_id_list_rx_info(dig_port, _cnt, byte);
if (ret < 0)
return ret;
 
-   size = ret;
+   byte += ret;
+   size = sizeof(struct hdcp2_rep_send_receiverid_list) -
+   HDCP_2_2_RXINFO_LEN - HDCP_2_2_RECEIVER_IDS_MAX_LEN +
+   (dev_cnt * HDCP_2_2_RECEIVER_ID_LEN);
}
-   bytes_to_recv = size - 1;
 
-   /* DP adaptation msgs has no msg_id */
-   byte++;
+   bytes_to_recv = size - 1;
 
while (bytes_to_recv) {
len = bytes_to_recv > DP_AUX_MAX_PAYLOAD_BYTES ?
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 3f2715eb965f..7476e7c6d0be 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1413,7 +1413,7 @@ enum drm_dp_phy {
 #define DP_HDCP_2_2_LC_INIT_OFFSET DP_HDCP_2_2_REG_RN_OFFSET
 #define DP_HDCP_2_2_LC_SEND_LPRIME_OFFSET  DP_HDCP_2_2_REG_LPRIME_OFFSET
 #define DP_HDCP_2_2_SKE_SEND_EKS_OFFSET
DP_HDCP_2_2_REG_EDKEY_KS_OFFSET
-#define DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET
DP_HDCP_2_2_REG_RXINFO_OFFSET
+#define DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET
DP_HDCP_2_2_REG_SEQ_NUM_V_OFFSET
 #define DP_HDCP_2_2_REP_SEND_ACK_OFFSETDP_HDCP_2_2_REG_V_OFFSET
 #define DP_HDCP_2_2_REP_STREAM_MANAGE_OFFSET   DP_HDCP_2_2_REG_SEQ_NUM_M_OFFSET
 #define DP_HDCP_2_2_REP_STREAM_READY_OFFSETDP_HDCP_2_2_REG_MPRIME_OFFSET
-- 
2.31.1



[Intel-gfx] [PATCH v3 1/3] drm/i915/hdcp: update cp_irq_count_cached in intel_dp_hdcp2_read_msg()

2021-08-10 Thread Juston Li
Update cp_irq_count_cached when reading messages rather than when
writing a message to make sure the value is up to date and not
stale from a previously handled CP_IRQ.

AKE flow  doesn't always respond to a read with a ACK write msg.
E.g. AKE_Send_Pairing_Info will "timeout" because we received
a CP_IRQ for reading AKE_Send_H_Prime but no write occurred between that
and reading AKE_Send_Pairing_Info so cp_irq_count_cached is stale
causing the wait to return right away rather than waiting for a new
CP_IRQ.

Signed-off-by: Juston Li 
Acked-by: Anshuman Gupta 
---
 drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c 
b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
index d697d169e8c1..1d0096654776 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
@@ -446,8 +446,6 @@ static
 int intel_dp_hdcp2_write_msg(struct intel_digital_port *dig_port,
 void *buf, size_t size)
 {
-   struct intel_dp *dp = _port->dp;
-   struct intel_hdcp *hdcp = >attached_connector->hdcp;
unsigned int offset;
u8 *byte = buf;
ssize_t ret, bytes_to_write, len;
@@ -463,8 +461,6 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port 
*dig_port,
bytes_to_write = size - 1;
byte++;
 
-   hdcp->cp_irq_count_cached = atomic_read(>cp_irq_count);
-
while (bytes_to_write) {
len = bytes_to_write > DP_AUX_MAX_PAYLOAD_BYTES ?
DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_write;
@@ -530,6 +526,8 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port 
*dig_port,
u8 msg_id, void *buf, size_t size)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   struct intel_dp *dp = _port->dp;
+   struct intel_hdcp *hdcp = >attached_connector->hdcp;
unsigned int offset;
u8 *byte = buf;
ssize_t ret, bytes_to_recv, len;
@@ -546,6 +544,8 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port 
*dig_port,
if (ret < 0)
return ret;
 
+   hdcp->cp_irq_count_cached = atomic_read(>cp_irq_count);
+
if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST) {
ret = get_receiver_id_list_size(dig_port);
if (ret < 0)
-- 
2.31.1



[Intel-gfx] [PATCH v3 0/3] drm/i915/hdcp: HDCP2.2 MST dock fixes

2021-08-10 Thread Juston Li
Fixes to get HDCP2.2 over MST working on MST docking stations with
certain behaviors that cause the current flow to fail.
Tested with Dell WD-19 and Lenovo ThinkPad USB Type-C Dock Gen 2.

These fixes should make the flow more robust to handle behaviors that as
far as I can tell are unclear in the HDCP spec:

RxInfo contains repeater topology information needed for MST. The
behavior on these docks is that this can only be read during 
RepeaterAuth_Send_ReceiverID_List when the RxStatus READY bit is set
otherwise the dock will return NACK. It seems these docks treat
reading this range at any other time as invalid when the READY bit
isn't set possibly because it could be stale. The HDCP spec also states
the READY bit is cleared after RxInfo is read.

These fixes address this behavior by only reading RxInfo once during the 
AKE flow and reusing that data.

Changes since v2:
 - Remove no longer used variables in _intel_hdcp2_enable()

Changes since v1:
 - Fix subject line for 3/3

Juston Li (3):
  drm/i915/hdcp: update cp_irq_count_cached in intel_dp_hdcp2_read_msg()
  drm/i915/hdcp: read RxInfo once when reading
RepeaterAuth_Send_ReceiverID_List
  drm/i915/hdcp: reuse rx_info for mst stream type1 capability check

 .../drm/i915/display/intel_display_types.h|  2 +
 drivers/gpu/drm/i915/display/intel_dp_hdcp.c  | 77 +--
 drivers/gpu/drm/i915/display/intel_hdcp.c | 49 +---
 include/drm/drm_dp_helper.h   |  2 +-
 4 files changed, 43 insertions(+), 87 deletions(-)

-- 
2.31.1



[Intel-gfx] [PATCH v2 3/3] drm/i915/hdcp: reuse rx_info for mst stream type1 capability check

2021-08-10 Thread Juston Li
On some MST docking stations, rx_info can only be read after
RepeaterAuth_Send_ReceiverID_List and the RxStatus READY bit is set
otherwise the read will return -EIO.

This behavior causes the mst stream type1 capability test to fail to
read rx_info and determine if the topology supports type1 and fallback
to type0.

To fix this, check for type1 capability when we receive rx_info within
the AKE flow when we read RepeaterAuth_Send_ReceiverID_List instead
of an explicit read just for type1 capability checking.

This does require moving where we set stream_types to after
hdcp2_authenticate_sink() when we get rx_info but this occurs before we
do hdcp2_propagate_stream_management_info.

Also, legacy HDCP 2.0/2.1 are not type 1 capable either so check for
that as well.

Signed-off-by: Juston Li 
---
 .../drm/i915/display/intel_display_types.h|  2 +
 drivers/gpu/drm/i915/display/intel_dp_hdcp.c  | 39 ---
 drivers/gpu/drm/i915/display/intel_hdcp.c | 47 +--
 3 files changed, 23 insertions(+), 65 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index dbdfe54d0340..c8b687ff0374 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -516,6 +516,8 @@ struct intel_hdcp {
enum transcoder cpu_transcoder;
/* Only used for DP MST stream encryption */
enum transcoder stream_transcoder;
+
+   bool topology_type1_capable;
 };
 
 struct intel_connector {
diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c 
b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
index 526fd58b9b51..2d39af63ec9b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
@@ -478,23 +478,6 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port 
*dig_port,
return size;
 }
 
-static int
-get_rxinfo_hdcp_1_dev_downstream(struct intel_digital_port *dig_port, bool 
*hdcp_1_x)
-{
-   u8 rx_info[HDCP_2_2_RXINFO_LEN];
-   int ret;
-
-   ret = drm_dp_dpcd_read(_port->dp.aux,
-  DP_HDCP_2_2_REG_RXINFO_OFFSET,
-  (void *)rx_info, HDCP_2_2_RXINFO_LEN);
-
-   if (ret != HDCP_2_2_RXINFO_LEN)
-   return ret >= 0 ? -EIO : ret;
-
-   *hdcp_1_x = HDCP_2_2_HDCP1_DEVICE_CONNECTED(rx_info[1]) ? true : false;
-   return 0;
-}
-
 static
 ssize_t get_receiver_id_list_rx_info(struct intel_digital_port *dig_port, u32 
*dev_cnt, u8 *byte)
 {
@@ -664,27 +647,6 @@ int intel_dp_hdcp2_capable(struct intel_digital_port 
*dig_port,
return 0;
 }
 
-static
-int intel_dp_mst_streams_type1_capable(struct intel_connector *connector,
-  bool *capable)
-{
-   struct intel_digital_port *dig_port = 
intel_attached_dig_port(connector);
-   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
-   int ret;
-   bool hdcp_1_x;
-
-   ret = get_rxinfo_hdcp_1_dev_downstream(dig_port, _1_x);
-   if (ret) {
-   drm_dbg_kms(>drm,
-   "[%s:%d] failed to read RxInfo ret=%d\n",
-   connector->base.name, connector->base.base.id, ret);
-   return ret;
-   }
-
-   *capable = !hdcp_1_x;
-   return 0;
-}
-
 static const struct intel_hdcp_shim intel_dp_hdcp_shim = {
.write_an_aksv = intel_dp_hdcp_write_an_aksv,
.read_bksv = intel_dp_hdcp_read_bksv,
@@ -833,7 +795,6 @@ static const struct intel_hdcp_shim intel_dp_mst_hdcp_shim 
= {
.stream_2_2_encryption = intel_dp_mst_hdcp2_stream_encryption,
.check_2_2_link = intel_dp_mst_hdcp2_check_link,
.hdcp_2_2_capable = intel_dp_hdcp2_capable,
-   .streams_type1_capable = intel_dp_mst_streams_type1_capable,
.protocol = HDCP_PROTOCOL_DP,
 };
 
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c 
b/drivers/gpu/drm/i915/display/intel_hdcp.c
index ebc2e32aec0b..fa6a60faa6a7 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -33,21 +33,6 @@ static int intel_conn_to_vcpi(struct intel_connector 
*connector)
return connector->port  ? connector->port->vcpi.vcpi : 0;
 }
 
-static bool
-intel_streams_type1_capable(struct intel_connector *connector)
-{
-   const struct intel_hdcp_shim *shim = connector->hdcp.shim;
-   bool capable = false;
-
-   if (!shim)
-   return capable;
-
-   if (shim->streams_type1_capable)
-   shim->streams_type1_capable(connector, );
-
-   return capable;
-}
-
 /*
  * intel_hdcp_required_content_stream selects the most highest common possible 
HDCP
  * content_type for all streams in DP MST topology because security f/w doesn't
@@ -86,7 +71,7 @@ intel_hdcp_required_content_stream(struct intel_digital_port 
*dig_port)

[Intel-gfx] [PATCH v2 2/3] drm/i915/hdcp: read RxInfo once when reading RepeaterAuth_Send_ReceiverID_List

2021-08-10 Thread Juston Li
When reading RepeaterAuth_Send_ReceiverID_List, RxInfo is read by itself
once to retrieve the DEVICE_COUNT to calculate the size of the
ReceiverID list then read a second time as a part of reading ReceiverID
list.

On some MST docking stations, RxInfo can only be read after the RxStatus
READY bit is set otherwise the read will return -EIO. The spec states that
the READY bit should be cleared as soon as RxInfo has been read.

In this case, the first RxInfo read succeeds but after the READY bit is
cleared, the second read fails.

Fix it by reading RxInfo once and storing it before reading the rest of
RepeaterAuth_Send_ReceiverID_List once we know the size.

Modify get_receiver_id_list_size() to read and store RxInfo in the
message buffer and also parse DEVICE_COUNT so we know the size of
RepeaterAuth_Send_ReceiverID_List.

Afterwards, retrieve the rest of the message at the offset for
seq_num_V.

Changes in v4:
- rebase and edit commit message

Changes in v3:
- remove comment

Changes in v2:
- remove unnecessary moving of drm_i915_private from patch 1

Signed-off-by: Juston Li 
Acked-by: Anshuman Gupta 
---
 drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 30 ++--
 include/drm/drm_dp_helper.h  |  2 +-
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c 
b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
index 1d0096654776..526fd58b9b51 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
@@ -496,11 +496,10 @@ get_rxinfo_hdcp_1_dev_downstream(struct 
intel_digital_port *dig_port, bool *hdcp
 }
 
 static
-ssize_t get_receiver_id_list_size(struct intel_digital_port *dig_port)
+ssize_t get_receiver_id_list_rx_info(struct intel_digital_port *dig_port, u32 
*dev_cnt, u8 *byte)
 {
-   u8 rx_info[HDCP_2_2_RXINFO_LEN];
-   u32 dev_cnt;
ssize_t ret;
+   u8 *rx_info = byte;
 
ret = drm_dp_dpcd_read(_port->dp.aux,
   DP_HDCP_2_2_REG_RXINFO_OFFSET,
@@ -508,15 +507,11 @@ ssize_t get_receiver_id_list_size(struct 
intel_digital_port *dig_port)
if (ret != HDCP_2_2_RXINFO_LEN)
return ret >= 0 ? -EIO : ret;
 
-   dev_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 |
+   *dev_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 |
   HDCP_2_2_DEV_COUNT_LO(rx_info[1]));
 
-   if (dev_cnt > HDCP_2_2_MAX_DEVICE_COUNT)
-   dev_cnt = HDCP_2_2_MAX_DEVICE_COUNT;
-
-   ret = sizeof(struct hdcp2_rep_send_receiverid_list) -
-   HDCP_2_2_RECEIVER_IDS_MAX_LEN +
-   (dev_cnt * HDCP_2_2_RECEIVER_ID_LEN);
+   if (*dev_cnt > HDCP_2_2_MAX_DEVICE_COUNT)
+   *dev_cnt = HDCP_2_2_MAX_DEVICE_COUNT;
 
return ret;
 }
@@ -534,6 +529,7 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port 
*dig_port,
const struct hdcp2_dp_msg_data *hdcp2_msg_data;
ktime_t msg_end = ktime_set(0, 0);
bool msg_expired;
+   u32 dev_cnt;
 
hdcp2_msg_data = get_hdcp2_dp_msg_data(msg_id);
if (!hdcp2_msg_data)
@@ -546,17 +542,21 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port 
*dig_port,
 
hdcp->cp_irq_count_cached = atomic_read(>cp_irq_count);
 
+   /* DP adaptation msgs has no msg_id */
+   byte++;
+
if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST) {
-   ret = get_receiver_id_list_size(dig_port);
+   ret = get_receiver_id_list_rx_info(dig_port, _cnt, byte);
if (ret < 0)
return ret;
 
-   size = ret;
+   byte += ret;
+   size = sizeof(struct hdcp2_rep_send_receiverid_list) -
+   HDCP_2_2_RXINFO_LEN - HDCP_2_2_RECEIVER_IDS_MAX_LEN +
+   (dev_cnt * HDCP_2_2_RECEIVER_ID_LEN);
}
-   bytes_to_recv = size - 1;
 
-   /* DP adaptation msgs has no msg_id */
-   byte++;
+   bytes_to_recv = size - 1;
 
while (bytes_to_recv) {
len = bytes_to_recv > DP_AUX_MAX_PAYLOAD_BYTES ?
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 3f2715eb965f..7476e7c6d0be 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1413,7 +1413,7 @@ enum drm_dp_phy {
 #define DP_HDCP_2_2_LC_INIT_OFFSET DP_HDCP_2_2_REG_RN_OFFSET
 #define DP_HDCP_2_2_LC_SEND_LPRIME_OFFSET  DP_HDCP_2_2_REG_LPRIME_OFFSET
 #define DP_HDCP_2_2_SKE_SEND_EKS_OFFSET
DP_HDCP_2_2_REG_EDKEY_KS_OFFSET
-#define DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET
DP_HDCP_2_2_REG_RXINFO_OFFSET
+#define DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET
DP_HDCP_2_2_REG_SEQ_NUM_V_OFFSET
 #define DP_HDCP_2_2_REP_SEND_ACK_OFFSETDP_HDCP_2_2_REG_V_OFFSET
 #define DP_HDCP_2_2_REP_STREAM_MANAGE_OFFSET   DP_HDCP_2_2_REG_SEQ_NUM_M_OFFSET
 #define DP_HDCP_2_2_REP_STREAM_READY_OFFSETDP_HDCP_2_2_REG_MPRIME_OFFSET
-- 
2.31.1



[Intel-gfx] [PATCH v2 1/3] drm/i915/hdcp: update cp_irq_count_cached in intel_dp_hdcp2_read_msg()

2021-08-10 Thread Juston Li
Update cp_irq_count_cached when reading messages rather than when
writing a message to make sure the value is up to date and not
stale from a previously handled CP_IRQ.

AKE flow  doesn't always respond to a read with a ACK write msg.
E.g. AKE_Send_Pairing_Info will "timeout" because we received
a CP_IRQ for reading AKE_Send_H_Prime but no write occurred between that
and reading AKE_Send_Pairing_Info so cp_irq_count_cached is stale
causing the wait to return right away rather than waiting for a new
CP_IRQ.

Signed-off-by: Juston Li 
Acked-by: Anshuman Gupta 
---
 drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c 
b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
index d697d169e8c1..1d0096654776 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
@@ -446,8 +446,6 @@ static
 int intel_dp_hdcp2_write_msg(struct intel_digital_port *dig_port,
 void *buf, size_t size)
 {
-   struct intel_dp *dp = _port->dp;
-   struct intel_hdcp *hdcp = >attached_connector->hdcp;
unsigned int offset;
u8 *byte = buf;
ssize_t ret, bytes_to_write, len;
@@ -463,8 +461,6 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port 
*dig_port,
bytes_to_write = size - 1;
byte++;
 
-   hdcp->cp_irq_count_cached = atomic_read(>cp_irq_count);
-
while (bytes_to_write) {
len = bytes_to_write > DP_AUX_MAX_PAYLOAD_BYTES ?
DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_write;
@@ -530,6 +526,8 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port 
*dig_port,
u8 msg_id, void *buf, size_t size)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   struct intel_dp *dp = _port->dp;
+   struct intel_hdcp *hdcp = >attached_connector->hdcp;
unsigned int offset;
u8 *byte = buf;
ssize_t ret, bytes_to_recv, len;
@@ -546,6 +544,8 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port 
*dig_port,
if (ret < 0)
return ret;
 
+   hdcp->cp_irq_count_cached = atomic_read(>cp_irq_count);
+
if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST) {
ret = get_receiver_id_list_size(dig_port);
if (ret < 0)
-- 
2.31.1



[Intel-gfx] [PATCH v2 0/3] drm/i915/hdcp: HDCP2.2 MST dock fixes

2021-08-10 Thread Juston Li
Fixes to get HDCP2.2 over MST working on MST docking stations with
certain behaviors that cause the current flow to fail.
Tested with Dell WD-19 and Lenovo ThinkPad USB Type-C Dock Gen 2.

These fixes should make the flow more robust to handle behaviors that as
far as I can tell are unclear in the HDCP spec:

RxInfo contains repeater topology information needed for MST. The
behavior on these docks is that this can only be read during 
RepeaterAuth_Send_ReceiverID_List when the RxStatus READY bit is set
otherwise the dock will return NACK. It seems these docks treat
reading this range at any other time as invalid when the READY bit
isn't set possibly because it could be stale. The HDCP spec also states
the READY bit is cleared after RxInfo is read.

These fixes address this behavior by only reading RxInfo once during the 
AKE flow and reusing that data.

Changes since v1:
 - Fix subject line for 3/3

Juston Li (3):
  drm/i915/hdcp: update cp_irq_count_cached in intel_dp_hdcp2_read_msg()
  drm/i915/hdcp: read RxInfo once when reading
RepeaterAuth_Send_ReceiverID_List
  drm/i915/hdcp: reuse rx_info for mst stream type1 capability check

 .../drm/i915/display/intel_display_types.h|  2 +
 drivers/gpu/drm/i915/display/intel_dp_hdcp.c  | 77 +--
 drivers/gpu/drm/i915/display/intel_hdcp.c | 47 +--
 include/drm/drm_dp_helper.h   |  2 +-
 4 files changed, 43 insertions(+), 85 deletions(-)

-- 
2.31.1



[Intel-gfx] [PATCH 2/3] drm/i915/hdcp: read RxInfo once when reading RepeaterAuth_Send_ReceiverID_List

2021-08-10 Thread Juston Li
From: Juston Li 
Date: Mon, 9 Aug 2021 12:55:06 -0700
Subject: [Intel-gfx] [PATCH 3/3] drm/i915/hdcp: reuse rx_info for mst stream
 type1 capability check

On some MST docking stations, rx_info can only be read after
RepeaterAuth_Send_ReceiverID_List and the RxStatus READY bit is set
otherwise the read will return -EIO.

This behavior causes the mst stream type1 capability test to fail to
read rx_info and determine if the topology supports type1 and fallback
to type0.

To fix this, check for type1 capability when we receive rx_info within
the AKE flow when we read RepeaterAuth_Send_ReceiverID_List instead
of an explicit read just for type1 capability checking.

This does require moving where we set stream_types to after
hdcp2_authenticate_sink() when we get rx_info but this occurs before we
do hdcp2_propagate_stream_management_info.

Also, legacy HDCP 2.0/2.1 are not type 1 capable either so check for
that as well.

Signed-off-by: Juston Li 
---
 .../drm/i915/display/intel_display_types.h|  2 +
 drivers/gpu/drm/i915/display/intel_dp_hdcp.c  | 39 ---
 drivers/gpu/drm/i915/display/intel_hdcp.c | 47 +--
 3 files changed, 23 insertions(+), 65 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h 
b/drivers/gpu/drm/i915/display/intel_display_types.h
index dbdfe54d0340..c8b687ff0374 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -516,6 +516,8 @@ struct intel_hdcp {
enum transcoder cpu_transcoder;
/* Only used for DP MST stream encryption */
enum transcoder stream_transcoder;
+
+   bool topology_type1_capable;
 };
 
 struct intel_connector {
diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c 
b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
index 526fd58b9b51..2d39af63ec9b 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
@@ -478,23 +478,6 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port 
*dig_port,
return size;
 }
 
-static int
-get_rxinfo_hdcp_1_dev_downstream(struct intel_digital_port *dig_port, bool 
*hdcp_1_x)
-{
-   u8 rx_info[HDCP_2_2_RXINFO_LEN];
-   int ret;
-
-   ret = drm_dp_dpcd_read(_port->dp.aux,
-  DP_HDCP_2_2_REG_RXINFO_OFFSET,
-  (void *)rx_info, HDCP_2_2_RXINFO_LEN);
-
-   if (ret != HDCP_2_2_RXINFO_LEN)
-   return ret >= 0 ? -EIO : ret;
-
-   *hdcp_1_x = HDCP_2_2_HDCP1_DEVICE_CONNECTED(rx_info[1]) ? true : false;
-   return 0;
-}
-
 static
 ssize_t get_receiver_id_list_rx_info(struct intel_digital_port *dig_port, u32 
*dev_cnt, u8 *byte)
 {
@@ -664,27 +647,6 @@ int intel_dp_hdcp2_capable(struct intel_digital_port 
*dig_port,
return 0;
 }
 
-static
-int intel_dp_mst_streams_type1_capable(struct intel_connector *connector,
-  bool *capable)
-{
-   struct intel_digital_port *dig_port = 
intel_attached_dig_port(connector);
-   struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
-   int ret;
-   bool hdcp_1_x;
-
-   ret = get_rxinfo_hdcp_1_dev_downstream(dig_port, _1_x);
-   if (ret) {
-   drm_dbg_kms(>drm,
-   "[%s:%d] failed to read RxInfo ret=%d\n",
-   connector->base.name, connector->base.base.id, ret);
-   return ret;
-   }
-
-   *capable = !hdcp_1_x;
-   return 0;
-}
-
 static const struct intel_hdcp_shim intel_dp_hdcp_shim = {
.write_an_aksv = intel_dp_hdcp_write_an_aksv,
.read_bksv = intel_dp_hdcp_read_bksv,
@@ -833,7 +795,6 @@ static const struct intel_hdcp_shim intel_dp_mst_hdcp_shim 
= {
.stream_2_2_encryption = intel_dp_mst_hdcp2_stream_encryption,
.check_2_2_link = intel_dp_mst_hdcp2_check_link,
.hdcp_2_2_capable = intel_dp_hdcp2_capable,
-   .streams_type1_capable = intel_dp_mst_streams_type1_capable,
.protocol = HDCP_PROTOCOL_DP,
 };
 
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c 
b/drivers/gpu/drm/i915/display/intel_hdcp.c
index ebc2e32aec0b..fa6a60faa6a7 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -33,21 +33,6 @@ static int intel_conn_to_vcpi(struct intel_connector 
*connector)
return connector->port  ? connector->port->vcpi.vcpi : 0;
 }
 
-static bool
-intel_streams_type1_capable(struct intel_connector *connector)
-{
-   const struct intel_hdcp_shim *shim = connector->hdcp.shim;
-   bool capable = false;
-
-   if (!shim)
-   return capable;
-
-   if (shim->streams_type1_capable)
-   shim->streams_type1_capable(connector, );
-
-   return capable;
-}
-
 /*
  * intel_hdcp_required_content_stream selects the most highest common possible 
HDCP
  * content_type for all s

[Intel-gfx] [PATCH 2/3] drm/i915/hdcp: read RxInfo once when reading RepeaterAuth_Send_ReceiverID_List

2021-08-10 Thread Juston Li
When reading RepeaterAuth_Send_ReceiverID_List, RxInfo is read by itself
once to retrieve the DEVICE_COUNT to calculate the size of the
ReceiverID list then read a second time as a part of reading ReceiverID
list.

On some MST docking stations, RxInfo can only be read after the RxStatus
READY bit is set otherwise the read will return -EIO. The spec states that
the READY bit should be cleared as soon as RxInfo has been read.

In this case, the first RxInfo read succeeds but after the READY bit is
cleared, the second read fails.

Fix it by reading RxInfo once and storing it before reading the rest of
RepeaterAuth_Send_ReceiverID_List once we know the size.

Modify get_receiver_id_list_size() to read and store RxInfo in the
message buffer and also parse DEVICE_COUNT so we know the size of
RepeaterAuth_Send_ReceiverID_List.

Afterwards, retrieve the rest of the message at the offset for
seq_num_V.

Changes in v4:
- rebase and edit commit message

Changes in v3:
- remove comment

Changes in v2:
- remove unnecessary moving of drm_i915_private from patch 1

Signed-off-by: Juston Li 
Acked-by: Anshuman Gupta 
---
 drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 30 ++--
 include/drm/drm_dp_helper.h  |  2 +-
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c 
b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
index 1d0096654776..526fd58b9b51 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
@@ -496,11 +496,10 @@ get_rxinfo_hdcp_1_dev_downstream(struct 
intel_digital_port *dig_port, bool *hdcp
 }
 
 static
-ssize_t get_receiver_id_list_size(struct intel_digital_port *dig_port)
+ssize_t get_receiver_id_list_rx_info(struct intel_digital_port *dig_port, u32 
*dev_cnt, u8 *byte)
 {
-   u8 rx_info[HDCP_2_2_RXINFO_LEN];
-   u32 dev_cnt;
ssize_t ret;
+   u8 *rx_info = byte;
 
ret = drm_dp_dpcd_read(_port->dp.aux,
   DP_HDCP_2_2_REG_RXINFO_OFFSET,
@@ -508,15 +507,11 @@ ssize_t get_receiver_id_list_size(struct 
intel_digital_port *dig_port)
if (ret != HDCP_2_2_RXINFO_LEN)
return ret >= 0 ? -EIO : ret;
 
-   dev_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 |
+   *dev_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 |
   HDCP_2_2_DEV_COUNT_LO(rx_info[1]));
 
-   if (dev_cnt > HDCP_2_2_MAX_DEVICE_COUNT)
-   dev_cnt = HDCP_2_2_MAX_DEVICE_COUNT;
-
-   ret = sizeof(struct hdcp2_rep_send_receiverid_list) -
-   HDCP_2_2_RECEIVER_IDS_MAX_LEN +
-   (dev_cnt * HDCP_2_2_RECEIVER_ID_LEN);
+   if (*dev_cnt > HDCP_2_2_MAX_DEVICE_COUNT)
+   *dev_cnt = HDCP_2_2_MAX_DEVICE_COUNT;
 
return ret;
 }
@@ -534,6 +529,7 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port 
*dig_port,
const struct hdcp2_dp_msg_data *hdcp2_msg_data;
ktime_t msg_end = ktime_set(0, 0);
bool msg_expired;
+   u32 dev_cnt;
 
hdcp2_msg_data = get_hdcp2_dp_msg_data(msg_id);
if (!hdcp2_msg_data)
@@ -546,17 +542,21 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port 
*dig_port,
 
hdcp->cp_irq_count_cached = atomic_read(>cp_irq_count);
 
+   /* DP adaptation msgs has no msg_id */
+   byte++;
+
if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST) {
-   ret = get_receiver_id_list_size(dig_port);
+   ret = get_receiver_id_list_rx_info(dig_port, _cnt, byte);
if (ret < 0)
return ret;
 
-   size = ret;
+   byte += ret;
+   size = sizeof(struct hdcp2_rep_send_receiverid_list) -
+   HDCP_2_2_RXINFO_LEN - HDCP_2_2_RECEIVER_IDS_MAX_LEN +
+   (dev_cnt * HDCP_2_2_RECEIVER_ID_LEN);
}
-   bytes_to_recv = size - 1;
 
-   /* DP adaptation msgs has no msg_id */
-   byte++;
+   bytes_to_recv = size - 1;
 
while (bytes_to_recv) {
len = bytes_to_recv > DP_AUX_MAX_PAYLOAD_BYTES ?
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index 3f2715eb965f..7476e7c6d0be 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1413,7 +1413,7 @@ enum drm_dp_phy {
 #define DP_HDCP_2_2_LC_INIT_OFFSET DP_HDCP_2_2_REG_RN_OFFSET
 #define DP_HDCP_2_2_LC_SEND_LPRIME_OFFSET  DP_HDCP_2_2_REG_LPRIME_OFFSET
 #define DP_HDCP_2_2_SKE_SEND_EKS_OFFSET
DP_HDCP_2_2_REG_EDKEY_KS_OFFSET
-#define DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET
DP_HDCP_2_2_REG_RXINFO_OFFSET
+#define DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET
DP_HDCP_2_2_REG_SEQ_NUM_V_OFFSET
 #define DP_HDCP_2_2_REP_SEND_ACK_OFFSETDP_HDCP_2_2_REG_V_OFFSET
 #define DP_HDCP_2_2_REP_STREAM_MANAGE_OFFSET   DP_HDCP_2_2_REG_SEQ_NUM_M_OFFSET
 #define DP_HDCP_2_2_REP_STREAM_READY_OFFSETDP_HDCP_2_2_REG_MPRIME_OFFSET
-- 
2.31.1



[Intel-gfx] [PATCH 1/3] drm/i915/hdcp: update cp_irq_count_cached in intel_dp_hdcp2_read_msg()

2021-08-10 Thread Juston Li
Update cp_irq_count_cached when reading messages rather than when
writing a message to make sure the value is up to date and not
stale from a previously handled CP_IRQ.

AKE flow  doesn't always respond to a read with a ACK write msg.
E.g. AKE_Send_Pairing_Info will "timeout" because we received
a CP_IRQ for reading AKE_Send_H_Prime but no write occurred between that
and reading AKE_Send_Pairing_Info so cp_irq_count_cached is stale
causing the wait to return right away rather than waiting for a new
CP_IRQ.

Signed-off-by: Juston Li 
Acked-by: Anshuman Gupta 
---
 drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c 
b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
index d697d169e8c1..1d0096654776 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
@@ -446,8 +446,6 @@ static
 int intel_dp_hdcp2_write_msg(struct intel_digital_port *dig_port,
 void *buf, size_t size)
 {
-   struct intel_dp *dp = _port->dp;
-   struct intel_hdcp *hdcp = >attached_connector->hdcp;
unsigned int offset;
u8 *byte = buf;
ssize_t ret, bytes_to_write, len;
@@ -463,8 +461,6 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port 
*dig_port,
bytes_to_write = size - 1;
byte++;
 
-   hdcp->cp_irq_count_cached = atomic_read(>cp_irq_count);
-
while (bytes_to_write) {
len = bytes_to_write > DP_AUX_MAX_PAYLOAD_BYTES ?
DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_write;
@@ -530,6 +526,8 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port 
*dig_port,
u8 msg_id, void *buf, size_t size)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   struct intel_dp *dp = _port->dp;
+   struct intel_hdcp *hdcp = >attached_connector->hdcp;
unsigned int offset;
u8 *byte = buf;
ssize_t ret, bytes_to_recv, len;
@@ -546,6 +544,8 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port 
*dig_port,
if (ret < 0)
return ret;
 
+   hdcp->cp_irq_count_cached = atomic_read(>cp_irq_count);
+
if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST) {
ret = get_receiver_id_list_size(dig_port);
if (ret < 0)
-- 
2.31.1



[Intel-gfx] [PATCH 0/3] drm/i915/hdcp: HDCP2.2 MST dock fixes

2021-08-10 Thread Juston Li
Fixes to get HDCP2.2 over MST working on MST docking stations with
certain behaviors that cause the current flow to fail.
Tested with Dell WD-19 and Lenovo ThinkPad USB Type-C Dock Gen 2.

These fixes should make the flow more robust to handle behaviors that as
far as I can tell are unclear in the HDCP spec:

RxInfo contains repeater topology information needed for MST. The
behavior on these docks is that this can only be read during 
RepeaterAuth_Send_ReceiverID_List when the RxStatus READY bit is set
otherwise the dock will return NACK. It seems these docks treat
reading this range at any other time as invalid when the READY bit
isn't set possibly because it could be stale. The HDCP spec also states
the READY bit is cleared after RxInfo is read.

These fixes address this behavior by only reading RxInfo once during the 
AKE flow and reusing that data.

Juston Li (3):
  drm/i915/hdcp: update cp_irq_count_cached in intel_dp_hdcp2_read_msg()
  drm/i915/hdcp: read RxInfo once when reading
RepeaterAuth_Send_ReceiverID_List
  drm/i915/hdcp: reuse rx_info for mst stream type1 capability check

 .../drm/i915/display/intel_display_types.h|  2 +
 drivers/gpu/drm/i915/display/intel_dp_hdcp.c  | 77 +--
 drivers/gpu/drm/i915/display/intel_hdcp.c | 47 +--
 include/drm/drm_dp_helper.h   |  2 +-
 4 files changed, 43 insertions(+), 85 deletions(-)

-- 
2.31.1



[Intel-gfx] [PATCH v3 2/2] drm/i915/hdcp: read RxInfo once when reading Send_Pairing_Info

2021-01-28 Thread Juston Li
Previously when reading Send_Pairing_Info, RxInfo by itself was read
once to retrieve the DEVICE_COUNT and then a second time when reading
the RepeaterAuth_Send_ReceiverID_List which contains RxInfo.

On a couple HDCP 2.2 docks, this second read attempt on RxInfo fails
due to no Ack response. This behavior doesn't seem to be defined but
regardless we can fix it by reading RxInfo once and storing it before
reading the rest of RepeaterAuth_Send_ReceiverID_List once we know the
size.

Modify get_receiver_id_list_size() to read and store RxInfo in the
message buffer and also parse DEVICE_COUNT so we know the size of
RepeaterAuth_Send_ReceiverID_List.

Afterwards, retrieve the rest of the message at the offset for
seq_num_V.

Changes in v3:
- remove comment

Changes in v2:
- remove unnecessary moving of drm_i915_private from patch 1

Signed-off-by: Juston Li 
Acked-by: Anshuman Gupta 
---
 drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 30 ++--
 include/drm/drm_dp_helper.h  |  2 +-
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c 
b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
index d1397af97f69..3c04576681b9 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
@@ -475,11 +475,10 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port 
*dig_port,
 }
 
 static
-ssize_t get_receiver_id_list_size(struct intel_digital_port *dig_port)
+ssize_t get_receiver_id_list_rx_info(struct intel_digital_port *dig_port, u32 
*dev_cnt, u8 *byte)
 {
-   u8 rx_info[HDCP_2_2_RXINFO_LEN];
-   u32 dev_cnt;
ssize_t ret;
+   u8 *rx_info = byte;
 
ret = drm_dp_dpcd_read(_port->dp.aux,
   DP_HDCP_2_2_REG_RXINFO_OFFSET,
@@ -487,15 +486,11 @@ ssize_t get_receiver_id_list_size(struct 
intel_digital_port *dig_port)
if (ret != HDCP_2_2_RXINFO_LEN)
return ret >= 0 ? -EIO : ret;
 
-   dev_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 |
+   *dev_cnt = (HDCP_2_2_DEV_COUNT_HI(rx_info[0]) << 4 |
   HDCP_2_2_DEV_COUNT_LO(rx_info[1]));
 
-   if (dev_cnt > HDCP_2_2_MAX_DEVICE_COUNT)
-   dev_cnt = HDCP_2_2_MAX_DEVICE_COUNT;
-
-   ret = sizeof(struct hdcp2_rep_send_receiverid_list) -
-   HDCP_2_2_RECEIVER_IDS_MAX_LEN +
-   (dev_cnt * HDCP_2_2_RECEIVER_ID_LEN);
+   if (*dev_cnt > HDCP_2_2_MAX_DEVICE_COUNT)
+   *dev_cnt = HDCP_2_2_MAX_DEVICE_COUNT;
 
return ret;
 }
@@ -511,6 +506,7 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port 
*dig_port,
u8 *byte = buf;
ssize_t ret, bytes_to_recv, len;
const struct hdcp2_dp_msg_data *hdcp2_msg_data;
+   u32 dev_cnt;
 
hdcp2_msg_data = get_hdcp2_dp_msg_data(msg_id);
if (!hdcp2_msg_data)
@@ -523,17 +519,21 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port 
*dig_port,
 
hdcp->cp_irq_count_cached = atomic_read(>cp_irq_count);
 
+   /* DP adaptation msgs has no msg_id */
+   byte++;
+
if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST) {
-   ret = get_receiver_id_list_size(dig_port);
+   ret = get_receiver_id_list_rx_info(dig_port, _cnt, byte);
if (ret < 0)
return ret;
 
-   size = ret;
+   byte += ret;
+   size = sizeof(struct hdcp2_rep_send_receiverid_list) -
+   HDCP_2_2_RXINFO_LEN - HDCP_2_2_RECEIVER_IDS_MAX_LEN +
+   (dev_cnt * HDCP_2_2_RECEIVER_ID_LEN);
}
-   bytes_to_recv = size - 1;
 
-   /* DP adaptation msgs has no msg_id */
-   byte++;
+   bytes_to_recv = size - 1;
 
while (bytes_to_recv) {
len = bytes_to_recv > DP_AUX_MAX_PAYLOAD_BYTES ?
diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h
index edffd1dcca3e..3b42392394ba 100644
--- a/include/drm/drm_dp_helper.h
+++ b/include/drm/drm_dp_helper.h
@@ -1388,7 +1388,7 @@ enum drm_dp_phy {
 #define DP_HDCP_2_2_LC_INIT_OFFSET DP_HDCP_2_2_REG_RN_OFFSET
 #define DP_HDCP_2_2_LC_SEND_LPRIME_OFFSET  DP_HDCP_2_2_REG_LPRIME_OFFSET
 #define DP_HDCP_2_2_SKE_SEND_EKS_OFFSET
DP_HDCP_2_2_REG_EDKEY_KS_OFFSET
-#define DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET
DP_HDCP_2_2_REG_RXINFO_OFFSET
+#define DP_HDCP_2_2_REP_SEND_RECVID_LIST_OFFSET
DP_HDCP_2_2_REG_SEQ_NUM_V_OFFSET
 #define DP_HDCP_2_2_REP_SEND_ACK_OFFSETDP_HDCP_2_2_REG_V_OFFSET
 #define DP_HDCP_2_2_REP_STREAM_MANAGE_OFFSET   DP_HDCP_2_2_REG_SEQ_NUM_M_OFFSET
 #define DP_HDCP_2_2_REP_STREAM_READY_OFFSETDP_HDCP_2_2_REG_MPRIME_OFFSET
-- 
2.29.2

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[Intel-gfx] [PATCH v3 1/2] drm/i915/hdcp: update cp_irq_count_cached in intel_dp_hdcp2_read_msg()

2021-01-28 Thread Juston Li
Update cp_irq_count_cached when we handle reading the messages rather
than writing a message to make sure the value is up to date and not
stale from a previously handled CP_IRQ. AKE flow  doesn't always respond
to a read with a write msg.

E.g. currently AKE_Send_Pairing_Info will "timeout" because we received
a CP_IRQ for reading AKE_Send_H_Prime but no write occurred between that
and reading AKE_Send_Pairing_Info so cp_irq_count_cached is stale
causing the wait to return right away rather than waiting for a new
CP_IRQ.

Signed-off-by: Juston Li 
Acked-by: Anshuman Gupta 
---
 drivers/gpu/drm/i915/display/intel_dp_hdcp.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c 
b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
index 4dba5bb15af5..d1397af97f69 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
@@ -442,8 +442,6 @@ static
 int intel_dp_hdcp2_write_msg(struct intel_digital_port *dig_port,
 void *buf, size_t size)
 {
-   struct intel_dp *dp = _port->dp;
-   struct intel_hdcp *hdcp = >attached_connector->hdcp;
unsigned int offset;
u8 *byte = buf;
ssize_t ret, bytes_to_write, len;
@@ -459,8 +457,6 @@ int intel_dp_hdcp2_write_msg(struct intel_digital_port 
*dig_port,
bytes_to_write = size - 1;
byte++;
 
-   hdcp->cp_irq_count_cached = atomic_read(>cp_irq_count);
-
while (bytes_to_write) {
len = bytes_to_write > DP_AUX_MAX_PAYLOAD_BYTES ?
DP_AUX_MAX_PAYLOAD_BYTES : bytes_to_write;
@@ -509,6 +505,8 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port 
*dig_port,
u8 msg_id, void *buf, size_t size)
 {
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+   struct intel_dp *dp = _port->dp;
+   struct intel_hdcp *hdcp = >attached_connector->hdcp;
unsigned int offset;
u8 *byte = buf;
ssize_t ret, bytes_to_recv, len;
@@ -523,6 +521,8 @@ int intel_dp_hdcp2_read_msg(struct intel_digital_port 
*dig_port,
if (ret < 0)
return ret;
 
+   hdcp->cp_irq_count_cached = atomic_read(>cp_irq_count);
+
if (msg_id == HDCP_2_2_REP_SEND_RECVID_LIST) {
ret = get_receiver_id_list_size(dig_port);
if (ret < 0)
-- 
2.29.2

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v8 libdrm 2/2] Add drmModeGetFB2

2020-02-11 Thread Juston Li
From: Daniel Stone 

Add a wrapper around the getfb2 ioctl, which returns extended
framebuffer information mirroring addfb2, including multiple planes and
modifiers.

Changes since v7:
 - add new symbols to core-symbol.txt (Eric Engestrom)

Changes since v5:
 - style change

Changes since v4:
 - Set fb_id at init instead of memclear() and set (Eric Engestrom)

Changes since v3:
 - remove unnecessary null check in drmModeFreeFB2 (Daniel Stone)

Changes since v2:
 - getfb2 ioctl has been merged upstream
 - sync include/drm/drm.h in a seperate patch

Changes since v1:
 - functions should be drm_public
 - modifier should be 64 bits
 - update ioctl number

Signed-off-by: Juston Li 
Signed-off-by: Daniel Stone 
Reviewed-by: Eric Engestrom 
---
 core-symbols.txt |  2 ++
 xf86drmMode.c| 35 +++
 xf86drmMode.h| 15 +++
 3 files changed, 52 insertions(+)

diff --git a/core-symbols.txt b/core-symbols.txt
index a62e01a069d3..1ff4ecaaf6ab 100644
--- a/core-symbols.txt
+++ b/core-symbols.txt
@@ -112,6 +112,7 @@ drmModeFreeConnector
 drmModeFreeCrtc
 drmModeFreeEncoder
 drmModeFreeFB
+drmModeFreeFB2
 drmModeFreeModeInfo
 drmModeFreeObjectProperties
 drmModeFreePlane
@@ -124,6 +125,7 @@ drmModeGetConnectorCurrent
 drmModeGetCrtc
 drmModeGetEncoder
 drmModeGetFB
+drmModeGetFB2
 drmModeGetLease
 drmModeGetPlane
 drmModeGetPlaneResources
diff --git a/xf86drmMode.c b/xf86drmMode.c
index 0cf7992c6e9a..2399e8ecea6f 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -1594,3 +1594,38 @@ drmModeRevokeLease(int fd, uint32_t lessee_id)
return 0;
return -errno;
 }
+
+drm_public drmModeFB2Ptr
+drmModeGetFB2(int fd, uint32_t fb_id)
+{
+   struct drm_mode_fb_cmd2 get = {
+   .fb_id = fb_id,
+   };
+   drmModeFB2Ptr ret;
+   int err;
+
+   err = DRM_IOCTL(fd, DRM_IOCTL_MODE_GETFB2, );
+   if (err != 0)
+   return NULL;
+
+   ret = drmMalloc(sizeof(drmModeFB2));
+   if (!ret)
+   return NULL;
+
+   ret->fb_id = fb_id;
+   ret->width = get.width;
+   ret->height = get.height;
+   ret->pixel_format = get.pixel_format;
+   ret->flags = get.flags;
+   ret->modifier = get.modifier[0];
+   memcpy(ret->handles, get.handles, sizeof(uint32_t) * 4);
+   memcpy(ret->pitches, get.pitches, sizeof(uint32_t) * 4);
+   memcpy(ret->offsets, get.offsets, sizeof(uint32_t) * 4);
+
+   return ret;
+}
+
+drm_public void drmModeFreeFB2(drmModeFB2Ptr ptr)
+{
+   drmFree(ptr);
+}
diff --git a/xf86drmMode.h b/xf86drmMode.h
index 159a39937240..fc0bbd8dcb67 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -225,6 +225,19 @@ typedef struct _drmModeFB {
uint32_t handle;
 } drmModeFB, *drmModeFBPtr;
 
+typedef struct _drmModeFB2 {
+   uint32_t fb_id;
+   uint32_t width, height;
+   uint32_t pixel_format; /* fourcc code from drm_fourcc.h */
+   uint64_t modifier; /* applies to all buffers */
+   uint32_t flags;
+
+   /* per-plane GEM handle; may be duplicate entries for multiple planes */
+   uint32_t handles[4];
+   uint32_t pitches[4]; /* bytes */
+   uint32_t offsets[4]; /* bytes */
+} drmModeFB2, *drmModeFB2Ptr;
+
 typedef struct drm_clip_rect drmModeClip, *drmModeClipPtr;
 
 typedef struct _drmModePropertyBlob {
@@ -343,6 +356,7 @@ typedef struct _drmModePlaneRes {
 extern void drmModeFreeModeInfo( drmModeModeInfoPtr ptr );
 extern void drmModeFreeResources( drmModeResPtr ptr );
 extern void drmModeFreeFB( drmModeFBPtr ptr );
+extern void drmModeFreeFB2( drmModeFB2Ptr ptr );
 extern void drmModeFreeCrtc( drmModeCrtcPtr ptr );
 extern void drmModeFreeConnector( drmModeConnectorPtr ptr );
 extern void drmModeFreeEncoder( drmModeEncoderPtr ptr );
@@ -362,6 +376,7 @@ extern drmModeResPtr drmModeGetResources(int fd);
  * Retrieve information about framebuffer bufferId
  */
 extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId);
+extern drmModeFB2Ptr drmModeGetFB2(int fd, uint32_t bufferId);
 
 /**
  * Creates a new framebuffer with an buffer object as its scanout buffer.
-- 
2.21.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v8 libdrm 1/2] include/drm: sync up drm.h

2020-02-11 Thread Juston Li
  a) delta: Adds DRM_IOCTL_MODE_GETFB2
  b) Generated using make headers_install
  c) Taken from drm-next-misc:
commit 3ff4c24bdb1f494c217c80348f9db4896043ed81
Author: Lyude Paul 
Date:   Fri Jan 17 17:47:48 2020 -0500

drm/dp_mst: Fix indenting in drm_dp_mst_topology_mgr_set_mst()

Signed-off-by: Juston Li 
Acked-by: Eric Engestrom 
---
 include/drm/drm.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/drm/drm.h b/include/drm/drm.h
index ab9403397815..c7fd2a35fd7b 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -942,6 +942,8 @@ extern "C" {
 #define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct 
drm_syncobj_transfer)
 #define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL  DRM_IOWR(0xCD, struct 
drm_syncobj_timeline_array)
 
+#define DRM_IOCTL_MODE_GETFB2  DRM_IOWR(0xCE, struct drm_mode_fb_cmd2)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x9f.
-- 
2.21.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 libdrm 2/2] Add drmModeGetFB2

2020-02-11 Thread Juston Li
From: Daniel Stone 

Add a wrapper around the getfb2 ioctl, which returns extended
framebuffer information mirroring addfb2, including multiple planes and
modifiers.

Changes since v5:
 - style change

Changes since v4:
 - Set fb_id at init instead of memclear() and set (Eric Engestrom)

Changes since v3:
 - remove unnecessary null check in drmModeFreeFB2 (Daniel Stone)

Changes since v2:
 - getfb2 ioctl has been merged upstream
 - sync include/drm/drm.h in a seperate patch

Changes since v1:
 - functions should be drm_public
 - modifier should be 64 bits
 - update ioctl number

Signed-off-by: Juston Li 
Signed-off-by: Daniel Stone 
Reviewed-by: Eric Engestrom 
---
 xf86drmMode.c | 35 +++
 xf86drmMode.h | 15 +++
 2 files changed, 50 insertions(+)

diff --git a/xf86drmMode.c b/xf86drmMode.c
index 0cf7992c6e9a..2399e8ecea6f 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -1594,3 +1594,38 @@ drmModeRevokeLease(int fd, uint32_t lessee_id)
return 0;
return -errno;
 }
+
+drm_public drmModeFB2Ptr
+drmModeGetFB2(int fd, uint32_t fb_id)
+{
+   struct drm_mode_fb_cmd2 get = {
+   .fb_id = fb_id,
+   };
+   drmModeFB2Ptr ret;
+   int err;
+
+   err = DRM_IOCTL(fd, DRM_IOCTL_MODE_GETFB2, );
+   if (err != 0)
+   return NULL;
+
+   ret = drmMalloc(sizeof(drmModeFB2));
+   if (!ret)
+   return NULL;
+
+   ret->fb_id = fb_id;
+   ret->width = get.width;
+   ret->height = get.height;
+   ret->pixel_format = get.pixel_format;
+   ret->flags = get.flags;
+   ret->modifier = get.modifier[0];
+   memcpy(ret->handles, get.handles, sizeof(uint32_t) * 4);
+   memcpy(ret->pitches, get.pitches, sizeof(uint32_t) * 4);
+   memcpy(ret->offsets, get.offsets, sizeof(uint32_t) * 4);
+
+   return ret;
+}
+
+drm_public void drmModeFreeFB2(drmModeFB2Ptr ptr)
+{
+   drmFree(ptr);
+}
diff --git a/xf86drmMode.h b/xf86drmMode.h
index 159a39937240..fc0bbd8dcb67 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -225,6 +225,19 @@ typedef struct _drmModeFB {
uint32_t handle;
 } drmModeFB, *drmModeFBPtr;
 
+typedef struct _drmModeFB2 {
+   uint32_t fb_id;
+   uint32_t width, height;
+   uint32_t pixel_format; /* fourcc code from drm_fourcc.h */
+   uint64_t modifier; /* applies to all buffers */
+   uint32_t flags;
+
+   /* per-plane GEM handle; may be duplicate entries for multiple planes */
+   uint32_t handles[4];
+   uint32_t pitches[4]; /* bytes */
+   uint32_t offsets[4]; /* bytes */
+} drmModeFB2, *drmModeFB2Ptr;
+
 typedef struct drm_clip_rect drmModeClip, *drmModeClipPtr;
 
 typedef struct _drmModePropertyBlob {
@@ -343,6 +356,7 @@ typedef struct _drmModePlaneRes {
 extern void drmModeFreeModeInfo( drmModeModeInfoPtr ptr );
 extern void drmModeFreeResources( drmModeResPtr ptr );
 extern void drmModeFreeFB( drmModeFBPtr ptr );
+extern void drmModeFreeFB2( drmModeFB2Ptr ptr );
 extern void drmModeFreeCrtc( drmModeCrtcPtr ptr );
 extern void drmModeFreeConnector( drmModeConnectorPtr ptr );
 extern void drmModeFreeEncoder( drmModeEncoderPtr ptr );
@@ -362,6 +376,7 @@ extern drmModeResPtr drmModeGetResources(int fd);
  * Retrieve information about framebuffer bufferId
  */
 extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId);
+extern drmModeFB2Ptr drmModeGetFB2(int fd, uint32_t bufferId);
 
 /**
  * Creates a new framebuffer with an buffer object as its scanout buffer.
-- 
2.21.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v7 libdrm 1/2] include/drm: sync up drm.h

2020-02-11 Thread Juston Li
  a) delta: Adds DRM_IOCTL_MODE_GETFB2
  b) Generated using make headers_install
  c) Taken from drm-next-misc:
commit 3ff4c24bdb1f494c217c80348f9db4896043ed81
Author: Lyude Paul 
Date:   Fri Jan 17 17:47:48 2020 -0500

drm/dp_mst: Fix indenting in drm_dp_mst_topology_mgr_set_mst()

Changes since v6:
 - clean up commit message per include/drm/README (Eric Engestrom)

Signed-off-by: Juston Li 
Acked-by: Eric Engestrom 
---
 include/drm/drm.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/drm/drm.h b/include/drm/drm.h
index ab9403397815..c7fd2a35fd7b 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -942,6 +942,8 @@ extern "C" {
 #define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct 
drm_syncobj_transfer)
 #define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL  DRM_IOWR(0xCD, struct 
drm_syncobj_timeline_array)
 
+#define DRM_IOCTL_MODE_GETFB2  DRM_IOWR(0xCE, struct drm_mode_fb_cmd2)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x9f.
-- 
2.21.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 libdrm 2/2] Add drmModeGetFB2

2020-02-05 Thread Juston Li
From: Daniel Stone 

Add a wrapper around the getfb2 ioctl, which returns extended
framebuffer information mirroring addfb2, including multiple planes and
modifiers.

Changes since v5:
 - style change

Changes since v4:
 - Set fb_id at init instead of memclear() and set (Eric Engestrom)

Changes since v3:
 - remove unnecessary null check in drmModeFreeFB2 (Daniel Stone)

Changes since v2:
 - getfb2 ioctl has been merged upstream
 - sync include/drm/drm.h in a seperate patch

Changes since v1:
 - functions should be drm_public
 - modifier should be 64 bits
 - update ioctl number

Signed-off-by: Juston Li 
Signed-off-by: Daniel Stone 
Reviewed-by: Eric Engestrom 
---
 xf86drmMode.c | 35 +++
 xf86drmMode.h | 15 +++
 2 files changed, 50 insertions(+)

diff --git a/xf86drmMode.c b/xf86drmMode.c
index 0cf7992c6e9a..2399e8ecea6f 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -1594,3 +1594,38 @@ drmModeRevokeLease(int fd, uint32_t lessee_id)
return 0;
return -errno;
 }
+
+drm_public drmModeFB2Ptr
+drmModeGetFB2(int fd, uint32_t fb_id)
+{
+   struct drm_mode_fb_cmd2 get = {
+   .fb_id = fb_id,
+   };
+   drmModeFB2Ptr ret;
+   int err;
+
+   err = DRM_IOCTL(fd, DRM_IOCTL_MODE_GETFB2, );
+   if (err != 0)
+   return NULL;
+
+   ret = drmMalloc(sizeof(drmModeFB2));
+   if (!ret)
+   return NULL;
+
+   ret->fb_id = fb_id;
+   ret->width = get.width;
+   ret->height = get.height;
+   ret->pixel_format = get.pixel_format;
+   ret->flags = get.flags;
+   ret->modifier = get.modifier[0];
+   memcpy(ret->handles, get.handles, sizeof(uint32_t) * 4);
+   memcpy(ret->pitches, get.pitches, sizeof(uint32_t) * 4);
+   memcpy(ret->offsets, get.offsets, sizeof(uint32_t) * 4);
+
+   return ret;
+}
+
+drm_public void drmModeFreeFB2(drmModeFB2Ptr ptr)
+{
+   drmFree(ptr);
+}
diff --git a/xf86drmMode.h b/xf86drmMode.h
index 159a39937240..fc0bbd8dcb67 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -225,6 +225,19 @@ typedef struct _drmModeFB {
uint32_t handle;
 } drmModeFB, *drmModeFBPtr;
 
+typedef struct _drmModeFB2 {
+   uint32_t fb_id;
+   uint32_t width, height;
+   uint32_t pixel_format; /* fourcc code from drm_fourcc.h */
+   uint64_t modifier; /* applies to all buffers */
+   uint32_t flags;
+
+   /* per-plane GEM handle; may be duplicate entries for multiple planes */
+   uint32_t handles[4];
+   uint32_t pitches[4]; /* bytes */
+   uint32_t offsets[4]; /* bytes */
+} drmModeFB2, *drmModeFB2Ptr;
+
 typedef struct drm_clip_rect drmModeClip, *drmModeClipPtr;
 
 typedef struct _drmModePropertyBlob {
@@ -343,6 +356,7 @@ typedef struct _drmModePlaneRes {
 extern void drmModeFreeModeInfo( drmModeModeInfoPtr ptr );
 extern void drmModeFreeResources( drmModeResPtr ptr );
 extern void drmModeFreeFB( drmModeFBPtr ptr );
+extern void drmModeFreeFB2( drmModeFB2Ptr ptr );
 extern void drmModeFreeCrtc( drmModeCrtcPtr ptr );
 extern void drmModeFreeConnector( drmModeConnectorPtr ptr );
 extern void drmModeFreeEncoder( drmModeEncoderPtr ptr );
@@ -362,6 +376,7 @@ extern drmModeResPtr drmModeGetResources(int fd);
  * Retrieve information about framebuffer bufferId
  */
 extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId);
+extern drmModeFB2Ptr drmModeGetFB2(int fd, uint32_t bufferId);
 
 /**
  * Creates a new framebuffer with an buffer object as its scanout buffer.
-- 
2.21.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v6 libdrm 1/2] include/drm: sync up drm.h

2020-02-05 Thread Juston Li
Adds DRM_IOCTL_MODE_GETFB2

Taken from drm-next-misc:
commit 3ff4c24bdb1f494c217c80348f9db4896043ed81
Author: Lyude Paul 
Date:   Fri Jan 17 17:47:48 2020 -0500

drm/dp_mst: Fix indenting in drm_dp_mst_topology_mgr_set_mst()

Signed-off-by: Juston Li 
---
 include/drm/drm.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/drm/drm.h b/include/drm/drm.h
index ab9403397815..c7fd2a35fd7b 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -942,6 +942,8 @@ extern "C" {
 #define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct 
drm_syncobj_transfer)
 #define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL  DRM_IOWR(0xCD, struct 
drm_syncobj_timeline_array)
 
+#define DRM_IOCTL_MODE_GETFB2  DRM_IOWR(0xCE, struct drm_mode_fb_cmd2)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x9f.
-- 
2.21.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v5 libdrm 2/2] Add drmModeGetFB2

2020-02-05 Thread Juston Li
From: Daniel Stone 

Add a wrapper around the getfb2 ioctl, which returns extended
framebuffer information mirroring addfb2, including multiple planes and
modifiers.

Changes since v4:
 - Set fb_id at init instead of memclear() and set (Eric Engestrom)

Changes since v3:
 - remove unnecessary null check in drmModeFreeFB2 (Daniel Stone)

Changes since v2:
 - getfb2 ioctl has been merged upstream
 - sync include/drm/drm.h in a seperate patch

Changes since v1:
 - functions should be drm_public
 - modifier should be 64 bits
 - update ioctl number

Signed-off-by: Juston Li 
Signed-off-by: Daniel Stone 
---
 xf86drmMode.c | 33 +
 xf86drmMode.h | 15 +++
 2 files changed, 48 insertions(+)

diff --git a/xf86drmMode.c b/xf86drmMode.c
index 0cf7992c6e9a..2eb7b765cce8 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -1594,3 +1594,36 @@ drmModeRevokeLease(int fd, uint32_t lessee_id)
return 0;
return -errno;
 }
+
+drm_public drmModeFB2Ptr
+drmModeGetFB2(int fd, uint32_t fb_id)
+{
+   struct drm_mode_fb_cmd2 get = { .fb_id = fb_id, };
+   drmModeFB2Ptr ret;
+   int err;
+
+   err = DRM_IOCTL(fd, DRM_IOCTL_MODE_GETFB2, );
+   if (err != 0)
+   return NULL;
+
+   ret = drmMalloc(sizeof(drmModeFB2));
+   if (!ret)
+   return NULL;
+
+   ret->fb_id = fb_id;
+   ret->width = get.width;
+   ret->height = get.height;
+   ret->pixel_format = get.pixel_format;
+   ret->flags = get.flags;
+   ret->modifier = get.modifier[0];
+   memcpy(ret->handles, get.handles, sizeof(uint32_t) * 4);
+   memcpy(ret->pitches, get.pitches, sizeof(uint32_t) * 4);
+   memcpy(ret->offsets, get.offsets, sizeof(uint32_t) * 4);
+
+   return ret;
+}
+
+drm_public void drmModeFreeFB2(drmModeFB2Ptr ptr)
+{
+   drmFree(ptr);
+}
diff --git a/xf86drmMode.h b/xf86drmMode.h
index 159a39937240..fc0bbd8dcb67 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -225,6 +225,19 @@ typedef struct _drmModeFB {
uint32_t handle;
 } drmModeFB, *drmModeFBPtr;
 
+typedef struct _drmModeFB2 {
+   uint32_t fb_id;
+   uint32_t width, height;
+   uint32_t pixel_format; /* fourcc code from drm_fourcc.h */
+   uint64_t modifier; /* applies to all buffers */
+   uint32_t flags;
+
+   /* per-plane GEM handle; may be duplicate entries for multiple planes */
+   uint32_t handles[4];
+   uint32_t pitches[4]; /* bytes */
+   uint32_t offsets[4]; /* bytes */
+} drmModeFB2, *drmModeFB2Ptr;
+
 typedef struct drm_clip_rect drmModeClip, *drmModeClipPtr;
 
 typedef struct _drmModePropertyBlob {
@@ -343,6 +356,7 @@ typedef struct _drmModePlaneRes {
 extern void drmModeFreeModeInfo( drmModeModeInfoPtr ptr );
 extern void drmModeFreeResources( drmModeResPtr ptr );
 extern void drmModeFreeFB( drmModeFBPtr ptr );
+extern void drmModeFreeFB2( drmModeFB2Ptr ptr );
 extern void drmModeFreeCrtc( drmModeCrtcPtr ptr );
 extern void drmModeFreeConnector( drmModeConnectorPtr ptr );
 extern void drmModeFreeEncoder( drmModeEncoderPtr ptr );
@@ -362,6 +376,7 @@ extern drmModeResPtr drmModeGetResources(int fd);
  * Retrieve information about framebuffer bufferId
  */
 extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId);
+extern drmModeFB2Ptr drmModeGetFB2(int fd, uint32_t bufferId);
 
 /**
  * Creates a new framebuffer with an buffer object as its scanout buffer.
-- 
2.21.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v5 libdrm 1/2] include/drm: sync up drm.h

2020-02-05 Thread Juston Li
Adds DRM_IOCTL_MODE_GETFB2

Taken from drm-next-misc:
commit 3ff4c24bdb1f494c217c80348f9db4896043ed81
Author: Lyude Paul 
Date:   Fri Jan 17 17:47:48 2020 -0500

drm/dp_mst: Fix indenting in drm_dp_mst_topology_mgr_set_mst()

Signed-off-by: Juston Li 
---
 include/drm/drm.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/drm/drm.h b/include/drm/drm.h
index ab9403397815..c7fd2a35fd7b 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -942,6 +942,8 @@ extern "C" {
 #define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct 
drm_syncobj_transfer)
 #define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL  DRM_IOWR(0xCD, struct 
drm_syncobj_timeline_array)
 
+#define DRM_IOCTL_MODE_GETFB2  DRM_IOWR(0xCE, struct drm_mode_fb_cmd2)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x9f.
-- 
2.21.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v4 libdrm 2/2] Add drmModeGetFB2

2020-01-31 Thread Juston Li
From: Daniel Stone 

Add a wrapper around the getfb2 ioctl, which returns extended
framebuffer information mirroring addfb2, including multiple planes and
modifiers.

Changes since v3:
 - remove unnecessary null check in drmModeFreeFB2 (Daniel Stone)

Changes since v2:
 - getfb2 ioctl has been merged upstream
 - sync include/drm/drm.h in a seperate patch

Changes since v1:
 - functions should be drm_public
 - modifier should be 64 bits
 - update ioctl number

Signed-off-by: Juston Li 
Signed-off-by: Daniel Stone 
---
 xf86drmMode.c | 36 
 xf86drmMode.h | 15 +++
 2 files changed, 51 insertions(+)

diff --git a/xf86drmMode.c b/xf86drmMode.c
index 0cf7992c6e9a..94dc8ce38a5e 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -1594,3 +1594,39 @@ drmModeRevokeLease(int fd, uint32_t lessee_id)
return 0;
return -errno;
 }
+
+drm_public drmModeFB2Ptr
+drmModeGetFB2(int fd, uint32_t fb_id)
+{
+   struct drm_mode_fb_cmd2 get;
+   drmModeFB2Ptr ret;
+   int err;
+
+   memclear(get);
+   get.fb_id = fb_id;
+
+   err = DRM_IOCTL(fd, DRM_IOCTL_MODE_GETFB2, );
+   if (err != 0)
+   return NULL;
+
+   ret = drmMalloc(sizeof(drmModeFB2));
+   if (!ret)
+   return NULL;
+
+   ret->fb_id = fb_id;
+   ret->width = get.width;
+   ret->height = get.height;
+   ret->pixel_format = get.pixel_format;
+   ret->flags = get.flags;
+   ret->modifier = get.modifier[0];
+   memcpy(ret->handles, get.handles, sizeof(uint32_t) * 4);
+   memcpy(ret->pitches, get.pitches, sizeof(uint32_t) * 4);
+   memcpy(ret->offsets, get.offsets, sizeof(uint32_t) * 4);
+
+   return ret;
+}
+
+drm_public void drmModeFreeFB2(drmModeFB2Ptr ptr)
+{
+   drmFree(ptr);
+}
diff --git a/xf86drmMode.h b/xf86drmMode.h
index 159a39937240..fc0bbd8dcb67 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -225,6 +225,19 @@ typedef struct _drmModeFB {
uint32_t handle;
 } drmModeFB, *drmModeFBPtr;
 
+typedef struct _drmModeFB2 {
+   uint32_t fb_id;
+   uint32_t width, height;
+   uint32_t pixel_format; /* fourcc code from drm_fourcc.h */
+   uint64_t modifier; /* applies to all buffers */
+   uint32_t flags;
+
+   /* per-plane GEM handle; may be duplicate entries for multiple planes */
+   uint32_t handles[4];
+   uint32_t pitches[4]; /* bytes */
+   uint32_t offsets[4]; /* bytes */
+} drmModeFB2, *drmModeFB2Ptr;
+
 typedef struct drm_clip_rect drmModeClip, *drmModeClipPtr;
 
 typedef struct _drmModePropertyBlob {
@@ -343,6 +356,7 @@ typedef struct _drmModePlaneRes {
 extern void drmModeFreeModeInfo( drmModeModeInfoPtr ptr );
 extern void drmModeFreeResources( drmModeResPtr ptr );
 extern void drmModeFreeFB( drmModeFBPtr ptr );
+extern void drmModeFreeFB2( drmModeFB2Ptr ptr );
 extern void drmModeFreeCrtc( drmModeCrtcPtr ptr );
 extern void drmModeFreeConnector( drmModeConnectorPtr ptr );
 extern void drmModeFreeEncoder( drmModeEncoderPtr ptr );
@@ -362,6 +376,7 @@ extern drmModeResPtr drmModeGetResources(int fd);
  * Retrieve information about framebuffer bufferId
  */
 extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId);
+extern drmModeFB2Ptr drmModeGetFB2(int fd, uint32_t bufferId);
 
 /**
  * Creates a new framebuffer with an buffer object as its scanout buffer.
-- 
2.21.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v4 libdrm 1/2] include/drm: sync up drm.h to 3ff4c24bdb1f

2020-01-31 Thread Juston Li
Adds DRM_IOCTL_MODE_GETFB2

Taken from drm-next-misc:
commit 3ff4c24bdb1f494c217c80348f9db4896043ed81
Author: Lyude Paul 
Date:   Fri Jan 17 17:47:48 2020 -0500

drm/dp_mst: Fix indenting in drm_dp_mst_topology_mgr_set_mst()

Signed-off-by: Juston Li 
---
 include/drm/drm.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/drm/drm.h b/include/drm/drm.h
index ab9403397815..c7fd2a35fd7b 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -942,6 +942,8 @@ extern "C" {
 #define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct 
drm_syncobj_transfer)
 #define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL  DRM_IOWR(0xCD, struct 
drm_syncobj_timeline_array)
 
+#define DRM_IOCTL_MODE_GETFB2  DRM_IOWR(0xCE, struct drm_mode_fb_cmd2)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x9f.
-- 
2.21.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 libdrm 1/2] include/drm: sync up drm.h

2020-01-22 Thread Juston Li
Adds DRM_IOCTL_MODE_GETFB2

Taken from drm-next-misc:
commit 3ff4c24bdb1f494c217c80348f9db4896043ed81
Author: Lyude Paul 
Date:   Fri Jan 17 17:47:48 2020 -0500

drm/dp_mst: Fix indenting in drm_dp_mst_topology_mgr_set_mst()

Signed-off-by: Juston Li 
---
 include/drm/drm.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/drm/drm.h b/include/drm/drm.h
index ab9403397815..c7fd2a35fd7b 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -942,6 +942,8 @@ extern "C" {
 #define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct 
drm_syncobj_transfer)
 #define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL  DRM_IOWR(0xCD, struct 
drm_syncobj_timeline_array)
 
+#define DRM_IOCTL_MODE_GETFB2  DRM_IOWR(0xCE, struct drm_mode_fb_cmd2)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x9f.
-- 
2.21.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 libdrm 2/2] Add drmModeGetFB2

2020-01-22 Thread Juston Li
From: Daniel Stone 

Add a wrapper around the getfb2 ioctl, which returns extended
framebuffer information mirroring addfb2, including multiple planes and
modifiers.

Changes since v2:
 - getfb2 ioctl has been merged upstream
 - sync include/drm/drm.h in a seperate patch

Changes since v1:
 - functions should be drm_public
 - modifier should be 64 bits
 - update ioctl number

Signed-off-by: Juston Li 
---
 xf86drmMode.c | 40 
 xf86drmMode.h | 15 +++
 2 files changed, 55 insertions(+)

diff --git a/xf86drmMode.c b/xf86drmMode.c
index 207d7be91caa..6c5f6cc2a075 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -1594,3 +1594,43 @@ drmModeRevokeLease(int fd, uint32_t lessee_id)
return 0;
return -errno;
 }
+
+drm_public drmModeFB2Ptr
+drmModeGetFB2(int fd, uint32_t fb_id)
+{
+   struct drm_mode_fb_cmd2 get;
+   drmModeFB2Ptr ret;
+   int err;
+
+   memclear(get);
+   get.fb_id = fb_id;
+
+   err = DRM_IOCTL(fd, DRM_IOCTL_MODE_GETFB2, );
+   if (err != 0)
+   return NULL;
+
+   ret = drmMalloc(sizeof(drmModeFB2));
+   if (!ret)
+   return NULL;
+
+   ret->fb_id = fb_id;
+   ret->width = get.width;
+   ret->height = get.height;
+   ret->pixel_format = get.pixel_format;
+   ret->flags = get.flags;
+   ret->modifier = get.modifier[0];
+   memcpy(ret->handles, get.handles, sizeof(uint32_t) * 4);
+   memcpy(ret->pitches, get.pitches, sizeof(uint32_t) * 4);
+   memcpy(ret->offsets, get.offsets, sizeof(uint32_t) * 4);
+
+   return ret;
+}
+
+drm_public void drmModeFreeFB2(drmModeFB2Ptr ptr)
+{
+   if (!ptr)
+   return;
+
+   /* we might add more frees later. */
+   drmFree(ptr);
+}
diff --git a/xf86drmMode.h b/xf86drmMode.h
index 159a39937240..fc0bbd8dcb67 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -225,6 +225,19 @@ typedef struct _drmModeFB {
uint32_t handle;
 } drmModeFB, *drmModeFBPtr;
 
+typedef struct _drmModeFB2 {
+   uint32_t fb_id;
+   uint32_t width, height;
+   uint32_t pixel_format; /* fourcc code from drm_fourcc.h */
+   uint64_t modifier; /* applies to all buffers */
+   uint32_t flags;
+
+   /* per-plane GEM handle; may be duplicate entries for multiple planes */
+   uint32_t handles[4];
+   uint32_t pitches[4]; /* bytes */
+   uint32_t offsets[4]; /* bytes */
+} drmModeFB2, *drmModeFB2Ptr;
+
 typedef struct drm_clip_rect drmModeClip, *drmModeClipPtr;
 
 typedef struct _drmModePropertyBlob {
@@ -343,6 +356,7 @@ typedef struct _drmModePlaneRes {
 extern void drmModeFreeModeInfo( drmModeModeInfoPtr ptr );
 extern void drmModeFreeResources( drmModeResPtr ptr );
 extern void drmModeFreeFB( drmModeFBPtr ptr );
+extern void drmModeFreeFB2( drmModeFB2Ptr ptr );
 extern void drmModeFreeCrtc( drmModeCrtcPtr ptr );
 extern void drmModeFreeConnector( drmModeConnectorPtr ptr );
 extern void drmModeFreeEncoder( drmModeEncoderPtr ptr );
@@ -362,6 +376,7 @@ extern drmModeResPtr drmModeGetResources(int fd);
  * Retrieve information about framebuffer bufferId
  */
 extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId);
+extern drmModeFB2Ptr drmModeGetFB2(int fd, uint32_t bufferId);
 
 /**
  * Creates a new framebuffer with an buffer object as its scanout buffer.
-- 
2.21.1

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3] drm: Add getfb2 ioctl

2019-12-16 Thread Juston Li
From: Daniel Stone 

getfb2 allows us to pass multiple planes and modifiers, just like addfb2
over addfb.

Changes since v2:
 - add privilege checks from getfb1 since handles should only be
   returned to master/root

Changes since v1:
 - unused modifiers set to 0 instead of DRM_FORMAT_MOD_INVALID
 - update ioctl number

Signed-off-by: Daniel Stone 
Signed-off-by: Juston Li 
Acked-by: Daniel Vetter 
---
 drivers/gpu/drm/drm_crtc_internal.h |   2 +
 drivers/gpu/drm/drm_framebuffer.c   | 122 
 drivers/gpu/drm/drm_ioctl.c |   1 +
 include/uapi/drm/drm.h  |   2 +
 4 files changed, 127 insertions(+)

diff --git a/drivers/gpu/drm/drm_crtc_internal.h 
b/drivers/gpu/drm/drm_crtc_internal.h
index c7d5e4c21423..16f2413403aa 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -216,6 +216,8 @@ int drm_mode_rmfb_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
 int drm_mode_getfb(struct drm_device *dev,
   void *data, struct drm_file *file_priv);
+int drm_mode_getfb2_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
 int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
   void *data, struct drm_file *file_priv);
 
diff --git a/drivers/gpu/drm/drm_framebuffer.c 
b/drivers/gpu/drm/drm_framebuffer.c
index 57564318ceea..57ac94ce9b9e 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -548,7 +549,128 @@ int drm_mode_getfb(struct drm_device *dev,
 
 out:
drm_framebuffer_put(fb);
+   return ret;
+}
+
+/**
+ * drm_mode_getfb2 - get extended FB info
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Lookup the FB given its ID and return info about it.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_getfb2_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv)
+{
+   struct drm_mode_fb_cmd2 *r = data;
+   struct drm_framebuffer *fb;
+   unsigned int i;
+   int ret;
+
+   if (!drm_core_check_feature(dev, DRIVER_MODESET))
+   return -EINVAL;
+
+   fb = drm_framebuffer_lookup(dev, file_priv, r->fb_id);
+   if (!fb)
+   return -ENOENT;
+
+   /* For multi-plane framebuffers, we require the driver to place the
+* GEM objects directly in the drm_framebuffer. For single-plane
+* framebuffers, we can fall back to create_handle.
+*/
+   if (!fb->obj[0] &&
+   (fb->format->num_planes > 1 || !fb->funcs->create_handle)) {
+   ret = -ENODEV;
+   goto out;
+   }
+
+   r->height = fb->height;
+   r->width = fb->width;
+   r->pixel_format = fb->format->format;
+
+   r->flags = 0;
+   if (dev->mode_config.allow_fb_modifiers)
+   r->flags |= DRM_MODE_FB_MODIFIERS;
+
+   for (i = 0; i < ARRAY_SIZE(r->handles); i++) {
+   r->handles[i] = 0;
+   r->pitches[i] = 0;
+   r->offsets[i] = 0;
+   r->modifier[i] = 0;
+   }
+
+   for (i = 0; i < fb->format->num_planes; i++) {
+   r->pitches[i] = fb->pitches[i];
+   r->offsets[i] = fb->offsets[i];
+   if (dev->mode_config.allow_fb_modifiers)
+   r->modifier[i] = fb->modifier;
+   }
+
+   /* GET_FB2() is an unprivileged ioctl so we must not return a
+* buffer-handle to non master/root processes! To match GET_FB()
+* just return invalid handles (0) for non masters/root
+* rather than making GET_FB2() privileged.
+*/
+   if (!drm_is_current_master(file_priv) && !capable(CAP_SYS_ADMIN)) {
+   ret = 0;
+   goto out;
+   }
 
+   for (i = 0; i < fb->format->num_planes; i++) {
+   int j;
+
+   /* If we reuse the same object for multiple planes, also
+* return the same handle.
+*/
+   for (j = 0; j < i; j++) {
+   if (fb->obj[i] == fb->obj[j]) {
+   r->handles[i] = r->handles[j];
+   break;
+   }
+   }
+
+   if (r->handles[i])
+   continue;
+
+   if (fb->obj[i]) {
+   ret = drm_gem_handle_create(file_priv, fb->obj[i],
+   >handles[i]);
+   } else {
+   

[PATCH i-g-t 2/2 v3] tests/kms_getfb: Add getfb2 tests

2019-10-15 Thread Juston Li
From: Daniel Stone 

Mirroring addfb2, add tests for the new ioctl which will return us
information about framebuffers containing multiple buffers, as well as
modifiers.

Changes since v1:
- Add test that uses getfb2 output to call addfb2 as suggested by Ville 

Signed-off-by: Daniel Stone 
Signed-off-by: Juston Li 
---
 tests/kms_getfb.c | 103 ++
 1 file changed, 103 insertions(+)

diff --git a/tests/kms_getfb.c b/tests/kms_getfb.c
index ca0b01c05e5c..848b896b7556 100644
--- a/tests/kms_getfb.c
+++ b/tests/kms_getfb.c
@@ -228,6 +228,106 @@ static void test_duplicate_handles(int fd)
}
 }
 
+static void test_getfb2(int fd)
+{
+   struct drm_mode_fb_cmd2 add_basic = {};
+
+   igt_fixture {
+   struct drm_mode_fb_cmd2 get = {};
+
+   add_basic.width = 1024;
+   add_basic.height = 1024;
+   add_basic.pixel_format = DRM_FORMAT_XRGB;
+   add_basic.pitches[0] = 1024*4;
+   add_basic.handles[0] = igt_create_bo_with_dimensions(fd, 1024, 
1024,
+   DRM_FORMAT_XRGB, 0, 0, NULL, NULL, NULL);
+   igt_assert(add_basic.handles[0]);
+   do_ioctl(fd, DRM_IOCTL_MODE_ADDFB2, _basic);
+
+   get.fb_id = add_basic.fb_id;
+   do_ioctl(fd, DRM_IOCTL_MODE_GETFB2, );
+   igt_assert_neq_u32(get.handles[0], 0);
+   gem_close(fd, get.handles[0]);
+   }
+
+   igt_subtest("getfb2-handle-zero") {
+   struct drm_mode_fb_cmd2 get = {};
+   do_ioctl_err(fd, DRM_IOCTL_MODE_GETFB2, , ENOENT);
+   }
+
+   igt_subtest("getfb2-handle-closed") {
+   struct drm_mode_fb_cmd2 add = add_basic;
+   struct drm_mode_fb_cmd2 get = { };
+
+   add.handles[0] = igt_create_bo_with_dimensions(fd, 1024, 1024,
+   DRM_FORMAT_XRGB, 0, 0, NULL, NULL, NULL);
+   igt_assert(add.handles[0]);
+   do_ioctl(fd, DRM_IOCTL_MODE_ADDFB2, );
+   do_ioctl(fd, DRM_IOCTL_MODE_RMFB, _id);
+
+   get.fb_id = add.fb_id;
+   do_ioctl_err(fd, DRM_IOCTL_MODE_GETFB2, , ENOENT);
+   gem_close(fd, add.handles[0]);
+   }
+
+   igt_subtest("getfb2-handle-not-fb") {
+   struct drm_mode_fb_cmd get = { .fb_id = get_any_prop_id(fd) };
+   igt_require(get.fb_id > 0);
+   do_ioctl_err(fd, DRM_IOCTL_MODE_GETFB, , ENOENT);
+   }
+
+   igt_subtest("getfb2-accept-ccs") {
+   struct drm_mode_fb_cmd2 add_ccs = { };
+   struct drm_mode_fb_cmd2 get = { };
+   int i;
+
+   get_ccs_fb(fd, _ccs);
+   igt_require(add_ccs.fb_id != 0);
+   get.fb_id = add_ccs.fb_id;
+   do_ioctl(fd, DRM_IOCTL_MODE_GETFB2, );
+
+   igt_assert_eq_u32(get.width, add_ccs.width);
+   igt_assert_eq_u32(get.height, add_ccs.height);
+   igt_assert(get.flags & DRM_MODE_FB_MODIFIERS);
+
+   for (i = 0; i < ARRAY_SIZE(get.handles); i++) {
+   igt_assert_eq_u32(get.pitches[i], add_ccs.pitches[i]);
+   igt_assert_eq_u32(get.offsets[i], add_ccs.offsets[i]);
+   if (add_ccs.handles[i] != 0) {
+   igt_assert_neq_u32(get.handles[i], 0);
+   igt_assert_neq_u32(get.handles[i],
+  add_ccs.handles[i]);
+   igt_assert_eq_u64(get.modifier[i],
+ add_ccs.modifier[i]);
+   } else {
+   igt_assert_eq_u32(get.handles[i], 0);
+   igt_assert_eq_u64(get.modifier[i], 0);
+   }
+   }
+   igt_assert_eq_u32(get.handles[0], get.handles[1]);
+
+   do_ioctl(fd, DRM_IOCTL_MODE_RMFB, _id);
+   gem_close(fd, add_ccs.handles[0]);
+   gem_close(fd, get.handles[0]);
+   }
+
+   igt_subtest("getfb2-into-addfb2") {
+   struct drm_mode_fb_cmd2 cmd = { };
+
+   cmd.fb_id = add_basic.fb_id;
+   do_ioctl(fd, DRM_IOCTL_MODE_GETFB2, );
+   do_ioctl(fd, DRM_IOCTL_MODE_ADDFB2, );
+
+   do_ioctl(fd, DRM_IOCTL_MODE_RMFB, _id);
+   gem_close(fd, cmd.handles[0]);
+   }
+
+   igt_fixture {
+   do_ioctl(fd, DRM_IOCTL_MODE_RMFB, _basic.fb_id);
+   gem_close(fd, add_basic.handles[0]);
+   }
+}
+
 igt_main
 {
int fd;
@@ -243,6 +343,9 @@ igt_main
igt_subtest_group
test_duplicate_handles(fd);
 
+   igt_subtest_group
+   test_getfb2(fd);
+
igt_fixture
close(fd);
 }
-- 
2.21.

[PATCH i-g-t 1/2 v3] NOMERGE: Import drm.h up to 54ecb8f7028c

2019-10-15 Thread Juston Li
Depends on ummerged kernel code for getfb2

Rest of drm.h taken from:
commit 54ecb8f7028c5eb3d740bb82b0f1d90f2df63c5c
Author: Linus Torvalds 
Date:   Mon Sep 30 10:35:40 2019 -0700

Linux 5.4-rc1

Signed-off-by: Juston Li 
---
 include/drm-uapi/drm.h | 39 +++
 1 file changed, 39 insertions(+)

diff --git a/include/drm-uapi/drm.h b/include/drm-uapi/drm.h
index 85c685a2075e..0b02f4c92d1e 100644
--- a/include/drm-uapi/drm.h
+++ b/include/drm-uapi/drm.h
@@ -643,6 +643,7 @@ struct drm_gem_open {
 #define DRM_CAP_PAGE_FLIP_TARGET   0x11
 #define DRM_CAP_CRTC_IN_VBLANK_EVENT   0x12
 #define DRM_CAP_SYNCOBJ0x13
+#define DRM_CAP_SYNCOBJ_TIMELINE   0x14
 
 /** DRM_IOCTL_GET_CAP ioctl argument type */
 struct drm_get_cap {
@@ -729,8 +730,18 @@ struct drm_syncobj_handle {
__u32 pad;
 };
 
+struct drm_syncobj_transfer {
+   __u32 src_handle;
+   __u32 dst_handle;
+   __u64 src_point;
+   __u64 dst_point;
+   __u32 flags;
+   __u32 pad;
+};
+
 #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0)
 #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1)
+#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE (1 << 2) /* wait for time point 
to become available */
 struct drm_syncobj_wait {
__u64 handles;
/* absolute timeout */
@@ -741,12 +752,33 @@ struct drm_syncobj_wait {
__u32 pad;
 };
 
+struct drm_syncobj_timeline_wait {
+   __u64 handles;
+   /* wait on specific timeline point for every handles*/
+   __u64 points;
+   /* absolute timeout */
+   __s64 timeout_nsec;
+   __u32 count_handles;
+   __u32 flags;
+   __u32 first_signaled; /* only valid when not waiting all */
+   __u32 pad;
+};
+
+
 struct drm_syncobj_array {
__u64 handles;
__u32 count_handles;
__u32 pad;
 };
 
+struct drm_syncobj_timeline_array {
+   __u64 handles;
+   __u64 points;
+   __u32 count_handles;
+   __u32 pad;
+};
+
+
 /* Query current scanout sequence number */
 struct drm_crtc_get_sequence {
__u32 crtc_id;  /* requested crtc_id */
@@ -903,6 +935,13 @@ extern "C" {
 #define DRM_IOCTL_MODE_GET_LEASE   DRM_IOWR(0xC8, struct 
drm_mode_get_lease)
 #define DRM_IOCTL_MODE_REVOKE_LEASEDRM_IOWR(0xC9, struct 
drm_mode_revoke_lease)
 
+#define DRM_IOCTL_SYNCOBJ_TIMELINE_WAITDRM_IOWR(0xCA, struct 
drm_syncobj_timeline_wait)
+#define DRM_IOCTL_SYNCOBJ_QUERYDRM_IOWR(0xCB, struct 
drm_syncobj_timeline_array)
+#define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct 
drm_syncobj_transfer)
+#define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL  DRM_IOWR(0xCD, struct 
drm_syncobj_timeline_array)
+
+#define DRM_IOCTL_MODE_GETFB2  DRM_IOWR(0xCE, struct drm_mode_fb_cmd2)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x9f.
-- 
2.21.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH i-g-t v2 1/2] tests/kms_getfb: Add getfb2 tests

2019-10-03 Thread Juston Li
From: Daniel Stone 

Mirroring addfb2, add tests for the new ioctl which will return us
information about framebuffers containing multiple buffers, as well as
modifiers.

Changes since v1:
 - Add test that uses getfb2 output to call addfb2 as suggested by Ville

Signed-off-by: Daniel Stone 
Signed-off-by: Juston Li 
---
 tests/kms_getfb.c | 103 ++
 1 file changed, 103 insertions(+)

diff --git a/tests/kms_getfb.c b/tests/kms_getfb.c
index ca0b01c05e5c..848b896b7556 100644
--- a/tests/kms_getfb.c
+++ b/tests/kms_getfb.c
@@ -228,6 +228,106 @@ static void test_duplicate_handles(int fd)
}
 }
 
+static void test_getfb2(int fd)
+{
+   struct drm_mode_fb_cmd2 add_basic = {};
+
+   igt_fixture {
+   struct drm_mode_fb_cmd2 get = {};
+
+   add_basic.width = 1024;
+   add_basic.height = 1024;
+   add_basic.pixel_format = DRM_FORMAT_XRGB;
+   add_basic.pitches[0] = 1024*4;
+   add_basic.handles[0] = igt_create_bo_with_dimensions(fd, 1024, 
1024,
+   DRM_FORMAT_XRGB, 0, 0, NULL, NULL, NULL);
+   igt_assert(add_basic.handles[0]);
+   do_ioctl(fd, DRM_IOCTL_MODE_ADDFB2, _basic);
+
+   get.fb_id = add_basic.fb_id;
+   do_ioctl(fd, DRM_IOCTL_MODE_GETFB2, );
+   igt_assert_neq_u32(get.handles[0], 0);
+   gem_close(fd, get.handles[0]);
+   }
+
+   igt_subtest("getfb2-handle-zero") {
+   struct drm_mode_fb_cmd2 get = {};
+   do_ioctl_err(fd, DRM_IOCTL_MODE_GETFB2, , ENOENT);
+   }
+
+   igt_subtest("getfb2-handle-closed") {
+   struct drm_mode_fb_cmd2 add = add_basic;
+   struct drm_mode_fb_cmd2 get = { };
+
+   add.handles[0] = igt_create_bo_with_dimensions(fd, 1024, 1024,
+   DRM_FORMAT_XRGB, 0, 0, NULL, NULL, NULL);
+   igt_assert(add.handles[0]);
+   do_ioctl(fd, DRM_IOCTL_MODE_ADDFB2, );
+   do_ioctl(fd, DRM_IOCTL_MODE_RMFB, _id);
+
+   get.fb_id = add.fb_id;
+   do_ioctl_err(fd, DRM_IOCTL_MODE_GETFB2, , ENOENT);
+   gem_close(fd, add.handles[0]);
+   }
+
+   igt_subtest("getfb2-handle-not-fb") {
+   struct drm_mode_fb_cmd get = { .fb_id = get_any_prop_id(fd) };
+   igt_require(get.fb_id > 0);
+   do_ioctl_err(fd, DRM_IOCTL_MODE_GETFB, , ENOENT);
+   }
+
+   igt_subtest("getfb2-accept-ccs") {
+   struct drm_mode_fb_cmd2 add_ccs = { };
+   struct drm_mode_fb_cmd2 get = { };
+   int i;
+
+   get_ccs_fb(fd, _ccs);
+   igt_require(add_ccs.fb_id != 0);
+   get.fb_id = add_ccs.fb_id;
+   do_ioctl(fd, DRM_IOCTL_MODE_GETFB2, );
+
+   igt_assert_eq_u32(get.width, add_ccs.width);
+   igt_assert_eq_u32(get.height, add_ccs.height);
+   igt_assert(get.flags & DRM_MODE_FB_MODIFIERS);
+
+   for (i = 0; i < ARRAY_SIZE(get.handles); i++) {
+   igt_assert_eq_u32(get.pitches[i], add_ccs.pitches[i]);
+   igt_assert_eq_u32(get.offsets[i], add_ccs.offsets[i]);
+   if (add_ccs.handles[i] != 0) {
+   igt_assert_neq_u32(get.handles[i], 0);
+   igt_assert_neq_u32(get.handles[i],
+  add_ccs.handles[i]);
+   igt_assert_eq_u64(get.modifier[i],
+ add_ccs.modifier[i]);
+   } else {
+   igt_assert_eq_u32(get.handles[i], 0);
+   igt_assert_eq_u64(get.modifier[i], 0);
+   }
+   }
+   igt_assert_eq_u32(get.handles[0], get.handles[1]);
+
+   do_ioctl(fd, DRM_IOCTL_MODE_RMFB, _id);
+   gem_close(fd, add_ccs.handles[0]);
+   gem_close(fd, get.handles[0]);
+   }
+
+   igt_subtest("getfb2-into-addfb2") {
+   struct drm_mode_fb_cmd2 cmd = { };
+
+   cmd.fb_id = add_basic.fb_id;
+   do_ioctl(fd, DRM_IOCTL_MODE_GETFB2, );
+   do_ioctl(fd, DRM_IOCTL_MODE_ADDFB2, );
+
+   do_ioctl(fd, DRM_IOCTL_MODE_RMFB, _id);
+   gem_close(fd, cmd.handles[0]);
+   }
+
+   igt_fixture {
+   do_ioctl(fd, DRM_IOCTL_MODE_RMFB, _basic.fb_id);
+   gem_close(fd, add_basic.handles[0]);
+   }
+}
+
 igt_main
 {
int fd;
@@ -243,6 +343,9 @@ igt_main
igt_subtest_group
test_duplicate_handles(fd);
 
+   igt_subtest_group
+   test_getfb2(fd);
+
igt_fixture
close(fd);
 }
-- 
2.21.

[PATCH i-g-t v2 2/2] NOMERGE: Import drm.h up to 54ecb8f7028c

2019-10-03 Thread Juston Li
Depends on ummerged kernel code for getfb2

Rest of drm.h taken from:
commit 54ecb8f7028c5eb3d740bb82b0f1d90f2df63c5c
Author: Linus Torvalds 
Date:   Mon Sep 30 10:35:40 2019 -0700

Linux 5.4-rc1

Signed-off-by: Juston Li 
---
 include/drm-uapi/drm.h | 39 +++
 1 file changed, 39 insertions(+)

diff --git a/include/drm-uapi/drm.h b/include/drm-uapi/drm.h
index 85c685a2075e..0b02f4c92d1e 100644
--- a/include/drm-uapi/drm.h
+++ b/include/drm-uapi/drm.h
@@ -643,6 +643,7 @@ struct drm_gem_open {
 #define DRM_CAP_PAGE_FLIP_TARGET   0x11
 #define DRM_CAP_CRTC_IN_VBLANK_EVENT   0x12
 #define DRM_CAP_SYNCOBJ0x13
+#define DRM_CAP_SYNCOBJ_TIMELINE   0x14
 
 /** DRM_IOCTL_GET_CAP ioctl argument type */
 struct drm_get_cap {
@@ -729,8 +730,18 @@ struct drm_syncobj_handle {
__u32 pad;
 };
 
+struct drm_syncobj_transfer {
+   __u32 src_handle;
+   __u32 dst_handle;
+   __u64 src_point;
+   __u64 dst_point;
+   __u32 flags;
+   __u32 pad;
+};
+
 #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0)
 #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1)
+#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE (1 << 2) /* wait for time point 
to become available */
 struct drm_syncobj_wait {
__u64 handles;
/* absolute timeout */
@@ -741,12 +752,33 @@ struct drm_syncobj_wait {
__u32 pad;
 };
 
+struct drm_syncobj_timeline_wait {
+   __u64 handles;
+   /* wait on specific timeline point for every handles*/
+   __u64 points;
+   /* absolute timeout */
+   __s64 timeout_nsec;
+   __u32 count_handles;
+   __u32 flags;
+   __u32 first_signaled; /* only valid when not waiting all */
+   __u32 pad;
+};
+
+
 struct drm_syncobj_array {
__u64 handles;
__u32 count_handles;
__u32 pad;
 };
 
+struct drm_syncobj_timeline_array {
+   __u64 handles;
+   __u64 points;
+   __u32 count_handles;
+   __u32 pad;
+};
+
+
 /* Query current scanout sequence number */
 struct drm_crtc_get_sequence {
__u32 crtc_id;  /* requested crtc_id */
@@ -903,6 +935,13 @@ extern "C" {
 #define DRM_IOCTL_MODE_GET_LEASE   DRM_IOWR(0xC8, struct 
drm_mode_get_lease)
 #define DRM_IOCTL_MODE_REVOKE_LEASEDRM_IOWR(0xC9, struct 
drm_mode_revoke_lease)
 
+#define DRM_IOCTL_SYNCOBJ_TIMELINE_WAITDRM_IOWR(0xCA, struct 
drm_syncobj_timeline_wait)
+#define DRM_IOCTL_SYNCOBJ_QUERYDRM_IOWR(0xCB, struct 
drm_syncobj_timeline_array)
+#define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct 
drm_syncobj_transfer)
+#define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL  DRM_IOWR(0xCD, struct 
drm_syncobj_timeline_array)
+
+#define DRM_IOCTL_MODE_GETFB2  DRM_IOWR(0xCE, struct drm_mode_fb_cmd2)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x9f.
-- 
2.21.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[RESEND PATCH libdrm v2] NOMERGE: Add drmModeGetFB2

2019-10-03 Thread Juston Li
From: Daniel Stone 

Add a wrapper around the getfb2 ioctl, which returns extended
framebuffer information mirroring addfb2, including multiple planes and
modifiers.

This depends on unmerged kernel API so should not be merged.

Changes since v1:
 - functions should be drm_public
 - modifier for should 64 bits
 - update ioctl number

Signed-off-by: Juston Li 
---
 include/drm/drm.h |  2 ++
 xf86drmMode.c | 40 
 xf86drmMode.h | 15 +++
 3 files changed, 57 insertions(+)

diff --git a/include/drm/drm.h b/include/drm/drm.h
index 438abde3621d..340a1b4e9cf6 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -941,6 +941,8 @@ extern "C" {
 #define DRM_IOCTL_SYNCOBJ_TRANSFER DRM_IOWR(0xCC, struct 
drm_syncobj_transfer)
 #define DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL  DRM_IOWR(0xCD, struct 
drm_syncobj_timeline_array)
 
+#define DRM_IOCTL_MODE_GETFB2  DRM_IOWR(0xCE, struct drm_mode_fb_cmd2)
+
 /**
  * Device specific ioctls should only be in their respective headers
  * The device specific ioctl range is from 0x40 to 0x9f.
diff --git a/xf86drmMode.c b/xf86drmMode.c
index 207d7be91caa..6c5f6cc2a075 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -1594,3 +1594,43 @@ drmModeRevokeLease(int fd, uint32_t lessee_id)
return 0;
return -errno;
 }
+
+drm_public drmModeFB2Ptr
+drmModeGetFB2(int fd, uint32_t fb_id)
+{
+   struct drm_mode_fb_cmd2 get;
+   drmModeFB2Ptr ret;
+   int err;
+
+   memclear(get);
+   get.fb_id = fb_id;
+
+   err = DRM_IOCTL(fd, DRM_IOCTL_MODE_GETFB2, );
+   if (err != 0)
+   return NULL;
+
+   ret = drmMalloc(sizeof(drmModeFB2));
+   if (!ret)
+   return NULL;
+
+   ret->fb_id = fb_id;
+   ret->width = get.width;
+   ret->height = get.height;
+   ret->pixel_format = get.pixel_format;
+   ret->flags = get.flags;
+   ret->modifier = get.modifier[0];
+   memcpy(ret->handles, get.handles, sizeof(uint32_t) * 4);
+   memcpy(ret->pitches, get.pitches, sizeof(uint32_t) * 4);
+   memcpy(ret->offsets, get.offsets, sizeof(uint32_t) * 4);
+
+   return ret;
+}
+
+drm_public void drmModeFreeFB2(drmModeFB2Ptr ptr)
+{
+   if (!ptr)
+   return;
+
+   /* we might add more frees later. */
+   drmFree(ptr);
+}
diff --git a/xf86drmMode.h b/xf86drmMode.h
index a32902f73289..07c98f42555d 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -223,6 +223,19 @@ typedef struct _drmModeFB {
uint32_t handle;
 } drmModeFB, *drmModeFBPtr;
 
+typedef struct _drmModeFB2 {
+   uint32_t fb_id;
+   uint32_t width, height;
+   uint32_t pixel_format; /* fourcc code from drm_fourcc.h */
+   uint64_t modifier; /* applies to all buffers */
+   uint32_t flags;
+
+   /* per-plane GEM handle; may be duplicate entries for multiple planes */
+   uint32_t handles[4];
+   uint32_t pitches[4]; /* bytes */
+   uint32_t offsets[4]; /* bytes */
+} drmModeFB2, *drmModeFB2Ptr;
+
 typedef struct drm_clip_rect drmModeClip, *drmModeClipPtr;
 
 typedef struct _drmModePropertyBlob {
@@ -341,6 +354,7 @@ typedef struct _drmModePlaneRes {
 extern void drmModeFreeModeInfo( drmModeModeInfoPtr ptr );
 extern void drmModeFreeResources( drmModeResPtr ptr );
 extern void drmModeFreeFB( drmModeFBPtr ptr );
+extern void drmModeFreeFB2( drmModeFB2Ptr ptr );
 extern void drmModeFreeCrtc( drmModeCrtcPtr ptr );
 extern void drmModeFreeConnector( drmModeConnectorPtr ptr );
 extern void drmModeFreeEncoder( drmModeEncoderPtr ptr );
@@ -360,6 +374,7 @@ extern drmModeResPtr drmModeGetResources(int fd);
  * Retrieve information about framebuffer bufferId
  */
 extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId);
+extern drmModeFB2Ptr drmModeGetFB2(int fd, uint32_t bufferId);
 
 /**
  * Creates a new framebuffer with an buffer object as its scanout buffer.
-- 
2.21.0

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[RESEND PATCH v2] drm: Add getfb2 ioctl

2019-10-03 Thread Juston Li
From: Daniel Stone 

getfb2 allows us to pass multiple planes and modifiers, just like addfb2
over addfb.

Changes since v1:
 - unused modifiers set to 0 instead of DRM_FORMAT_MOD_INVALID
 - update ioctl number

Signed-off-by: Daniel Stone 
Signed-off-by: Juston Li 
---
 drivers/gpu/drm/drm_crtc_internal.h |   2 +
 drivers/gpu/drm/drm_framebuffer.c   | 110 
 drivers/gpu/drm/drm_ioctl.c |   1 +
 include/uapi/drm/drm.h  |   2 +
 4 files changed, 115 insertions(+)

diff --git a/drivers/gpu/drm/drm_crtc_internal.h 
b/drivers/gpu/drm/drm_crtc_internal.h
index c7d5e4c21423..16f2413403aa 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -216,6 +216,8 @@ int drm_mode_rmfb_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
 int drm_mode_getfb(struct drm_device *dev,
   void *data, struct drm_file *file_priv);
+int drm_mode_getfb2_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
 int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
   void *data, struct drm_file *file_priv);
 
diff --git a/drivers/gpu/drm/drm_framebuffer.c 
b/drivers/gpu/drm/drm_framebuffer.c
index 57564318ceea..6db54f177443 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -31,6 +31,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -548,7 +549,116 @@ int drm_mode_getfb(struct drm_device *dev,
 
 out:
drm_framebuffer_put(fb);
+   return ret;
+}
+
+/**
+ * drm_mode_getfb2 - get extended FB info
+ * @dev: drm device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: drm file for the ioctl call
+ *
+ * Lookup the FB given its ID and return info about it.
+ *
+ * Called by the user via ioctl.
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_mode_getfb2_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv)
+{
+   struct drm_mode_fb_cmd2 *r = data;
+   struct drm_framebuffer *fb;
+   unsigned int i;
+   int ret;
+
+   if (!drm_core_check_feature(dev, DRIVER_MODESET))
+   return -EINVAL;
+
+   fb = drm_framebuffer_lookup(dev, file_priv, r->fb_id);
+   if (!fb)
+   return -ENOENT;
+
+   /* For multi-plane framebuffers, we require the driver to place the
+* GEM objects directly in the drm_framebuffer. For single-plane
+* framebuffers, we can fall back to create_handle.
+*/
+   if (!fb->obj[0] &&
+   (fb->format->num_planes > 1 || !fb->funcs->create_handle)) {
+   ret = -ENODEV;
+   goto out;
+   }
+
+   r->height = fb->height;
+   r->width = fb->width;
+   r->pixel_format = fb->format->format;
+
+   r->flags = 0;
+   if (dev->mode_config.allow_fb_modifiers)
+   r->flags |= DRM_MODE_FB_MODIFIERS;
+
+   for (i = 0; i < ARRAY_SIZE(r->handles); i++) {
+   r->handles[i] = 0;
+   r->pitches[i] = 0;
+   r->offsets[i] = 0;
+   r->modifier[i] = 0;
+   }
 
+   for (i = 0; i < fb->format->num_planes; i++) {
+   int j;
+
+   r->pitches[i] = fb->pitches[i];
+   r->offsets[i] = fb->offsets[i];
+   if (dev->mode_config.allow_fb_modifiers)
+   r->modifier[i] = fb->modifier;
+
+   /* If we reuse the same object for multiple planes, also
+* return the same handle.
+*/
+   for (j = 0; j < i; j++) {
+   if (fb->obj[i] == fb->obj[j]) {
+   r->handles[i] = r->handles[j];
+   break;
+   }
+   }
+
+   if (r->handles[i])
+   continue;
+
+   if (fb->obj[i]) {
+   ret = drm_gem_handle_create(file_priv, fb->obj[i],
+   >handles[i]);
+   } else {
+   WARN_ON(i > 0);
+   ret = fb->funcs->create_handle(fb, file_priv,
+  >handles[i]);
+   }
+
+   if (ret != 0)
+   goto out;
+   }
+
+out:
+   if (ret != 0) {
+   /* Delete any previously-created handles on failure. */
+   for (i = 0; i < ARRAY_SIZE(r->handles); i++) {
+   int j;
+
+   if (r->handles[i])
+   drm_gem_handle_delete(file_priv, r->handles[i]);
+
+   /* Zero out any handles iden

[RESEND PATCH v2 1/2] drm/dp/mst: Reprobe EDID for MST ports on resume

2018-10-23 Thread Juston Li
From: Lyude 

As observed with the latest ThinkPad docks, we unfortunately can't rely
on docks keeping us updated with hotplug events that happened while we
were suspended. On top of that, even if the number of connectors remains
the same between suspend and resume it's still not safe to assume that
there were no hotplugs, since a different monitor might have been
plugged into a port another monitor previously occupied. As such, we
need to go through all of the MST ports and check whether or not their
EDIDs have changed.

In addition to that, we also now return -EINVAL from
drm_dp_mst_topology_mgr_resume to indicate to callers that they need to
reset the MST connection, and that they can't rely on any other method
of reprobing.

Cc: sta...@vger.kernel.org
Signed-off-by: Lyude 
Signed-off-by: Juston Li 
---
 drivers/gpu/drm/drm_dp_mst_topology.c | 94 ++-
 1 file changed, 93 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c 
b/drivers/gpu/drm/drm_dp_mst_topology.c
index 5ff1d79b86c4..88abebe52021 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -29,6 +29,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -2201,6 +2202,64 @@ void drm_dp_mst_topology_mgr_suspend(struct 
drm_dp_mst_topology_mgr *mgr)
 }
 EXPORT_SYMBOL(drm_dp_mst_topology_mgr_suspend);
 
+static bool drm_dp_mst_edids_changed(struct drm_dp_mst_topology_mgr *mgr,
+struct drm_dp_mst_port *port)
+{
+   struct drm_device *dev;
+   struct drm_connector *connector;
+   struct drm_dp_mst_port *dport;
+   struct drm_dp_mst_branch *mstb;
+   struct edid *current_edid, *cached_edid;
+   bool ret = false;
+
+   port = drm_dp_get_validated_port_ref(mgr, port);
+   if (!port)
+   return false;
+
+   mstb = drm_dp_get_validated_mstb_ref(mgr, port->mstb);
+   if (mstb) {
+   list_for_each_entry(dport, >mstb->ports, next) {
+   ret = drm_dp_mst_edids_changed(mgr, dport);
+   if (ret)
+   break;
+   }
+
+   drm_dp_put_mst_branch_device(mstb);
+   if (ret)
+   goto out;
+   }
+
+   connector = port->connector;
+   if (!connector || !port->aux.ddc.algo)
+   goto out;
+
+   dev = connector->dev;
+   mutex_lock(>mode_config.mutex);
+
+   current_edid = drm_get_edid(connector, >aux.ddc);
+   if (connector->edid_blob_ptr)
+   cached_edid = (void *)connector->edid_blob_ptr->data;
+   else
+   return false;
+
+   if ((current_edid && cached_edid && memcmp(current_edid, cached_edid,
+  sizeof(struct edid)) != 0) ||
+   (!current_edid && cached_edid) || (current_edid && !cached_edid)) {
+   ret = true;
+   DRM_DEBUG_KMS("EDID on %s changed, reprobing connectors\n",
+ connector->name);
+   }
+
+   mutex_unlock(>mode_config.mutex);
+
+   kfree(current_edid);
+
+out:
+   drm_dp_put_port(port);
+
+   return ret;
+}
+
 /**
  * drm_dp_mst_topology_mgr_resume() - resume the MST manager
  * @mgr: manager to resume
@@ -2210,9 +2269,15 @@ EXPORT_SYMBOL(drm_dp_mst_topology_mgr_suspend);
  *
  * if the device fails this returns -1, and the driver should do
  * a full MST reprobe, in case we were undocked.
+ *
+ * if the device can no longer be trusted, this returns -EINVAL
+ * and the driver should unconditionally disconnect and reconnect
+ * the dock.
  */
 int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr)
 {
+   struct drm_dp_mst_branch *mstb;
+   struct drm_dp_mst_port *port;
int ret = 0;
 
mutex_lock(>lock);
@@ -2246,8 +2311,35 @@ int drm_dp_mst_topology_mgr_resume(struct 
drm_dp_mst_topology_mgr *mgr)
drm_dp_check_mstb_guid(mgr->mst_primary, guid);
 
ret = 0;
-   } else
+
+   /*
+* Some hubs also forget to notify us of hotplugs that happened
+* while we were in suspend, so we need to verify that the edid
+* hasn't changed for any of the connectors. If it has been,
+* we unfortunately can't rely on the dock updating us with
+* hotplug events, so indicate we need a full reconnect.
+*/
+
+   /* MST's I2C helpers can't be used while holding this lock */
+   mutex_unlock(>lock);
+
+   mstb = drm_dp_get_validated_mstb_ref(mgr, mgr->mst_primary);
+   if (mstb) {
+   list_for_each_entry(port, >ports, next) {
+   if (drm_dp_mst_edids_changed(mgr, port)) {
+   

[RESEND PATCH v2 2/2] drm/i915/mst: Reset MST after resume when necessary

2018-10-23 Thread Juston Li
From: Lyude 

A follow-up to the previous commit, we skip checking the status of the
MST device and completely reprobe it if drm_dp_mst_topology_mgr_resume()
returns -EINVAL.

Cc: sta...@vger.kernel.org
Signed-off-by: Lyude 
Signed-off-by: Juston Li 
---
 drivers/gpu/drm/i915/intel_dp.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 8c38efef77a1..cb5ffec73094 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -6793,7 +6793,12 @@ void intel_dp_mst_resume(struct drm_i915_private 
*dev_priv)
continue;
 
ret = drm_dp_mst_topology_mgr_resume(_dp->mst_mgr);
-   if (ret)
+   /* A full reset is required */
+   if (ret == -EINVAL) {
+   drm_dp_mst_topology_mgr_set_mst(_dp->mst_mgr, 
false);
+   intel_dp_configure_mst(intel_dp);
+   } else if (ret != 0) {
intel_dp_check_mst_status(intel_dp);
+   }
}
 }
-- 
2.17.2

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[RESEND PATCH v2 0/2] Check MST topology change on resume

2018-10-23 Thread Juston Li
Updated and resending these patches from Lyude:
https://lkml.org/lkml/2016/5/19/361
https://lkml.org/lkml/2016/5/19/360

As Lyude explains in patch 1/2, we can't rely on MST hubs to handle
hotplugs during suspend. This patchset will check if any EDID's changed
upon resume and reset the MST connections if they did.

This resolves issues with monitors not being detected when hotplugging them
during suspend.

Signed-off-by: Juston Li 

Changes since v1:
 - update functions that have been renamed since the original patch
 - add a null check for the cached EDID in case a new device was added
 - checkpatch fixes

Lyude (2):
  drm/dp/mst: Reprobe EDID for MST ports on resume
  drm/i915/mst: Reset MST after resume when necessary

 drivers/gpu/drm/drm_dp_mst_topology.c | 94 ++-
 drivers/gpu/drm/i915/intel_dp.c   |  7 +-
 2 files changed, 99 insertions(+), 2 deletions(-)

-- 
2.17.2

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel